gnu.go (21908B)
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 }