Source file src/cmd/vendor/golang.org/x/arch/arm64/arm64asm/plan9x.go
1
2
3
4
5 package arm64asm
6
7 import (
8 "fmt"
9 "io"
10 "sort"
11 "strings"
12 )
13
14
15
16
17
18
19
20
21
22
23
24 func GoSyntax(inst Inst, pc uint64, symname func(uint64) (string, uint64), text io.ReaderAt) string {
25 if symname == nil {
26 symname = func(uint64) (string, uint64) { return "", 0 }
27 }
28
29 var args []string
30 for _, a := range inst.Args {
31 if a == nil {
32 break
33 }
34 args = append(args, plan9Arg(&inst, pc, symname, a))
35 }
36
37 op := inst.Op.String()
38
39 switch inst.Op {
40 case LDR, LDRB, LDRH, LDRSB, LDRSH, LDRSW:
41
42 if offset, ok := inst.Args[1].(PCRel); ok {
43 addr := pc + uint64(offset)
44 if _, ok := inst.Args[0].(Reg); !ok {
45 break
46 }
47 if s, base := symname(addr); s != "" && addr == base {
48 args[1] = fmt.Sprintf("$%s(SB)", s)
49 }
50 }
51 }
52
53
54 suffix := ""
55 switch inst.Op {
56 case LDR, LDRB, LDRH, LDRSB, LDRSH, LDRSW, STR, STRB, STRH, STUR, STURB, STURH, LD1, ST1:
57 switch mem := inst.Args[1].(type) {
58 case MemImmediate:
59 switch mem.Mode {
60 case AddrOffset:
61
62 case AddrPreIndex:
63 suffix = ".W"
64 case AddrPostIndex, AddrPostReg:
65 suffix = ".P"
66 }
67 }
68
69 case STP, LDP:
70 switch mem := inst.Args[2].(type) {
71 case MemImmediate:
72 switch mem.Mode {
73 case AddrOffset:
74
75 case AddrPreIndex:
76 suffix = ".W"
77 case AddrPostIndex:
78 suffix = ".P"
79 }
80 }
81 }
82
83 switch inst.Op {
84 case BL:
85 return "CALL " + args[0]
86
87 case BLR:
88 r := inst.Args[0].(Reg)
89 regno := uint16(r) & 31
90 return fmt.Sprintf("CALL (R%d)", regno)
91
92 case RET:
93 if r, ok := inst.Args[0].(Reg); ok && r == X30 {
94 return "RET"
95 }
96
97 case B:
98 if cond, ok := inst.Args[0].(Cond); ok {
99 return "B" + cond.String() + " " + args[1]
100 }
101 return "JMP" + " " + args[0]
102
103 case BR:
104 r := inst.Args[0].(Reg)
105 regno := uint16(r) & 31
106 return fmt.Sprintf("JMP (R%d)", regno)
107
108 case MOV:
109 rno := -1
110 switch a := inst.Args[0].(type) {
111 case Reg:
112 rno = int(a)
113 case RegSP:
114 rno = int(a)
115 case RegisterWithArrangementAndIndex:
116 op = "VMOV"
117 case RegisterWithArrangement:
118 op = "VMOV"
119 }
120 if rno >= 0 && rno <= int(WZR) {
121 op = "MOVW"
122 } else if rno >= int(X0) && rno <= int(XZR) {
123 op = "MOVD"
124 }
125 if _, ok := inst.Args[1].(RegisterWithArrangementAndIndex); ok {
126 op = "VMOV"
127 }
128
129 case LDR:
130 var rno uint16
131 if r, ok := inst.Args[0].(Reg); ok {
132 rno = uint16(r)
133 } else {
134 rno = uint16(inst.Args[0].(RegSP))
135 }
136 if rno <= uint16(WZR) {
137 op = "MOVWU" + suffix
138 } else if rno >= uint16(S0) && rno <= uint16(S31) {
139 op = "FMOVS" + suffix
140 args[0] = fmt.Sprintf("F%d", rno&31)
141 } else if rno >= uint16(D0) && rno <= uint16(D31) {
142 op = "FMOVD" + suffix
143 args[0] = fmt.Sprintf("F%d", rno&31)
144 } else {
145 op = "MOVD" + suffix
146 }
147
148 case LDRB:
149 op = "MOVBU" + suffix
150
151 case LDRH:
152 op = "MOVHU" + suffix
153
154 case LDRSW:
155 op = "MOVW" + suffix
156
157 case LDRSB:
158 if r, ok := inst.Args[0].(Reg); ok {
159 rno := uint16(r)
160 if rno <= uint16(WZR) {
161 op = "MOVBW" + suffix
162 } else {
163 op = "MOVB" + suffix
164 }
165 }
166 case LDRSH:
167 if r, ok := inst.Args[0].(Reg); ok {
168 rno := uint16(r)
169 if rno <= uint16(WZR) {
170 op = "MOVHW" + suffix
171 } else {
172 op = "MOVH" + suffix
173 }
174 }
175 case STR, STUR:
176 var rno uint16
177 if r, ok := inst.Args[0].(Reg); ok {
178 rno = uint16(r)
179 } else {
180 rno = uint16(inst.Args[0].(RegSP))
181 }
182 if rno <= uint16(WZR) {
183 op = "MOVW" + suffix
184 } else if rno >= uint16(S0) && rno <= uint16(S31) {
185 op = "FMOVS" + suffix
186 args[0] = fmt.Sprintf("F%d", rno&31)
187 } else if rno >= uint16(D0) && rno <= uint16(D31) {
188 op = "FMOVD" + suffix
189 args[0] = fmt.Sprintf("F%d", rno&31)
190 } else {
191 op = "MOVD" + suffix
192 }
193 args[0], args[1] = args[1], args[0]
194
195 case STRB, STURB:
196 op = "MOVB" + suffix
197 args[0], args[1] = args[1], args[0]
198
199 case STRH, STURH:
200 op = "MOVH" + suffix
201 args[0], args[1] = args[1], args[0]
202
203 case TBNZ, TBZ:
204 args[0], args[1], args[2] = args[2], args[0], args[1]
205
206 case MADD, MSUB, SMADDL, SMSUBL, UMADDL, UMSUBL:
207 if r, ok := inst.Args[0].(Reg); ok {
208 rno := uint16(r)
209 if rno <= uint16(WZR) {
210 op += "W"
211 }
212 }
213 args[2], args[3] = args[3], args[2]
214 case STLR:
215 if r, ok := inst.Args[0].(Reg); ok {
216 rno := uint16(r)
217 if rno <= uint16(WZR) {
218 op += "W"
219 }
220 }
221 args[0], args[1] = args[1], args[0]
222
223 case STLRB, STLRH:
224 args[0], args[1] = args[1], args[0]
225
226 case STLXR, STXR:
227 if r, ok := inst.Args[1].(Reg); ok {
228 rno := uint16(r)
229 if rno <= uint16(WZR) {
230 op += "W"
231 }
232 }
233 args[1], args[2] = args[2], args[1]
234
235 case STLXRB, STLXRH, STXRB, STXRH:
236 args[1], args[2] = args[2], args[1]
237
238 case BFI, BFXIL, SBFIZ, SBFX, UBFIZ, UBFX:
239 if r, ok := inst.Args[0].(Reg); ok {
240 rno := uint16(r)
241 if rno <= uint16(WZR) {
242 op += "W"
243 }
244 }
245 args[1], args[2], args[3] = args[3], args[1], args[2]
246
247 case LDAXP, LDXP:
248 if r, ok := inst.Args[0].(Reg); ok {
249 rno := uint16(r)
250 if rno <= uint16(WZR) {
251 op += "W"
252 }
253 }
254 fallthrough
255
256 case STP, LDP:
257 args[0] = fmt.Sprintf("(%s, %s)", args[0], args[1])
258 args[1] = args[2]
259 if op == "STP" {
260 op = op + suffix
261 return op + " " + args[0] + ", " + args[1]
262 } else if op == "LDP" {
263 op = op + suffix
264 return op + " " + args[1] + ", " + args[0]
265 } else if op == "LDAXP" || op == "LDXP" || op == "LDAXPW" || op == "LDXPW" {
266 return op + " " + args[1] + ", " + args[0]
267 }
268
269 case STLXP, STXP:
270 if r, ok := inst.Args[1].(Reg); ok {
271 rno := uint16(r)
272 if rno <= uint16(WZR) {
273 op += "W"
274 }
275 }
276 args[1] = fmt.Sprintf("(%s, %s)", args[1], args[2])
277 args[2] = args[3]
278 return op + " " + args[1] + ", " + args[2] + ", " + args[0]
279
280 case FCCMP, FCCMPE:
281 args[0], args[1] = args[1], args[0]
282 fallthrough
283
284 case FCMP, FCMPE:
285 if _, ok := inst.Args[1].(Imm); ok {
286 args[1] = "$(0.0)"
287 }
288 fallthrough
289
290 case FADD, FSUB, FMUL, FNMUL, FDIV, FMAX, FMIN, FMAXNM, FMINNM, FCSEL, FMADD, FMSUB, FNMADD, FNMSUB:
291 if strings.HasSuffix(op, "MADD") || strings.HasSuffix(op, "MSUB") {
292 args[2], args[3] = args[3], args[2]
293 }
294 if r, ok := inst.Args[0].(Reg); ok {
295 rno := uint16(r)
296 if rno >= uint16(S0) && rno <= uint16(S31) {
297 op = fmt.Sprintf("%sS", op)
298 } else if rno >= uint16(D0) && rno <= uint16(D31) {
299 op = fmt.Sprintf("%sD", op)
300 }
301 }
302
303 case FCVT:
304 for i := 1; i >= 0; i-- {
305 if r, ok := inst.Args[i].(Reg); ok {
306 rno := uint16(r)
307 if rno >= uint16(H0) && rno <= uint16(H31) {
308 op = fmt.Sprintf("%sH", op)
309 } else if rno >= uint16(S0) && rno <= uint16(S31) {
310 op = fmt.Sprintf("%sS", op)
311 } else if rno >= uint16(D0) && rno <= uint16(D31) {
312 op = fmt.Sprintf("%sD", op)
313 }
314 }
315 }
316
317 case FABS, FNEG, FSQRT, FRINTN, FRINTP, FRINTM, FRINTZ, FRINTA, FRINTX, FRINTI:
318 if r, ok := inst.Args[1].(Reg); ok {
319 rno := uint16(r)
320 if rno >= uint16(S0) && rno <= uint16(S31) {
321 op = fmt.Sprintf("%sS", op)
322 } else if rno >= uint16(D0) && rno <= uint16(D31) {
323 op = fmt.Sprintf("%sD", op)
324 }
325 }
326
327 case FCVTZS, FCVTZU, SCVTF, UCVTF:
328 if _, ok := inst.Args[2].(Imm); !ok {
329 for i := 1; i >= 0; i-- {
330 if r, ok := inst.Args[i].(Reg); ok {
331 rno := uint16(r)
332 if rno >= uint16(S0) && rno <= uint16(S31) {
333 op = fmt.Sprintf("%sS", op)
334 } else if rno >= uint16(D0) && rno <= uint16(D31) {
335 op = fmt.Sprintf("%sD", op)
336 } else if rno <= uint16(WZR) {
337 op += "W"
338 }
339 }
340 }
341 }
342
343 case FMOV:
344 for i := 0; i <= 1; i++ {
345 if r, ok := inst.Args[i].(Reg); ok {
346 rno := uint16(r)
347 if rno >= uint16(S0) && rno <= uint16(S31) {
348 op = fmt.Sprintf("%sS", op)
349 break
350 } else if rno >= uint16(D0) && rno <= uint16(D31) {
351 op = fmt.Sprintf("%sD", op)
352 break
353 }
354 }
355 }
356
357 case SYSL:
358 op1 := int(inst.Args[1].(Imm).Imm)
359 cn := int(inst.Args[2].(Imm_c))
360 cm := int(inst.Args[3].(Imm_c))
361 op2 := int(inst.Args[4].(Imm).Imm)
362 sysregno := int32(op1<<16 | cn<<12 | cm<<8 | op2<<5)
363 args[1] = fmt.Sprintf("$%d", sysregno)
364 return op + " " + args[1] + ", " + args[0]
365
366 case CBNZ, CBZ:
367 if r, ok := inst.Args[0].(Reg); ok {
368 rno := uint16(r)
369 if rno <= uint16(WZR) {
370 op += "W"
371 }
372 }
373 args[0], args[1] = args[1], args[0]
374
375 case ADR, ADRP:
376 addr := int64(inst.Args[1].(PCRel))
377 args[1] = fmt.Sprintf("%d(PC)", addr)
378
379 case MSR:
380 args[0] = inst.Args[0].String()
381
382 case ST1:
383 op = fmt.Sprintf("V%s", op) + suffix
384 args[0], args[1] = args[1], args[0]
385
386 case LD1:
387 op = fmt.Sprintf("V%s", op) + suffix
388
389 case UMOV:
390 op = "VMOV"
391
392 default:
393 index := sort.SearchStrings(noSuffixOpSet, op)
394 if !(index < len(noSuffixOpSet) && noSuffixOpSet[index] == op) {
395 rno := -1
396 switch a := inst.Args[0].(type) {
397 case Reg:
398 rno = int(a)
399 case RegSP:
400 rno = int(a)
401 case RegisterWithArrangement:
402 op = fmt.Sprintf("V%s", op)
403 }
404
405 if rno >= int(B0) && rno <= int(Q31) && !strings.HasPrefix(op, "F") {
406 op = fmt.Sprintf("V%s", op)
407 }
408 if rno >= 0 && rno <= int(WZR) {
409
410 op += "W"
411 }
412 }
413 op = op + suffix
414 }
415
416
417 if _, ok := inst.Args[3].(Cond); ok {
418 if _, ok := inst.Args[2].(Reg); ok {
419 args[1], args[2] = args[2], args[1]
420 } else {
421 args[0], args[2] = args[2], args[0]
422 }
423 }
424
425 for i, j := 0, len(args)-1; i < j; i, j = i+1, j-1 {
426 args[i], args[j] = args[j], args[i]
427 }
428
429 if args != nil {
430 op += " " + strings.Join(args, ", ")
431 }
432
433 return op
434 }
435
436
437
438 var noSuffixOpSet = strings.Fields(`
439 AESD
440 AESE
441 AESIMC
442 AESMC
443 CRC32B
444 CRC32CB
445 CRC32CH
446 CRC32CW
447 CRC32CX
448 CRC32H
449 CRC32W
450 CRC32X
451 LDARB
452 LDARH
453 LDAXRB
454 LDAXRH
455 LDTRH
456 LDXRB
457 LDXRH
458 SHA1C
459 SHA1H
460 SHA1M
461 SHA1P
462 SHA1SU0
463 SHA1SU1
464 SHA256H
465 SHA256H2
466 SHA256SU0
467 SHA256SU1
468 `)
469
470 func plan9Arg(inst *Inst, pc uint64, symname func(uint64) (string, uint64), arg Arg) string {
471 switch a := arg.(type) {
472 case Imm:
473 return fmt.Sprintf("$%d", uint32(a.Imm))
474
475 case Imm64:
476 return fmt.Sprintf("$%d", int64(a.Imm))
477
478 case ImmShift:
479 if a.shift == 0 {
480 return fmt.Sprintf("$%d", a.imm)
481 }
482 return fmt.Sprintf("$(%d<<%d)", a.imm, a.shift)
483
484 case PCRel:
485 addr := int64(pc) + int64(a)
486 if s, base := symname(uint64(addr)); s != "" && uint64(addr) == base {
487 return fmt.Sprintf("%s(SB)", s)
488 }
489 return fmt.Sprintf("%d(PC)", a/4)
490
491 case Reg:
492 regenum := uint16(a)
493 regno := uint16(a) & 31
494
495 if regenum >= uint16(B0) && regenum <= uint16(D31) {
496 if strings.HasPrefix(inst.Op.String(), "F") || strings.HasSuffix(inst.Op.String(), "CVTF") {
497
498
499 return fmt.Sprintf("F%d", regno)
500 } else {
501 return fmt.Sprintf("V%d", regno)
502 }
503
504 } else if regenum >= uint16(Q0) && regenum <= uint16(Q31) {
505
506 return fmt.Sprintf("V%d", regno)
507 }
508
509 if regno == 31 {
510 return "ZR"
511 }
512 return fmt.Sprintf("R%d", regno)
513
514 case RegSP:
515 regno := uint16(a) & 31
516 if regno == 31 {
517 return "RSP"
518 }
519 return fmt.Sprintf("R%d", regno)
520
521 case RegExtshiftAmount:
522 reg := ""
523 regno := uint16(a.reg) & 31
524 if regno == 31 {
525 reg = "ZR"
526 } else {
527 reg = fmt.Sprintf("R%d", uint16(a.reg)&31)
528 }
529 extshift := ""
530 amount := ""
531 if a.extShift != ExtShift(0) {
532 switch a.extShift {
533 default:
534 extshift = "." + a.extShift.String()
535
536 case lsl:
537 extshift = "<<"
538 amount = fmt.Sprintf("%d", a.amount)
539 return reg + extshift + amount
540
541 case lsr:
542 extshift = ">>"
543 amount = fmt.Sprintf("%d", a.amount)
544 return reg + extshift + amount
545
546 case asr:
547 extshift = "->"
548 amount = fmt.Sprintf("%d", a.amount)
549 return reg + extshift + amount
550 case ror:
551 extshift = "@>"
552 amount = fmt.Sprintf("%d", a.amount)
553 return reg + extshift + amount
554 }
555 if a.amount != 0 {
556 amount = fmt.Sprintf("<<%d", a.amount)
557 }
558 }
559 return reg + extshift + amount
560
561 case MemImmediate:
562 off := ""
563 base := ""
564 regno := uint16(a.Base) & 31
565 if regno == 31 {
566 base = "(RSP)"
567 } else {
568 base = fmt.Sprintf("(R%d)", regno)
569 }
570 if a.imm != 0 && a.Mode != AddrPostReg {
571 off = fmt.Sprintf("%d", a.imm)
572 } else if a.Mode == AddrPostReg {
573 postR := fmt.Sprintf("(R%d)", a.imm)
574 return base + postR
575 }
576 return off + base
577
578 case MemExtend:
579 base := ""
580 index := ""
581 indexreg := ""
582 regno := uint16(a.Base) & 31
583 if regno == 31 {
584 base = "(RSP)"
585 } else {
586 base = fmt.Sprintf("(R%d)", regno)
587 }
588 regno = uint16(a.Index) & 31
589 if regno == 31 {
590 indexreg = "ZR"
591 } else {
592 indexreg = fmt.Sprintf("R%d", regno)
593 }
594
595 if a.Extend == lsl {
596
597
598
599
600
601
602 if a.Amount != 0 && !a.ShiftMustBeZero {
603 index = fmt.Sprintf("(%s<<%d)", indexreg, a.Amount)
604 } else {
605 index = fmt.Sprintf("(%s)", indexreg)
606 }
607 } else {
608 if a.Amount != 0 && !a.ShiftMustBeZero {
609 index = fmt.Sprintf("(%s.%s<<%d)", indexreg, a.Extend.String(), a.Amount)
610 } else {
611 index = fmt.Sprintf("(%s.%s)", indexreg, a.Extend.String())
612 }
613 }
614
615 return base + index
616
617 case Cond:
618 switch arg.String() {
619 case "CS":
620 return "HS"
621 case "CC":
622 return "LO"
623 }
624
625 case Imm_clrex:
626 return fmt.Sprintf("$%d", uint32(a))
627
628 case Imm_dcps:
629 return fmt.Sprintf("$%d", uint32(a))
630
631 case Imm_option:
632 return fmt.Sprintf("$%d", uint8(a))
633
634 case Imm_hint:
635 return fmt.Sprintf("$%d", uint8(a))
636
637 case Imm_fp:
638 var s, pre, numerator, denominator int16
639 var result float64
640 if a.s == 0 {
641 s = 1
642 } else {
643 s = -1
644 }
645 pre = s * int16(16+a.pre)
646 if a.exp > 0 {
647 numerator = (pre << uint8(a.exp))
648 denominator = 16
649 } else {
650 numerator = pre
651 denominator = (16 << uint8(-1*a.exp))
652 }
653 result = float64(numerator) / float64(denominator)
654 return strings.TrimRight(fmt.Sprintf("$%f", result), "0")
655
656 case RegisterWithArrangement:
657 result := a.r.String()
658 arrange := a.a.String()
659 c := []rune(arrange)
660 switch len(c) {
661 case 3:
662 c[1], c[2] = c[2], c[1]
663 case 4:
664 c[1], c[2], c[3] = c[3], c[1], c[2]
665 }
666 arrange = string(c)
667 result += arrange
668 if a.cnt > 0 {
669 result = "[" + result
670 for i := 1; i < int(a.cnt); i++ {
671 cur := V0 + Reg((uint16(a.r)-uint16(V0)+uint16(i))&31)
672 result += ", " + cur.String() + arrange
673 }
674 result += "]"
675 }
676 return result
677
678 case RegisterWithArrangementAndIndex:
679 result := a.r.String()
680 arrange := a.a.String()
681 result += arrange
682 if a.cnt > 1 {
683 result = "[" + result
684 for i := 1; i < int(a.cnt); i++ {
685 cur := V0 + Reg((uint16(a.r)-uint16(V0)+uint16(i))&31)
686 result += ", " + cur.String() + arrange
687 }
688 result += "]"
689 }
690 return fmt.Sprintf("%s[%d]", result, a.index)
691
692 case Systemreg:
693 return fmt.Sprintf("$%d", uint32(a.op0&1)<<14|uint32(a.op1&7)<<11|uint32(a.cn&15)<<7|uint32(a.cm&15)<<3|uint32(a.op2)&7)
694
695 case Imm_prfop:
696 if strings.Contains(a.String(), "#") {
697 return fmt.Sprintf("$%d", a)
698 }
699 }
700
701 return strings.ToUpper(arg.String())
702 }
703
View as plain text