summaryrefslogtreecommitdiff
path: root/vendor/golang.org/x/arch/x86/x86asm/gnu.go
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/golang.org/x/arch/x86/x86asm/gnu.go')
-rw-r--r--vendor/golang.org/x/arch/x86/x86asm/gnu.go956
1 files changed, 0 insertions, 956 deletions
diff --git a/vendor/golang.org/x/arch/x86/x86asm/gnu.go b/vendor/golang.org/x/arch/x86/x86asm/gnu.go
deleted file mode 100644
index 8eba1fd0c..000000000
--- a/vendor/golang.org/x/arch/x86/x86asm/gnu.go
+++ /dev/null
@@ -1,956 +0,0 @@
-// Copyright 2014 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package x86asm
-
-import (
- "fmt"
- "strings"
-)
-
-// GNUSyntax returns the GNU assembler syntax for the instruction, as defined by GNU binutils.
-// This general form is often called “AT&T syntax” as a reference to AT&T System V Unix.
-func GNUSyntax(inst Inst, pc uint64, symname SymLookup) string {
- // Rewrite instruction to mimic GNU peculiarities.
- // Note that inst has been passed by value and contains
- // no pointers, so any changes we make here are local
- // and will not propagate back out to the caller.
-
- if symname == nil {
- symname = func(uint64) (string, uint64) { return "", 0 }
- }
-
- // Adjust opcode [sic].
- switch inst.Op {
- case FDIV, FDIVR, FSUB, FSUBR, FDIVP, FDIVRP, FSUBP, FSUBRP:
- // DC E0, DC F0: libopcodes swaps FSUBR/FSUB and FDIVR/FDIV, at least
- // if you believe the Intel manual is correct (the encoding is irregular as given;
- // libopcodes uses the more regular expected encoding).
- // TODO(rsc): Test to ensure Intel manuals are correct and report to libopcodes maintainers?
- // NOTE: iant thinks this is deliberate, but we can't find the history.
- _, reg1 := inst.Args[0].(Reg)
- _, reg2 := inst.Args[1].(Reg)
- if reg1 && reg2 && (inst.Opcode>>24 == 0xDC || inst.Opcode>>24 == 0xDE) {
- switch inst.Op {
- case FDIV:
- inst.Op = FDIVR
- case FDIVR:
- inst.Op = FDIV
- case FSUB:
- inst.Op = FSUBR
- case FSUBR:
- inst.Op = FSUB
- case FDIVP:
- inst.Op = FDIVRP
- case FDIVRP:
- inst.Op = FDIVP
- case FSUBP:
- inst.Op = FSUBRP
- case FSUBRP:
- inst.Op = FSUBP
- }
- }
-
- case MOVNTSD:
- // MOVNTSD is F2 0F 2B /r.
- // MOVNTSS is F3 0F 2B /r (supposedly; not in manuals).
- // Usually inner prefixes win for display,
- // so that F3 F2 0F 2B 11 is REP MOVNTSD
- // and F2 F3 0F 2B 11 is REPN MOVNTSS.
- // Libopcodes always prefers MOVNTSS regardless of prefix order.
- if countPrefix(&inst, 0xF3) > 0 {
- found := false
- for i := len(inst.Prefix) - 1; i >= 0; i-- {
- switch inst.Prefix[i] & 0xFF {
- case 0xF3:
- if !found {
- found = true
- inst.Prefix[i] |= PrefixImplicit
- }
- case 0xF2:
- inst.Prefix[i] &^= PrefixImplicit
- }
- }
- inst.Op = MOVNTSS
- }
- }
-
- // Add implicit arguments.
- switch inst.Op {
- case MONITOR:
- inst.Args[0] = EDX
- inst.Args[1] = ECX
- inst.Args[2] = EAX
- if inst.AddrSize == 16 {
- inst.Args[2] = AX
- }
-
- case MWAIT:
- if inst.Mode == 64 {
- inst.Args[0] = RCX
- inst.Args[1] = RAX
- } else {
- inst.Args[0] = ECX
- inst.Args[1] = EAX
- }
- }
-
- // Adjust which prefixes will be displayed.
- // The rule is to display all the prefixes not implied by
- // the usual instruction display, that is, all the prefixes
- // except the ones with PrefixImplicit set.
- // However, of course, there are exceptions to the rule.
- switch inst.Op {
- case CRC32:
- // CRC32 has a mandatory F2 prefix.
- // If there are multiple F2s and no F3s, the extra F2s do not print.
- // (And Decode has already marked them implicit.)
- // However, if there is an F3 anywhere, then the extra F2s do print.
- // If there are multiple F2 prefixes *and* an (ignored) F3,
- // then libopcodes prints the extra F2s as REPNs.
- if countPrefix(&inst, 0xF2) > 1 {
- unmarkImplicit(&inst, 0xF2)
- markLastImplicit(&inst, 0xF2)
- }
-
- // An unused data size override should probably be shown,
- // to distinguish DATA16 CRC32B from plain CRC32B,
- // but libopcodes always treats the final override as implicit
- // and the others as explicit.
- unmarkImplicit(&inst, PrefixDataSize)
- markLastImplicit(&inst, PrefixDataSize)
-
- case CVTSI2SD, CVTSI2SS:
- if !isMem(inst.Args[1]) {
- markLastImplicit(&inst, PrefixDataSize)
- }
-
- case CVTSD2SI, CVTSS2SI, CVTTSD2SI, CVTTSS2SI,
- ENTER, FLDENV, FNSAVE, FNSTENV, FRSTOR, LGDT, LIDT, LRET,
- POP, PUSH, RET, SGDT, SIDT, SYSRET, XBEGIN:
- markLastImplicit(&inst, PrefixDataSize)
-
- case LOOP, LOOPE, LOOPNE, MONITOR:
- markLastImplicit(&inst, PrefixAddrSize)
-
- case MOV:
- // The 16-bit and 32-bit forms of MOV Sreg, dst and MOV src, Sreg
- // cannot be distinguished when src or dst refers to memory, because
- // Sreg is always a 16-bit value, even when we're doing a 32-bit
- // instruction. Because the instruction tables distinguished these two,
- // any operand size prefix has been marked as used (to decide which
- // branch to take). Unmark it, so that it will show up in disassembly,
- // so that the reader can tell the size of memory operand.
- // up with the same arguments
- dst, _ := inst.Args[0].(Reg)
- src, _ := inst.Args[1].(Reg)
- if ES <= src && src <= GS && isMem(inst.Args[0]) || ES <= dst && dst <= GS && isMem(inst.Args[1]) {
- unmarkImplicit(&inst, PrefixDataSize)
- }
-
- case MOVDQU:
- if countPrefix(&inst, 0xF3) > 1 {
- unmarkImplicit(&inst, 0xF3)
- markLastImplicit(&inst, 0xF3)
- }
-
- case MOVQ2DQ:
- markLastImplicit(&inst, PrefixDataSize)
-
- case SLDT, SMSW, STR, FXRSTOR, XRSTOR, XSAVE, XSAVEOPT, CMPXCHG8B:
- if isMem(inst.Args[0]) {
- unmarkImplicit(&inst, PrefixDataSize)
- }
-
- case SYSEXIT:
- unmarkImplicit(&inst, PrefixDataSize)
- }
-
- if isCondJmp[inst.Op] || isLoop[inst.Op] || inst.Op == JCXZ || inst.Op == JECXZ || inst.Op == JRCXZ {
- if countPrefix(&inst, PrefixCS) > 0 && countPrefix(&inst, PrefixDS) > 0 {
- for i, p := range inst.Prefix {
- switch p & 0xFFF {
- case PrefixPN, PrefixPT:
- inst.Prefix[i] &= 0xF0FF // cut interpretation bits, producing original segment prefix
- }
- }
- }
- }
-
- // XACQUIRE/XRELEASE adjustment.
- if inst.Op == MOV {
- // MOV into memory is a candidate for turning REP into XRELEASE.
- // However, if the REP is followed by a REPN, that REPN blocks the
- // conversion.
- haveREPN := false
- for i := len(inst.Prefix) - 1; i >= 0; i-- {
- switch inst.Prefix[i] &^ PrefixIgnored {
- case PrefixREPN:
- haveREPN = true
- case PrefixXRELEASE:
- if haveREPN {
- inst.Prefix[i] = PrefixREP
- }
- }
- }
- }
-
- // We only format the final F2/F3 as XRELEASE/XACQUIRE.
- haveXA := false
- haveXR := false
- for i := len(inst.Prefix) - 1; i >= 0; i-- {
- switch inst.Prefix[i] &^ PrefixIgnored {
- case PrefixXRELEASE:
- if !haveXR {
- haveXR = true
- } else {
- inst.Prefix[i] = PrefixREP
- }
-
- case PrefixXACQUIRE:
- if !haveXA {
- haveXA = true
- } else {
- inst.Prefix[i] = PrefixREPN
- }
- }
- }
-
- // Determine opcode.
- op := strings.ToLower(inst.Op.String())
- if alt := gnuOp[inst.Op]; alt != "" {
- op = alt
- }
-
- // Determine opcode suffix.
- // Libopcodes omits the suffix if the width of the operation
- // can be inferred from a register arguments. For example,
- // add $1, %ebx has no suffix because you can tell from the
- // 32-bit register destination that it is a 32-bit add,
- // but in addl $1, (%ebx), the destination is memory, so the
- // size is not evident without the l suffix.
- needSuffix := true
-SuffixLoop:
- for i, a := range inst.Args {
- if a == nil {
- break
- }
- switch a := a.(type) {
- case Reg:
- switch inst.Op {
- case MOVSX, MOVZX:
- continue
-
- case SHL, SHR, RCL, RCR, ROL, ROR, SAR:
- if i == 1 {
- // shift count does not tell us operand size
- continue
- }
-
- case CRC32:
- // The source argument does tell us operand size,
- // but libopcodes still always puts a suffix on crc32.
- continue
-
- case PUSH, POP:
- // Even though segment registers are 16-bit, push and pop
- // can save/restore them from 32-bit slots, so they
- // do not imply operand size.
- if ES <= a && a <= GS {
- continue
- }
-
- case CVTSI2SD, CVTSI2SS:
- // The integer register argument takes priority.
- if X0 <= a && a <= X15 {
- continue
- }
- }
-
- if AL <= a && a <= R15 || ES <= a && a <= GS || X0 <= a && a <= X15 || M0 <= a && a <= M7 {
- needSuffix = false
- break SuffixLoop
- }
- }
- }
-
- if needSuffix {
- switch inst.Op {
- case CMPXCHG8B, FLDCW, FNSTCW, FNSTSW, LDMXCSR, LLDT, LMSW, LTR, PCLMULQDQ,
- SETA, SETAE, SETB, SETBE, SETE, SETG, SETGE, SETL, SETLE, SETNE, SETNO, SETNP, SETNS, SETO, SETP, SETS,
- SLDT, SMSW, STMXCSR, STR, VERR, VERW:
- // For various reasons, libopcodes emits no suffix for these instructions.
-
- case CRC32:
- op += byteSizeSuffix(argBytes(&inst, inst.Args[1]))
-
- case LGDT, LIDT, SGDT, SIDT:
- op += byteSizeSuffix(inst.DataSize / 8)
-
- case MOVZX, MOVSX:
- // Integer size conversions get two suffixes.
- op = op[:4] + byteSizeSuffix(argBytes(&inst, inst.Args[1])) + byteSizeSuffix(argBytes(&inst, inst.Args[0]))
-
- case LOOP, LOOPE, LOOPNE:
- // Add w suffix to indicate use of CX register instead of ECX.
- if inst.AddrSize == 16 {
- op += "w"
- }
-
- case CALL, ENTER, JMP, LCALL, LEAVE, LJMP, LRET, RET, SYSRET, XBEGIN:
- // Add w suffix to indicate use of 16-bit target.
- // Exclude JMP rel8.
- if inst.Opcode>>24 == 0xEB {
- break
- }
- if inst.DataSize == 16 && inst.Mode != 16 {
- markLastImplicit(&inst, PrefixDataSize)
- op += "w"
- } else if inst.Mode == 64 {
- op += "q"
- }
-
- case FRSTOR, FNSAVE, FNSTENV, FLDENV:
- // Add s suffix to indicate shortened FPU state (I guess).
- if inst.DataSize == 16 {
- op += "s"
- }
-
- case PUSH, POP:
- if markLastImplicit(&inst, PrefixDataSize) {
- op += byteSizeSuffix(inst.DataSize / 8)
- } else if inst.Mode == 64 {
- op += "q"
- } else {
- op += byteSizeSuffix(inst.MemBytes)
- }
-
- default:
- if isFloat(inst.Op) {
- // I can't explain any of this, but it's what libopcodes does.
- switch inst.MemBytes {
- default:
- if (inst.Op == FLD || inst.Op == FSTP) && isMem(inst.Args[0]) {
- op += "t"
- }
- case 4:
- if isFloatInt(inst.Op) {
- op += "l"
- } else {
- op += "s"
- }
- case 8:
- if isFloatInt(inst.Op) {
- op += "ll"
- } else {
- op += "l"
- }
- }
- break
- }
-
- op += byteSizeSuffix(inst.MemBytes)
- }
- }
-
- // Adjust special case opcodes.
- switch inst.Op {
- case 0:
- if inst.Prefix[0] != 0 {
- return strings.ToLower(inst.Prefix[0].String())
- }
-
- case INT:
- if inst.Opcode>>24 == 0xCC {
- inst.Args[0] = nil
- op = "int3"
- }
-
- case CMPPS, CMPPD, CMPSD_XMM, CMPSS:
- imm, ok := inst.Args[2].(Imm)
- if ok && 0 <= imm && imm < 8 {
- inst.Args[2] = nil
- op = cmppsOps[imm] + op[3:]
- }
-
- case PCLMULQDQ:
- imm, ok := inst.Args[2].(Imm)
- if ok && imm&^0x11 == 0 {
- inst.Args[2] = nil
- op = pclmulqOps[(imm&0x10)>>3|(imm&1)]
- }
-
- case XLATB:
- if markLastImplicit(&inst, PrefixAddrSize) {
- op = "xlat" // not xlatb
- }
- }
-
- // Build list of argument strings.
- var (
- usedPrefixes bool // segment prefixes consumed by Mem formatting
- args []string // formatted arguments
- )
- for i, a := range inst.Args {
- if a == nil {
- break
- }
- switch inst.Op {
- case MOVSB, MOVSW, MOVSD, MOVSQ, OUTSB, OUTSW, OUTSD:
- if i == 0 {
- usedPrefixes = true // disable use of prefixes for first argument
- } else {
- usedPrefixes = false
- }
- }
- if a == Imm(1) && (inst.Opcode>>24)&^1 == 0xD0 {
- continue
- }
- args = append(args, gnuArg(&inst, pc, symname, a, &usedPrefixes))
- }
-
- // The default is to print the arguments in reverse Intel order.
- // A few instructions inhibit this behavior.
- switch inst.Op {
- case BOUND, LCALL, ENTER, LJMP:
- // no reverse
- default:
- // reverse args
- for i, j := 0, len(args)-1; i < j; i, j = i+1, j-1 {
- args[i], args[j] = args[j], args[i]
- }
- }
-
- // Build prefix string.
- // Must be after argument formatting, which can turn off segment prefixes.
- var (
- prefix = "" // output string
- numAddr = 0
- numData = 0
- implicitData = false
- )
- for _, p := range inst.Prefix {
- if p&0xFF == PrefixDataSize && p&PrefixImplicit != 0 {
- implicitData = true
- }
- }
- for _, p := range inst.Prefix {
- if p == 0 || p.IsVEX() {
- break
- }
- if p&PrefixImplicit != 0 {
- continue
- }
- switch p &^ (PrefixIgnored | PrefixInvalid) {
- default:
- if p.IsREX() {
- if p&0xFF == PrefixREX {
- prefix += "rex "
- } else {
- prefix += "rex." + p.String()[4:] + " "
- }
- break
- }
- prefix += strings.ToLower(p.String()) + " "
-
- case PrefixPN:
- op += ",pn"
- continue
-
- case PrefixPT:
- op += ",pt"
- continue
-
- case PrefixAddrSize, PrefixAddr16, PrefixAddr32:
- // For unknown reasons, if the addr16 prefix is repeated,
- // libopcodes displays all but the last as addr32, even though
- // the addressing form used in a memory reference is clearly
- // still 16-bit.
- n := 32
- if inst.Mode == 32 {
- n = 16
- }
- numAddr++
- if countPrefix(&inst, PrefixAddrSize) > numAddr {
- n = inst.Mode
- }
- prefix += fmt.Sprintf("addr%d ", n)
- continue
-
- case PrefixData16, PrefixData32:
- if implicitData && countPrefix(&inst, PrefixDataSize) > 1 {
- // Similar to the addr32 logic above, but it only kicks in
- // when something used the data size prefix (one is implicit).
- n := 16
- if inst.Mode == 16 {
- n = 32
- }
- numData++
- if countPrefix(&inst, PrefixDataSize) > numData {
- if inst.Mode == 16 {
- n = 16
- } else {
- n = 32
- }
- }
- prefix += fmt.Sprintf("data%d ", n)
- continue
- }
- prefix += strings.ToLower(p.String()) + " "
- }
- }
-
- // Finally! Put it all together.
- text := prefix + op
- if args != nil {
- text += " "
- // Indirect call/jmp gets a star to distinguish from direct jump address.
- if (inst.Op == CALL || inst.Op == JMP || inst.Op == LJMP || inst.Op == LCALL) && (isMem(inst.Args[0]) || isReg(inst.Args[0])) {
- text += "*"
- }
- text += strings.Join(args, ",")
- }
- return text
-}
-
-// gnuArg returns the GNU syntax for the argument x from the instruction inst.
-// If *usedPrefixes is false and x is a Mem, then the formatting
-// includes any segment prefixes and sets *usedPrefixes to true.
-func gnuArg(inst *Inst, pc uint64, symname SymLookup, x Arg, usedPrefixes *bool) string {
- if x == nil {
- return "<nil>"
- }
- switch x := x.(type) {
- case Reg:
- switch inst.Op {
- case CVTSI2SS, CVTSI2SD, CVTSS2SI, CVTSD2SI, CVTTSD2SI, CVTTSS2SI:
- if inst.DataSize == 16 && EAX <= x && x <= R15L {
- x -= EAX - AX
- }
-
- case IN, INSB, INSW, INSD, OUT, OUTSB, OUTSW, OUTSD:
- // DX is the port, but libopcodes prints it as if it were a memory reference.
- if x == DX {
- return "(%dx)"
- }
- case VMOVDQA, VMOVDQU, VMOVNTDQA, VMOVNTDQ:
- return strings.Replace(gccRegName[x], "xmm", "ymm", -1)
- }
- return gccRegName[x]
- case Mem:
- if s, disp := memArgToSymbol(x, pc, inst.Len, symname); s != "" {
- suffix := ""
- if disp != 0 {
- suffix = fmt.Sprintf("%+d", disp)
- }
- return fmt.Sprintf("%s%s", s, suffix)
- }
- seg := ""
- var haveCS, haveDS, haveES, haveFS, haveGS, haveSS bool
- switch x.Segment {
- case CS:
- haveCS = true
- case DS:
- haveDS = true
- case ES:
- haveES = true
- case FS:
- haveFS = true
- case GS:
- haveGS = true
- case SS:
- haveSS = true
- }
- switch inst.Op {
- case INSB, INSW, INSD, STOSB, STOSW, STOSD, STOSQ, SCASB, SCASW, SCASD, SCASQ:
- // These do not accept segment prefixes, at least in the GNU rendering.
- default:
- if *usedPrefixes {
- break
- }
- for i := len(inst.Prefix) - 1; i >= 0; i-- {
- p := inst.Prefix[i] &^ PrefixIgnored
- if p == 0 {
- continue
- }
- switch p {
- case PrefixCS:
- if !haveCS {
- haveCS = true
- inst.Prefix[i] |= PrefixImplicit
- }
- case PrefixDS:
- if !haveDS {
- haveDS = true
- inst.Prefix[i] |= PrefixImplicit
- }
- case PrefixES:
- if !haveES {
- haveES = true
- inst.Prefix[i] |= PrefixImplicit
- }
- case PrefixFS:
- if !haveFS {
- haveFS = true
- inst.Prefix[i] |= PrefixImplicit
- }
- case PrefixGS:
- if !haveGS {
- haveGS = true
- inst.Prefix[i] |= PrefixImplicit
- }
- case PrefixSS:
- if !haveSS {
- haveSS = true
- inst.Prefix[i] |= PrefixImplicit
- }
- }
- }
- *usedPrefixes = true
- }
- if haveCS {
- seg += "%cs:"
- }
- if haveDS {
- seg += "%ds:"
- }
- if haveSS {
- seg += "%ss:"
- }
- if haveES {
- seg += "%es:"
- }
- if haveFS {
- seg += "%fs:"
- }
- if haveGS {
- seg += "%gs:"
- }
- disp := ""
- if x.Disp != 0 {
- disp = fmt.Sprintf("%#x", x.Disp)
- }
- if x.Scale == 0 || x.Index == 0 && x.Scale == 1 && (x.Base == ESP || x.Base == RSP || x.Base == 0 && inst.Mode == 64) {
- if x.Base == 0 {
- return seg + disp
- }
- return fmt.Sprintf("%s%s(%s)", seg, disp, gccRegName[x.Base])
- }
- base := gccRegName[x.Base]
- if x.Base == 0 {
- base = ""
- }
- index := gccRegName[x.Index]
- if x.Index == 0 {
- if inst.AddrSize == 64 {
- index = "%riz"
- } else {
- index = "%eiz"
- }
- }
- if AX <= x.Base && x.Base <= DI {
- // 16-bit addressing - no scale
- return fmt.Sprintf("%s%s(%s,%s)", seg, disp, base, index)
- }
- return fmt.Sprintf("%s%s(%s,%s,%d)", seg, disp, base, index, x.Scale)
- case Rel:
- if pc == 0 {
- return fmt.Sprintf(".%+#x", int64(x))
- } else {
- addr := pc + uint64(inst.Len) + uint64(x)
- if s, base := symname(addr); s != "" && addr == base {
- return fmt.Sprintf("%s", s)
- } else {
- addr := pc + uint64(inst.Len) + uint64(x)
- return fmt.Sprintf("%#x", addr)
- }
- }
- case Imm:
- if s, base := symname(uint64(x)); s != "" {
- suffix := ""
- if uint64(x) != base {
- suffix = fmt.Sprintf("%+d", uint64(x)-base)
- }
- return fmt.Sprintf("$%s%s", s, suffix)
- }
- if inst.Mode == 32 {
- return fmt.Sprintf("$%#x", uint32(x))
- }
- return fmt.Sprintf("$%#x", int64(x))
- }
- return x.String()
-}
-
-var gccRegName = [...]string{
- 0: "REG0",
- AL: "%al",
- CL: "%cl",
- BL: "%bl",
- DL: "%dl",
- AH: "%ah",
- CH: "%ch",
- BH: "%bh",
- DH: "%dh",
- SPB: "%spl",
- BPB: "%bpl",
- SIB: "%sil",
- DIB: "%dil",
- R8B: "%r8b",
- R9B: "%r9b",
- R10B: "%r10b",
- R11B: "%r11b",
- R12B: "%r12b",
- R13B: "%r13b",
- R14B: "%r14b",
- R15B: "%r15b",
- AX: "%ax",
- CX: "%cx",
- BX: "%bx",
- DX: "%dx",
- SP: "%sp",
- BP: "%bp",
- SI: "%si",
- DI: "%di",
- R8W: "%r8w",
- R9W: "%r9w",
- R10W: "%r10w",
- R11W: "%r11w",
- R12W: "%r12w",
- R13W: "%r13w",
- R14W: "%r14w",
- R15W: "%r15w",
- EAX: "%eax",
- ECX: "%ecx",
- EDX: "%edx",
- EBX: "%ebx",
- ESP: "%esp",
- EBP: "%ebp",
- ESI: "%esi",
- EDI: "%edi",
- R8L: "%r8d",
- R9L: "%r9d",
- R10L: "%r10d",
- R11L: "%r11d",
- R12L: "%r12d",
- R13L: "%r13d",
- R14L: "%r14d",
- R15L: "%r15d",
- RAX: "%rax",
- RCX: "%rcx",
- RDX: "%rdx",
- RBX: "%rbx",
- RSP: "%rsp",
- RBP: "%rbp",
- RSI: "%rsi",
- RDI: "%rdi",
- R8: "%r8",
- R9: "%r9",
- R10: "%r10",
- R11: "%r11",
- R12: "%r12",
- R13: "%r13",
- R14: "%r14",
- R15: "%r15",
- IP: "%ip",
- EIP: "%eip",
- RIP: "%rip",
- F0: "%st",
- F1: "%st(1)",
- F2: "%st(2)",
- F3: "%st(3)",
- F4: "%st(4)",
- F5: "%st(5)",
- F6: "%st(6)",
- F7: "%st(7)",
- M0: "%mm0",
- M1: "%mm1",
- M2: "%mm2",
- M3: "%mm3",
- M4: "%mm4",
- M5: "%mm5",
- M6: "%mm6",
- M7: "%mm7",
- X0: "%xmm0",
- X1: "%xmm1",
- X2: "%xmm2",
- X3: "%xmm3",
- X4: "%xmm4",
- X5: "%xmm5",
- X6: "%xmm6",
- X7: "%xmm7",
- X8: "%xmm8",
- X9: "%xmm9",
- X10: "%xmm10",
- X11: "%xmm11",
- X12: "%xmm12",
- X13: "%xmm13",
- X14: "%xmm14",
- X15: "%xmm15",
- CS: "%cs",
- SS: "%ss",
- DS: "%ds",
- ES: "%es",
- FS: "%fs",
- GS: "%gs",
- GDTR: "%gdtr",
- IDTR: "%idtr",
- LDTR: "%ldtr",
- MSW: "%msw",
- TASK: "%task",
- CR0: "%cr0",
- CR1: "%cr1",
- CR2: "%cr2",
- CR3: "%cr3",
- CR4: "%cr4",
- CR5: "%cr5",
- CR6: "%cr6",
- CR7: "%cr7",
- CR8: "%cr8",
- CR9: "%cr9",
- CR10: "%cr10",
- CR11: "%cr11",
- CR12: "%cr12",
- CR13: "%cr13",
- CR14: "%cr14",
- CR15: "%cr15",
- DR0: "%db0",
- DR1: "%db1",
- DR2: "%db2",
- DR3: "%db3",
- DR4: "%db4",
- DR5: "%db5",
- DR6: "%db6",
- DR7: "%db7",
- TR0: "%tr0",
- TR1: "%tr1",
- TR2: "%tr2",
- TR3: "%tr3",
- TR4: "%tr4",
- TR5: "%tr5",
- TR6: "%tr6",
- TR7: "%tr7",
-}
-
-var gnuOp = map[Op]string{
- CBW: "cbtw",
- CDQ: "cltd",
- CMPSD: "cmpsl",
- CMPSD_XMM: "cmpsd",
- CWD: "cwtd",
- CWDE: "cwtl",
- CQO: "cqto",
- INSD: "insl",
- IRET: "iretw",
- IRETD: "iret",
- IRETQ: "iretq",
- LODSB: "lods",
- LODSD: "lods",
- LODSQ: "lods",
- LODSW: "lods",
- MOVSD: "movsl",
- MOVSD_XMM: "movsd",
- OUTSD: "outsl",
- POPA: "popaw",
- POPAD: "popa",
- POPF: "popfw",
- POPFD: "popf",
- PUSHA: "pushaw",
- PUSHAD: "pusha",
- PUSHF: "pushfw",
- PUSHFD: "pushf",
- SCASB: "scas",
- SCASD: "scas",
- SCASQ: "scas",
- SCASW: "scas",
- STOSB: "stos",
- STOSD: "stos",
- STOSQ: "stos",
- STOSW: "stos",
- XLATB: "xlat",
-}
-
-var cmppsOps = []string{
- "cmpeq",
- "cmplt",
- "cmple",
- "cmpunord",
- "cmpneq",
- "cmpnlt",
- "cmpnle",
- "cmpord",
-}
-
-var pclmulqOps = []string{
- "pclmullqlqdq",
- "pclmulhqlqdq",
- "pclmullqhqdq",
- "pclmulhqhqdq",
-}
-
-func countPrefix(inst *Inst, target Prefix) int {
- n := 0
- for _, p := range inst.Prefix {
- if p&0xFF == target&0xFF {
- n++
- }
- }
- return n
-}
-
-func markLastImplicit(inst *Inst, prefix Prefix) bool {
- for i := len(inst.Prefix) - 1; i >= 0; i-- {
- p := inst.Prefix[i]
- if p&0xFF == prefix {
- inst.Prefix[i] |= PrefixImplicit
- return true
- }
- }
- return false
-}
-
-func unmarkImplicit(inst *Inst, prefix Prefix) {
- for i := len(inst.Prefix) - 1; i >= 0; i-- {
- p := inst.Prefix[i]
- if p&0xFF == prefix {
- inst.Prefix[i] &^= PrefixImplicit
- }
- }
-}
-
-func byteSizeSuffix(b int) string {
- switch b {
- case 1:
- return "b"
- case 2:
- return "w"
- case 4:
- return "l"
- case 8:
- return "q"
- }
- return ""
-}
-
-func argBytes(inst *Inst, arg Arg) int {
- if isMem(arg) {
- return inst.MemBytes
- }
- return regBytes(arg)
-}
-
-func isFloat(op Op) bool {
- switch op {
- case FADD, FCOM, FCOMP, FDIV, FDIVR, FIADD, FICOM, FICOMP, FIDIV, FIDIVR, FILD, FIMUL, FIST, FISTP, FISTTP, FISUB, FISUBR, FLD, FMUL, FST, FSTP, FSUB, FSUBR:
- return true
- }
- return false
-}
-
-func isFloatInt(op Op) bool {
- switch op {
- case FIADD, FICOM, FICOMP, FIDIV, FIDIVR, FILD, FIMUL, FIST, FISTP, FISTTP, FISUB, FISUBR:
- return true
- }
- return false
-}