1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 package main
16
17 import (
18 "bufio"
19 "encoding/csv"
20 "flag"
21 "fmt"
22 "log"
23 "os"
24 "sort"
25 "strconv"
26 "strings"
27 )
28
29 var format = flag.String("fmt", "text", "output format: text, decoder")
30
31 var inputFile string
32
33 func usage() {
34 fmt.Fprintf(os.Stderr, "usage: armmap [-fmt=format] x86.csv\n")
35 os.Exit(2)
36 }
37
38 func main() {
39 log.SetFlags(0)
40 log.SetPrefix("armmap: ")
41
42 flag.Usage = usage
43 flag.Parse()
44 if flag.NArg() != 1 {
45 usage()
46 }
47
48 inputFile = flag.Arg(0)
49
50 var print func(*Prog)
51 switch *format {
52 default:
53 log.Fatalf("unknown output format %q", *format)
54 case "text":
55 print = printText
56 case "decoder":
57 print = printDecoder
58 }
59
60 p, err := readCSV(flag.Arg(0))
61 if err != nil {
62 log.Fatal(err)
63 }
64
65 print(p)
66 }
67
68
69
70 func readCSV(file string) (*Prog, error) {
71
72
73 f, err := os.Open(file)
74 if err != nil {
75 return nil, err
76 }
77 b := bufio.NewReader(f)
78 for {
79 c, err := b.ReadByte()
80 if err != nil {
81 break
82 }
83 if c == '\n' {
84 continue
85 }
86 if c == '#' {
87 b.ReadBytes('\n')
88 continue
89 }
90 b.UnreadByte()
91 break
92 }
93 table, err := csv.NewReader(b).ReadAll()
94 if err != nil {
95 return nil, fmt.Errorf("parsing %s: %v", file, err)
96 }
97 if len(table) == 0 {
98 return nil, fmt.Errorf("empty csv input")
99 }
100 if len(table[0]) < 5 {
101 return nil, fmt.Errorf("csv too narrow: need at least five columns")
102 }
103
104 p := &Prog{}
105 for _, row := range table {
106 add(p, row[0], row[1], row[2], row[3], row[4])
107 }
108 return p, nil
109 }
110
111 type Prog struct {
112 Inst []Inst
113 OpRanges map[string]string
114 }
115
116 type Inst struct {
117 Text string
118 Encoding string
119 Mask uint32
120 Value uint32
121 Priority int
122 OpBase string
123 OpBits uint64
124 Args []string
125 }
126
127 type Arg struct {
128 Name string
129 Bits uint64
130 }
131
132
133
134 func add(p *Prog, maskstr, valuestr, text, encoding, tags string) {
135 if strings.Contains(tags, "pseudo") {
136 return
137 }
138
139
140 if strings.HasPrefix(text, "V") && !strings.Contains(tags, "vfp") {
141
142 return
143 }
144
145 mask, err := strconv.ParseUint(maskstr, 0, 32)
146 if err != nil {
147 log.Printf("invalid mask %q", maskstr)
148 return
149 }
150 value, err := strconv.ParseUint(valuestr, 0, 32)
151 if err != nil {
152 log.Printf("invalid value %q", valuestr)
153 return
154 }
155
156
157
158 fuzzy := uint32(0)
159 fieldOffset := map[string]int{}
160 fieldWidth := map[string]int{}
161 off := 32
162 for _, f := range strings.Split(encoding, "|") {
163 n := 1
164 if i := strings.Index(f, ":"); i >= 0 {
165 n, _ = strconv.Atoi(f[i+1:])
166 }
167 off -= n
168 fieldOffset[f] = off
169 fieldWidth[f] = n
170 if f == "(0)" || f == "(1)" {
171 fuzzy |= 1 << uint(off)
172 }
173 }
174 if off != 0 {
175 fmt.Fprintf(os.Stderr, "%s: counted %d bits in %s\n", text, 32-off, encoding)
176 }
177
178
179
180 fieldUsed := map[string]bool{}
181
182
183 var op, argstr string
184 if i := strings.Index(text, " "); i >= 0 {
185 op = text[:i]
186 argstr = text[i:]
187 } else {
188 op = text
189 }
190 op = strings.TrimSpace(op)
191 argstr = strings.TrimSpace(argstr)
192
193
194 i := strings.Index(op, "<")
195 if i < 0 {
196 i = len(op)
197 }
198 if j := strings.Index(op, "{"); j >= 0 && j < i {
199 i = j
200 }
201 op, suffix := op[:i], op[i:]
202 if suffix != "" && opSuffix[suffix] == "" {
203 fmt.Fprintf(os.Stderr, "%s: invalid op suffix %q in %s\n", text, suffix, op+suffix)
204 }
205
206
207 for _, f := range strings.Split(opSuffix[suffix], ",") {
208 if f != "" && fieldWidth[f] == 0 {
209 fmt.Fprintf(os.Stderr, "%s: opsuffix %s missing %s in encoding %s\n", text, suffix, f, encoding)
210 }
211 fieldUsed[f] = true
212 }
213
214
215
216
217
218
219
220
221
222 ops := []string{op}
223 opBits := uint64(0)
224 opFields := strings.Split(opSuffix[suffix], ",")
225
226 for strings.HasPrefix(suffix, "{") {
227 i := strings.Index(suffix, "}")
228 var f, option string
229 option, suffix = suffix[1:i], suffix[i+1:]
230 f, opFields = opFields[0], opFields[1:]
231 if option == "W" {
232
233 ops = cross(ops, "."+option, "")
234 } else {
235 ops = cross(ops, "", "."+option)
236 }
237 if fieldWidth[f] != 1 {
238 fmt.Fprintf(os.Stderr, "%s: have %d bits for {%s}\n", text, fieldWidth[f], option)
239 }
240
241
242 opBits = opBits<<16 | uint64(fieldOffset[f])<<8 | 1
243 }
244
245 haveCond := false
246 for strings.Contains(suffix, "<") {
247 var f, literal, x string
248 if len(opFields) == 0 {
249 fmt.Fprintf(os.Stderr, "%s: ran out of suffix fields for <%s>\n", text, x)
250 break
251 }
252 f, opFields = opFields[0], opFields[1:]
253 i := strings.Index(suffix, "<")
254 j := strings.Index(suffix, ">")
255 literal, x, suffix = suffix[:i], suffix[i+1:j], suffix[j+1:]
256
257
258 ops = cross(ops, literal)
259
260
261
262
263
264 if x == "c" && f == "cond:4" {
265 haveCond = true
266 ops = cross(ops, "_COND_")
267 continue
268 }
269
270
271
272 expand := choices[x]
273 if expand == nil && strings.Contains(x, ",") {
274 expand = strings.Split(x, ",")
275 }
276 if expand == nil {
277 fmt.Fprintf(os.Stderr, "%s: unknown choices for <%s>\n", text, x)
278 expand = []string{x}
279 } else if len(expand) != 1<<uint(fieldWidth[f]) {
280 fmt.Fprintf(os.Stderr, "%s: have %d choices for <%s> but %d bits\n", text, len(expand), x, fieldWidth[f])
281 }
282 opBits = opBits<<16 | uint64(fieldOffset[f])<<8 | uint64(fieldWidth[f])
283 ops = cross(ops, expand...)
284 }
285 if haveCond {
286
287 opBits = opBits<<16 | 28<<8 | 4
288 ops = crossCond(ops)
289 }
290 ops = cross(ops, suffix)
291
292
293
294
295
296
297
298
299 if p.OpRanges == nil {
300 p.OpRanges = make(map[string]string)
301 }
302 opstr := "," + strings.Join(ops, ",") + ","
303 for _, op := range ops {
304 if old := p.OpRanges[op]; old != "" && old != opstr {
305 if strings.Contains(old, opstr) {
306 opstr = old
307 } else if strings.Contains(opstr, old) {
308
309 } else {
310
311
312
313
314 fmt.Fprintf(os.Stderr, "%s: %s appears in both %s and %s\n", text, op, old, opstr)
315 }
316 }
317 }
318 for _, op := range strings.Split(opstr, ",") {
319 if op != "" {
320 p.OpRanges[op] = opstr
321 }
322 }
323
324
325
326
327
328
329 var args []string
330 for argstr != "" {
331
332 best := 0
333 for a := range argSuffixes {
334 if argstr == a || strings.HasPrefix(argstr, a+",") {
335 if best < len(a) {
336 best = len(a)
337 }
338 }
339 }
340 if best == 0 {
341 fmt.Fprintf(os.Stderr, "%s: unknown arg %s\n", text, argstr)
342 break
343 }
344
345 var arg, desc string
346 arg, argstr = argstr[:best], strings.TrimSpace(strings.TrimLeft(argstr[best:], ","))
347 desc = arg
348 for _, f := range strings.Split(argSuffixes[desc], ",") {
349 if f == "" {
350 continue
351 }
352 if fieldWidth[f] == 0 {
353 fmt.Fprintf(os.Stderr, "%s: arg %s missing %s in encoding %s\n", text, arg, f, encoding)
354 }
355 fieldUsed[f] = true
356 desc += fmt.Sprintf("|%s@%d", f, fieldOffset[f])
357 }
358 args = append(args, desc)
359 }
360
361
362 for f := range fieldWidth {
363 switch f {
364 case "0", "1", "(0)", "(1)":
365
366 default:
367 if !fieldUsed[f] {
368 fmt.Fprintf(os.Stderr, "%s: encoding field %s not used in %s\n", text, f, encoding)
369 }
370 }
371 }
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387 pri := 4
388 if strings.Contains(tags, "SEE") {
389 pri = 2
390 }
391
392 inst := Inst{
393 Text: text,
394 Encoding: encoding,
395 Mask: uint32(mask),
396 Value: uint32(value),
397 Priority: pri,
398 OpBase: ops[0],
399 OpBits: opBits,
400 Args: args,
401 }
402 p.Inst = append(p.Inst, inst)
403
404 if fuzzy != 0 {
405 inst.Mask &^= fuzzy
406 inst.Priority--
407 p.Inst = append(p.Inst, inst)
408 }
409 }
410
411
412 var opSuffix = map[string]string{
413 "<ADD,SUB>": "op",
414 "<BIF,BIT,BSL>": "op:2",
415 "<MLA,MLS><c>.F<32,64>": "op,cond:4,sz",
416 "<MLS,MLA><c>.F<32,64>": "op,cond:4,sz",
417 "<BT,TB><c>": "tb,cond:4",
418 "<TBL,TBX>.8": "op",
419 "<c>": "cond:4",
420 "<c>.32": "cond:4",
421 "<c>.F<32,64>": "cond:4,sz",
422 "<x><y><c>": "N,M,cond:4",
423 "<y><c>": "M,cond:4",
424 "{B}<c>": "B,cond:4",
425 "{E}<c>.F<32,64>": "E,cond:4,sz",
426 "{R}<c>": "R,cond:4",
427 "<c>.F<32,64>.<U,S>32": "cond:4,sz,op",
428 "<R,><c>.<U,S>32.F<32,64>": "op,cond:4,signed,sz",
429 "{S}<c>": "S,cond:4",
430 "{W}": "R",
431 "{X}<c>": "M,cond:4",
432 "<B,T><c>.<F32.F16,F16.F32>": "T,cond:4,op",
433 "<c>.<F64.F32,F32.F64>": "cond:4,sz",
434 "<c>.FX<S,U><16,32>.F<32,64>": "cond:4,U,sx,sz",
435 "<c>.F<32,64>.FX<S,U><16,32>": "cond:4,sz,U,sx",
436 }
437
438
439
440
441 var choices = map[string][]string{
442 "c": {".EQ", ".NE", ".CS", ".CC", ".MI", ".PL", ".VS", ".VC", ".HI", ".LS", ".GE", ".LT", ".GT", ".LE", "", ".ZZ"},
443 "x": {"B", "T"},
444 "y": {"B", "T"},
445 }
446
447
448 var argOps = map[string]string{
449
450 "<Rm>|Rm:4@0": "arg_R_0",
451 "<Rn>|Rn:4@0": "arg_R_0",
452 "<Rt>|Rt:4@0": "arg_R_0",
453 "<Rm>|Rm:4@8": "arg_R_8",
454 "<Ra>|Ra:4@12": "arg_R_12",
455 "<Rd>|Rd:4@12": "arg_R_12",
456 "<RdLo>|RdLo:4@12": "arg_R_12",
457 "<Rt>|Rt:4@12": "arg_R_12",
458 "<Rt_nzcv>|Rt:4@12": "arg_R_12_nzcv",
459 "<Rd>|Rd:4@16": "arg_R_16",
460 "<RdHi>|RdHi:4@16": "arg_R_16",
461 "<Rn>|Rn:4@16": "arg_R_16",
462
463
464 "<Rt1>|Rt:4@0": "arg_R1_0",
465 "<Rt1>|Rt:4@12": "arg_R1_12",
466 "<Rt2>|Rt:4@0": "arg_R2_0",
467 "<Rt2>|Rt:4@12": "arg_R2_12",
468
469
470 "<Rm>,<type> <Rs>|Rm:4@0|Rs:4@8|type:2@5": "arg_R_shift_R",
471 "<Rm>{,<shift>}|Rm:4@0|imm5:5@7|type:2@5": "arg_R_shift_imm",
472 "<Rn>{,<shift>}|Rn:4@0|imm5:5@7|sh@6": "arg_R_shift_imm",
473 "<Rm>{,LSL #<imm5>}|Rm:4@0|imm5:5@7": "arg_R_shift_imm",
474 "<Rm>{,<rotation>}|Rm:4@0|rotate:2@10": "arg_R_rotate",
475
476
477 "<Rn>{!}|Rn:4@16|W@21": "arg_R_16_WB",
478 "[<Rn>]|Rn:4@16": "arg_mem_R",
479 "[<Rn>,+/-<Rm>{, <shift>}]{!}|Rn:4@16|U@23|Rm:4@0|type:2@5|imm5:5@7|P@24|W@21": "arg_mem_R_pm_R_shift_imm_W",
480 "[<Rn>{,#+/-<imm8>}]{!}|Rn:4@16|P@24|U@23|W@21|imm4H:4@8|imm4L:4@0": "arg_mem_R_pm_imm8_W",
481 "[<Rn>] {,#+/-<imm8>}|Rn:4@16|U@23|imm4H:4@8|imm4L:4@0": "arg_mem_R_pm_imm8_postindex",
482 "[<Rn>{,#+/-<imm12>}]{!}|Rn:4@16|P@24|U@23|W@21|imm12:12@0": "arg_mem_R_pm_imm12_W",
483 "[<Rn>],#+/-<imm12>|Rn:4@16|imm12:12@0|U@23": "arg_mem_R_pm_imm12_postindex",
484 "[<Rn>,#+/-<imm12>]|Rn:4@16|U@23|imm12:12@0": "arg_mem_R_pm_imm12_offset",
485 "[<Rn>] {,#+/-<imm12>}|Rn:4@16|U@23|imm12:12@0": "arg_mem_R_pm_imm12_postindex",
486 "[<Rn>], +/-<Rm>|Rn:4@16|U@23|Rm:4@0": "arg_mem_R_pm_R_postindex",
487 "[<Rn>,+/-<Rm>]{!}|Rn:4@16|U@23|Rm:4@0|P@24|W@21": "arg_mem_R_pm_R_W",
488 "[<Rn>],+/-<Rm>{, <shift>}|Rn:4@16|Rm:4@0|imm5:5@7|type:2@5|U@23": "arg_mem_R_pm_R_shift_imm_postindex",
489 "[<Rn>,+/-<Rm>{, <shift>}]|Rn:4@16|U@23|Rm:4@0|type:2@5|imm5:5@7": "arg_mem_R_pm_R_shift_imm_offset",
490 "[<Rn>{,#+/-<imm8>}]|Rn:4@16|U@23|imm8:8@0": "arg_mem_R_pm_imm8at0_offset",
491
492
493 "<label+12>|imm12:12@0": "arg_label_p_12",
494 "<label-12>|imm12:12@0": "arg_label_m_12",
495 "<label+/-12>|imm12:12@0|U@23": "arg_label_pm_12",
496 "<label+/-4+4>|imm4H:4@8|imm4L:4@0|U@23": "arg_label_pm_4_4",
497
498
499 "#<const>|imm12:12@0": "arg_const",
500 "#<imm5>|imm5:5@7": "arg_imm5",
501 "#<imm5_nz>|imm5:5@7": "arg_imm5_nz",
502 "#<imm5_32>|imm5:5@7": "arg_imm5_32",
503 "<label24>|imm24:24@0": "arg_label24",
504 "#<lsb>|lsb:5@7": "arg_imm5",
505 "#<width>|lsb:5@7|msb:5@16": "arg_lsb_width",
506 "#<imm12+4>|imm12:12@8|imm4:4@0": "arg_imm_12at8_4at0",
507 "#<imm12+4>|imm12:12@0|imm4:4@16": "arg_imm_4at16_12at0",
508 "<label24H>|imm24:24@0|H@24": "arg_label24H",
509 "#<option>|option:4@0": "arg_option",
510 "#<widthm1>|widthm1:5@16": "arg_widthm1",
511 "#<sat_imm4>|sat_imm:4@16": "arg_satimm4",
512 "#<sat_imm5>|sat_imm:5@16": "arg_satimm5",
513 "#<sat_imm4m1>|sat_imm:4@16": "arg_satimm4m1",
514 "#<sat_imm5m1>|sat_imm:5@16": "arg_satimm5m1",
515 "#<imm24>|imm24:24@0": "arg_imm24",
516
517
518 "<registers>|register_list:16@0": "arg_registers",
519 "<registers2>|register_list:16@0": "arg_registers2",
520 "<registers1>|Rt:4@12": "arg_registers1",
521 "<endian_specifier>|E@9": "arg_endian",
522
523 "SP": "arg_SP",
524 "APSR": "arg_APSR",
525 "FPSCR": "arg_FPSCR",
526
527
528 "<Sd>|Vd:4@12|D@22": "arg_Sd",
529 "<Sd,Dd>|Vd:4@12|D@22|sz@8": "arg_Sd_Dd",
530 "<Dd,Sd>|Vd:4@12|D@22|sz@8": "arg_Dd_Sd",
531 "<Sn>|Vn:4@16|N@7": "arg_Sn",
532 "<Sn,Dn>|Vn:4@16|N@7|sz@8": "arg_Sn_Dn",
533 "<Sm>|Vm:4@0|M@5": "arg_Sm",
534 "<Sm,Dm>|Vm:4@0|M@5|sz@8": "arg_Sm_Dm",
535 "#0.0": "arg_fp_0",
536 "#<imm_vfp>|imm4H:4@16|imm4L:4@0|sz@8": "arg_imm_vfp",
537 "#<fbits>|sx@7|imm4:4@0|i@5": "arg_fbits",
538 "<Dn[x]>|N@7|Vn:4@16|opc1@21": "arg_Dn_half",
539 "<Dd[x]>|D@7|Vd:4@16|opc1@21": "arg_Dn_half",
540 }
541
542
543
544
545
546
547
548
549 var argSuffixes = map[string]string{
550 "#0": "",
551 "#0.0": "",
552 "#<const>": "imm12:12",
553 "#<fbits>": "sx,imm4:4,i",
554 "#<imm12+4>": "imm12:12,imm4:4",
555 "#<imm24>": "imm24:24",
556 "#<imm3>": "imm3:3",
557 "#<imm4>": "imm4:4",
558 "#<imm5>": "imm5:5",
559 "#<imm5_nz>": "imm5:5",
560 "#<imm5_32>": "imm5:5",
561 "#<imm6>": "imm6:6",
562 "#<immsize>": "size:2",
563 "#<imm_vfp>": "imm4H:4,imm4L:4,sz",
564 "#<sat_imm4>": "sat_imm:4",
565 "#<sat_imm5>": "sat_imm:5",
566 "#<sat_imm4m1>": "sat_imm:4",
567 "#<sat_imm5m1>": "sat_imm:5",
568 "#<lsb>": "lsb:5",
569 "#<option>": "option:4",
570 "#<width>": "lsb:5,msb:5",
571 "#<widthm1>": "widthm1:5",
572 "+/-<Rm>": "Rm:4,U",
573 "<Dd>": "D,Vd:4",
574 "<Dd[x]>": "D,Vd:4,opc1",
575 "<Dm>": "M,Vm:4",
576 "<Dm[x]>": "M,Vm:4,size:2",
577 "<Dn>": "N,Vn:4",
578 "<Dn[x]>": "N,Vn:4,opc1",
579 "<Dm[size_x]>": "imm4:4",
580 "<Qd>": "D,Vd:4",
581 "<Qm>": "M,Vm:4",
582 "<Qn>": "N,Vn:4",
583 "<Ra>": "Ra:4",
584 "<Rd>": "Rd:4",
585 "<RdHi>": "RdHi:4",
586 "<RdLo>": "RdLo:4",
587 "<Rm>": "Rm:4",
588 "<Rm>{,<rotation>}": "Rm:4,rotate:2",
589 "<Rm>{,<shift>}": "Rm:4,imm5:5,type:2",
590 "<Rm>{,LSL #<imm5>}": "Rm:4,imm5:5",
591 "<Rn>": "Rn:4",
592 "<Rn>{!}": "Rn:4,W",
593 "<Rn>{,<shift>}": "Rn:4,imm5:5,sh",
594 "<Rs>": "Rs:4",
595 "<Rt1>": "Rt:4",
596 "<Rt2>": "Rt:4",
597 "<Rt>": "Rt:4",
598 "<Rt_nzcv>": "Rt:4",
599 "<Sd>": "Vd:4,D",
600 "<Sm1>": "Vm:4,M",
601 "<Sm>": "Vm:4,M",
602 "<Sn>": "Vn:4,N",
603 "<Sd,Dd>": "Vd:4,D,sz",
604 "<Dd,Sd>": "Vd:4,D,sz",
605 "<Sn,Dn>": "Vn:4,N,sz",
606 "<Sm,Dm>": "Vm:4,M,sz",
607 "<endian_specifier>": "E",
608 "<label+/-12>": "imm12:12,U",
609 "<label+12>": "imm12:12",
610 "<label-12>": "imm12:12",
611 "<label24>": "imm24:24",
612 "<label24H>": "imm24:24,H",
613 "<label+/-4+4>": "imm4H:4,imm4L:4,U",
614 "<list4>": "D,Vd:4,type:4",
615 "<list3>": "D,Vd:4,index_align:4",
616 "<list3t>": "D,Vd:4,T",
617 "<list1>": "D,Vd:4",
618 "<list_len>": "N,Vn:4,len:2",
619 "<vlist32>": "D,Vd:4,imm8:8",
620 "<vlist64>": "D,Vd:4,imm8:8",
621 "<registers>": "register_list:16",
622 "<registers2>": "register_list:16",
623 "<registers1>": "Rt:4",
624 "APSR": "",
625 "<Rm>,<type> <Rs>": "Rm:4,Rs:4,type:2",
626 "FPSCR": "",
627 "SP": "",
628 "[<Rn>,#+/-<imm12>]": "Rn:4,U,imm12:12",
629 "[<Rn>,+/-<Rm>]{!}": "Rn:4,U,Rm:4,P,W",
630 "[<Rn>,+/-<Rm>{, <shift>}]": "Rn:4,U,Rm:4,type:2,imm5:5",
631 "[<Rn>,+/-<Rm>{, <shift>}]{!}": "Rn:4,U,Rm:4,type:2,imm5:5,P,W",
632 "[<Rn>] {,#+/-<imm12>}": "Rn:4,U,imm12:12",
633 "[<Rn>] {,#+/-<imm8>}": "Rn:4,U,imm4H:4,imm4L:4",
634 "[<Rn>]": "Rn:4",
635 "[<Rn>],#+/-<imm12>": "Rn:4,imm12:12,U",
636 "[<Rn>],+/-<Rm>{, <shift>}": "Rn:4,Rm:4,imm5:5,type:2,U",
637 "[<Rn>]{!}": "Rn:4,Rm:4",
638 "[<Rn>{@<align>}]{!}": "XXX",
639 "[<Rn>{,#+/-<imm12>}]{!}": "Rn:4,P,U,W,imm12:12",
640 "[<Rn>{,#+/-<imm8>}]{!}": "Rn:4,P,U,W,imm4H:4,imm4L:4",
641 "[<Rn>{,#+/-<imm8>}]": "Rn:4,U,imm8:8",
642 "[<Rn>], +/-<Rm>": "Rn:4,U,Rm:4",
643 "#<imm_simd1>": "i,imm3:3,imm4:4,cmode:4",
644 "#<imm_simd>": "op,i,imm3:3,imm4:4,cmode:4",
645 "#<imm_vs>": "L,imm6:6",
646 "#<imm_vsn>": "imm6:6",
647 }
648
649
650 func cross(xs []string, ys ...string) []string {
651 var xys []string
652
653 for _, x := range xs {
654 for _, y := range ys {
655 xys = append(xys, x+y)
656 }
657 }
658 return xys
659 }
660
661
662
663
664
665 func crossCond(xs []string) []string {
666 ys := choices["c"]
667 var xys []string
668
669 for _, x := range xs {
670 i := strings.Index(x, "_COND_")
671 pre, post := x[:i], x[i+6:]
672 for _, y := range ys {
673 xys = append(xys, pre+y+post)
674 }
675 }
676 return xys
677 }
678
679
680 func printText(p *Prog) {
681 log.Fatal("-fmt=text not implemented")
682 }
683
684
685
686 func printDecoder(p *Prog) {
687 fmt.Printf("package armasm\n\n")
688
689
690
691 haveRange := make(map[string]string)
692 for _, r := range p.OpRanges {
693 haveRange[r] = r
694 }
695 var ranges []string
696 for _, r := range haveRange {
697 ranges = append(ranges, r)
698 }
699 sort.Strings(ranges)
700
701
702 fmt.Printf("const (\n")
703 iota := 0
704 fmt.Printf("\t_ Op = iota\n")
705 iota++
706 for _, r := range ranges {
707 for _, op := range strings.Split(r, ",") {
708 if op == "" {
709 continue
710 }
711
712
713
714 if strings.Contains(op, ".EQ") {
715 for iota&15 != 0 {
716 fmt.Printf("\t_\n")
717 iota++
718 }
719 }
720 fmt.Printf("\t%s\n", strings.Replace(op, ".", "_", -1))
721 iota++
722 }
723 }
724 fmt.Printf(")\n")
725
726
727 fmt.Printf("\nvar opstr = [...]string{\n")
728 for _, r := range ranges {
729 for _, op := range strings.Split(r, ",") {
730 if op == "" {
731 continue
732 }
733 fmt.Printf("\t%s: %q,\n", strings.Replace(op, ".", "_", -1), op)
734 }
735 }
736 fmt.Printf("}\n")
737
738
739 unknown := map[string]bool{}
740 fmt.Printf("\nvar instFormats = [...]instFormat{\n")
741 for _, inst := range p.Inst {
742 fmt.Printf("\t{%#08x, %#08x, %d, %s, %#x, instArgs{", inst.Mask, inst.Value, inst.Priority, strings.Replace(inst.OpBase, ".", "_", -1), inst.OpBits)
743 for i, a := range inst.Args {
744 if i > 0 {
745 fmt.Printf(", ")
746 }
747 str := argOps[a]
748 if str == "" && !unknown[a] {
749 fmt.Fprintf(os.Stderr, "%s: unknown arg %s\n", inst.Text, a)
750 unknown[a] = true
751 }
752 fmt.Printf("%s", str)
753 }
754 fmt.Printf("}}, // %s %s\n", inst.Text, inst.Encoding)
755 }
756 fmt.Printf("}\n")
757 }
758
View as plain text