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 ANDN, BEXTR, BLSI, BLSMSK, BLSR,
   257  				BZHI, MULX, PDEP, PEXT, RORX, SARX, SHLX, SHRX:
   258  				// The register arguments do tell us operand size, but
   259  				// libopcodes still always puts a suffix on the BMI1 and
   260  				// BMI2 instructions.
   261  				continue
   262  
   263  			case PUSH, POP:
   264  				// Even though segment registers are 16-bit, push and pop
   265  				// can save/restore them from 32-bit slots, so they
   266  				// do not imply operand size.
   267  				if ES <= a && a <= GS {
   268  					continue
   269  				}
   270  
   271  			case CVTSI2SD, CVTSI2SS:
   272  				// The integer register argument takes priority.
   273  				if X0 <= a && a <= X15 {
   274  					continue
   275  				}
   276  			}
   277  
   278  			if AL <= a && a <= R15 || ES <= a && a <= GS || X0 <= a && a <= Z31 || M0 <= a && a <= M7 || K0 <= a && a <= K7 {
   279  				needSuffix = false
   280  				break SuffixLoop
   281  			}
   282  		}
   283  	}
   284  
   285  	if needSuffix {
   286  		switch inst.Op {
   287  		case CMPXCHG8B, FLDCW, FNSTCW, FNSTSW, LDMXCSR, LLDT, LMSW, LTR, PCLMULQDQ,
   288  			SETA, SETAE, SETB, SETBE, SETE, SETG, SETGE, SETL, SETLE, SETNE, SETNO, SETNP, SETNS, SETO, SETP, SETS,
   289  			SLDT, SMSW, STMXCSR, STR, VERR, VERW, VLDMXCSR, VSTMXCSR:
   290  			// For various reasons, libopcodes emits no suffix for these instructions.
   291  
   292  		case CRC32:
   293  			op += byteSizeSuffix(argBytes(&inst, inst.Args[1]))
   294  
   295  		case ANDN, BEXTR, BLSI, BLSMSK, BLSR, BZHI, MULX, PDEP, PEXT, RORX, SARX, SHLX, SHRX:
   296  			op += byteSizeSuffix(inst.DataSize / 8)
   297  
   298  		case LGDT, LIDT, SGDT, SIDT:
   299  			op += byteSizeSuffix(inst.DataSize / 8)
   300  
   301  		case MOVZX, MOVSX:
   302  			// Integer size conversions get two suffixes.
   303  			op = op[:4] + byteSizeSuffix(argBytes(&inst, inst.Args[1])) + byteSizeSuffix(argBytes(&inst, inst.Args[0]))
   304  
   305  		case LOOP, LOOPE, LOOPNE:
   306  			// Add w suffix to indicate use of CX register instead of ECX.
   307  			if inst.AddrSize == 16 {
   308  				op += "w"
   309  			}
   310  
   311  		case CALL, ENTER, JMP, LCALL, LEAVE, LJMP, LRET, RET, SYSRET, XBEGIN:
   312  			// Add w suffix to indicate use of 16-bit target.
   313  			// Exclude JMP rel8.
   314  			if inst.Opcode>>24 == 0xEB {
   315  				break
   316  			}
   317  			if inst.DataSize == 16 && inst.Mode != 16 {
   318  				markLastImplicit(&inst, PrefixDataSize)
   319  				op += "w"
   320  			} else if inst.Mode == 64 {
   321  				op += "q"
   322  			}
   323  
   324  		case FRSTOR, FNSAVE, FNSTENV, FLDENV:
   325  			// Add s suffix to indicate shortened FPU state (I guess).
   326  			if inst.DataSize == 16 {
   327  				op += "s"
   328  			}
   329  
   330  		case PUSH, POP:
   331  			if markLastImplicit(&inst, PrefixDataSize) {
   332  				op += byteSizeSuffix(inst.DataSize / 8)
   333  			} else if inst.Mode == 64 {
   334  				op += "q"
   335  			} else {
   336  				op += byteSizeSuffix(inst.MemBytes)
   337  			}
   338  
   339  		default:
   340  			if isFloat(inst.Op) {
   341  				// I can't explain any of this, but it's what libopcodes does.
   342  				switch inst.MemBytes {
   343  				default:
   344  					if (inst.Op == FLD || inst.Op == FSTP) && isMem(inst.Args[0]) {
   345  						op += "t"
   346  					}
   347  				case 4:
   348  					if isFloatInt(inst.Op) {
   349  						op += "l"
   350  					} else {
   351  						op += "s"
   352  					}
   353  				case 8:
   354  					if isFloatInt(inst.Op) {
   355  						op += "ll"
   356  					} else {
   357  						op += "l"
   358  					}
   359  				}
   360  				break
   361  			}
   362  
   363  			op += byteSizeSuffix(inst.MemBytes)
   364  		}
   365  	}
   366  
   367  	isVexOrEvex := false
   368  	for _, p := range inst.Prefix {
   369  		if p.IsVEX() || p&0xFF == 0x62 {
   370  			isVexOrEvex = true
   371  			break
   372  		}
   373  	}
   374  	if isVexOrEvex {
   375  		hasMem := false
   376  		for _, a := range inst.Args {
   377  			if _, ok := a.(Mem); ok {
   378  				hasMem = true
   379  				break
   380  			}
   381  		}
   382  		if hasMem {
   383  			if inst.Op == VFPCLASSPD || inst.Op == VFPCLASSPS || inst.Op == VCVTTPD2DQ || inst.Op == VCVTTPD2UDQ || inst.Op == VCVTTPD2QQ || inst.Op == VCVTTPD2UQQ || inst.Op == VCVTPD2DQ || inst.Op == VCVTPD2UDQ || inst.Op == VCVTPD2QQ || inst.Op == VCVTPD2UQQ || inst.Op == VCVTPD2PS {
   384  				vexL := 0
   385  				isEvex := false
   386  				for i, p := range inst.Prefix {
   387  					if p.IsEVEX() && i+3 < len(inst.Prefix) && inst.Prefix[i+3] != 0 {
   388  						vexL = int((inst.Prefix[i+3]&0xFF)>>5) & 3
   389  						isEvex = true
   390  						break
   391  					} else if p.IsVEX() && i+2 < len(inst.Prefix) {
   392  						if p&0xFF == 0xC4 {
   393  							vexL = int((inst.Prefix[i+2]&0xFF)>>2) & 1
   394  						} else if p&0xFF == 0xC5 {
   395  							vexL = int((inst.Prefix[i+1]&0xFF)>>2) & 1
   396  						}
   397  						break
   398  					}
   399  				}
   400  				if !isEvex || inst.Op == VFPCLASSPD || inst.Op == VFPCLASSPS || inst.Op == VCVTPD2DQ {
   401  					switch vexL {
   402  					case 0:
   403  						op += "x"
   404  					case 1:
   405  						if inst.Op != VCMPPD && inst.Op != VCMPPS && inst.Op != VCMPPH && inst.Op != VCMPBF16 {
   406  							op += "y"
   407  						}
   408  					case 2:
   409  						if inst.Op != VCMPPD && inst.Op != VCMPPS && inst.Op != VCMPPH && inst.Op != VCMPBF16 {
   410  							op += "z"
   411  						}
   412  					}
   413  				}
   414  			} else if inst.Op == VCVTSI2SD || inst.Op == VCVTSI2SS {
   415  				is64 := false
   416  				if (inst.Op == VCVTSI2SD || inst.Op == VCVTSI2SS) && inst.MemBytes == 8 {
   417  					is64 = true
   418  				} else {
   419  					for _, a := range inst.Args {
   420  						if r, ok := a.(Reg); ok && RAX <= r && r <= R15 {
   421  							is64 = true
   422  							break
   423  						}
   424  					}
   425  				}
   426  				if is64 {
   427  					op += "q"
   428  				} else {
   429  					op += "l"
   430  				}
   431  			}
   432  		}
   433  	}
   434  
   435  	// Adjust special case opcodes.
   436  	switch inst.Op {
   437  	case 0:
   438  		if inst.Prefix[0] != 0 {
   439  			return strings.ToLower(inst.Prefix[0].String())
   440  		}
   441  
   442  	case INT:
   443  		if inst.Opcode>>24 == 0xCC {
   444  			inst.Args[0] = nil
   445  			op = "int3"
   446  		}
   447  
   448  	case CMPPS, CMPPD, CMPSD_XMM, CMPSS:
   449  		imm, ok := inst.Args[2].(Imm)
   450  		if ok && 0 <= imm && imm < 8 {
   451  			inst.Args[2] = nil
   452  			op = cmppsOps[imm] + op[3:]
   453  		}
   454  
   455  	case VCMPPD, VCMPPS, VCMPSD, VCMPSS, VCMPPH, VCMPSH, VCMPBF16:
   456  		for i := len(inst.Args) - 1; i >= 0; i-- {
   457  			if imm, ok := inst.Args[i].(Imm); ok {
   458  				if 0 <= imm && imm < 8 {
   459  					inst.Args[i] = nil
   460  					op = "v" + cmppsOps[imm] + op[4:]
   461  				}
   462  				break
   463  			}
   464  			if inst.Args[i] != nil {
   465  				break
   466  			}
   467  		}
   468  
   469  	case PCLMULQDQ:
   470  		imm, ok := inst.Args[2].(Imm)
   471  		if ok && imm&^0x11 == 0 {
   472  			inst.Args[2] = nil
   473  			op = pclmulqOps[(imm&0x10)>>3|(imm&1)]
   474  		}
   475  
   476  	case XLATB:
   477  		if markLastImplicit(&inst, PrefixAddrSize) {
   478  			op = "xlat" // not xlatb
   479  		}
   480  	}
   481  
   482  	// Build list of argument strings.
   483  	var (
   484  		usedPrefixes bool     // segment prefixes consumed by Mem formatting
   485  		args         []string // formatted arguments
   486  	)
   487  	for i, a := range inst.Args {
   488  		if a == nil {
   489  			break
   490  		}
   491  		switch inst.Op {
   492  		case MOVSB, MOVSW, MOVSD, MOVSQ, OUTSB, OUTSW, OUTSD:
   493  			if i == 0 {
   494  				usedPrefixes = true // disable use of prefixes for first argument
   495  			} else {
   496  				usedPrefixes = false
   497  			}
   498  		}
   499  		if a == Imm(1) && (inst.Opcode>>24)&^1 == 0xD0 {
   500  			continue
   501  		}
   502  		argStr := gnuArg(&inst, pc, symname, a, &usedPrefixes)
   503  		if i == 1 {
   504  			r, ok := a.(Reg)
   505  			// In GNU syntax, the mask register usually appears as the second argument (index 1).
   506  			if ok && K1 <= r && r <= K7 {
   507  				if !strings.HasPrefix(inst.Op.String(), "K") {
   508  					if len(args) > 0 {
   509  						args[0] += fmt.Sprintf(" {%s}", argStr)
   510  						if inst.Zeroing {
   511  							args[0] += " {z}"
   512  						}
   513  					}
   514  					continue
   515  				}
   516  			} else if ok && r == K0 {
   517  				if !strings.HasPrefix(inst.Op.String(), "K") {
   518  					if inst.Zeroing && len(args) > 0 {
   519  						args[0] += "{z}"
   520  					}
   521  					continue
   522  				}
   523  			}
   524  		}
   525  		if _, ok := a.(Mem); ok && inst.Broadcast && len(args) > 0 {
   526  			if dstReg, ok := inst.Args[0].(Reg); ok {
   527  				var vBytes int
   528  				if X0 <= dstReg && dstReg <= X31 {
   529  					vBytes = 16
   530  				} else if Y0 <= dstReg && dstReg <= Y31 {
   531  					vBytes = 32
   532  				} else if Z0 <= dstReg && dstReg <= Z31 {
   533  					vBytes = 64
   534  				}
   535  				if vBytes > 0 && inst.MemBytes > 0 {
   536  					argStr += fmt.Sprintf("{1to%d}", vBytes/inst.MemBytes)
   537  				}
   538  			}
   539  		}
   540  		args = append(args, argStr)
   541  	}
   542  
   543  	if inst.SAE {
   544  		var sae string
   545  		if hasRC(inst.Op) {
   546  			switch inst.Rounding {
   547  			case 0:
   548  				sae = "{rn-sae}"
   549  			case 1:
   550  				sae = "{rd-sae}"
   551  			case 2:
   552  				sae = "{ru-sae}"
   553  			case 3:
   554  				sae = "{rz-sae}"
   555  			}
   556  		} else {
   557  			sae = "{sae}"
   558  		}
   559  		args = append(args, sae)
   560  	}
   561  
   562  	// The default is to print the arguments in reverse Intel order.
   563  	// A few instructions inhibit this behavior.
   564  	switch inst.Op {
   565  	case BOUND, LCALL, ENTER, LJMP:
   566  		// no reverse
   567  	default:
   568  		// reverse args
   569  		for i, j := 0, len(args)-1; i < j; i, j = i+1, j-1 {
   570  			args[i], args[j] = args[j], args[i]
   571  		}
   572  	}
   573  
   574  	// Build prefix string.
   575  	// Must be after argument formatting, which can turn off segment prefixes.
   576  	var (
   577  		prefix       = "" // output string
   578  		numAddr      = 0
   579  		numData      = 0
   580  		implicitData = false
   581  	)
   582  	for _, p := range inst.Prefix {
   583  		if p&0xFF == PrefixDataSize && p&PrefixImplicit != 0 {
   584  			implicitData = true
   585  		}
   586  	}
   587  	for _, p := range inst.Prefix {
   588  		if p == 0 || p.IsVEX() || p.IsEVEX() {
   589  			break
   590  		}
   591  		if p&PrefixImplicit != 0 {
   592  			continue
   593  		}
   594  		switch p &^ (PrefixIgnored | PrefixInvalid) {
   595  		default:
   596  			if p.IsREX() {
   597  				if p&0xFF == PrefixREX {
   598  					prefix += "rex "
   599  				} else {
   600  					prefix += "rex." + p.String()[4:] + " "
   601  				}
   602  				break
   603  			}
   604  			prefix += strings.ToLower(p.String()) + " "
   605  
   606  		case PrefixPN:
   607  			op += ",pn"
   608  			continue
   609  
   610  		case PrefixPT:
   611  			op += ",pt"
   612  			continue
   613  
   614  		case PrefixAddrSize, PrefixAddr16, PrefixAddr32:
   615  			// For unknown reasons, if the addr16 prefix is repeated,
   616  			// libopcodes displays all but the last as addr32, even though
   617  			// the addressing form used in a memory reference is clearly
   618  			// still 16-bit.
   619  			n := 32
   620  			if inst.Mode == 32 {
   621  				n = 16
   622  			}
   623  			numAddr++
   624  			if countPrefix(&inst, PrefixAddrSize) > numAddr {
   625  				n = inst.Mode
   626  			}
   627  			prefix += fmt.Sprintf("addr%d ", n)
   628  			continue
   629  
   630  		case PrefixData16, PrefixData32:
   631  			if implicitData && countPrefix(&inst, PrefixDataSize) > 1 {
   632  				// Similar to the addr32 logic above, but it only kicks in
   633  				// when something used the data size prefix (one is implicit).
   634  				n := 16
   635  				if inst.Mode == 16 {
   636  					n = 32
   637  				}
   638  				numData++
   639  				if countPrefix(&inst, PrefixDataSize) > numData {
   640  					if inst.Mode == 16 {
   641  						n = 16
   642  					} else {
   643  						n = 32
   644  					}
   645  				}
   646  				prefix += fmt.Sprintf("data%d ", n)
   647  				continue
   648  			}
   649  			prefix += strings.ToLower(p.String()) + " "
   650  		}
   651  	}
   652  
   653  	// Finally! Put it all together.
   654  	text := prefix + op
   655  	if args != nil {
   656  		text += " "
   657  		// Indirect call/jmp gets a star to distinguish from direct jump address.
   658  		if (inst.Op == CALL || inst.Op == JMP || inst.Op == LJMP || inst.Op == LCALL) && (isMem(inst.Args[0]) || isReg(inst.Args[0])) {
   659  			text += "*"
   660  		}
   661  		text += strings.Join(args, ",")
   662  	}
   663  	return text
   664  }
   665  
   666  // gnuArg returns the GNU syntax for the argument x from the instruction inst.
   667  // If *usedPrefixes is false and x is a Mem, then the formatting
   668  // includes any segment prefixes and sets *usedPrefixes to true.
   669  func gnuArg(inst *Inst, pc uint64, symname SymLookup, x Arg, usedPrefixes *bool) string {
   670  	if x == nil {
   671  		return "<nil>"
   672  	}
   673  	switch x := x.(type) {
   674  	case Reg:
   675  		switch inst.Op {
   676  		case CVTSI2SS, CVTSI2SD, CVTSS2SI, CVTSD2SI, CVTTSD2SI, CVTTSS2SI:
   677  			if inst.DataSize == 16 && EAX <= x && x <= R15L {
   678  				x -= EAX - AX
   679  			}
   680  
   681  		case IN, INSB, INSW, INSD, OUT, OUTSB, OUTSW, OUTSD:
   682  			// DX is the port, but libopcodes prints it as if it were a memory reference.
   683  			if x == DX {
   684  				return "(%dx)"
   685  			}
   686  		}
   687  		return gccRegName[x]
   688  	case Mem:
   689  		if s, disp := memArgToSymbol(x, pc, inst.Len, symname); s != "" {
   690  			suffix := ""
   691  			if disp != 0 {
   692  				suffix = fmt.Sprintf("%+d", disp)
   693  			}
   694  			return fmt.Sprintf("%s%s", s, suffix)
   695  		}
   696  		seg := ""
   697  		var haveCS, haveDS, haveES, haveFS, haveGS, haveSS bool
   698  		switch x.Segment {
   699  		case CS:
   700  			haveCS = true
   701  		case DS:
   702  			haveDS = true
   703  		case ES:
   704  			haveES = true
   705  		case FS:
   706  			haveFS = true
   707  		case GS:
   708  			haveGS = true
   709  		case SS:
   710  			haveSS = true
   711  		}
   712  		switch inst.Op {
   713  		case INSB, INSW, INSD, STOSB, STOSW, STOSD, STOSQ, SCASB, SCASW, SCASD, SCASQ:
   714  			// These do not accept segment prefixes, at least in the GNU rendering.
   715  		default:
   716  			if isVSIB(inst.Op) {
   717  				haveCS, haveDS, haveES, haveSS = false, false, false, false
   718  				break
   719  			}
   720  			if *usedPrefixes {
   721  				break
   722  			}
   723  			for i := len(inst.Prefix) - 1; i >= 0; i-- {
   724  				p := inst.Prefix[i] &^ PrefixIgnored
   725  				if p == 0 {
   726  					continue
   727  				}
   728  				switch p {
   729  				case PrefixCS:
   730  					if !haveCS {
   731  						haveCS = true
   732  						inst.Prefix[i] |= PrefixImplicit
   733  					}
   734  				case PrefixDS:
   735  					if !haveDS {
   736  						haveDS = true
   737  						inst.Prefix[i] |= PrefixImplicit
   738  					}
   739  				case PrefixES:
   740  					if !haveES {
   741  						haveES = true
   742  						inst.Prefix[i] |= PrefixImplicit
   743  					}
   744  				case PrefixFS:
   745  					if !haveFS {
   746  						haveFS = true
   747  						inst.Prefix[i] |= PrefixImplicit
   748  					}
   749  				case PrefixGS:
   750  					if !haveGS {
   751  						haveGS = true
   752  						inst.Prefix[i] |= PrefixImplicit
   753  					}
   754  				case PrefixSS:
   755  					if !haveSS {
   756  						haveSS = true
   757  						inst.Prefix[i] |= PrefixImplicit
   758  					}
   759  				}
   760  			}
   761  			*usedPrefixes = true
   762  		}
   763  		if haveCS {
   764  			seg += "%cs:"
   765  		}
   766  		if haveDS {
   767  			seg += "%ds:"
   768  		}
   769  		if haveSS {
   770  			seg += "%ss:"
   771  		}
   772  		if haveES {
   773  			seg += "%es:"
   774  		}
   775  		if haveFS {
   776  			seg += "%fs:"
   777  		}
   778  		if haveGS {
   779  			seg += "%gs:"
   780  		}
   781  		disp := ""
   782  		if x.Disp != 0 {
   783  			disp = fmt.Sprintf("%#x", x.Disp)
   784  		}
   785  		if x.Scale == 0 || x.Index == 0 && x.Scale == 1 && (x.Base == ESP || x.Base == RSP || x.Base == 0 && inst.Mode == 64) {
   786  			if x.Base == 0 {
   787  				return seg + disp
   788  			}
   789  			return fmt.Sprintf("%s%s(%s)", seg, disp, gccRegName[x.Base])
   790  		}
   791  		base := gccRegName[x.Base]
   792  		if x.Base == 0 {
   793  			base = ""
   794  		}
   795  		index := gccRegName[x.Index]
   796  		if x.Index == 0 {
   797  			if inst.AddrSize == 64 {
   798  				index = "%riz"
   799  			} else {
   800  				index = "%eiz"
   801  			}
   802  		}
   803  		if AX <= x.Base && x.Base <= DI {
   804  			// 16-bit addressing - no scale
   805  			return fmt.Sprintf("%s%s(%s,%s)", seg, disp, base, index)
   806  		}
   807  		if x.Scale == 1 {
   808  			// Special case to match objdump output for explicit scale 1.
   809  			// XXX is this the only one?
   810  			if inst.Op.String() == "VMOVNTDQA" {
   811  				return fmt.Sprintf("%s%s(%s,%s,1)", seg, disp, base, index)
   812  			}
   813  			return fmt.Sprintf("%s%s(%s,%s)", seg, disp, base, index)
   814  		}
   815  		return fmt.Sprintf("%s%s(%s,%s,%d)", seg, disp, base, index, x.Scale)
   816  	case Rel:
   817  		if pc == 0 {
   818  			return fmt.Sprintf(".%+#x", int64(x))
   819  		} else {
   820  			addr := pc + uint64(inst.Len) + uint64(x)
   821  			if s, base := symname(addr); s != "" && addr == base {
   822  				return fmt.Sprintf("%s", s)
   823  			} else {
   824  				addr := pc + uint64(inst.Len) + uint64(x)
   825  				return fmt.Sprintf("%#x", addr)
   826  			}
   827  		}
   828  	case Imm:
   829  		if (inst.Op == MOV || inst.Op == PUSH) && inst.DataSize == 32 { // See comment in plan9x.go.
   830  			if s, base := symname(uint64(x)); s != "" {
   831  				suffix := ""
   832  				if uint64(x) != base {
   833  					suffix = fmt.Sprintf("%+d", uint64(x)-base)
   834  				}
   835  				return fmt.Sprintf("$%s%s", s, suffix)
   836  			}
   837  		}
   838  		if inst.Mode == 32 {
   839  			return fmt.Sprintf("$%#x", uint32(x))
   840  		}
   841  		return fmt.Sprintf("$%#x", int64(x))
   842  	}
   843  	return x.String()
   844  }
   845  
   846  var gccRegName = [...]string{
   847  	0:    "REG0",
   848  	AL:   "%al",
   849  	CL:   "%cl",
   850  	BL:   "%bl",
   851  	DL:   "%dl",
   852  	AH:   "%ah",
   853  	CH:   "%ch",
   854  	BH:   "%bh",
   855  	DH:   "%dh",
   856  	SPB:  "%spl",
   857  	BPB:  "%bpl",
   858  	SIB:  "%sil",
   859  	DIB:  "%dil",
   860  	R8B:  "%r8b",
   861  	R9B:  "%r9b",
   862  	R10B: "%r10b",
   863  	R11B: "%r11b",
   864  	R12B: "%r12b",
   865  	R13B: "%r13b",
   866  	R14B: "%r14b",
   867  	R15B: "%r15b",
   868  	AX:   "%ax",
   869  	CX:   "%cx",
   870  	BX:   "%bx",
   871  	DX:   "%dx",
   872  	SP:   "%sp",
   873  	BP:   "%bp",
   874  	SI:   "%si",
   875  	DI:   "%di",
   876  	R8W:  "%r8w",
   877  	R9W:  "%r9w",
   878  	R10W: "%r10w",
   879  	R11W: "%r11w",
   880  	R12W: "%r12w",
   881  	R13W: "%r13w",
   882  	R14W: "%r14w",
   883  	R15W: "%r15w",
   884  	EAX:  "%eax",
   885  	ECX:  "%ecx",
   886  	EDX:  "%edx",
   887  	EBX:  "%ebx",
   888  	ESP:  "%esp",
   889  	EBP:  "%ebp",
   890  	ESI:  "%esi",
   891  	EDI:  "%edi",
   892  	R8L:  "%r8d",
   893  	R9L:  "%r9d",
   894  	R10L: "%r10d",
   895  	R11L: "%r11d",
   896  	R12L: "%r12d",
   897  	R13L: "%r13d",
   898  	R14L: "%r14d",
   899  	R15L: "%r15d",
   900  	RAX:  "%rax",
   901  	RCX:  "%rcx",
   902  	RDX:  "%rdx",
   903  	RBX:  "%rbx",
   904  	RSP:  "%rsp",
   905  	RBP:  "%rbp",
   906  	RSI:  "%rsi",
   907  	RDI:  "%rdi",
   908  	R8:   "%r8",
   909  	R9:   "%r9",
   910  	R10:  "%r10",
   911  	R11:  "%r11",
   912  	R12:  "%r12",
   913  	R13:  "%r13",
   914  	R14:  "%r14",
   915  	R15:  "%r15",
   916  	IP:   "%ip",
   917  	EIP:  "%eip",
   918  	RIP:  "%rip",
   919  	F0:   "%st",
   920  	F1:   "%st(1)",
   921  	F2:   "%st(2)",
   922  	F3:   "%st(3)",
   923  	F4:   "%st(4)",
   924  	F5:   "%st(5)",
   925  	F6:   "%st(6)",
   926  	F7:   "%st(7)",
   927  	M0:   "%mm0",
   928  	M1:   "%mm1",
   929  	M2:   "%mm2",
   930  	M3:   "%mm3",
   931  	M4:   "%mm4",
   932  	M5:   "%mm5",
   933  	M6:   "%mm6",
   934  	M7:   "%mm7",
   935  	X0:   "%xmm0",
   936  	X1:   "%xmm1",
   937  	X2:   "%xmm2",
   938  	X3:   "%xmm3",
   939  	X4:   "%xmm4",
   940  	X5:   "%xmm5",
   941  	X6:   "%xmm6",
   942  	X7:   "%xmm7",
   943  	X8:   "%xmm8",
   944  	X9:   "%xmm9",
   945  	X10:  "%xmm10",
   946  	X11:  "%xmm11",
   947  	X12:  "%xmm12",
   948  	X13:  "%xmm13",
   949  	X14:  "%xmm14",
   950  	X15:  "%xmm15",
   951  	X16:  "%xmm16",
   952  	X17:  "%xmm17",
   953  	X18:  "%xmm18",
   954  	X19:  "%xmm19",
   955  	X20:  "%xmm20",
   956  	X21:  "%xmm21",
   957  	X22:  "%xmm22",
   958  	X23:  "%xmm23",
   959  	X24:  "%xmm24",
   960  	X25:  "%xmm25",
   961  	X26:  "%xmm26",
   962  	X27:  "%xmm27",
   963  	X28:  "%xmm28",
   964  	X29:  "%xmm29",
   965  	X30:  "%xmm30",
   966  	X31:  "%xmm31",
   967  	Y0:   "%ymm0",
   968  	Y1:   "%ymm1",
   969  	Y2:   "%ymm2",
   970  	Y3:   "%ymm3",
   971  	Y4:   "%ymm4",
   972  	Y5:   "%ymm5",
   973  	Y6:   "%ymm6",
   974  	Y7:   "%ymm7",
   975  	Y8:   "%ymm8",
   976  	Y9:   "%ymm9",
   977  	Y10:  "%ymm10",
   978  	Y11:  "%ymm11",
   979  	Y12:  "%ymm12",
   980  	Y13:  "%ymm13",
   981  	Y14:  "%ymm14",
   982  	Y15:  "%ymm15",
   983  	Y16:  "%ymm16",
   984  	Y17:  "%ymm17",
   985  	Y18:  "%ymm18",
   986  	Y19:  "%ymm19",
   987  	Y20:  "%ymm20",
   988  	Y21:  "%ymm21",
   989  	Y22:  "%ymm22",
   990  	Y23:  "%ymm23",
   991  	Y24:  "%ymm24",
   992  	Y25:  "%ymm25",
   993  	Y26:  "%ymm26",
   994  	Y27:  "%ymm27",
   995  	Y28:  "%ymm28",
   996  	Y29:  "%ymm29",
   997  	Y30:  "%ymm30",
   998  	Y31:  "%ymm31",
   999  	Z0:   "%zmm0",
  1000  	Z1:   "%zmm1",
  1001  	Z2:   "%zmm2",
  1002  	Z3:   "%zmm3",
  1003  	Z4:   "%zmm4",
  1004  	Z5:   "%zmm5",
  1005  	Z6:   "%zmm6",
  1006  	Z7:   "%zmm7",
  1007  	Z8:   "%zmm8",
  1008  	Z9:   "%zmm9",
  1009  	Z10:  "%zmm10",
  1010  	Z11:  "%zmm11",
  1011  	Z12:  "%zmm12",
  1012  	Z13:  "%zmm13",
  1013  	Z14:  "%zmm14",
  1014  	Z15:  "%zmm15",
  1015  	Z16:  "%zmm16",
  1016  	Z17:  "%zmm17",
  1017  	Z18:  "%zmm18",
  1018  	Z19:  "%zmm19",
  1019  	Z20:  "%zmm20",
  1020  	Z21:  "%zmm21",
  1021  	Z22:  "%zmm22",
  1022  	Z23:  "%zmm23",
  1023  	Z24:  "%zmm24",
  1024  	Z25:  "%zmm25",
  1025  	Z26:  "%zmm26",
  1026  	Z27:  "%zmm27",
  1027  	Z28:  "%zmm28",
  1028  	Z29:  "%zmm29",
  1029  	Z30:  "%zmm30",
  1030  	Z31:  "%zmm31",
  1031  	K0:   "%k0",
  1032  	K1:   "%k1",
  1033  	K2:   "%k2",
  1034  	K3:   "%k3",
  1035  	K4:   "%k4",
  1036  	K5:   "%k5",
  1037  	K6:   "%k6",
  1038  	K7:   "%k7",
  1039  	CS:   "%cs",
  1040  	SS:   "%ss",
  1041  	DS:   "%ds",
  1042  	ES:   "%es",
  1043  	FS:   "%fs",
  1044  	GS:   "%gs",
  1045  	GDTR: "%gdtr",
  1046  	IDTR: "%idtr",
  1047  	LDTR: "%ldtr",
  1048  	MSW:  "%msw",
  1049  	TASK: "%task",
  1050  	CR0:  "%cr0",
  1051  	CR1:  "%cr1",
  1052  	CR2:  "%cr2",
  1053  	CR3:  "%cr3",
  1054  	CR4:  "%cr4",
  1055  	CR5:  "%cr5",
  1056  	CR6:  "%cr6",
  1057  	CR7:  "%cr7",
  1058  	CR8:  "%cr8",
  1059  	CR9:  "%cr9",
  1060  	CR10: "%cr10",
  1061  	CR11: "%cr11",
  1062  	CR12: "%cr12",
  1063  	CR13: "%cr13",
  1064  	CR14: "%cr14",
  1065  	CR15: "%cr15",
  1066  	DR0:  "%db0",
  1067  	DR1:  "%db1",
  1068  	DR2:  "%db2",
  1069  	DR3:  "%db3",
  1070  	DR4:  "%db4",
  1071  	DR5:  "%db5",
  1072  	DR6:  "%db6",
  1073  	DR7:  "%db7",
  1074  	TR0:  "%tr0",
  1075  	TR1:  "%tr1",
  1076  	TR2:  "%tr2",
  1077  	TR3:  "%tr3",
  1078  	TR4:  "%tr4",
  1079  	TR5:  "%tr5",
  1080  	TR6:  "%tr6",
  1081  	TR7:  "%tr7",
  1082  }
  1083  
  1084  var gnuOp = map[Op]string{
  1085  	CBW:       "cbtw",
  1086  	CDQ:       "cltd",
  1087  	CMPSD:     "cmpsl",
  1088  	CMPSD_XMM: "cmpsd",
  1089  	CWD:       "cwtd",
  1090  	CWDE:      "cwtl",
  1091  	CQO:       "cqto",
  1092  	INSD:      "insl",
  1093  	IRET:      "iretw",
  1094  	IRETD:     "iret",
  1095  	IRETQ:     "iretq",
  1096  	LODSB:     "lods",
  1097  	LODSD:     "lods",
  1098  	LODSQ:     "lods",
  1099  	LODSW:     "lods",
  1100  	MOVSD:     "movsl",
  1101  	MOVSD_XMM: "movsd",
  1102  	OUTSD:     "outsl",
  1103  	POPA:      "popaw",
  1104  	POPAD:     "popa",
  1105  	POPF:      "popfw",
  1106  	POPFD:     "popf",
  1107  	PUSHA:     "pushaw",
  1108  	PUSHAD:    "pusha",
  1109  	PUSHF:     "pushfw",
  1110  	PUSHFD:    "pushf",
  1111  	SCASB:     "scas",
  1112  	SCASD:     "scas",
  1113  	SCASQ:     "scas",
  1114  	SCASW:     "scas",
  1115  	STOSB:     "stos",
  1116  	STOSD:     "stos",
  1117  	STOSQ:     "stos",
  1118  	STOSW:     "stos",
  1119  	XLATB:     "xlat",
  1120  }
  1121  
  1122  var cmppsOps = []string{
  1123  	"cmpeq",
  1124  	"cmplt",
  1125  	"cmple",
  1126  	"cmpunord",
  1127  	"cmpneq",
  1128  	"cmpnlt",
  1129  	"cmpnle",
  1130  	"cmpord",
  1131  }
  1132  
  1133  var pclmulqOps = []string{
  1134  	"pclmullqlqdq",
  1135  	"pclmulhqlqdq",
  1136  	"pclmullqhqdq",
  1137  	"pclmulhqhqdq",
  1138  }
  1139  
  1140  func countPrefix(inst *Inst, target Prefix) int {
  1141  	n := 0
  1142  	for _, p := range inst.Prefix {
  1143  		if p&0xFF == target&0xFF {
  1144  			n++
  1145  		}
  1146  	}
  1147  	return n
  1148  }
  1149  
  1150  func markLastImplicit(inst *Inst, prefix Prefix) bool {
  1151  	for i := len(inst.Prefix) - 1; i >= 0; i-- {
  1152  		p := inst.Prefix[i]
  1153  		if p&0xFF == prefix {
  1154  			inst.Prefix[i] |= PrefixImplicit
  1155  			return true
  1156  		}
  1157  	}
  1158  	return false
  1159  }
  1160  
  1161  func unmarkImplicit(inst *Inst, prefix Prefix) {
  1162  	for i := len(inst.Prefix) - 1; i >= 0; i-- {
  1163  		p := inst.Prefix[i]
  1164  		if p&0xFF == prefix {
  1165  			inst.Prefix[i] &^= PrefixImplicit
  1166  		}
  1167  	}
  1168  }
  1169  
  1170  func byteSizeSuffix(b int) string {
  1171  	switch b {
  1172  	case 1:
  1173  		return "b"
  1174  	case 2:
  1175  		return "w"
  1176  	case 4:
  1177  		return "l"
  1178  	case 8:
  1179  		return "q"
  1180  	}
  1181  	return ""
  1182  }
  1183  
  1184  func argBytes(inst *Inst, arg Arg) int {
  1185  	if isMem(arg) {
  1186  		return inst.MemBytes
  1187  	}
  1188  	return regBytes(arg)
  1189  }
  1190  
  1191  func isFloat(op Op) bool {
  1192  	switch op {
  1193  	case FADD, FCOM, FCOMP, FDIV, FDIVR, FIADD, FICOM, FICOMP, FIDIV, FIDIVR, FILD, FIMUL, FIST, FISTP, FISTTP, FISUB, FISUBR, FLD, FMUL, FST, FSTP, FSUB, FSUBR:
  1194  		return true
  1195  	}
  1196  	return false
  1197  }
  1198  
  1199  func isFloatInt(op Op) bool {
  1200  	switch op {
  1201  	case FIADD, FICOM, FICOMP, FIDIV, FIDIVR, FILD, FIMUL, FIST, FISTP, FISTTP, FISUB, FISUBR:
  1202  		return true
  1203  	}
  1204  	return false
  1205  }
  1206  

View as plain text