1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package main
20
21 import (
22 "bytes"
23 "encoding/csv"
24 "flag"
25 "fmt"
26 gofmt "go/format"
27 asm "golang.org/x/arch/ppc64/ppc64asm"
28 "log"
29 "math/bits"
30 "os"
31 "regexp"
32 "sort"
33 "strconv"
34 "strings"
35 "text/template"
36 )
37
38 var format = flag.String("fmt", "text", "output format: text, decoder, asm")
39 var debug = flag.Bool("debug", false, "enable debugging output")
40
41 var inputFile string
42
43 type isaversion uint32
44
45 const (
46
47
48
49 ISA_P1 isaversion = iota
50 ISA_P2
51 ISA_PPC
52 ISA_V200
53 ISA_V201
54 ISA_V202
55 ISA_V203
56 ISA_V205
57 ISA_V206
58 ISA_V207
59 ISA_V30
60 ISA_V30B
61 ISA_V30C
62 ISA_V31
63 ISA_V31B
64 )
65
66 var isaToISA = map[string]isaversion{
67 "P1": ISA_P1,
68 "P2": ISA_P2,
69 "PPC": ISA_PPC,
70 "v2.00": ISA_V200,
71 "v2.01": ISA_V201,
72 "v2.02": ISA_V202,
73 "v2.03": ISA_V203,
74 "v2.05": ISA_V205,
75 "v2.06": ISA_V206,
76 "v2.07": ISA_V207,
77 "v3.0": ISA_V30,
78 "v3.0B": ISA_V30B,
79 "v3.0C": ISA_V30C,
80 "v3.1": ISA_V31,
81 "v3.1B": ISA_V31B,
82 }
83
84 func usage() {
85 fmt.Fprintf(os.Stderr, "usage: ppc64map [-fmt=format] ppc64.csv\n")
86 os.Exit(2)
87 }
88
89 func main() {
90 log.SetFlags(0)
91 log.SetPrefix("ppc64map: ")
92
93 flag.Usage = usage
94 flag.Parse()
95 if flag.NArg() != 1 {
96 usage()
97 }
98
99 inputFile = flag.Arg(0)
100
101 var print func(*Prog)
102 switch *format {
103 default:
104 log.Fatalf("unknown output format %q", *format)
105 case "text":
106 print = printText
107 case "decoder":
108 print = printDecoder
109 case "asm":
110 print = printASM
111 case "encoder":
112 print = printEncoder
113 }
114
115 p, err := readCSV(flag.Arg(0))
116 if err != nil {
117 log.Fatal(err)
118 }
119 log.Printf("Parsed %d instruction forms.", len(p.Insts))
120 print(p)
121 }
122
123
124
125 func readCSV(file string) (*Prog, error) {
126
127
128 f, err := os.Open(file)
129 if err != nil {
130 return nil, err
131 }
132 csvReader := csv.NewReader(f)
133 csvReader.Comment = '#'
134 table, err := csvReader.ReadAll()
135 if err != nil {
136 return nil, fmt.Errorf("parsing %s: %v", file, err)
137 }
138 if len(table) == 0 {
139 return nil, fmt.Errorf("empty csv input")
140 }
141 if len(table[0]) < 4 {
142 return nil, fmt.Errorf("csv too narrow: need at least four columns")
143 }
144
145 p := &Prog{}
146 for _, row := range table {
147 add(p, row[0], row[1], row[2], row[3])
148 }
149 return p, nil
150 }
151
152 type Prog struct {
153 Insts []Inst
154 OpRanges map[string]string
155 nextOrder int
156 }
157
158 type Field struct {
159 Name string
160 BitFields asm.BitFields
161 BitFieldNames []string
162 Type asm.ArgType
163 Shift uint8
164 }
165
166 func (f Field) String() string {
167 return fmt.Sprintf("%v(%s%v)", f.Type, f.Name, f.BitFields)
168 }
169
170 type Inst struct {
171 Text string
172 Encoding string
173 Op string
174 Mask uint32
175 Value uint32
176 DontCare uint32
177 SMask uint32
178 SValue uint32
179 SDontCare uint32
180 Fields []Field
181 Words int
182 Isa isaversion
183 memOp bool
184 memOpX bool
185 memOpSt bool
186 order int
187 }
188
189 func (i Inst) String() string {
190 return fmt.Sprintf("%s (%s) %08x/%08x[%08x] %v (%s)", i.Op, i.Encoding, i.Value, i.Mask, i.DontCare, i.Fields, i.Text)
191 }
192
193 type Arg struct {
194 Name string
195 Bits int8
196 Offs int8
197
198
199 Word int8
200 }
201
202 func (a Arg) String() string {
203 return fmt.Sprintf("%s[%d:%d]", a.Name, a.Offs, a.Offs+a.Bits-1)
204 }
205
206 func (a Arg) Maximum() int {
207 return 1<<uint8(a.Bits) - 1
208 }
209
210 func (a Arg) BitMask() uint32 {
211 return uint32(a.Maximum()) << a.Shift()
212 }
213
214 func (a Arg) Shift() uint8 {
215 return uint8(32 - a.Offs - a.Bits)
216 }
217
218 type Args []Arg
219
220 func (as Args) String() string {
221 ss := make([]string, len(as))
222 for i := range as {
223 ss[i] = as[i].String()
224 }
225 return strings.Join(ss, "|")
226 }
227
228 func (as Args) Find(name string) int {
229 for i := range as {
230 if as[i].Name == name {
231 return i
232 }
233 }
234 return -1
235 }
236
237 func (as *Args) Append(a Arg) {
238 *as = append(*as, a)
239 }
240
241 func (as *Args) Delete(i int) {
242 *as = append((*as)[:i], (*as)[i+1:]...)
243 }
244
245 func (as Args) Clone() Args {
246 return append(Args{}, as...)
247 }
248
249 func (a Arg) isDontCare() bool {
250 return a.Name[0] == '/' && a.Name == strings.Repeat("/", len(a.Name))
251 }
252
253 type instArray []Inst
254
255 func (i instArray) Len() int {
256 return len(i)
257 }
258
259 func (i instArray) Swap(j, k int) {
260 i[j], i[k] = i[k], i[j]
261 }
262
263
264
265 func (i instArray) Less(j, k int) bool {
266 return bits.OnesCount32(i[j].Mask) > bits.OnesCount32(i[k].Mask)
267 }
268
269
270
271 func parseFields(encoding, text string, word int8) Args {
272 var err error
273 var args Args
274
275 fields := strings.Split(encoding, "|")
276
277 for i, f := range fields {
278 name, off := "", -1
279 if f == "" {
280 off = 32
281 if i == 0 || i != len(fields)-1 {
282 fmt.Fprintf(os.Stderr, "%s: wrong %d-th encoding field: %q\n", text, i, f)
283 panic("Invalid encoding entry.")
284 }
285 } else {
286 j := strings.Index(f, "@")
287 if j < 0 {
288 fmt.Fprintf(os.Stderr, "%s: wrong %d-th encoding field: %q\n", text, i, f)
289 panic("Invalid encoding entry.")
290 continue
291 }
292 k := strings.Index(f[j+1:], " ")
293 if k >= 0 {
294 if strings.HasSuffix(f[j+1:], " 31") {
295 f = f[:len(f)-3]
296 }
297 }
298 off, err = strconv.Atoi(f[j+1:])
299 if err != nil {
300 fmt.Fprintf(os.Stderr, "err for: %s has: %s for %s\n", f[:j], err, f[j+1:])
301 }
302 name = f[:j]
303 }
304 if len(args) > 0 {
305 args[len(args)-1].Bits += int8(off)
306 }
307 if name != "" {
308 arg := Arg{Name: name, Offs: int8(off), Bits: int8(-off), Word: word}
309 args.Append(arg)
310 }
311 }
312
313 return args
314 }
315
316
317
318
319 func computeMaskValueReserved(args Args, text string) (mask, value, reserved uint32) {
320 for i := 0; i < len(args); i++ {
321 arg := args[i]
322 v, err := strconv.Atoi(arg.Name)
323 switch {
324 case err == nil:
325 if v < 0 || v > arg.Maximum() {
326 fmt.Fprintf(os.Stderr, "%s: field %s value (%d) is out of range (%d-bit)\n", text, arg, v, arg.Bits)
327 }
328 mask |= arg.BitMask()
329 value |= uint32(v) << arg.Shift()
330 args.Delete(i)
331 i--
332 case arg.Name[0] == '/':
333 if arg.Name != strings.Repeat("/", len(arg.Name)) {
334 log.Fatalf("%s: arg %v named like a don't care bit, but it's not", text, arg)
335 }
336 reserved |= arg.BitMask()
337 args.Delete(i)
338 i--
339 default:
340 continue
341 }
342 }
343
344
345
346 for i := 1; i < len(args); i++ {
347 if args[:i].Find(args[i].Name) >= 0 {
348 args[i].Name += "2"
349 }
350 if args[:i].Find(args[i].Name) >= 0 {
351 log.Fatalf("%s: more than one duplicated fields: %s", text, args)
352 }
353 }
354
355
356 if mask&reserved != 0 {
357 log.Fatalf("%s: mask (%08x) and don't care (%08x) collide", text, mask, reserved)
358 }
359 if value&^mask != 0 {
360 log.Fatalf("%s: value (%08x) out of range of mask (%08x)", text, value, mask)
361 }
362
363 var argMask uint32
364 for _, arg := range args {
365 if arg.Bits <= 0 || arg.Bits > 32 || arg.Offs > 31 || arg.Offs <= 0 {
366 log.Fatalf("%s: arg %v has wrong bit field spec", text, arg)
367 }
368 if mask&arg.BitMask() != 0 {
369 log.Fatalf("%s: mask (%08x) intersect with arg %v", text, mask, arg)
370 }
371 if argMask&arg.BitMask() != 0 {
372 log.Fatalf("%s: arg %v overlap with other args %v", text, arg, args)
373 }
374 argMask |= arg.BitMask()
375 }
376 if 1<<32-1 != mask|reserved|argMask {
377 log.Fatalf("%s: args %v fail to cover all 32 bits", text, args)
378 }
379
380 return
381 }
382
383
384
385
386
387 func add(p *Prog, text, mnemonics, encoding, isa string) {
388
389
390
391
392 var args, pargs Args
393 var pmask, pvalue, presv, resv uint32
394 iword := int8(0)
395 ispfx := false
396
397 isaLevel, fnd := isaToISA[isa]
398 if !fnd {
399 log.Fatalf("%s: ISA level '%s' is unknown\n", text, isa)
400 return
401 }
402
403
404 if encoding[0] == ',' {
405 pfields := strings.Split(encoding, ",")[1:]
406
407 if len(pfields) != 2 {
408 log.Fatalf("%s: Prefixed instruction must be 2 words long.\n", text)
409 return
410 }
411 pargs = parseFields(pfields[0], text, iword)
412 pmask, pvalue, presv = computeMaskValueReserved(pargs, text)
413
414 iword++
415 encoding = pfields[1]
416 ispfx = true
417 }
418
419 args = parseFields(encoding, text, iword)
420 mask, value, dontCare := computeMaskValueReserved(args, text)
421
422 if ispfx {
423 args = append(args, pargs...)
424 }
425
426
427
428 insts := strings.Split(categoryRe.ReplaceAllString(mnemonics, ""), "|")
429 foundInst := []Inst{}
430 for _, inst := range insts {
431 value, mask := value, mask
432 pvalue, pmask := pvalue, pmask
433 args := args.Clone()
434 if inst == "" {
435 continue
436 }
437
438 parts := instRe.FindStringSubmatch(inst)
439 if parts == nil {
440 log.Fatalf("%v couldn't match %s", instRe, inst)
441 }
442 conds := condRe.FindAllStringSubmatch(parts[2], -1)
443 isPCRel := true
444 for _, cond := range conds {
445 i := args.Find(cond[1])
446 v, _ := strconv.ParseInt(cond[2], 16, 32)
447 if i < 0 {
448 log.Fatalf("%s: %s don't contain arg %s used in %s", text, args, cond[1], inst)
449 }
450 if cond[1] == "AA" && v == 1 {
451 isPCRel = false
452 }
453 mask |= args[i].BitMask()
454 value |= uint32(v) << args[i].Shift()
455 args.Delete(i)
456 }
457 inst := Inst{Text: text, Encoding: parts[1], Value: value, Mask: mask, DontCare: dontCare}
458 if ispfx {
459 inst = Inst{Text: text, Encoding: parts[1], Value: pvalue, Mask: pmask, DontCare: presv, SValue: value, SMask: mask, SDontCare: resv}
460 }
461
462
463 for i, opr := range operandRe.FindAllString(parts[1], -1) {
464 if i == 0 {
465 inst.Op = opr
466 continue
467 }
468 field := Field{Name: opr}
469 typ := asm.TypeUnknown
470 var shift uint8
471 opr2 := ""
472 opr3 := ""
473 switch opr {
474 case "target_addr":
475 shift = 2
476 if isPCRel {
477 typ = asm.TypePCRel
478 } else {
479 typ = asm.TypeLabel
480 }
481 if args.Find("LI") >= 0 {
482 opr = "LI"
483 } else {
484 opr = "BD"
485 }
486
487 case "offset":
488 switch inst.Op {
489
490
491 case "hashchk", "hashchkp", "hashst", "hashstp":
492 typ = asm.TypeNegOffset
493 opr = "DX"
494 opr2 = "D"
495 shift = 3
496
497 }
498
499 case "XMSK", "YMSK", "PMSK", "IX", "BHRBE":
500 typ = asm.TypeImmUnsigned
501
502 case "IMM32":
503 typ = asm.TypeImmUnsigned
504 opr = "imm0"
505 opr2 = "imm1"
506
507
508
509 case "R", "UIM", "IMM":
510 if ispfx {
511 typ = asm.TypeImmUnsigned
512 break
513 }
514 fallthrough
515
516 case "UI", "BO", "BH", "TH", "LEV", "NB", "L", "TO", "FXM", "FC", "U", "W", "FLM", "IMM8", "RIC", "PRS", "SHB", "SHW", "ST", "SIX", "PS", "DCM", "DGM", "RMC", "SP", "S", "DM", "CT", "EH", "E", "MO", "WC", "A", "IH", "OC", "DUI", "DUIS", "CY", "SC", "PL", "MP", "N", "DRM", "RM":
517 typ = asm.TypeImmUnsigned
518 if i := args.Find(opr); i < 0 {
519 log.Printf("coerce to D: %s: couldn't find extended field %s in %s", text, opr, args)
520 opr = "D"
521 }
522 case "bm":
523 opr = "b0"
524 opr2 = "b1"
525 opr3 = "b2"
526 typ = asm.TypeImmUnsigned
527
528 case "SH":
529 typ = asm.TypeImmUnsigned
530 if args.Find("sh2") >= 0 {
531 opr = "sh2"
532 opr2 = "sh"
533 }
534 case "MB", "ME":
535 typ = asm.TypeImmUnsigned
536 if n := strings.ToLower(opr); args.Find(n) >= 0 {
537 opr = n
538 }
539 case "SI", "SIM", "TE":
540 if ispfx {
541 typ = asm.TypeImmSigned
542 opr = "si0"
543 opr2 = "si1"
544 break
545 }
546 typ = asm.TypeImmSigned
547 if i := args.Find(opr); i < 0 {
548 opr = "D"
549 }
550 case "DCMX":
551 typ = asm.TypeImmUnsigned
552
553 if i := args.Find(opr); i >= 0 {
554 break
555 }
556 typ = asm.TypeImmUnsigned
557 opr = "dc"
558 opr2 = "dm"
559 opr3 = "dx"
560 case "DS":
561 typ = asm.TypeOffset
562 shift = 2
563 case "DQ":
564 typ = asm.TypeOffset
565 shift = 4
566 case "D":
567 if ispfx {
568 typ = asm.TypeOffset
569 opr = "d0"
570 opr2 = "d1"
571 break
572 }
573 if i := args.Find(opr); i >= 0 {
574 typ = asm.TypeOffset
575 break
576 }
577 if i := args.Find("UI"); i >= 0 {
578 typ = asm.TypeImmUnsigned
579 opr = "UI"
580 break
581 }
582 if i := args.Find("SI"); i >= 0 {
583 typ = asm.TypeImmSigned
584 opr = "SI"
585 break
586 }
587 if i := args.Find("d0"); i >= 0 {
588 typ = asm.TypeImmSigned
589
590 opr = "d0"
591 opr2 = "d1"
592 opr3 = "d2"
593 }
594 case "RA", "RB", "RC", "RS", "RSp", "RT", "RTp":
595 typ = asm.TypeReg
596 case "BT", "BA", "BB", "BC", "BI":
597 if strings.HasPrefix(inst.Op, "mtfs") {
598
599 typ = asm.TypeImmUnsigned
600 } else {
601 typ = asm.TypeCondRegBit
602 }
603 case "BF", "BFA":
604 if strings.HasPrefix(inst.Op, "mtfs") {
605
606 typ = asm.TypeImmUnsigned
607 } else {
608 typ = asm.TypeCondRegField
609 }
610 case "FRA", "FRB", "FRBp", "FRC", "FRS", "FRSp", "FRT", "FRTp", "FRAp":
611 typ = asm.TypeFPReg
612 case "XA", "XB", "XC", "XS", "XT":
613 typ = asm.TypeVecSReg
614 opr2 = opr[1:]
615 opr = opr[1:] + "X"
616 case "XTp", "XSp":
617
618 typ = asm.TypeVecSpReg
619 opr2 = opr[1:2] + "p"
620 opr = opr[1:2] + "X"
621
622 case "XAp":
623
624
625 typ = asm.TypeVecSReg
626 opr2 = opr[1:2] + "p"
627 opr = opr[1:2] + "X"
628
629 case "AT", "AS":
630 typ = asm.TypeMMAReg
631
632 case "VRA", "VRB", "VRC", "VRS", "VRT":
633 typ = asm.TypeVecReg
634
635 case "SPR", "TBR":
636 typ = asm.TypeSpReg
637 if n := strings.ToLower(opr); n != opr && args.Find(n) >= 0 {
638 opr = n
639 }
640 }
641 if typ == asm.TypeUnknown {
642 log.Fatalf("%s %s unknown type for opr %s", text, inst, opr)
643 }
644 field.Type = typ
645 field.Shift = shift
646 var f1, f2, f3 asm.BitField
647 switch {
648 case opr3 != "":
649 b0 := args.Find(opr)
650 b1 := args.Find(opr2)
651 b2 := args.Find(opr3)
652 f1.Offs, f1.Bits, f1.Word = uint8(args[b0].Offs), uint8(args[b0].Bits), uint8(args[b0].Word)
653 f2.Offs, f2.Bits, f2.Word = uint8(args[b1].Offs), uint8(args[b1].Bits), uint8(args[b1].Word)
654 f3.Offs, f3.Bits, f3.Word = uint8(args[b2].Offs), uint8(args[b2].Bits), uint8(args[b2].Word)
655
656 case opr2 != "":
657 ext := args.Find(opr)
658 if ext < 0 {
659 log.Fatalf("%s: couldn't find extended field %s in %s", text, opr, args)
660 }
661 f1.Offs, f1.Bits, f1.Word = uint8(args[ext].Offs), uint8(args[ext].Bits), uint8(args[ext].Word)
662 base := args.Find(opr2)
663 if base < 0 {
664 log.Fatalf("%s: couldn't find base field %s in %s", text, opr2, args)
665 }
666 f2.Offs, f2.Bits, f2.Word = uint8(args[base].Offs), uint8(args[base].Bits), uint8(args[base].Word)
667 case opr == "mb", opr == "me":
668 i := args.Find(opr)
669 if i < 0 {
670 log.Fatalf("%s: couldn't find special 'm[be]' field for %s in %s", text, opr, args)
671 }
672 f1.Offs, f1.Bits, f1.Word = uint8(args[i].Offs+args[i].Bits)-1, 1, uint8(args[i].Word)
673 f2.Offs, f2.Bits, f2.Word = uint8(args[i].Offs), uint8(args[i].Bits)-1, uint8(args[i].Word)
674 case opr == "spr", opr == "tbr", opr == "tmr", opr == "dcr":
675 i := args.Find(opr)
676 if i < 0 {
677 log.Fatalf("%s: couldn't find special 'spr' field for %s in %s", text, opr, args)
678 }
679 if args[i].Bits != 10 {
680 log.Fatalf("%s: special 'spr' field is not 10-bit: %s", text, args)
681 }
682 f1.Offs, f1.Bits, f2.Word = uint8(args[i].Offs)+5, 5, uint8(args[i].Word)
683 f2.Offs, f2.Bits, f2.Word = uint8(args[i].Offs), 5, uint8(args[i].Word)
684 default:
685 i := args.Find(opr)
686 if i < 0 {
687 log.Fatalf("%s: couldn't find %s in %s", text, opr, args)
688 }
689 f1.Offs, f1.Bits, f1.Word = uint8(args[i].Offs), uint8(args[i].Bits), uint8(args[i].Word)
690 }
691 field.BitFields.Append(f1)
692 field.BitFieldNames = append(field.BitFieldNames, opr)
693 if f2.Bits > 0 {
694 field.BitFields.Append(f2)
695 field.BitFieldNames = append(field.BitFieldNames, opr2)
696 }
697 if f3.Bits > 0 {
698 field.BitFields.Append(f3)
699 field.BitFieldNames = append(field.BitFieldNames, opr3)
700 }
701 inst.Fields = append(inst.Fields, field)
702 }
703 if *debug {
704 fmt.Printf("%v\n", inst)
705 }
706 inst.Isa = isaLevel
707 inst.memOp = hasMemoryArg(&inst)
708 inst.memOpX = inst.memOp && inst.Op[len(inst.Op)-1] == 'x'
709 inst.memOpSt = inst.memOp && strings.Contains(inst.Text, "Store")
710 inst.Words = 1
711 inst.order = p.nextOrder
712 p.nextOrder++
713 if ispfx {
714 inst.Words = 2
715 }
716 foundInst = append(foundInst, inst)
717 }
718
719
720
721 sort.Sort(instArray(foundInst))
722
723 p.Insts = append(p.Insts, foundInst...)
724 }
725
726
727 const condRegexp = `\s*([[:alpha:]]+)=([0-9a-f]+)\s*`
728
729
730 var condRe = regexp.MustCompile(condRegexp)
731
732
733 var instRe = regexp.MustCompile(`^(.*?)\s?(\((` + condRegexp + `)+\))?$`)
734
735
736 var categoryRe = regexp.MustCompile(`(\s*\[Category:[^]]*\]\s*)|(\s*\[Co-requisite[^]]*\]\s*)|(\s*\(\s*0[Xx][[0-9A-Fa-f_]{9}\s*\)\s*)`)
737
738
739 var operandRe = regexp.MustCompile(`([[:alpha:]][[:alnum:]_]*\.?)`)
740
741
742 func printText(p *Prog) {
743 log.Fatal("-fmt=text not implemented")
744 }
745
746
747 var isNotMemopMap = map[string]bool{
748 "lxvkq": true,
749 "lvsl": true,
750 "lvsr": true,
751 }
752
753
754 var isMemopMap = map[string]bool{
755 "hashst": true,
756 "hashstp": true,
757 "hashchk": true,
758 "hashchkp": true,
759 }
760
761
762 func hasMemoryArg(insn *Inst) bool {
763 return ((strings.HasPrefix(insn.Text, "Load") || strings.HasPrefix(insn.Text, "Store") ||
764 strings.HasPrefix(insn.Text, "Prefixed Load") || strings.HasPrefix(insn.Text, "Prefixed Store")) && !isNotMemopMap[insn.Op]) ||
765 isMemopMap[insn.Op]
766 }
767
768
769
770
771 func insnEncFuncStr(insn *Inst, firstName [2]string) string {
772 buf := new(bytes.Buffer)
773
774
775 argOrder := []string{
776 "p.To",
777 "p.From",
778 "p",
779 "p.RestArgs[0].Addr",
780 "p.RestArgs[1].Addr",
781 "p.RestArgs[2].Addr",
782 }
783 if len(insn.Fields) > len(argOrder) {
784 log.Fatalf("cannot handle %v. Only %d args supported.", insn, len(argOrder))
785 }
786
787
788 isImmediate := func(t asm.ArgType) bool {
789 return t == asm.TypeImmUnsigned || t == asm.TypeSpReg || t == asm.TypeImmSigned || t == asm.TypeOffset || t == asm.TypeNegOffset
790 }
791
792 if insn.memOp {
793
794
795 if insn.memOpSt {
796
797 argOrder[0], argOrder[1] = argOrder[1], argOrder[0]
798 }
799 argOrder[2] = argOrder[1]
800 } else if len(insn.Fields) > 2 && isImmediate(insn.Fields[2].Type) {
801
802 argOrder = append(argOrder[0:2], argOrder[3:]...)
803 }
804
805 fmt.Fprintf(buf, "// %s\n", insn.Encoding)
806 fmt.Fprintf(buf, "func type_%s(c *ctxt9, p *obj.Prog, t *Optab, out *[5]uint32) {\n", insn.Op)
807 if insn.Words > 1 {
808 fmt.Fprintf(buf, "o0 := GenPfxOpcodes[p.As - A%s]\n", firstName[1])
809 }
810 fmt.Fprintf(buf, "o%d := GenOpcodes[p.As - A%s]\n", insn.Words-1, firstName[0])
811
812 errCheck := ""
813 for j, atype := range insn.Fields {
814 itype := ".Reg"
815 if isImmediate(atype.Type) {
816 itype = ".Offset"
817 } else if insn.memOpX && atype.Name == "RA" {
818
819 itype = ".Index"
820 }
821
822 bitPos := uint64(0)
823
824 if atype.Type == asm.TypeVecSpReg {
825 bitPos += 1
826 }
827
828 for _, f := range atype.BitFields {
829 bitPos += uint64(f.Bits)
830 }
831
832 bitPos += uint64(atype.Shift)
833 bits := bitPos
834
835
836 for i, f := range atype.BitFields {
837 bitPos -= uint64(f.Bits)
838 argStr := argOrder[j] + itype
839 if bitPos != 0 {
840 argStr = fmt.Sprintf("(%s>>%d)", argStr, bitPos)
841 }
842 mask := (1 << uint64(f.Bits)) - 1
843 shift := 32 - uint64(f.Offs) - uint64(f.Bits)
844 fmt.Fprintf(buf, "o%d |= uint32(%s&0x%x)<<%d // %s\n", f.Word, argStr, mask, shift, atype.BitFieldNames[i])
845 }
846
847
848
849 if atype.Type != asm.TypeNegOffset && atype.Shift != 0 && atype.Shift != 16 && bits != 32 {
850 arg := argOrder[j] + itype
851 mod := (1 << atype.Shift) - 1
852 errCheck += fmt.Sprintf("if %s & 0x%x != 0 {\n", arg, mod)
853 errCheck += fmt.Sprintf("c.ctxt.Diag(\"Constant 0x%%x (%%d) is not a multiple of %d\\n%%v\",%s,%s,p)\n", mod+1, arg, arg)
854 errCheck += fmt.Sprintf("}\n")
855 }
856
857 if atype.Type == asm.TypeNegOffset {
858 arg := argOrder[j] + itype
859 mask := -1 << (atype.BitFields.NumBits() + int(atype.Shift))
860 maskl := mask
861 mask |= (1 << atype.Shift) - 1
862 min := maskl
863 max := maskl | (^mask)
864 step := 1 << atype.Shift
865 errCheck += fmt.Sprintf("if %s & 0x%x != 0x%x {\n", arg, uint32(mask), uint32(maskl))
866 errCheck += fmt.Sprintf("c.ctxt.Diag(\"Constant(%%d) must within the range of [%d,%d] in steps of %d\\n%%v\",%s,p)\n", min, max, step, arg)
867 errCheck += fmt.Sprintf("}\n")
868 }
869 j++
870 }
871 buf.WriteString(errCheck)
872 if insn.Words > 1 {
873 fmt.Fprintf(buf, "out[1] = o1\n")
874 }
875 fmt.Fprintf(buf, "out[0] = o0\n")
876 fmt.Fprintf(buf, "}\n")
877 return buf.String()
878 }
879
880
881
882 func insnTypeStr(insn *Inst, uniqueRegTypes bool) string {
883 if len(insn.Fields) == 0 {
884 return "type_none"
885 }
886
887 ret := "type_"
888
889
890
891 if insn.memOp {
892 if insn.memOpSt {
893 ret += "st_"
894 } else {
895 ret += "ld_"
896 }
897 }
898
899
900 for _, atype := range insn.Fields {
901 switch atype.Type {
902
903 case asm.TypeReg, asm.TypeFPReg, asm.TypeVecReg, asm.TypeCondRegBit:
904 if uniqueRegTypes {
905 ret += map[asm.ArgType]string{asm.TypeReg: "R", asm.TypeFPReg: "F", asm.TypeVecReg: "V", asm.TypeCondRegBit: "C"}[atype.Type]
906
907 if atype.Name[len(atype.Name)-1] == 'p' {
908 ret += "p"
909 }
910 } else {
911 ret += "R"
912 }
913 case asm.TypeMMAReg, asm.TypeCondRegField:
914 ret += "M"
915 case asm.TypeSpReg:
916 ret += "P"
917 case asm.TypeVecSReg:
918 ret += "X"
919 case asm.TypeVecSpReg:
920 ret += "Y"
921 case asm.TypeImmSigned, asm.TypeOffset, asm.TypeImmUnsigned:
922 if atype.Type == asm.TypeImmUnsigned {
923 ret += "I"
924 } else {
925 ret += "S"
926 }
927 if atype.Shift != 0 {
928 ret += fmt.Sprintf("%d", atype.Shift)
929 }
930 case asm.TypeNegOffset:
931 ret += "N"
932 default:
933 log.Fatalf("Unhandled type in insnTypeStr: %v\n", atype)
934 }
935
936
937 for _, bf := range atype.BitFields {
938 ret += fmt.Sprintf("_%d_%d", bf.Word*32+bf.Offs, bf.Bits)
939 }
940 }
941 return ret
942 }
943
944 type AggInfo struct {
945 Insns []*Inst
946 Typef string
947 }
948
949
950
951 func genOptabEntry(ta *AggInfo, typeMap map[string]*Inst) string {
952 buf := new(bytes.Buffer)
953 fitArg := func(f *Field, i *Inst) string {
954 argToRegType := map[asm.ArgType]string{
955
956 asm.TypeReg: "C_REG",
957 asm.TypeCondRegField: "C_CREG",
958 asm.TypeCondRegBit: "C_CRBIT",
959 asm.TypeFPReg: "C_FREG",
960 asm.TypeVecReg: "C_VREG",
961 asm.TypeVecSReg: "C_VSREG",
962 asm.TypeVecSpReg: "C_VSREG",
963 asm.TypeMMAReg: "C_AREG",
964 asm.TypeSpReg: "C_SPR",
965 }
966 if t, fnd := argToRegType[f.Type]; fnd {
967 if f.Name[len(f.Name)-1] == 'p' {
968 return t + "P"
969 }
970 return t
971 }
972 bits := f.Shift
973 for _, sf := range f.BitFields {
974 bits += sf.Bits
975 }
976 shift := ""
977 if f.Shift != 0 {
978 shift = fmt.Sprintf("S%d", f.Shift)
979 }
980 sign := "U"
981 if f.Type == asm.TypeImmSigned || f.Type == asm.TypeOffset {
982 sign = "S"
983
984
985
986 if f.Type == asm.TypeOffset {
987 shift = ""
988 }
989 }
990 if f.Type == asm.TypeNegOffset {
991
992
993
994 sign = "S"
995 bits = 16
996 shift = ""
997 }
998 return fmt.Sprintf("C_%s%d%sCON", sign, bits, shift)
999 }
1000 insn := ta.Insns[0]
1001 args := [6]string{}
1002
1003 argOrder := []int{
1004 5,
1005 0,
1006 1,
1007 2,
1008 3,
1009 4}
1010
1011 i := 0
1012 for _, j := range insn.Fields {
1013
1014 at := fitArg(&j, insn)
1015 if argOrder[i] == 1 && !strings.HasSuffix(at, "REG") {
1016 i++
1017 }
1018 args[argOrder[i]] = at
1019 i++
1020 }
1021
1022
1023
1024 if insn.memOp {
1025 switch args[0] + " " + args[1] {
1026 case "C_REG C_REG":
1027 args[0] = "C_XOREG"
1028 case "C_S16CON C_REG":
1029 args[0] = "C_SOREG"
1030 case "C_S34CON C_REG":
1031 args[0] = "C_LOREG"
1032 }
1033 args[1] = ""
1034
1035 if insn.memOpSt {
1036 args[0], args[5] = args[5], args[0]
1037 }
1038
1039 }
1040 fmt.Fprintf(buf, "{as: A%s,", opName(insn.Op))
1041 for i, s := range args {
1042 if len(s) <= 0 {
1043 continue
1044 }
1045 fmt.Fprintf(buf, "a%d: %s, ", i+1, s)
1046 }
1047 typef := typeMap[ta.Typef].Op
1048
1049 pfx := ""
1050 if insn.Words > 1 {
1051 pfx = " ispfx: true,"
1052 }
1053 fmt.Fprintf(buf, "asmout: type_%s,%s size: %d},\n", typef, pfx, insn.Words*4)
1054 return buf.String()
1055 }
1056
1057
1058
1059
1060
1061
1062
1063 func printEncoder(p *Prog) {
1064 const minISA = ISA_V31
1065
1066
1067
1068 typeMap := map[string]*Inst{}
1069 typeAggMap := map[string]*AggInfo{}
1070 var oplistBuf bytes.Buffer
1071 var opnameBuf bytes.Buffer
1072
1073
1074 firstInsn := [2]string{}
1075
1076
1077 sort.Slice(p.Insts, func(i, j int) bool {
1078 if p.Insts[i].Words != p.Insts[j].Words {
1079 return p.Insts[i].Words < p.Insts[j].Words
1080 }
1081 return p.Insts[i].order > p.Insts[j].order
1082 })
1083
1084
1085 for i, insn := range p.Insts {
1086 if insn.Isa < minISA {
1087 continue
1088 }
1089 extra := ""
1090 if firstInsn[insn.Words-1] == "" {
1091 firstInsn[insn.Words-1] = opName(insn.Op)
1092 if insn.Words == 1 {
1093 extra = " = ALASTAOUT + iota"
1094 }
1095 }
1096 opType := insnTypeStr(&insn, false)
1097 opTypeOptab := insnTypeStr(&insn, true)
1098 fmt.Fprintf(&oplistBuf, "A%s%s\n", opName(insn.Op), extra)
1099 fmt.Fprintf(&opnameBuf, "\"%s\",\n", opName(insn.Op))
1100
1101
1102 if _, fnd := typeMap[opType]; !fnd {
1103 typeMap[opType] = &p.Insts[i]
1104 }
1105 at, fnd := typeAggMap[opTypeOptab]
1106 if !fnd {
1107 typeAggMap[opTypeOptab] = &AggInfo{[]*Inst{&p.Insts[i]}, opType}
1108 } else {
1109 at.Insns = append(at.Insns, &p.Insts[i])
1110 }
1111 }
1112 fmt.Fprintf(&oplistBuf, "ALASTGEN\n")
1113 fmt.Fprintf(&oplistBuf, "AFIRSTGEN = A%s\n", firstInsn[0])
1114
1115
1116 targ := struct {
1117 InputFile string
1118 Insts []Inst
1119 MinISA isaversion
1120 TypeAggList []*AggInfo
1121 TypeList []*Inst
1122 FirstInsn [2]string
1123 TypeMap map[string]*Inst
1124 Oplist string
1125 Opnames string
1126 }{InputFile: inputFile, Insts: p.Insts, MinISA: minISA, FirstInsn: firstInsn, TypeMap: typeMap, Oplist: oplistBuf.String(), Opnames: opnameBuf.String()}
1127 for _, v := range typeAggMap {
1128 targ.TypeAggList = append(targ.TypeAggList, v)
1129 }
1130 for _, v := range typeMap {
1131 targ.TypeList = append(targ.TypeList, v)
1132 }
1133 sort.Slice(targ.TypeAggList, func(i, j int) bool {
1134
1135 return targ.TypeAggList[i].Insns[0].Op < targ.TypeAggList[j].Insns[0].Op
1136 })
1137 sort.Slice(targ.TypeList, func(i, j int) bool {
1138 return targ.TypeList[i].Op < targ.TypeList[j].Op
1139 })
1140
1141
1142 asm9_gtable_go := `
1143 // DO NOT EDIT
1144 // generated by: ppc64map -fmt=encoder {{.InputFile}}
1145
1146 package ppc64
1147
1148 import (
1149 "cmd/internal/obj"
1150 )
1151
1152 const (
1153 {{print $.Oplist -}}
1154 )
1155
1156 var GenAnames = []string {
1157 {{print $.Opnames -}}
1158 }
1159
1160 var GenOpcodes = [...]uint32 {
1161 {{range $v := .Insts}}{{if ge $v.Isa $.MinISA -}}
1162 {{if (eq $v.Words 1)}}{{printf "0x%08x, // A%s" $v.Value (opname $v.Op)}}
1163 {{else}} {{printf "0x%08x, // A%s" $v.SValue (opname $v.Op)}}
1164 {{end}}{{end}}{{end -}}
1165 }
1166
1167 var GenPfxOpcodes = [...]uint32 {
1168 {{range $v := .Insts}}{{if and (ge $v.Isa $.MinISA) (eq $v.Words 2) -}}
1169 {{printf "0x%08x, // A%s" $v.Value (opname $v.Op)}}
1170 {{end}}{{end -}}
1171 }
1172
1173 var optabGen = []Optab {
1174 {{range $v := .TypeAggList -}}
1175 {{genoptabentry $v $.TypeMap -}}
1176 {{end -}}
1177 }
1178
1179 {{range $v := .TypeList}}
1180 {{genencoderfunc $v $.FirstInsn}}
1181 {{end}}
1182
1183 func opsetGen(from obj.As) bool {
1184 r0 := from & obj.AMask
1185 switch from {
1186 {{range $v := .TypeAggList -}}
1187 case A{{opname (index $v.Insns 0).Op}}:
1188 {{range $w := (slice $v.Insns 1) -}}
1189 opset(A{{opname $w.Op}},r0)
1190 {{end -}}
1191 {{end -}}
1192 default:
1193 return false
1194 }
1195 return true
1196 }
1197 `
1198 tmpl := template.New("asm9_gtable.go")
1199 tmpl.Funcs(template.FuncMap{
1200 "opname": opName,
1201 "genencoderfunc": insnEncFuncStr,
1202 "genoptabentry": genOptabEntry,
1203 })
1204 tmpl.Parse(asm9_gtable_go)
1205
1206
1207 var tbuf bytes.Buffer
1208 if err := tmpl.Execute(&tbuf, targ); err != nil {
1209 log.Fatal(err)
1210 }
1211 tout, err := gofmt.Source(tbuf.Bytes())
1212 if err != nil {
1213 fmt.Printf("%s", tbuf.Bytes())
1214 log.Fatalf("gofmt error: %v", err)
1215 }
1216 if err := os.WriteFile("asm9_gtables.go.new", tout, 0666); err != nil {
1217 log.Fatalf("Failed to create asm9_gtables.new: %v", err)
1218 }
1219 }
1220
1221
1222
1223
1224
1225 func printASM(p *Prog) {
1226 fmt.Printf("#include \"hack.h\"\n")
1227 fmt.Printf(".text\n")
1228 for _, inst := range p.Insts {
1229
1230
1231 str := inst.Encoding
1232 if str[0] == 'p' && str[len(str)-1] == 'R' {
1233 str = strings.Replace(str, "D(RA),R", "Dpfx(RApfx),Rpfx", 1)
1234 str = strings.Replace(str, "RA,SI,R", "RApfx,SIpfx,Rpfx", 1)
1235 }
1236 fmt.Printf("\t%s\n", str)
1237 }
1238 }
1239
1240
1241 func opName(op string) string {
1242 return strings.ToUpper(strings.Replace(op, ".", "CC", 1))
1243 }
1244
1245
1246 func argFieldName(f Field) string {
1247 ns := []string{"ap", f.Type.String()}
1248 for _, b := range f.BitFields {
1249 ns = append(ns, fmt.Sprintf("%d_%d", b.Word*32+b.Offs, b.Word*32+b.Offs+b.Bits-1))
1250 }
1251 if f.Shift > 0 {
1252 ns = append(ns, fmt.Sprintf("shift%d", f.Shift))
1253 }
1254 return strings.Join(ns, "_")
1255 }
1256
1257 var funcBodyTmpl = template.Must(template.New("funcBody").Parse(``))
1258
1259
1260
1261 func printDecoder(p *Prog) {
1262 var buf bytes.Buffer
1263
1264 fmt.Fprintf(&buf, "// Code generated by ppc64map -fmt=decoder %s DO NOT EDIT.\n", inputFile)
1265 fmt.Fprintf(&buf, "\n")
1266
1267 fmt.Fprintf(&buf, "package ppc64asm\n\n")
1268
1269
1270 m := map[string]bool{}
1271 fmt.Fprintf(&buf, "const (\n\t_ Op = iota\n")
1272 for _, inst := range p.Insts {
1273 name := opName(inst.Op)
1274 if ok := m[name]; ok {
1275 continue
1276 }
1277 m[name] = true
1278 fmt.Fprintf(&buf, "\t%s\n", name)
1279 }
1280 fmt.Fprint(&buf, ")\n\n\n")
1281
1282
1283 m = map[string]bool{}
1284 fmt.Fprintf(&buf, "var opstr = [...]string{\n")
1285 for _, inst := range p.Insts {
1286 name := opName(inst.Op)
1287 if ok := m[name]; ok {
1288 continue
1289 }
1290 m[name] = true
1291 fmt.Fprintf(&buf, "\t%s: %q,\n", opName(inst.Op), inst.Op)
1292 }
1293 fmt.Fprint(&buf, "}\n\n\n")
1294
1295
1296 fmt.Fprintf(&buf, "var (\n")
1297 m = map[string]bool{}
1298 for _, inst := range p.Insts {
1299 for _, f := range inst.Fields {
1300 name := argFieldName(f)
1301 if ok := m[name]; ok {
1302 continue
1303 }
1304 m[name] = true
1305 fmt.Fprintf(&buf, "\t%s = &argField{Type: %#v, Shift: %d, BitFields: BitFields{", name, f.Type, f.Shift)
1306 for _, b := range f.BitFields {
1307 fmt.Fprintf(&buf, "{%d, %d, %d},", b.Offs, b.Bits, b.Word)
1308 }
1309 fmt.Fprintf(&buf, "}}\n")
1310 }
1311 }
1312 fmt.Fprint(&buf, ")\n\n\n")
1313
1314
1315 fmt.Fprintf(&buf, "var instFormats = [...]instFormat{\n")
1316 for _, inst := range p.Insts {
1317 m, v, dc := uint64(inst.Mask)<<32, uint64(inst.Value)<<32, uint64(inst.DontCare)<<32
1318 m, v, dc = uint64(inst.SMask)|m, uint64(inst.SValue)|v, uint64(inst.SDontCare)|dc
1319 fmt.Fprintf(&buf, "\t{ %s, %#x, %#x, %#x,", opName(inst.Op), m, v, dc)
1320 fmt.Fprintf(&buf, " // %s (%s)\n\t\t[6]*argField{", inst.Text, inst.Encoding)
1321 for _, f := range inst.Fields {
1322 fmt.Fprintf(&buf, "%s, ", argFieldName(f))
1323 }
1324 fmt.Fprintf(&buf, "}},\n")
1325 }
1326 fmt.Fprint(&buf, "}\n\n")
1327
1328 out, err := gofmt.Source(buf.Bytes())
1329 if err != nil {
1330 log.Fatalf("gofmt error: %v", err)
1331 fmt.Printf("%s", buf.Bytes())
1332 } else {
1333 fmt.Printf("%s", out)
1334 }
1335 }
1336
View as plain text