...

Source file src/cmd/vendor/golang.org/x/arch/x86/x86asm/gnu.go

     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	

View as plain text