gnu.go raw
1 // Copyright 2014 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
4
5 package x86asm
6
7 import (
8 "fmt"
9 "strings"
10 )
11
12 // GNUSyntax returns the GNU assembler syntax for the instruction, as defined by GNU binutils.
13 // This general form is often called “AT&T syntax” as a reference to AT&T System V Unix.
14 func GNUSyntax(inst Inst, pc uint64, symname SymLookup) string {
15 // Rewrite instruction to mimic GNU peculiarities.
16 // Note that inst has been passed by value and contains
17 // no pointers, so any changes we make here are local
18 // and will not propagate back out to the caller.
19
20 if symname == nil {
21 symname = func(uint64) (string, uint64) { return "", 0 }
22 }
23
24 // Adjust opcode [sic].
25 switch inst.Op {
26 case FDIV, FDIVR, FSUB, FSUBR, FDIVP, FDIVRP, FSUBP, FSUBRP:
27 // DC E0, DC F0: libopcodes swaps FSUBR/FSUB and FDIVR/FDIV, at least
28 // if you believe the Intel manual is correct (the encoding is irregular as given;
29 // libopcodes uses the more regular expected encoding).
30 // TODO(rsc): Test to ensure Intel manuals are correct and report to libopcodes maintainers?
31 // NOTE: iant thinks this is deliberate, but we can't find the history.
32 _, reg1 := inst.Args[0].(Reg)
33 _, reg2 := inst.Args[1].(Reg)
34 if reg1 && reg2 && (inst.Opcode>>24 == 0xDC || inst.Opcode>>24 == 0xDE) {
35 switch inst.Op {
36 case FDIV:
37 inst.Op = FDIVR
38 case FDIVR:
39 inst.Op = FDIV
40 case FSUB:
41 inst.Op = FSUBR
42 case FSUBR:
43 inst.Op = FSUB
44 case FDIVP:
45 inst.Op = FDIVRP
46 case FDIVRP:
47 inst.Op = FDIVP
48 case FSUBP:
49 inst.Op = FSUBRP
50 case FSUBRP:
51 inst.Op = FSUBP
52 }
53 }
54
55 case MOVNTSD:
56 // MOVNTSD is F2 0F 2B /r.
57 // MOVNTSS is F3 0F 2B /r (supposedly; not in manuals).
58 // Usually inner prefixes win for display,
59 // so that F3 F2 0F 2B 11 is REP MOVNTSD
60 // and F2 F3 0F 2B 11 is REPN MOVNTSS.
61 // Libopcodes always prefers MOVNTSS regardless of prefix order.
62 if countPrefix(&inst, 0xF3) > 0 {
63 found := false
64 for i := len(inst.Prefix) - 1; i >= 0; i-- {
65 switch inst.Prefix[i] & 0xFF {
66 case 0xF3:
67 if !found {
68 found = true
69 inst.Prefix[i] |= PrefixImplicit
70 }
71 case 0xF2:
72 inst.Prefix[i] &^= PrefixImplicit
73 }
74 }
75 inst.Op = MOVNTSS
76 }
77 }
78
79 // Add implicit arguments.
80 switch inst.Op {
81 case MONITOR:
82 inst.Args[0] = EDX
83 inst.Args[1] = ECX
84 inst.Args[2] = EAX
85 if inst.AddrSize == 16 {
86 inst.Args[2] = AX
87 }
88
89 case MWAIT:
90 if inst.Mode == 64 {
91 inst.Args[0] = RCX
92 inst.Args[1] = RAX
93 } else {
94 inst.Args[0] = ECX
95 inst.Args[1] = EAX
96 }
97 }
98
99 // Adjust which prefixes will be displayed.
100 // The rule is to display all the prefixes not implied by
101 // the usual instruction display, that is, all the prefixes
102 // except the ones with PrefixImplicit set.
103 // However, of course, there are exceptions to the rule.
104 switch inst.Op {
105 case CRC32:
106 // CRC32 has a mandatory F2 prefix.
107 // If there are multiple F2s and no F3s, the extra F2s do not print.
108 // (And Decode has already marked them implicit.)
109 // However, if there is an F3 anywhere, then the extra F2s do print.
110 // If there are multiple F2 prefixes *and* an (ignored) F3,
111 // then libopcodes prints the extra F2s as REPNs.
112 if countPrefix(&inst, 0xF2) > 1 {
113 unmarkImplicit(&inst, 0xF2)
114 markLastImplicit(&inst, 0xF2)
115 }
116
117 // An unused data size override should probably be shown,
118 // to distinguish DATA16 CRC32B from plain CRC32B,
119 // but libopcodes always treats the final override as implicit
120 // and the others as explicit.
121 unmarkImplicit(&inst, PrefixDataSize)
122 markLastImplicit(&inst, PrefixDataSize)
123
124 case CVTSI2SD, CVTSI2SS:
125 if !isMem(inst.Args[1]) {
126 markLastImplicit(&inst, PrefixDataSize)
127 }
128
129 case CVTSD2SI, CVTSS2SI, CVTTSD2SI, CVTTSS2SI,
130 ENTER, FLDENV, FNSAVE, FNSTENV, FRSTOR, LGDT, LIDT, LRET,
131 POP, PUSH, RET, SGDT, SIDT, SYSRET, XBEGIN:
132 markLastImplicit(&inst, PrefixDataSize)
133
134 case LOOP, LOOPE, LOOPNE, MONITOR:
135 markLastImplicit(&inst, PrefixAddrSize)
136
137 case MOV:
138 // The 16-bit and 32-bit forms of MOV Sreg, dst and MOV src, Sreg
139 // cannot be distinguished when src or dst refers to memory, because
140 // Sreg is always a 16-bit value, even when we're doing a 32-bit
141 // instruction. Because the instruction tables distinguished these two,
142 // any operand size prefix has been marked as used (to decide which
143 // branch to take). Unmark it, so that it will show up in disassembly,
144 // so that the reader can tell the size of memory operand.
145 // up with the same arguments
146 dst, _ := inst.Args[0].(Reg)
147 src, _ := inst.Args[1].(Reg)
148 if ES <= src && src <= GS && isMem(inst.Args[0]) || ES <= dst && dst <= GS && isMem(inst.Args[1]) {
149 unmarkImplicit(&inst, PrefixDataSize)
150 }
151
152 case MOVDQU:
153 if countPrefix(&inst, 0xF3) > 1 {
154 unmarkImplicit(&inst, 0xF3)
155 markLastImplicit(&inst, 0xF3)
156 }
157
158 case MOVQ2DQ:
159 markLastImplicit(&inst, PrefixDataSize)
160
161 case SLDT, SMSW, STR, FXRSTOR, XRSTOR, XSAVE, XSAVEOPT, CMPXCHG8B:
162 if isMem(inst.Args[0]) {
163 unmarkImplicit(&inst, PrefixDataSize)
164 }
165
166 case SYSEXIT:
167 unmarkImplicit(&inst, PrefixDataSize)
168 }
169
170 if isCondJmp[inst.Op] || isLoop[inst.Op] || inst.Op == JCXZ || inst.Op == JECXZ || inst.Op == JRCXZ {
171 if countPrefix(&inst, PrefixCS) > 0 && countPrefix(&inst, PrefixDS) > 0 {
172 for i, p := range inst.Prefix {
173 switch p & 0xFFF {
174 case PrefixPN, PrefixPT:
175 inst.Prefix[i] &= 0xF0FF // cut interpretation bits, producing original segment prefix
176 }
177 }
178 }
179 }
180
181 // XACQUIRE/XRELEASE adjustment.
182 if inst.Op == MOV {
183 // MOV into memory is a candidate for turning REP into XRELEASE.
184 // However, if the REP is followed by a REPN, that REPN blocks the
185 // conversion.
186 haveREPN := false
187 for i := len(inst.Prefix) - 1; i >= 0; i-- {
188 switch inst.Prefix[i] &^ PrefixIgnored {
189 case PrefixREPN:
190 haveREPN = true
191 case PrefixXRELEASE:
192 if haveREPN {
193 inst.Prefix[i] = PrefixREP
194 }
195 }
196 }
197 }
198
199 // We only format the final F2/F3 as XRELEASE/XACQUIRE.
200 haveXA := false
201 haveXR := false
202 for i := len(inst.Prefix) - 1; i >= 0; i-- {
203 switch inst.Prefix[i] &^ PrefixIgnored {
204 case PrefixXRELEASE:
205 if !haveXR {
206 haveXR = true
207 } else {
208 inst.Prefix[i] = PrefixREP
209 }
210
211 case PrefixXACQUIRE:
212 if !haveXA {
213 haveXA = true
214 } else {
215 inst.Prefix[i] = PrefixREPN
216 }
217 }
218 }
219
220 // Determine opcode.
221 op := strings.ToLower(inst.Op.String())
222 if alt := gnuOp[inst.Op]; alt != "" {
223 op = alt
224 }
225
226 // Determine opcode suffix.
227 // Libopcodes omits the suffix if the width of the operation
228 // can be inferred from a register arguments. For example,
229 // add $1, %ebx has no suffix because you can tell from the
230 // 32-bit register destination that it is a 32-bit add,
231 // but in addl $1, (%ebx), the destination is memory, so the
232 // size is not evident without the l suffix.
233 needSuffix := true
234 SuffixLoop:
235 for i, a := range inst.Args {
236 if a == nil {
237 break
238 }
239 switch a := a.(type) {
240 case Reg:
241 switch inst.Op {
242 case MOVSX, MOVZX:
243 continue
244
245 case SHL, SHR, RCL, RCR, ROL, ROR, SAR:
246 if i == 1 {
247 // shift count does not tell us operand size
248 continue
249 }
250
251 case CRC32:
252 // The source argument does tell us operand size,
253 // but libopcodes still always puts a suffix on crc32.
254 continue
255
256 case PUSH, POP:
257 // Even though segment registers are 16-bit, push and pop
258 // can save/restore them from 32-bit slots, so they
259 // do not imply operand size.
260 if ES <= a && a <= GS {
261 continue
262 }
263
264 case CVTSI2SD, CVTSI2SS:
265 // The integer register argument takes priority.
266 if X0 <= a && a <= X15 {
267 continue
268 }
269 }
270
271 if AL <= a && a <= R15 || ES <= a && a <= GS || X0 <= a && a <= X15 || M0 <= a && a <= M7 {
272 needSuffix = false
273 break SuffixLoop
274 }
275 }
276 }
277
278 if needSuffix {
279 switch inst.Op {
280 case CMPXCHG8B, FLDCW, FNSTCW, FNSTSW, LDMXCSR, LLDT, LMSW, LTR, PCLMULQDQ,
281 SETA, SETAE, SETB, SETBE, SETE, SETG, SETGE, SETL, SETLE, SETNE, SETNO, SETNP, SETNS, SETO, SETP, SETS,
282 SLDT, SMSW, STMXCSR, STR, VERR, VERW:
283 // For various reasons, libopcodes emits no suffix for these instructions.
284
285 case CRC32:
286 op += byteSizeSuffix(argBytes(&inst, inst.Args[1]))
287
288 case LGDT, LIDT, SGDT, SIDT:
289 op += byteSizeSuffix(inst.DataSize / 8)
290
291 case MOVZX, MOVSX:
292 // Integer size conversions get two suffixes.
293 op = op[:4] + byteSizeSuffix(argBytes(&inst, inst.Args[1])) + byteSizeSuffix(argBytes(&inst, inst.Args[0]))
294
295 case LOOP, LOOPE, LOOPNE:
296 // Add w suffix to indicate use of CX register instead of ECX.
297 if inst.AddrSize == 16 {
298 op += "w"
299 }
300
301 case CALL, ENTER, JMP, LCALL, LEAVE, LJMP, LRET, RET, SYSRET, XBEGIN:
302 // Add w suffix to indicate use of 16-bit target.
303 // Exclude JMP rel8.
304 if inst.Opcode>>24 == 0xEB {
305 break
306 }
307 if inst.DataSize == 16 && inst.Mode != 16 {
308 markLastImplicit(&inst, PrefixDataSize)
309 op += "w"
310 } else if inst.Mode == 64 {
311 op += "q"
312 }
313
314 case FRSTOR, FNSAVE, FNSTENV, FLDENV:
315 // Add s suffix to indicate shortened FPU state (I guess).
316 if inst.DataSize == 16 {
317 op += "s"
318 }
319
320 case PUSH, POP:
321 if markLastImplicit(&inst, PrefixDataSize) {
322 op += byteSizeSuffix(inst.DataSize / 8)
323 } else if inst.Mode == 64 {
324 op += "q"
325 } else {
326 op += byteSizeSuffix(inst.MemBytes)
327 }
328
329 default:
330 if isFloat(inst.Op) {
331 // I can't explain any of this, but it's what libopcodes does.
332 switch inst.MemBytes {
333 default:
334 if (inst.Op == FLD || inst.Op == FSTP) && isMem(inst.Args[0]) {
335 op += "t"
336 }
337 case 4:
338 if isFloatInt(inst.Op) {
339 op += "l"
340 } else {
341 op += "s"
342 }
343 case 8:
344 if isFloatInt(inst.Op) {
345 op += "ll"
346 } else {
347 op += "l"
348 }
349 }
350 break
351 }
352
353 op += byteSizeSuffix(inst.MemBytes)
354 }
355 }
356
357 // Adjust special case opcodes.
358 switch inst.Op {
359 case 0:
360 if inst.Prefix[0] != 0 {
361 return strings.ToLower(inst.Prefix[0].String())
362 }
363
364 case INT:
365 if inst.Opcode>>24 == 0xCC {
366 inst.Args[0] = nil
367 op = "int3"
368 }
369
370 case CMPPS, CMPPD, CMPSD_XMM, CMPSS:
371 imm, ok := inst.Args[2].(Imm)
372 if ok && 0 <= imm && imm < 8 {
373 inst.Args[2] = nil
374 op = cmppsOps[imm] + op[3:]
375 }
376
377 case PCLMULQDQ:
378 imm, ok := inst.Args[2].(Imm)
379 if ok && imm&^0x11 == 0 {
380 inst.Args[2] = nil
381 op = pclmulqOps[(imm&0x10)>>3|(imm&1)]
382 }
383
384 case XLATB:
385 if markLastImplicit(&inst, PrefixAddrSize) {
386 op = "xlat" // not xlatb
387 }
388 }
389
390 // Build list of argument strings.
391 var (
392 usedPrefixes bool // segment prefixes consumed by Mem formatting
393 args []string // formatted arguments
394 )
395 for i, a := range inst.Args {
396 if a == nil {
397 break
398 }
399 switch inst.Op {
400 case MOVSB, MOVSW, MOVSD, MOVSQ, OUTSB, OUTSW, OUTSD:
401 if i == 0 {
402 usedPrefixes = true // disable use of prefixes for first argument
403 } else {
404 usedPrefixes = false
405 }
406 }
407 if a == Imm(1) && (inst.Opcode>>24)&^1 == 0xD0 {
408 continue
409 }
410 args = append(args, gnuArg(&inst, pc, symname, a, &usedPrefixes))
411 }
412
413 // The default is to print the arguments in reverse Intel order.
414 // A few instructions inhibit this behavior.
415 switch inst.Op {
416 case BOUND, LCALL, ENTER, LJMP:
417 // no reverse
418 default:
419 // reverse args
420 for i, j := 0, len(args)-1; i < j; i, j = i+1, j-1 {
421 args[i], args[j] = args[j], args[i]
422 }
423 }
424
425 // Build prefix string.
426 // Must be after argument formatting, which can turn off segment prefixes.
427 var (
428 prefix = "" // output string
429 numAddr = 0
430 numData = 0
431 implicitData = false
432 )
433 for _, p := range inst.Prefix {
434 if p&0xFF == PrefixDataSize && p&PrefixImplicit != 0 {
435 implicitData = true
436 }
437 }
438 for _, p := range inst.Prefix {
439 if p == 0 || p.IsVEX() {
440 break
441 }
442 if p&PrefixImplicit != 0 {
443 continue
444 }
445 switch p &^ (PrefixIgnored | PrefixInvalid) {
446 default:
447 if p.IsREX() {
448 if p&0xFF == PrefixREX {
449 prefix += "rex "
450 } else {
451 prefix += "rex." + p.String()[4:] + " "
452 }
453 break
454 }
455 prefix += strings.ToLower(p.String()) + " "
456
457 case PrefixPN:
458 op += ",pn"
459 continue
460
461 case PrefixPT:
462 op += ",pt"
463 continue
464
465 case PrefixAddrSize, PrefixAddr16, PrefixAddr32:
466 // For unknown reasons, if the addr16 prefix is repeated,
467 // libopcodes displays all but the last as addr32, even though
468 // the addressing form used in a memory reference is clearly
469 // still 16-bit.
470 n := 32
471 if inst.Mode == 32 {
472 n = 16
473 }
474 numAddr++
475 if countPrefix(&inst, PrefixAddrSize) > numAddr {
476 n = inst.Mode
477 }
478 prefix += fmt.Sprintf("addr%d ", n)
479 continue
480
481 case PrefixData16, PrefixData32:
482 if implicitData && countPrefix(&inst, PrefixDataSize) > 1 {
483 // Similar to the addr32 logic above, but it only kicks in
484 // when something used the data size prefix (one is implicit).
485 n := 16
486 if inst.Mode == 16 {
487 n = 32
488 }
489 numData++
490 if countPrefix(&inst, PrefixDataSize) > numData {
491 if inst.Mode == 16 {
492 n = 16
493 } else {
494 n = 32
495 }
496 }
497 prefix += fmt.Sprintf("data%d ", n)
498 continue
499 }
500 prefix += strings.ToLower(p.String()) + " "
501 }
502 }
503
504 // Finally! Put it all together.
505 text := prefix + op
506 if args != nil {
507 text += " "
508 // Indirect call/jmp gets a star to distinguish from direct jump address.
509 if (inst.Op == CALL || inst.Op == JMP || inst.Op == LJMP || inst.Op == LCALL) && (isMem(inst.Args[0]) || isReg(inst.Args[0])) {
510 text += "*"
511 }
512 text += strings.Join(args, ",")
513 }
514 return text
515 }
516
517 // gnuArg returns the GNU syntax for the argument x from the instruction inst.
518 // If *usedPrefixes is false and x is a Mem, then the formatting
519 // includes any segment prefixes and sets *usedPrefixes to true.
520 func gnuArg(inst *Inst, pc uint64, symname SymLookup, x Arg, usedPrefixes *bool) string {
521 if x == nil {
522 return "<nil>"
523 }
524 switch x := x.(type) {
525 case Reg:
526 switch inst.Op {
527 case CVTSI2SS, CVTSI2SD, CVTSS2SI, CVTSD2SI, CVTTSD2SI, CVTTSS2SI:
528 if inst.DataSize == 16 && EAX <= x && x <= R15L {
529 x -= EAX - AX
530 }
531
532 case IN, INSB, INSW, INSD, OUT, OUTSB, OUTSW, OUTSD:
533 // DX is the port, but libopcodes prints it as if it were a memory reference.
534 if x == DX {
535 return "(%dx)"
536 }
537 case VMOVDQA, VMOVDQU, VMOVNTDQA, VMOVNTDQ:
538 return strings.Replace(gccRegName[x], "xmm", "ymm", -1)
539 }
540 return gccRegName[x]
541 case Mem:
542 if s, disp := memArgToSymbol(x, pc, inst.Len, symname); s != "" {
543 suffix := ""
544 if disp != 0 {
545 suffix = fmt.Sprintf("%+d", disp)
546 }
547 return fmt.Sprintf("%s%s", s, suffix)
548 }
549 seg := ""
550 var haveCS, haveDS, haveES, haveFS, haveGS, haveSS bool
551 switch x.Segment {
552 case CS:
553 haveCS = true
554 case DS:
555 haveDS = true
556 case ES:
557 haveES = true
558 case FS:
559 haveFS = true
560 case GS:
561 haveGS = true
562 case SS:
563 haveSS = true
564 }
565 switch inst.Op {
566 case INSB, INSW, INSD, STOSB, STOSW, STOSD, STOSQ, SCASB, SCASW, SCASD, SCASQ:
567 // These do not accept segment prefixes, at least in the GNU rendering.
568 default:
569 if *usedPrefixes {
570 break
571 }
572 for i := len(inst.Prefix) - 1; i >= 0; i-- {
573 p := inst.Prefix[i] &^ PrefixIgnored
574 if p == 0 {
575 continue
576 }
577 switch p {
578 case PrefixCS:
579 if !haveCS {
580 haveCS = true
581 inst.Prefix[i] |= PrefixImplicit
582 }
583 case PrefixDS:
584 if !haveDS {
585 haveDS = true
586 inst.Prefix[i] |= PrefixImplicit
587 }
588 case PrefixES:
589 if !haveES {
590 haveES = true
591 inst.Prefix[i] |= PrefixImplicit
592 }
593 case PrefixFS:
594 if !haveFS {
595 haveFS = true
596 inst.Prefix[i] |= PrefixImplicit
597 }
598 case PrefixGS:
599 if !haveGS {
600 haveGS = true
601 inst.Prefix[i] |= PrefixImplicit
602 }
603 case PrefixSS:
604 if !haveSS {
605 haveSS = true
606 inst.Prefix[i] |= PrefixImplicit
607 }
608 }
609 }
610 *usedPrefixes = true
611 }
612 if haveCS {
613 seg += "%cs:"
614 }
615 if haveDS {
616 seg += "%ds:"
617 }
618 if haveSS {
619 seg += "%ss:"
620 }
621 if haveES {
622 seg += "%es:"
623 }
624 if haveFS {
625 seg += "%fs:"
626 }
627 if haveGS {
628 seg += "%gs:"
629 }
630 disp := ""
631 if x.Disp != 0 {
632 disp = fmt.Sprintf("%#x", x.Disp)
633 }
634 if x.Scale == 0 || x.Index == 0 && x.Scale == 1 && (x.Base == ESP || x.Base == RSP || x.Base == 0 && inst.Mode == 64) {
635 if x.Base == 0 {
636 return seg + disp
637 }
638 return fmt.Sprintf("%s%s(%s)", seg, disp, gccRegName[x.Base])
639 }
640 base := gccRegName[x.Base]
641 if x.Base == 0 {
642 base = ""
643 }
644 index := gccRegName[x.Index]
645 if x.Index == 0 {
646 if inst.AddrSize == 64 {
647 index = "%riz"
648 } else {
649 index = "%eiz"
650 }
651 }
652 if AX <= x.Base && x.Base <= DI {
653 // 16-bit addressing - no scale
654 return fmt.Sprintf("%s%s(%s,%s)", seg, disp, base, index)
655 }
656 return fmt.Sprintf("%s%s(%s,%s,%d)", seg, disp, base, index, x.Scale)
657 case Rel:
658 if pc == 0 {
659 return fmt.Sprintf(".%+#x", int64(x))
660 } else {
661 addr := pc + uint64(inst.Len) + uint64(x)
662 if s, base := symname(addr); s != "" && addr == base {
663 return fmt.Sprintf("%s", s)
664 } else {
665 addr := pc + uint64(inst.Len) + uint64(x)
666 return fmt.Sprintf("%#x", addr)
667 }
668 }
669 case Imm:
670 if s, base := symname(uint64(x)); s != "" {
671 suffix := ""
672 if uint64(x) != base {
673 suffix = fmt.Sprintf("%+d", uint64(x)-base)
674 }
675 return fmt.Sprintf("$%s%s", s, suffix)
676 }
677 if inst.Mode == 32 {
678 return fmt.Sprintf("$%#x", uint32(x))
679 }
680 return fmt.Sprintf("$%#x", int64(x))
681 }
682 return x.String()
683 }
684
685 var gccRegName = [...]string{
686 0: "REG0",
687 AL: "%al",
688 CL: "%cl",
689 BL: "%bl",
690 DL: "%dl",
691 AH: "%ah",
692 CH: "%ch",
693 BH: "%bh",
694 DH: "%dh",
695 SPB: "%spl",
696 BPB: "%bpl",
697 SIB: "%sil",
698 DIB: "%dil",
699 R8B: "%r8b",
700 R9B: "%r9b",
701 R10B: "%r10b",
702 R11B: "%r11b",
703 R12B: "%r12b",
704 R13B: "%r13b",
705 R14B: "%r14b",
706 R15B: "%r15b",
707 AX: "%ax",
708 CX: "%cx",
709 BX: "%bx",
710 DX: "%dx",
711 SP: "%sp",
712 BP: "%bp",
713 SI: "%si",
714 DI: "%di",
715 R8W: "%r8w",
716 R9W: "%r9w",
717 R10W: "%r10w",
718 R11W: "%r11w",
719 R12W: "%r12w",
720 R13W: "%r13w",
721 R14W: "%r14w",
722 R15W: "%r15w",
723 EAX: "%eax",
724 ECX: "%ecx",
725 EDX: "%edx",
726 EBX: "%ebx",
727 ESP: "%esp",
728 EBP: "%ebp",
729 ESI: "%esi",
730 EDI: "%edi",
731 R8L: "%r8d",
732 R9L: "%r9d",
733 R10L: "%r10d",
734 R11L: "%r11d",
735 R12L: "%r12d",
736 R13L: "%r13d",
737 R14L: "%r14d",
738 R15L: "%r15d",
739 RAX: "%rax",
740 RCX: "%rcx",
741 RDX: "%rdx",
742 RBX: "%rbx",
743 RSP: "%rsp",
744 RBP: "%rbp",
745 RSI: "%rsi",
746 RDI: "%rdi",
747 R8: "%r8",
748 R9: "%r9",
749 R10: "%r10",
750 R11: "%r11",
751 R12: "%r12",
752 R13: "%r13",
753 R14: "%r14",
754 R15: "%r15",
755 IP: "%ip",
756 EIP: "%eip",
757 RIP: "%rip",
758 F0: "%st",
759 F1: "%st(1)",
760 F2: "%st(2)",
761 F3: "%st(3)",
762 F4: "%st(4)",
763 F5: "%st(5)",
764 F6: "%st(6)",
765 F7: "%st(7)",
766 M0: "%mm0",
767 M1: "%mm1",
768 M2: "%mm2",
769 M3: "%mm3",
770 M4: "%mm4",
771 M5: "%mm5",
772 M6: "%mm6",
773 M7: "%mm7",
774 X0: "%xmm0",
775 X1: "%xmm1",
776 X2: "%xmm2",
777 X3: "%xmm3",
778 X4: "%xmm4",
779 X5: "%xmm5",
780 X6: "%xmm6",
781 X7: "%xmm7",
782 X8: "%xmm8",
783 X9: "%xmm9",
784 X10: "%xmm10",
785 X11: "%xmm11",
786 X12: "%xmm12",
787 X13: "%xmm13",
788 X14: "%xmm14",
789 X15: "%xmm15",
790 CS: "%cs",
791 SS: "%ss",
792 DS: "%ds",
793 ES: "%es",
794 FS: "%fs",
795 GS: "%gs",
796 GDTR: "%gdtr",
797 IDTR: "%idtr",
798 LDTR: "%ldtr",
799 MSW: "%msw",
800 TASK: "%task",
801 CR0: "%cr0",
802 CR1: "%cr1",
803 CR2: "%cr2",
804 CR3: "%cr3",
805 CR4: "%cr4",
806 CR5: "%cr5",
807 CR6: "%cr6",
808 CR7: "%cr7",
809 CR8: "%cr8",
810 CR9: "%cr9",
811 CR10: "%cr10",
812 CR11: "%cr11",
813 CR12: "%cr12",
814 CR13: "%cr13",
815 CR14: "%cr14",
816 CR15: "%cr15",
817 DR0: "%db0",
818 DR1: "%db1",
819 DR2: "%db2",
820 DR3: "%db3",
821 DR4: "%db4",
822 DR5: "%db5",
823 DR6: "%db6",
824 DR7: "%db7",
825 TR0: "%tr0",
826 TR1: "%tr1",
827 TR2: "%tr2",
828 TR3: "%tr3",
829 TR4: "%tr4",
830 TR5: "%tr5",
831 TR6: "%tr6",
832 TR7: "%tr7",
833 }
834
835 var gnuOp = map[Op]string{
836 CBW: "cbtw",
837 CDQ: "cltd",
838 CMPSD: "cmpsl",
839 CMPSD_XMM: "cmpsd",
840 CWD: "cwtd",
841 CWDE: "cwtl",
842 CQO: "cqto",
843 INSD: "insl",
844 IRET: "iretw",
845 IRETD: "iret",
846 IRETQ: "iretq",
847 LODSB: "lods",
848 LODSD: "lods",
849 LODSQ: "lods",
850 LODSW: "lods",
851 MOVSD: "movsl",
852 MOVSD_XMM: "movsd",
853 OUTSD: "outsl",
854 POPA: "popaw",
855 POPAD: "popa",
856 POPF: "popfw",
857 POPFD: "popf",
858 PUSHA: "pushaw",
859 PUSHAD: "pusha",
860 PUSHF: "pushfw",
861 PUSHFD: "pushf",
862 SCASB: "scas",
863 SCASD: "scas",
864 SCASQ: "scas",
865 SCASW: "scas",
866 STOSB: "stos",
867 STOSD: "stos",
868 STOSQ: "stos",
869 STOSW: "stos",
870 XLATB: "xlat",
871 }
872
873 var cmppsOps = []string{
874 "cmpeq",
875 "cmplt",
876 "cmple",
877 "cmpunord",
878 "cmpneq",
879 "cmpnlt",
880 "cmpnle",
881 "cmpord",
882 }
883
884 var pclmulqOps = []string{
885 "pclmullqlqdq",
886 "pclmulhqlqdq",
887 "pclmullqhqdq",
888 "pclmulhqhqdq",
889 }
890
891 func countPrefix(inst *Inst, target Prefix) int {
892 n := 0
893 for _, p := range inst.Prefix {
894 if p&0xFF == target&0xFF {
895 n++
896 }
897 }
898 return n
899 }
900
901 func markLastImplicit(inst *Inst, prefix Prefix) bool {
902 for i := len(inst.Prefix) - 1; i >= 0; i-- {
903 p := inst.Prefix[i]
904 if p&0xFF == prefix {
905 inst.Prefix[i] |= PrefixImplicit
906 return true
907 }
908 }
909 return false
910 }
911
912 func unmarkImplicit(inst *Inst, prefix Prefix) {
913 for i := len(inst.Prefix) - 1; i >= 0; i-- {
914 p := inst.Prefix[i]
915 if p&0xFF == prefix {
916 inst.Prefix[i] &^= PrefixImplicit
917 }
918 }
919 }
920
921 func byteSizeSuffix(b int) string {
922 switch b {
923 case 1:
924 return "b"
925 case 2:
926 return "w"
927 case 4:
928 return "l"
929 case 8:
930 return "q"
931 }
932 return ""
933 }
934
935 func argBytes(inst *Inst, arg Arg) int {
936 if isMem(arg) {
937 return inst.MemBytes
938 }
939 return regBytes(arg)
940 }
941
942 func isFloat(op Op) bool {
943 switch op {
944 case FADD, FCOM, FCOMP, FDIV, FDIVR, FIADD, FICOM, FICOMP, FIDIV, FIDIVR, FILD, FIMUL, FIST, FISTP, FISTTP, FISUB, FISUBR, FLD, FMUL, FST, FSTP, FSUB, FSUBR:
945 return true
946 }
947 return false
948 }
949
950 func isFloatInt(op Op) bool {
951 switch op {
952 case FIADD, FICOM, FICOMP, FIDIV, FIDIVR, FILD, FIMUL, FIST, FISTP, FISTTP, FISUB, FISUBR:
953 return true
954 }
955 return false
956 }
957