github.com/tetratelabs/wazero@v1.7.3-0.20240513003603-48f702e154b5/internal/engine/wazevo/backend/isa/amd64/instr.go (about)

     1  package amd64
     2  
     3  import (
     4  	"fmt"
     5  
     6  	"github.com/tetratelabs/wazero/internal/engine/wazevo/backend"
     7  	"github.com/tetratelabs/wazero/internal/engine/wazevo/backend/regalloc"
     8  	"github.com/tetratelabs/wazero/internal/engine/wazevo/ssa"
     9  )
    10  
    11  type instruction struct {
    12  	prev, next          *instruction
    13  	op1, op2            operand
    14  	u1, u2              uint64
    15  	b1                  bool
    16  	addedBeforeRegAlloc bool
    17  	kind                instructionKind
    18  }
    19  
    20  // Next implements regalloc.Instr.
    21  func (i *instruction) Next() regalloc.Instr {
    22  	return i.next
    23  }
    24  
    25  // Prev implements regalloc.Instr.
    26  func (i *instruction) Prev() regalloc.Instr {
    27  	return i.prev
    28  }
    29  
    30  // IsCall implements regalloc.Instr.
    31  func (i *instruction) IsCall() bool { return i.kind == call }
    32  
    33  // IsIndirectCall implements regalloc.Instr.
    34  func (i *instruction) IsIndirectCall() bool { return i.kind == callIndirect }
    35  
    36  // IsReturn implements regalloc.Instr.
    37  func (i *instruction) IsReturn() bool { return i.kind == ret }
    38  
    39  // AddedBeforeRegAlloc implements regalloc.Instr.
    40  func (i *instruction) AddedBeforeRegAlloc() bool { return i.addedBeforeRegAlloc }
    41  
    42  // String implements regalloc.Instr.
    43  func (i *instruction) String() string {
    44  	switch i.kind {
    45  	case nop0:
    46  		return "nop"
    47  	case sourceOffsetInfo:
    48  		return fmt.Sprintf("source_offset_info %d", i.u1)
    49  	case ret:
    50  		return "ret"
    51  	case imm:
    52  		if i.b1 {
    53  			return fmt.Sprintf("movabsq $%d, %s", int64(i.u1), i.op2.format(true))
    54  		} else {
    55  			return fmt.Sprintf("movl $%d, %s", int32(i.u1), i.op2.format(false))
    56  		}
    57  	case aluRmiR:
    58  		return fmt.Sprintf("%s %s, %s", aluRmiROpcode(i.u1), i.op1.format(i.b1), i.op2.format(i.b1))
    59  	case movRR:
    60  		if i.b1 {
    61  			return fmt.Sprintf("movq %s, %s", i.op1.format(true), i.op2.format(true))
    62  		} else {
    63  			return fmt.Sprintf("movl %s, %s", i.op1.format(false), i.op2.format(false))
    64  		}
    65  	case xmmRmR:
    66  		return fmt.Sprintf("%s %s, %s", sseOpcode(i.u1), i.op1.format(false), i.op2.format(false))
    67  	case gprToXmm:
    68  		return fmt.Sprintf("%s %s, %s", sseOpcode(i.u1), i.op1.format(i.b1), i.op2.format(i.b1))
    69  	case xmmUnaryRmR:
    70  		return fmt.Sprintf("%s %s, %s", sseOpcode(i.u1), i.op1.format(false), i.op2.format(false))
    71  	case xmmUnaryRmRImm:
    72  		return fmt.Sprintf("%s $%d, %s, %s", sseOpcode(i.u1), roundingMode(i.u2), i.op1.format(false), i.op2.format(false))
    73  	case unaryRmR:
    74  		var suffix string
    75  		if i.b1 {
    76  			suffix = "q"
    77  		} else {
    78  			suffix = "l"
    79  		}
    80  		return fmt.Sprintf("%s%s %s, %s", unaryRmROpcode(i.u1), suffix, i.op1.format(i.b1), i.op2.format(i.b1))
    81  	case not:
    82  		var op string
    83  		if i.b1 {
    84  			op = "notq"
    85  		} else {
    86  			op = "notl"
    87  		}
    88  		return fmt.Sprintf("%s %s", op, i.op1.format(i.b1))
    89  	case neg:
    90  		var op string
    91  		if i.b1 {
    92  			op = "negq"
    93  		} else {
    94  			op = "negl"
    95  		}
    96  		return fmt.Sprintf("%s %s", op, i.op1.format(i.b1))
    97  	case div:
    98  		var prefix string
    99  		var op string
   100  		if i.b1 {
   101  			op = "divq"
   102  		} else {
   103  			op = "divl"
   104  		}
   105  		if i.u1 != 0 {
   106  			prefix = "i"
   107  		}
   108  		return fmt.Sprintf("%s%s %s", prefix, op, i.op1.format(i.b1))
   109  	case mulHi:
   110  		signed, _64 := i.u1 != 0, i.b1
   111  		var op string
   112  		switch {
   113  		case signed && _64:
   114  			op = "imulq"
   115  		case !signed && _64:
   116  			op = "mulq"
   117  		case signed && !_64:
   118  			op = "imull"
   119  		case !signed && !_64:
   120  			op = "mull"
   121  		}
   122  		return fmt.Sprintf("%s %s", op, i.op1.format(i.b1))
   123  	case signExtendData:
   124  		var op string
   125  		if i.b1 {
   126  			op = "cqo"
   127  		} else {
   128  			op = "cdq"
   129  		}
   130  		return op
   131  	case movzxRmR:
   132  		return fmt.Sprintf("movzx.%s %s, %s", extMode(i.u1), i.op1.format(true), i.op2.format(true))
   133  	case mov64MR:
   134  		return fmt.Sprintf("movq %s, %s", i.op1.format(true), i.op2.format(true))
   135  	case lea:
   136  		return fmt.Sprintf("lea %s, %s", i.op1.format(true), i.op2.format(true))
   137  	case movsxRmR:
   138  		return fmt.Sprintf("movsx.%s %s, %s", extMode(i.u1), i.op1.format(true), i.op2.format(true))
   139  	case movRM:
   140  		var suffix string
   141  		switch i.u1 {
   142  		case 1:
   143  			suffix = "b"
   144  		case 2:
   145  			suffix = "w"
   146  		case 4:
   147  			suffix = "l"
   148  		case 8:
   149  			suffix = "q"
   150  		}
   151  		return fmt.Sprintf("mov.%s %s, %s", suffix, i.op1.format(true), i.op2.format(true))
   152  	case shiftR:
   153  		var suffix string
   154  		if i.b1 {
   155  			suffix = "q"
   156  		} else {
   157  			suffix = "l"
   158  		}
   159  		return fmt.Sprintf("%s%s %s, %s", shiftROp(i.u1), suffix, i.op1.format(false), i.op2.format(i.b1))
   160  	case xmmRmiReg:
   161  		return fmt.Sprintf("%s %s, %s", sseOpcode(i.u1), i.op1.format(true), i.op2.format(true))
   162  	case cmpRmiR:
   163  		var op, suffix string
   164  		if i.u1 != 0 {
   165  			op = "cmp"
   166  		} else {
   167  			op = "test"
   168  		}
   169  		if i.b1 {
   170  			suffix = "q"
   171  		} else {
   172  			suffix = "l"
   173  		}
   174  		if op == "test" && i.op1.kind == operandKindMem {
   175  			// Print consistently with AT&T syntax.
   176  			return fmt.Sprintf("%s%s %s, %s", op, suffix, i.op2.format(i.b1), i.op1.format(i.b1))
   177  		}
   178  		return fmt.Sprintf("%s%s %s, %s", op, suffix, i.op1.format(i.b1), i.op2.format(i.b1))
   179  	case setcc:
   180  		return fmt.Sprintf("set%s %s", cond(i.u1), i.op2.format(true))
   181  	case cmove:
   182  		var suffix string
   183  		if i.b1 {
   184  			suffix = "q"
   185  		} else {
   186  			suffix = "l"
   187  		}
   188  		return fmt.Sprintf("cmov%s%s %s, %s", cond(i.u1), suffix, i.op1.format(i.b1), i.op2.format(i.b1))
   189  	case push64:
   190  		return fmt.Sprintf("pushq %s", i.op1.format(true))
   191  	case pop64:
   192  		return fmt.Sprintf("popq %s", i.op1.format(true))
   193  	case xmmMovRM:
   194  		return fmt.Sprintf("%s %s, %s", sseOpcode(i.u1), i.op1.format(true), i.op2.format(true))
   195  	case xmmLoadConst:
   196  		panic("TODO")
   197  	case xmmToGpr:
   198  		return fmt.Sprintf("%s %s, %s", sseOpcode(i.u1), i.op1.format(i.b1), i.op2.format(i.b1))
   199  	case cvtUint64ToFloatSeq:
   200  		panic("TODO")
   201  	case cvtFloatToSintSeq:
   202  		panic("TODO")
   203  	case cvtFloatToUintSeq:
   204  		panic("TODO")
   205  	case xmmMinMaxSeq:
   206  		panic("TODO")
   207  	case xmmCmpRmR:
   208  		return fmt.Sprintf("%s %s, %s", sseOpcode(i.u1), i.op1.format(false), i.op2.format(false))
   209  	case xmmRmRImm:
   210  		op := sseOpcode(i.u1)
   211  		r1, r2 := i.op1.format(op == sseOpcodePextrq || op == sseOpcodePinsrq),
   212  			i.op2.format(op == sseOpcodePextrq || op == sseOpcodePinsrq)
   213  		return fmt.Sprintf("%s $%d, %s, %s", op, i.u2, r1, r2)
   214  	case jmp:
   215  		return fmt.Sprintf("jmp %s", i.op1.format(true))
   216  	case jmpIf:
   217  		return fmt.Sprintf("j%s %s", cond(i.u1), i.op1.format(true))
   218  	case jmpTableIsland:
   219  		return fmt.Sprintf("jump_table_island: jmp_table_index=%d", i.u1)
   220  	case exitSequence:
   221  		return fmt.Sprintf("exit_sequence %s", i.op1.format(true))
   222  	case ud2:
   223  		return "ud2"
   224  	case call:
   225  		return fmt.Sprintf("call %s", ssa.FuncRef(i.u1))
   226  	case callIndirect:
   227  		return fmt.Sprintf("callq *%s", i.op1.format(true))
   228  	case xchg:
   229  		var suffix string
   230  		switch i.u1 {
   231  		case 1:
   232  			suffix = "b"
   233  		case 2:
   234  			suffix = "w"
   235  		case 4:
   236  			suffix = "l"
   237  		case 8:
   238  			suffix = "q"
   239  		}
   240  		return fmt.Sprintf("xchg.%s %s, %s", suffix, i.op1.format(true), i.op2.format(true))
   241  	case zeros:
   242  		return fmt.Sprintf("xor %s, %s", i.op2.format(true), i.op2.format(true))
   243  	case fcvtToSintSequence:
   244  		execCtx, src, tmpGp, tmpGp2, tmpXmm, src64, dst64, sat := i.fcvtToSintSequenceData()
   245  		return fmt.Sprintf(
   246  			"fcvtToSintSequence execCtx=%s, src=%s, tmpGp=%s, tmpGp2=%s, tmpXmm=%s, src64=%v, dst64=%v, sat=%v",
   247  			formatVRegSized(execCtx, true),
   248  			formatVRegSized(src, true),
   249  			formatVRegSized(tmpGp, true),
   250  			formatVRegSized(tmpGp2, true),
   251  			formatVRegSized(tmpXmm, true), src64, dst64, sat)
   252  	case fcvtToUintSequence:
   253  		execCtx, src, tmpGp, tmpGp2, tmpXmm, tmpXmm2, src64, dst64, sat := i.fcvtToUintSequenceData()
   254  		return fmt.Sprintf(
   255  			"fcvtToUintSequence execCtx=%s, src=%s, tmpGp=%s, tmpGp2=%s, tmpXmm=%s, tmpXmm2=%s, src64=%v, dst64=%v, sat=%v",
   256  			formatVRegSized(execCtx, true),
   257  			formatVRegSized(src, true),
   258  			formatVRegSized(tmpGp, true),
   259  			formatVRegSized(tmpGp2, true),
   260  			formatVRegSized(tmpXmm, true),
   261  			formatVRegSized(tmpXmm2, true), src64, dst64, sat)
   262  	case idivRemSequence:
   263  		execCtx, divisor, tmpGp, isDiv, signed, _64 := i.idivRemSequenceData()
   264  		return fmt.Sprintf("idivRemSequence execCtx=%s, divisor=%s, tmpGp=%s, isDiv=%v, signed=%v, _64=%v",
   265  			formatVRegSized(execCtx, true), formatVRegSized(divisor, _64), formatVRegSized(tmpGp, _64), isDiv, signed, _64)
   266  	case defineUninitializedReg:
   267  		return fmt.Sprintf("defineUninitializedReg %s", i.op2.format(true))
   268  	case xmmCMov:
   269  		return fmt.Sprintf("xmmcmov%s %s, %s", cond(i.u1), i.op1.format(true), i.op2.format(true))
   270  	case blendvpd:
   271  		return fmt.Sprintf("blendvpd %s, %s, %%xmm0", i.op1.format(false), i.op2.format(false))
   272  	case mfence:
   273  		return "mfence"
   274  	case lockcmpxchg:
   275  		var suffix string
   276  		switch i.u1 {
   277  		case 1:
   278  			suffix = "b"
   279  		case 2:
   280  			suffix = "w"
   281  		case 4:
   282  			suffix = "l"
   283  		case 8:
   284  			suffix = "q"
   285  		}
   286  		return fmt.Sprintf("lock cmpxchg.%s %s, %s", suffix, i.op1.format(true), i.op2.format(true))
   287  	case lockxadd:
   288  		var suffix string
   289  		switch i.u1 {
   290  		case 1:
   291  			suffix = "b"
   292  		case 2:
   293  			suffix = "w"
   294  		case 4:
   295  			suffix = "l"
   296  		case 8:
   297  			suffix = "q"
   298  		}
   299  		return fmt.Sprintf("lock xadd.%s %s, %s", suffix, i.op1.format(true), i.op2.format(true))
   300  
   301  	case nopUseReg:
   302  		return fmt.Sprintf("nop_use_reg %s", i.op1.format(true))
   303  
   304  	default:
   305  		panic(fmt.Sprintf("BUG: %d", int(i.kind)))
   306  	}
   307  }
   308  
   309  // Defs implements regalloc.Instr.
   310  func (i *instruction) Defs(regs *[]regalloc.VReg) []regalloc.VReg {
   311  	*regs = (*regs)[:0]
   312  	switch dk := defKinds[i.kind]; dk {
   313  	case defKindNone:
   314  	case defKindOp2:
   315  		*regs = append(*regs, i.op2.reg())
   316  	case defKindCall:
   317  		_, _, retIntRealRegs, retFloatRealRegs, _ := backend.ABIInfoFromUint64(i.u2)
   318  		for i := byte(0); i < retIntRealRegs; i++ {
   319  			*regs = append(*regs, regInfo.RealRegToVReg[intArgResultRegs[i]])
   320  		}
   321  		for i := byte(0); i < retFloatRealRegs; i++ {
   322  			*regs = append(*regs, regInfo.RealRegToVReg[floatArgResultRegs[i]])
   323  		}
   324  	case defKindDivRem:
   325  		_, _, _, isDiv, _, _ := i.idivRemSequenceData()
   326  		if isDiv {
   327  			*regs = append(*regs, raxVReg)
   328  		} else {
   329  			*regs = append(*regs, rdxVReg)
   330  		}
   331  	default:
   332  		panic(fmt.Sprintf("BUG: invalid defKind \"%s\" for %s", dk, i))
   333  	}
   334  	return *regs
   335  }
   336  
   337  // Uses implements regalloc.Instr.
   338  func (i *instruction) Uses(regs *[]regalloc.VReg) []regalloc.VReg {
   339  	*regs = (*regs)[:0]
   340  	switch uk := useKinds[i.kind]; uk {
   341  	case useKindNone:
   342  	case useKindOp1Op2Reg, useKindOp1RegOp2:
   343  		opAny, opReg := &i.op1, &i.op2
   344  		if uk == useKindOp1RegOp2 {
   345  			opAny, opReg = opReg, opAny
   346  		}
   347  		// The destination operand (op2) can be only reg,
   348  		// the source operand (op1) can be imm32, reg or mem.
   349  		switch opAny.kind {
   350  		case operandKindReg:
   351  			*regs = append(*regs, opAny.reg())
   352  		case operandKindMem:
   353  			opAny.addressMode().uses(regs)
   354  		case operandKindImm32:
   355  		default:
   356  			panic(fmt.Sprintf("BUG: invalid operand: %s", i))
   357  		}
   358  		if opReg.kind != operandKindReg {
   359  			panic(fmt.Sprintf("BUG: invalid operand: %s", i))
   360  		}
   361  		*regs = append(*regs, opReg.reg())
   362  	case useKindOp1:
   363  		op := i.op1
   364  		switch op.kind {
   365  		case operandKindReg:
   366  			*regs = append(*regs, op.reg())
   367  		case operandKindMem:
   368  			op.addressMode().uses(regs)
   369  		case operandKindImm32, operandKindLabel:
   370  		default:
   371  			panic(fmt.Sprintf("BUG: invalid operand: %s", i))
   372  		}
   373  	case useKindCallInd:
   374  		op := i.op1
   375  		switch op.kind {
   376  		case operandKindReg:
   377  			*regs = append(*regs, op.reg())
   378  		case operandKindMem:
   379  			op.addressMode().uses(regs)
   380  		default:
   381  			panic(fmt.Sprintf("BUG: invalid operand: %s", i))
   382  		}
   383  		fallthrough
   384  	case useKindCall:
   385  		argIntRealRegs, argFloatRealRegs, _, _, _ := backend.ABIInfoFromUint64(i.u2)
   386  		for i := byte(0); i < argIntRealRegs; i++ {
   387  			*regs = append(*regs, regInfo.RealRegToVReg[intArgResultRegs[i]])
   388  		}
   389  		for i := byte(0); i < argFloatRealRegs; i++ {
   390  			*regs = append(*regs, regInfo.RealRegToVReg[floatArgResultRegs[i]])
   391  		}
   392  	case useKindFcvtToSintSequence:
   393  		execCtx, src, tmpGp, tmpGp2, tmpXmm, _, _, _ := i.fcvtToSintSequenceData()
   394  		*regs = append(*regs, execCtx, src, tmpGp, tmpGp2, tmpXmm)
   395  	case useKindFcvtToUintSequence:
   396  		execCtx, src, tmpGp, tmpGp2, tmpXmm, tmpXmm2, _, _, _ := i.fcvtToUintSequenceData()
   397  		*regs = append(*regs, execCtx, src, tmpGp, tmpGp2, tmpXmm, tmpXmm2)
   398  	case useKindDivRem:
   399  		execCtx, divisor, tmpGp, _, _, _ := i.idivRemSequenceData()
   400  		// idiv uses rax and rdx as implicit operands.
   401  		*regs = append(*regs, raxVReg, rdxVReg, execCtx, divisor, tmpGp)
   402  	case useKindBlendvpd:
   403  		*regs = append(*regs, xmm0VReg)
   404  
   405  		opAny, opReg := &i.op1, &i.op2
   406  		switch opAny.kind {
   407  		case operandKindReg:
   408  			*regs = append(*regs, opAny.reg())
   409  		case operandKindMem:
   410  			opAny.addressMode().uses(regs)
   411  		default:
   412  			panic(fmt.Sprintf("BUG: invalid operand: %s", i))
   413  		}
   414  		if opReg.kind != operandKindReg {
   415  			panic(fmt.Sprintf("BUG: invalid operand: %s", i))
   416  		}
   417  		*regs = append(*regs, opReg.reg())
   418  
   419  	case useKindRaxOp1RegOp2:
   420  		opReg, opAny := &i.op1, &i.op2
   421  		*regs = append(*regs, raxVReg, opReg.reg())
   422  		switch opAny.kind {
   423  		case operandKindReg:
   424  			*regs = append(*regs, opAny.reg())
   425  		case operandKindMem:
   426  			opAny.addressMode().uses(regs)
   427  		default:
   428  			panic(fmt.Sprintf("BUG: invalid operand: %s", i))
   429  		}
   430  		if opReg.kind != operandKindReg {
   431  			panic(fmt.Sprintf("BUG: invalid operand: %s", i))
   432  		}
   433  
   434  	default:
   435  		panic(fmt.Sprintf("BUG: invalid useKind %s for %s", uk, i))
   436  	}
   437  	return *regs
   438  }
   439  
   440  // AssignUse implements regalloc.Instr.
   441  func (i *instruction) AssignUse(index int, v regalloc.VReg) {
   442  	switch uk := useKinds[i.kind]; uk {
   443  	case useKindNone:
   444  	case useKindCallInd:
   445  		if index != 0 {
   446  			panic("BUG")
   447  		}
   448  		op := &i.op1
   449  		switch op.kind {
   450  		case operandKindReg:
   451  			op.setReg(v)
   452  		case operandKindMem:
   453  			op.addressMode().assignUses(index, v)
   454  		default:
   455  			panic("BUG")
   456  		}
   457  	case useKindOp1Op2Reg, useKindOp1RegOp2:
   458  		op, opMustBeReg := &i.op1, &i.op2
   459  		if uk == useKindOp1RegOp2 {
   460  			op, opMustBeReg = opMustBeReg, op
   461  		}
   462  		switch op.kind {
   463  		case operandKindReg:
   464  			if index == 0 {
   465  				op.setReg(v)
   466  			} else if index == 1 {
   467  				opMustBeReg.setReg(v)
   468  			} else {
   469  				panic("BUG")
   470  			}
   471  		case operandKindMem:
   472  			nregs := op.addressMode().nregs()
   473  			if index < nregs {
   474  				op.addressMode().assignUses(index, v)
   475  			} else if index == nregs {
   476  				opMustBeReg.setReg(v)
   477  			} else {
   478  				panic("BUG")
   479  			}
   480  		case operandKindImm32:
   481  			if index == 0 {
   482  				opMustBeReg.setReg(v)
   483  			} else {
   484  				panic("BUG")
   485  			}
   486  		default:
   487  			panic(fmt.Sprintf("BUG: invalid operand pair: %s", i))
   488  		}
   489  	case useKindOp1:
   490  		op := &i.op1
   491  		switch op.kind {
   492  		case operandKindReg:
   493  			if index != 0 {
   494  				panic("BUG")
   495  			}
   496  			op.setReg(v)
   497  		case operandKindMem:
   498  			op.addressMode().assignUses(index, v)
   499  		default:
   500  			panic(fmt.Sprintf("BUG: invalid operand: %s", i))
   501  		}
   502  	case useKindFcvtToSintSequence:
   503  		switch index {
   504  		case 0:
   505  			i.op1.addressMode().base = v
   506  		case 1:
   507  			i.op1.addressMode().index = v
   508  		case 2:
   509  			i.op2.addressMode().base = v
   510  		case 3:
   511  			i.op2.addressMode().index = v
   512  		case 4:
   513  			i.u1 = uint64(v)
   514  		default:
   515  			panic("BUG")
   516  		}
   517  	case useKindFcvtToUintSequence:
   518  		switch index {
   519  		case 0:
   520  			i.op1.addressMode().base = v
   521  		case 1:
   522  			i.op1.addressMode().index = v
   523  		case 2:
   524  			i.op2.addressMode().base = v
   525  		case 3:
   526  			i.op2.addressMode().index = v
   527  		case 4:
   528  			i.u1 = uint64(v)
   529  		case 5:
   530  			i.u2 = uint64(v)
   531  		default:
   532  			panic("BUG")
   533  		}
   534  	case useKindDivRem:
   535  		switch index {
   536  		case 0:
   537  			if v != raxVReg {
   538  				panic("BUG")
   539  			}
   540  		case 1:
   541  			if v != rdxVReg {
   542  				panic("BUG")
   543  			}
   544  		case 2:
   545  			i.op1.setReg(v)
   546  		case 3:
   547  			i.op2.setReg(v)
   548  		case 4:
   549  			i.u1 = uint64(v)
   550  		default:
   551  			panic("BUG")
   552  		}
   553  	case useKindBlendvpd:
   554  		op, opMustBeReg := &i.op1, &i.op2
   555  		if index == 0 {
   556  			if v.RealReg() != xmm0 {
   557  				panic("BUG")
   558  			}
   559  		} else {
   560  			switch op.kind {
   561  			case operandKindReg:
   562  				switch index {
   563  				case 1:
   564  					op.setReg(v)
   565  				case 2:
   566  					opMustBeReg.setReg(v)
   567  				default:
   568  					panic("BUG")
   569  				}
   570  			case operandKindMem:
   571  				nregs := op.addressMode().nregs()
   572  				index--
   573  				if index < nregs {
   574  					op.addressMode().assignUses(index, v)
   575  				} else if index == nregs {
   576  					opMustBeReg.setReg(v)
   577  				} else {
   578  					panic("BUG")
   579  				}
   580  			default:
   581  				panic(fmt.Sprintf("BUG: invalid operand pair: %s", i))
   582  			}
   583  		}
   584  
   585  	case useKindRaxOp1RegOp2:
   586  		switch index {
   587  		case 0:
   588  			if v.RealReg() != rax {
   589  				panic("BUG")
   590  			}
   591  		case 1:
   592  			i.op1.setReg(v)
   593  		default:
   594  			op := &i.op2
   595  			switch op.kind {
   596  			case operandKindReg:
   597  				switch index {
   598  				case 1:
   599  					op.setReg(v)
   600  				case 2:
   601  					op.setReg(v)
   602  				default:
   603  					panic("BUG")
   604  				}
   605  			case operandKindMem:
   606  				nregs := op.addressMode().nregs()
   607  				index -= 2
   608  				if index < nregs {
   609  					op.addressMode().assignUses(index, v)
   610  				} else if index == nregs {
   611  					op.setReg(v)
   612  				} else {
   613  					panic("BUG")
   614  				}
   615  			default:
   616  				panic(fmt.Sprintf("BUG: invalid operand pair: %s", i))
   617  			}
   618  		}
   619  	default:
   620  		panic(fmt.Sprintf("BUG: invalid useKind %s for %s", uk, i))
   621  	}
   622  }
   623  
   624  // AssignDef implements regalloc.Instr.
   625  func (i *instruction) AssignDef(reg regalloc.VReg) {
   626  	switch dk := defKinds[i.kind]; dk {
   627  	case defKindNone:
   628  	case defKindOp2:
   629  		i.op2.setReg(reg)
   630  	default:
   631  		panic(fmt.Sprintf("BUG: invalid defKind \"%s\" for %s", dk, i))
   632  	}
   633  }
   634  
   635  // IsCopy implements regalloc.Instr.
   636  func (i *instruction) IsCopy() bool {
   637  	k := i.kind
   638  	if k == movRR {
   639  		return true
   640  	}
   641  	if k == xmmUnaryRmR {
   642  		if i.op1.kind == operandKindReg {
   643  			sse := sseOpcode(i.u1)
   644  			return sse == sseOpcodeMovss || sse == sseOpcodeMovsd || sse == sseOpcodeMovdqu
   645  		}
   646  	}
   647  	return false
   648  }
   649  
   650  func resetInstruction(i *instruction) {
   651  	*i = instruction{}
   652  }
   653  
   654  func setNext(i *instruction, next *instruction) {
   655  	i.next = next
   656  }
   657  
   658  func setPrev(i *instruction, prev *instruction) {
   659  	i.prev = prev
   660  }
   661  
   662  func asNop(i *instruction) {
   663  	i.kind = nop0
   664  }
   665  
   666  func (i *instruction) asNop0WithLabel(label backend.Label) *instruction { //nolint
   667  	i.kind = nop0
   668  	i.u1 = uint64(label)
   669  	return i
   670  }
   671  
   672  func (i *instruction) nop0Label() backend.Label {
   673  	return backend.Label(i.u1)
   674  }
   675  
   676  type instructionKind byte
   677  
   678  const (
   679  	nop0 instructionKind = iota + 1
   680  
   681  	// Integer arithmetic/bit-twiddling: (add sub and or xor mul, etc.) (32 64) (reg addr imm) reg
   682  	aluRmiR
   683  
   684  	// Instructions on GPR that only read src and defines dst (dst is not modified): bsr, etc.
   685  	unaryRmR
   686  
   687  	// Bitwise not
   688  	not
   689  
   690  	// Integer negation
   691  	neg
   692  
   693  	// Integer quotient and remainder: (div idiv) $rax $rdx (reg addr)
   694  	div
   695  
   696  	// The high bits (RDX) of a (un)signed multiply: RDX:RAX := RAX * rhs.
   697  	mulHi
   698  
   699  	// Do a sign-extend based on the sign of the value in rax into rdx: (cwd cdq cqo)
   700  	// or al into ah: (cbw)
   701  	signExtendData
   702  
   703  	// Constant materialization: (imm32 imm64) reg.
   704  	// Either: movl $imm32, %reg32 or movabsq $imm64, %reg64.
   705  	imm
   706  
   707  	// GPR to GPR move: mov (64 32) reg reg.
   708  	movRR
   709  
   710  	// movzxRmR is zero-extended loads or move (R to R), except for 64 bits: movz (bl bq wl wq lq) addr reg.
   711  	// Note that the lq variant doesn't really exist since the default zero-extend rule makes it
   712  	// unnecessary. For that case we emit the equivalent "movl AM, reg32".
   713  	movzxRmR
   714  
   715  	// mov64MR is a plain 64-bit integer load, since movzxRmR can't represent that.
   716  	mov64MR
   717  
   718  	// Loads the memory address of addr into dst.
   719  	lea
   720  
   721  	// Sign-extended loads and moves: movs (bl bq wl wq lq) addr reg.
   722  	movsxRmR
   723  
   724  	// Integer stores: mov (b w l q) reg addr.
   725  	movRM
   726  
   727  	// Arithmetic shifts: (shl shr sar) (b w l q) imm reg.
   728  	shiftR
   729  
   730  	// Arithmetic SIMD shifts.
   731  	xmmRmiReg
   732  
   733  	// Integer comparisons/tests: cmp or test (b w l q) (reg addr imm) reg.
   734  	cmpRmiR
   735  
   736  	// Materializes the requested condition code in the destination reg.
   737  	setcc
   738  
   739  	// Integer conditional move.
   740  	// Overwrites the destination register.
   741  	cmove
   742  
   743  	// pushq (reg addr imm)
   744  	push64
   745  
   746  	// popq reg
   747  	pop64
   748  
   749  	// XMM (scalar or vector) binary op: (add sub and or xor mul adc? sbb?) (32 64) (reg addr) reg
   750  	xmmRmR
   751  
   752  	// XMM (scalar or vector) unary op: mov between XMM registers (32 64) (reg addr) reg.
   753  	//
   754  	// This differs from xmmRmR in that the dst register of xmmUnaryRmR is not used in the
   755  	// computation of the instruction dst value and so does not have to be a previously valid
   756  	// value. This is characteristic of mov instructions.
   757  	xmmUnaryRmR
   758  
   759  	// XMM (scalar or vector) unary op with immediate: roundss, roundsd, etc.
   760  	//
   761  	// This differs from XMM_RM_R_IMM in that the dst register of
   762  	// XmmUnaryRmRImm is not used in the computation of the instruction dst
   763  	// value and so does not have to be a previously valid value.
   764  	xmmUnaryRmRImm
   765  
   766  	// XMM (scalar or vector) unary op (from xmm to mem): stores, movd, movq
   767  	xmmMovRM
   768  
   769  	// XMM (vector) unary op (to move a constant value into an xmm register): movups
   770  	xmmLoadConst
   771  
   772  	// XMM (scalar) unary op (from xmm to integer reg): movd, movq, cvtts{s,d}2si
   773  	xmmToGpr
   774  
   775  	// XMM (scalar) unary op (from integer to float reg): movd, movq, cvtsi2s{s,d}
   776  	gprToXmm
   777  
   778  	// Converts an unsigned int64 to a float32/float64.
   779  	cvtUint64ToFloatSeq
   780  
   781  	// Converts a scalar xmm to a signed int32/int64.
   782  	cvtFloatToSintSeq
   783  
   784  	// Converts a scalar xmm to an unsigned int32/int64.
   785  	cvtFloatToUintSeq
   786  
   787  	// A sequence to compute min/max with the proper NaN semantics for xmm registers.
   788  	xmmMinMaxSeq
   789  
   790  	// Float comparisons/tests: cmp (b w l q) (reg addr imm) reg.
   791  	xmmCmpRmR
   792  
   793  	// A binary XMM instruction with an 8-bit immediate: e.g. cmp (ps pd) imm (reg addr) reg
   794  	xmmRmRImm
   795  
   796  	// Direct call: call simm32.
   797  	// Note that the offset is the relative to the *current RIP*, which points to the first byte of the next instruction.
   798  	call
   799  
   800  	// Indirect call: callq (reg mem).
   801  	callIndirect
   802  
   803  	// Return.
   804  	ret
   805  
   806  	// Jump: jmp (reg, mem, imm32 or label)
   807  	jmp
   808  
   809  	// Jump conditionally: jcond cond label.
   810  	jmpIf
   811  
   812  	// jmpTableIsland is to emit the jump table.
   813  	jmpTableIsland
   814  
   815  	// exitSequence exits the execution and go back to the Go world.
   816  	exitSequence
   817  
   818  	// An instruction that will always trigger the illegal instruction exception.
   819  	ud2
   820  
   821  	// xchg is described in https://www.felixcloutier.com/x86/xchg.
   822  	// This instruction uses two operands, where one of them can be a memory address, and swaps their values.
   823  	// If the dst is a memory address, the execution is atomic.
   824  	xchg
   825  
   826  	// lockcmpxchg is the cmpxchg instruction https://www.felixcloutier.com/x86/cmpxchg with a lock prefix.
   827  	lockcmpxchg
   828  
   829  	// zeros puts zeros into the destination register. This is implemented as xor reg, reg for
   830  	// either integer or XMM registers. The reason why we have this instruction instead of using aluRmiR
   831  	// is that it requires the already-defined registers. From reg alloc's perspective, this defines
   832  	// the destination register and takes no inputs.
   833  	zeros
   834  
   835  	// sourceOffsetInfo is a dummy instruction to emit source offset info.
   836  	// The existence of this instruction does not affect the execution.
   837  	sourceOffsetInfo
   838  
   839  	// defineUninitializedReg is a no-op instruction that defines a register without a defining instruction.
   840  	defineUninitializedReg
   841  
   842  	// fcvtToSintSequence is a sequence of instructions to convert a float to a signed integer.
   843  	fcvtToSintSequence
   844  
   845  	// fcvtToUintSequence is a sequence of instructions to convert a float to an unsigned integer.
   846  	fcvtToUintSequence
   847  
   848  	// xmmCMov is a conditional move instruction for XMM registers. Lowered after register allocation.
   849  	xmmCMov
   850  
   851  	// idivRemSequence is a sequence of instructions to compute both the quotient and remainder of a division.
   852  	idivRemSequence
   853  
   854  	// blendvpd is https://www.felixcloutier.com/x86/blendvpd.
   855  	blendvpd
   856  
   857  	// mfence is https://www.felixcloutier.com/x86/mfence
   858  	mfence
   859  
   860  	// lockxadd is xadd https://www.felixcloutier.com/x86/xadd with a lock prefix.
   861  	lockxadd
   862  
   863  	// nopUseReg is a meta instruction that uses one register and does nothing.
   864  	nopUseReg
   865  
   866  	instrMax
   867  )
   868  
   869  func (i *instruction) asMFence() *instruction {
   870  	i.kind = mfence
   871  	return i
   872  }
   873  
   874  func (i *instruction) asNopUseReg(r regalloc.VReg) *instruction {
   875  	i.kind = nopUseReg
   876  	i.op1 = newOperandReg(r)
   877  	return i
   878  }
   879  
   880  func (i *instruction) asIdivRemSequence(execCtx, divisor, tmpGp regalloc.VReg, isDiv, signed, _64 bool) *instruction {
   881  	i.kind = idivRemSequence
   882  	i.op1 = newOperandReg(execCtx)
   883  	i.op2 = newOperandReg(divisor)
   884  	i.u1 = uint64(tmpGp)
   885  	if isDiv {
   886  		i.u2 |= 1
   887  	}
   888  	if signed {
   889  		i.u2 |= 2
   890  	}
   891  	if _64 {
   892  		i.u2 |= 4
   893  	}
   894  	return i
   895  }
   896  
   897  func (i *instruction) idivRemSequenceData() (
   898  	execCtx, divisor, tmpGp regalloc.VReg, isDiv, signed, _64 bool,
   899  ) {
   900  	if i.kind != idivRemSequence {
   901  		panic("BUG")
   902  	}
   903  	return i.op1.reg(), i.op2.reg(), regalloc.VReg(i.u1), i.u2&1 != 0, i.u2&2 != 0, i.u2&4 != 0
   904  }
   905  
   906  func (i *instruction) asXmmCMov(cc cond, x operand, rd regalloc.VReg, size byte) *instruction {
   907  	i.kind = xmmCMov
   908  	i.op1 = x
   909  	i.op2 = newOperandReg(rd)
   910  	i.u1 = uint64(cc)
   911  	i.u2 = uint64(size)
   912  	return i
   913  }
   914  
   915  func (i *instruction) asDefineUninitializedReg(r regalloc.VReg) *instruction {
   916  	i.kind = defineUninitializedReg
   917  	i.op2 = newOperandReg(r)
   918  	return i
   919  }
   920  
   921  func (m *machine) allocateFcvtToUintSequence(
   922  	execCtx, src, tmpGp, tmpGp2, tmpXmm, tmpXmm2 regalloc.VReg,
   923  	src64, dst64, sat bool,
   924  ) *instruction {
   925  	i := m.allocateInstr()
   926  	i.kind = fcvtToUintSequence
   927  	op1a := m.amodePool.Allocate()
   928  	op2a := m.amodePool.Allocate()
   929  	i.op1 = newOperandMem(op1a)
   930  	i.op2 = newOperandMem(op2a)
   931  	if src64 {
   932  		op1a.imm32 = 1
   933  	} else {
   934  		op1a.imm32 = 0
   935  	}
   936  	if dst64 {
   937  		op1a.imm32 |= 2
   938  	}
   939  	if sat {
   940  		op1a.imm32 |= 4
   941  	}
   942  
   943  	op1a.base = execCtx
   944  	op1a.index = src
   945  	op2a.base = tmpGp
   946  	op2a.index = tmpGp2
   947  	i.u1 = uint64(tmpXmm)
   948  	i.u2 = uint64(tmpXmm2)
   949  	return i
   950  }
   951  
   952  func (i *instruction) fcvtToUintSequenceData() (
   953  	execCtx, src, tmpGp, tmpGp2, tmpXmm, tmpXmm2 regalloc.VReg, src64, dst64, sat bool,
   954  ) {
   955  	if i.kind != fcvtToUintSequence {
   956  		panic("BUG")
   957  	}
   958  	op1a := i.op1.addressMode()
   959  	op2a := i.op2.addressMode()
   960  	return op1a.base, op1a.index, op2a.base, op2a.index, regalloc.VReg(i.u1), regalloc.VReg(i.u2),
   961  		op1a.imm32&1 != 0, op1a.imm32&2 != 0, op1a.imm32&4 != 0
   962  }
   963  
   964  func (m *machine) allocateFcvtToSintSequence(
   965  	execCtx, src, tmpGp, tmpGp2, tmpXmm regalloc.VReg,
   966  	src64, dst64, sat bool,
   967  ) *instruction {
   968  	i := m.allocateInstr()
   969  	i.kind = fcvtToSintSequence
   970  	op1a := m.amodePool.Allocate()
   971  	op2a := m.amodePool.Allocate()
   972  	i.op1 = newOperandMem(op1a)
   973  	i.op2 = newOperandMem(op2a)
   974  	op1a.base = execCtx
   975  	op1a.index = src
   976  	op2a.base = tmpGp
   977  	op2a.index = tmpGp2
   978  	i.u1 = uint64(tmpXmm)
   979  	if src64 {
   980  		i.u2 = 1
   981  	} else {
   982  		i.u2 = 0
   983  	}
   984  	if dst64 {
   985  		i.u2 |= 2
   986  	}
   987  	if sat {
   988  		i.u2 |= 4
   989  	}
   990  	return i
   991  }
   992  
   993  func (i *instruction) fcvtToSintSequenceData() (
   994  	execCtx, src, tmpGp, tmpGp2, tmpXmm regalloc.VReg, src64, dst64, sat bool,
   995  ) {
   996  	if i.kind != fcvtToSintSequence {
   997  		panic("BUG")
   998  	}
   999  	op1a := i.op1.addressMode()
  1000  	op2a := i.op2.addressMode()
  1001  	return op1a.base, op1a.index, op2a.base, op2a.index, regalloc.VReg(i.u1),
  1002  		i.u2&1 != 0, i.u2&2 != 0, i.u2&4 != 0
  1003  }
  1004  
  1005  func (k instructionKind) String() string {
  1006  	switch k {
  1007  	case nop0:
  1008  		return "nop"
  1009  	case ret:
  1010  		return "ret"
  1011  	case imm:
  1012  		return "imm"
  1013  	case aluRmiR:
  1014  		return "aluRmiR"
  1015  	case movRR:
  1016  		return "movRR"
  1017  	case xmmRmR:
  1018  		return "xmmRmR"
  1019  	case gprToXmm:
  1020  		return "gprToXmm"
  1021  	case xmmUnaryRmR:
  1022  		return "xmmUnaryRmR"
  1023  	case xmmUnaryRmRImm:
  1024  		return "xmmUnaryRmRImm"
  1025  	case unaryRmR:
  1026  		return "unaryRmR"
  1027  	case not:
  1028  		return "not"
  1029  	case neg:
  1030  		return "neg"
  1031  	case div:
  1032  		return "div"
  1033  	case mulHi:
  1034  		return "mulHi"
  1035  	case signExtendData:
  1036  		return "signExtendData"
  1037  	case movzxRmR:
  1038  		return "movzxRmR"
  1039  	case mov64MR:
  1040  		return "mov64MR"
  1041  	case lea:
  1042  		return "lea"
  1043  	case movsxRmR:
  1044  		return "movsxRmR"
  1045  	case movRM:
  1046  		return "movRM"
  1047  	case shiftR:
  1048  		return "shiftR"
  1049  	case xmmRmiReg:
  1050  		return "xmmRmiReg"
  1051  	case cmpRmiR:
  1052  		return "cmpRmiR"
  1053  	case setcc:
  1054  		return "setcc"
  1055  	case cmove:
  1056  		return "cmove"
  1057  	case push64:
  1058  		return "push64"
  1059  	case pop64:
  1060  		return "pop64"
  1061  	case xmmMovRM:
  1062  		return "xmmMovRM"
  1063  	case xmmLoadConst:
  1064  		return "xmmLoadConst"
  1065  	case xmmToGpr:
  1066  		return "xmmToGpr"
  1067  	case cvtUint64ToFloatSeq:
  1068  		return "cvtUint64ToFloatSeq"
  1069  	case cvtFloatToSintSeq:
  1070  		return "cvtFloatToSintSeq"
  1071  	case cvtFloatToUintSeq:
  1072  		return "cvtFloatToUintSeq"
  1073  	case xmmMinMaxSeq:
  1074  		return "xmmMinMaxSeq"
  1075  	case xmmCmpRmR:
  1076  		return "xmmCmpRmR"
  1077  	case xmmRmRImm:
  1078  		return "xmmRmRImm"
  1079  	case jmpIf:
  1080  		return "jmpIf"
  1081  	case jmp:
  1082  		return "jmp"
  1083  	case jmpTableIsland:
  1084  		return "jmpTableIsland"
  1085  	case exitSequence:
  1086  		return "exit_sequence"
  1087  	case ud2:
  1088  		return "ud2"
  1089  	case xchg:
  1090  		return "xchg"
  1091  	case zeros:
  1092  		return "zeros"
  1093  	case fcvtToSintSequence:
  1094  		return "fcvtToSintSequence"
  1095  	case fcvtToUintSequence:
  1096  		return "fcvtToUintSequence"
  1097  	case xmmCMov:
  1098  		return "xmmCMov"
  1099  	case idivRemSequence:
  1100  		return "idivRemSequence"
  1101  	case mfence:
  1102  		return "mfence"
  1103  	case lockcmpxchg:
  1104  		return "lockcmpxchg"
  1105  	case lockxadd:
  1106  		return "lockxadd"
  1107  	default:
  1108  		panic("BUG")
  1109  	}
  1110  }
  1111  
  1112  type aluRmiROpcode byte
  1113  
  1114  const (
  1115  	aluRmiROpcodeAdd aluRmiROpcode = iota + 1
  1116  	aluRmiROpcodeSub
  1117  	aluRmiROpcodeAnd
  1118  	aluRmiROpcodeOr
  1119  	aluRmiROpcodeXor
  1120  	aluRmiROpcodeMul
  1121  )
  1122  
  1123  func (a aluRmiROpcode) String() string {
  1124  	switch a {
  1125  	case aluRmiROpcodeAdd:
  1126  		return "add"
  1127  	case aluRmiROpcodeSub:
  1128  		return "sub"
  1129  	case aluRmiROpcodeAnd:
  1130  		return "and"
  1131  	case aluRmiROpcodeOr:
  1132  		return "or"
  1133  	case aluRmiROpcodeXor:
  1134  		return "xor"
  1135  	case aluRmiROpcodeMul:
  1136  		return "imul"
  1137  	default:
  1138  		panic("BUG")
  1139  	}
  1140  }
  1141  
  1142  func (i *instruction) asJmpIf(cond cond, target operand) *instruction {
  1143  	i.kind = jmpIf
  1144  	i.u1 = uint64(cond)
  1145  	i.op1 = target
  1146  	return i
  1147  }
  1148  
  1149  // asJmpTableSequence is used to emit the jump table.
  1150  // targetSliceIndex is the index of the target slice in machine.jmpTableTargets.
  1151  func (i *instruction) asJmpTableSequence(targetSliceIndex int, targetCount int) *instruction {
  1152  	i.kind = jmpTableIsland
  1153  	i.u1 = uint64(targetSliceIndex)
  1154  	i.u2 = uint64(targetCount)
  1155  	return i
  1156  }
  1157  
  1158  func (i *instruction) asJmp(target operand) *instruction {
  1159  	i.kind = jmp
  1160  	i.op1 = target
  1161  	return i
  1162  }
  1163  
  1164  func (i *instruction) jmpLabel() backend.Label {
  1165  	switch i.kind {
  1166  	case jmp, jmpIf, lea, xmmUnaryRmR:
  1167  		return i.op1.label()
  1168  	default:
  1169  		panic("BUG")
  1170  	}
  1171  }
  1172  
  1173  func (i *instruction) asLEA(target operand, rd regalloc.VReg) *instruction {
  1174  	i.kind = lea
  1175  	i.op1 = target
  1176  	i.op2 = newOperandReg(rd)
  1177  	return i
  1178  }
  1179  
  1180  func (i *instruction) asCall(ref ssa.FuncRef, abi *backend.FunctionABI) *instruction {
  1181  	i.kind = call
  1182  	i.u1 = uint64(ref)
  1183  	if abi != nil {
  1184  		i.u2 = abi.ABIInfoAsUint64()
  1185  	}
  1186  	return i
  1187  }
  1188  
  1189  func (i *instruction) asCallIndirect(ptr operand, abi *backend.FunctionABI) *instruction {
  1190  	if ptr.kind != operandKindReg && ptr.kind != operandKindMem {
  1191  		panic("BUG")
  1192  	}
  1193  	i.kind = callIndirect
  1194  	i.op1 = ptr
  1195  	if abi != nil {
  1196  		i.u2 = abi.ABIInfoAsUint64()
  1197  	}
  1198  	return i
  1199  }
  1200  
  1201  func (i *instruction) asRet() *instruction {
  1202  	i.kind = ret
  1203  	return i
  1204  }
  1205  
  1206  func (i *instruction) asImm(dst regalloc.VReg, value uint64, _64 bool) *instruction {
  1207  	i.kind = imm
  1208  	i.op2 = newOperandReg(dst)
  1209  	i.u1 = value
  1210  	i.b1 = _64
  1211  	return i
  1212  }
  1213  
  1214  func (i *instruction) asAluRmiR(op aluRmiROpcode, rm operand, rd regalloc.VReg, _64 bool) *instruction {
  1215  	if rm.kind != operandKindReg && rm.kind != operandKindMem && rm.kind != operandKindImm32 {
  1216  		panic("BUG")
  1217  	}
  1218  	i.kind = aluRmiR
  1219  	i.op1 = rm
  1220  	i.op2 = newOperandReg(rd)
  1221  	i.u1 = uint64(op)
  1222  	i.b1 = _64
  1223  	return i
  1224  }
  1225  
  1226  func (i *instruction) asZeros(dst regalloc.VReg) *instruction {
  1227  	i.kind = zeros
  1228  	i.op2 = newOperandReg(dst)
  1229  	return i
  1230  }
  1231  
  1232  func (i *instruction) asBlendvpd(rm operand, rd regalloc.VReg) *instruction {
  1233  	if rm.kind != operandKindReg && rm.kind != operandKindMem {
  1234  		panic("BUG")
  1235  	}
  1236  	i.kind = blendvpd
  1237  	i.op1 = rm
  1238  	i.op2 = newOperandReg(rd)
  1239  	return i
  1240  }
  1241  
  1242  func (i *instruction) asXmmRmR(op sseOpcode, rm operand, rd regalloc.VReg) *instruction {
  1243  	if rm.kind != operandKindReg && rm.kind != operandKindMem {
  1244  		panic("BUG")
  1245  	}
  1246  	i.kind = xmmRmR
  1247  	i.op1 = rm
  1248  	i.op2 = newOperandReg(rd)
  1249  	i.u1 = uint64(op)
  1250  	return i
  1251  }
  1252  
  1253  func (i *instruction) asXmmRmRImm(op sseOpcode, imm uint8, rm operand, rd regalloc.VReg) *instruction {
  1254  	if rm.kind != operandKindReg && rm.kind != operandKindMem {
  1255  		panic("BUG")
  1256  	}
  1257  	i.kind = xmmRmRImm
  1258  	i.op1 = rm
  1259  	i.op2 = newOperandReg(rd)
  1260  	i.u1 = uint64(op)
  1261  	i.u2 = uint64(imm)
  1262  	return i
  1263  }
  1264  
  1265  func (i *instruction) asGprToXmm(op sseOpcode, rm operand, rd regalloc.VReg, _64 bool) *instruction {
  1266  	if rm.kind != operandKindReg && rm.kind != operandKindMem {
  1267  		panic("BUG")
  1268  	}
  1269  	i.kind = gprToXmm
  1270  	i.op1 = rm
  1271  	i.op2 = newOperandReg(rd)
  1272  	i.u1 = uint64(op)
  1273  	i.b1 = _64
  1274  	return i
  1275  }
  1276  
  1277  func (i *instruction) asEmitSourceOffsetInfo(l ssa.SourceOffset) *instruction {
  1278  	i.kind = sourceOffsetInfo
  1279  	i.u1 = uint64(l)
  1280  	return i
  1281  }
  1282  
  1283  func (i *instruction) sourceOffsetInfo() ssa.SourceOffset {
  1284  	return ssa.SourceOffset(i.u1)
  1285  }
  1286  
  1287  func (i *instruction) asXmmToGpr(op sseOpcode, rm, rd regalloc.VReg, _64 bool) *instruction {
  1288  	i.kind = xmmToGpr
  1289  	i.op1 = newOperandReg(rm)
  1290  	i.op2 = newOperandReg(rd)
  1291  	i.u1 = uint64(op)
  1292  	i.b1 = _64
  1293  	return i
  1294  }
  1295  
  1296  func (i *instruction) asMovRM(rm regalloc.VReg, rd operand, size byte) *instruction {
  1297  	if rd.kind != operandKindMem {
  1298  		panic("BUG")
  1299  	}
  1300  	i.kind = movRM
  1301  	i.op1 = newOperandReg(rm)
  1302  	i.op2 = rd
  1303  	i.u1 = uint64(size)
  1304  	return i
  1305  }
  1306  
  1307  func (i *instruction) asMovsxRmR(ext extMode, src operand, rd regalloc.VReg) *instruction {
  1308  	if src.kind != operandKindReg && src.kind != operandKindMem {
  1309  		panic("BUG")
  1310  	}
  1311  	i.kind = movsxRmR
  1312  	i.op1 = src
  1313  	i.op2 = newOperandReg(rd)
  1314  	i.u1 = uint64(ext)
  1315  	return i
  1316  }
  1317  
  1318  func (i *instruction) asMovzxRmR(ext extMode, src operand, rd regalloc.VReg) *instruction {
  1319  	if src.kind != operandKindReg && src.kind != operandKindMem {
  1320  		panic("BUG")
  1321  	}
  1322  	i.kind = movzxRmR
  1323  	i.op1 = src
  1324  	i.op2 = newOperandReg(rd)
  1325  	i.u1 = uint64(ext)
  1326  	return i
  1327  }
  1328  
  1329  func (i *instruction) asSignExtendData(_64 bool) *instruction {
  1330  	i.kind = signExtendData
  1331  	i.b1 = _64
  1332  	return i
  1333  }
  1334  
  1335  func (i *instruction) asUD2() *instruction {
  1336  	i.kind = ud2
  1337  	return i
  1338  }
  1339  
  1340  func (i *instruction) asDiv(rn operand, signed bool, _64 bool) *instruction {
  1341  	i.kind = div
  1342  	i.op1 = rn
  1343  	i.b1 = _64
  1344  	if signed {
  1345  		i.u1 = 1
  1346  	}
  1347  	return i
  1348  }
  1349  
  1350  func (i *instruction) asMov64MR(rm operand, rd regalloc.VReg) *instruction {
  1351  	if rm.kind != operandKindMem {
  1352  		panic("BUG")
  1353  	}
  1354  	i.kind = mov64MR
  1355  	i.op1 = rm
  1356  	i.op2 = newOperandReg(rd)
  1357  	return i
  1358  }
  1359  
  1360  func (i *instruction) asMovRR(rm, rd regalloc.VReg, _64 bool) *instruction {
  1361  	i.kind = movRR
  1362  	i.op1 = newOperandReg(rm)
  1363  	i.op2 = newOperandReg(rd)
  1364  	i.b1 = _64
  1365  	return i
  1366  }
  1367  
  1368  func (i *instruction) asNot(rm operand, _64 bool) *instruction {
  1369  	if rm.kind != operandKindReg && rm.kind != operandKindMem {
  1370  		panic("BUG")
  1371  	}
  1372  	i.kind = not
  1373  	i.op1 = rm
  1374  	i.b1 = _64
  1375  	return i
  1376  }
  1377  
  1378  func (i *instruction) asNeg(rm operand, _64 bool) *instruction {
  1379  	if rm.kind != operandKindReg && rm.kind != operandKindMem {
  1380  		panic("BUG")
  1381  	}
  1382  	i.kind = neg
  1383  	i.op1 = rm
  1384  	i.b1 = _64
  1385  	return i
  1386  }
  1387  
  1388  func (i *instruction) asMulHi(rm operand, signed, _64 bool) *instruction {
  1389  	if rm.kind != operandKindReg && (rm.kind != operandKindMem) {
  1390  		panic("BUG")
  1391  	}
  1392  	i.kind = mulHi
  1393  	i.op1 = rm
  1394  	i.b1 = _64
  1395  	if signed {
  1396  		i.u1 = 1
  1397  	}
  1398  	return i
  1399  }
  1400  
  1401  func (i *instruction) asUnaryRmR(op unaryRmROpcode, rm operand, rd regalloc.VReg, _64 bool) *instruction {
  1402  	if rm.kind != operandKindReg && rm.kind != operandKindMem {
  1403  		panic("BUG")
  1404  	}
  1405  	i.kind = unaryRmR
  1406  	i.op1 = rm
  1407  	i.op2 = newOperandReg(rd)
  1408  	i.u1 = uint64(op)
  1409  	i.b1 = _64
  1410  	return i
  1411  }
  1412  
  1413  func (i *instruction) asShiftR(op shiftROp, amount operand, rd regalloc.VReg, _64 bool) *instruction {
  1414  	if amount.kind != operandKindReg && amount.kind != operandKindImm32 {
  1415  		panic("BUG")
  1416  	}
  1417  	i.kind = shiftR
  1418  	i.op1 = amount
  1419  	i.op2 = newOperandReg(rd)
  1420  	i.u1 = uint64(op)
  1421  	i.b1 = _64
  1422  	return i
  1423  }
  1424  
  1425  func (i *instruction) asXmmRmiReg(op sseOpcode, rm operand, rd regalloc.VReg) *instruction {
  1426  	if rm.kind != operandKindReg && rm.kind != operandKindImm32 && rm.kind != operandKindMem {
  1427  		panic("BUG")
  1428  	}
  1429  	i.kind = xmmRmiReg
  1430  	i.op1 = rm
  1431  	i.op2 = newOperandReg(rd)
  1432  	i.u1 = uint64(op)
  1433  	return i
  1434  }
  1435  
  1436  func (i *instruction) asCmpRmiR(cmp bool, rm operand, rn regalloc.VReg, _64 bool) *instruction {
  1437  	if rm.kind != operandKindReg && rm.kind != operandKindImm32 && rm.kind != operandKindMem {
  1438  		panic("BUG")
  1439  	}
  1440  	i.kind = cmpRmiR
  1441  	i.op1 = rm
  1442  	i.op2 = newOperandReg(rn)
  1443  	if cmp {
  1444  		i.u1 = 1
  1445  	}
  1446  	i.b1 = _64
  1447  	return i
  1448  }
  1449  
  1450  func (i *instruction) asSetcc(c cond, rd regalloc.VReg) *instruction {
  1451  	i.kind = setcc
  1452  	i.op2 = newOperandReg(rd)
  1453  	i.u1 = uint64(c)
  1454  	return i
  1455  }
  1456  
  1457  func (i *instruction) asCmove(c cond, rm operand, rd regalloc.VReg, _64 bool) *instruction {
  1458  	i.kind = cmove
  1459  	i.op1 = rm
  1460  	i.op2 = newOperandReg(rd)
  1461  	i.u1 = uint64(c)
  1462  	i.b1 = _64
  1463  	return i
  1464  }
  1465  
  1466  func (m *machine) allocateExitSeq(execCtx regalloc.VReg) *instruction {
  1467  	i := m.allocateInstr()
  1468  	i.kind = exitSequence
  1469  	i.op1 = newOperandReg(execCtx)
  1470  	// Allocate the address mode that will be used in encoding the exit sequence.
  1471  	i.op2 = newOperandMem(m.amodePool.Allocate())
  1472  	return i
  1473  }
  1474  
  1475  func (i *instruction) asXmmUnaryRmR(op sseOpcode, rm operand, rd regalloc.VReg) *instruction {
  1476  	if rm.kind != operandKindReg && rm.kind != operandKindMem {
  1477  		panic("BUG")
  1478  	}
  1479  	i.kind = xmmUnaryRmR
  1480  	i.op1 = rm
  1481  	i.op2 = newOperandReg(rd)
  1482  	i.u1 = uint64(op)
  1483  	return i
  1484  }
  1485  
  1486  func (i *instruction) asXmmUnaryRmRImm(op sseOpcode, imm byte, rm operand, rd regalloc.VReg) *instruction {
  1487  	if rm.kind != operandKindReg && rm.kind != operandKindMem {
  1488  		panic("BUG")
  1489  	}
  1490  	i.kind = xmmUnaryRmRImm
  1491  	i.op1 = rm
  1492  	i.op2 = newOperandReg(rd)
  1493  	i.u1 = uint64(op)
  1494  	i.u2 = uint64(imm)
  1495  	return i
  1496  }
  1497  
  1498  func (i *instruction) asXmmCmpRmR(op sseOpcode, rm operand, rd regalloc.VReg) *instruction {
  1499  	if rm.kind != operandKindReg && rm.kind != operandKindMem {
  1500  		panic("BUG")
  1501  	}
  1502  	i.kind = xmmCmpRmR
  1503  	i.op1 = rm
  1504  	i.op2 = newOperandReg(rd)
  1505  	i.u1 = uint64(op)
  1506  	return i
  1507  }
  1508  
  1509  func (i *instruction) asXmmMovRM(op sseOpcode, rm regalloc.VReg, rd operand) *instruction {
  1510  	if rd.kind != operandKindMem {
  1511  		panic("BUG")
  1512  	}
  1513  	i.kind = xmmMovRM
  1514  	i.op1 = newOperandReg(rm)
  1515  	i.op2 = rd
  1516  	i.u1 = uint64(op)
  1517  	return i
  1518  }
  1519  
  1520  func (i *instruction) asPop64(rm regalloc.VReg) *instruction {
  1521  	i.kind = pop64
  1522  	i.op1 = newOperandReg(rm)
  1523  	return i
  1524  }
  1525  
  1526  func (i *instruction) asPush64(op operand) *instruction {
  1527  	if op.kind != operandKindReg && op.kind != operandKindMem && op.kind != operandKindImm32 {
  1528  		panic("BUG")
  1529  	}
  1530  	i.kind = push64
  1531  	i.op1 = op
  1532  	return i
  1533  }
  1534  
  1535  func (i *instruction) asXCHG(rm regalloc.VReg, rd operand, size byte) *instruction {
  1536  	i.kind = xchg
  1537  	i.op1 = newOperandReg(rm)
  1538  	i.op2 = rd
  1539  	i.u1 = uint64(size)
  1540  	return i
  1541  }
  1542  
  1543  func (i *instruction) asLockCmpXCHG(rm regalloc.VReg, rd *amode, size byte) *instruction {
  1544  	i.kind = lockcmpxchg
  1545  	i.op1 = newOperandReg(rm)
  1546  	i.op2 = newOperandMem(rd)
  1547  	i.u1 = uint64(size)
  1548  	return i
  1549  }
  1550  
  1551  func (i *instruction) asLockXAdd(rm regalloc.VReg, rd *amode, size byte) *instruction {
  1552  	i.kind = lockxadd
  1553  	i.op1 = newOperandReg(rm)
  1554  	i.op2 = newOperandMem(rd)
  1555  	i.u1 = uint64(size)
  1556  	return i
  1557  }
  1558  
  1559  type unaryRmROpcode byte
  1560  
  1561  const (
  1562  	unaryRmROpcodeBsr unaryRmROpcode = iota
  1563  	unaryRmROpcodeBsf
  1564  	unaryRmROpcodeLzcnt
  1565  	unaryRmROpcodeTzcnt
  1566  	unaryRmROpcodePopcnt
  1567  )
  1568  
  1569  func (u unaryRmROpcode) String() string {
  1570  	switch u {
  1571  	case unaryRmROpcodeBsr:
  1572  		return "bsr"
  1573  	case unaryRmROpcodeBsf:
  1574  		return "bsf"
  1575  	case unaryRmROpcodeLzcnt:
  1576  		return "lzcnt"
  1577  	case unaryRmROpcodeTzcnt:
  1578  		return "tzcnt"
  1579  	case unaryRmROpcodePopcnt:
  1580  		return "popcnt"
  1581  	default:
  1582  		panic("BUG")
  1583  	}
  1584  }
  1585  
  1586  type shiftROp byte
  1587  
  1588  const (
  1589  	shiftROpRotateLeft           shiftROp = 0
  1590  	shiftROpRotateRight          shiftROp = 1
  1591  	shiftROpShiftLeft            shiftROp = 4
  1592  	shiftROpShiftRightLogical    shiftROp = 5
  1593  	shiftROpShiftRightArithmetic shiftROp = 7
  1594  )
  1595  
  1596  func (s shiftROp) String() string {
  1597  	switch s {
  1598  	case shiftROpRotateLeft:
  1599  		return "rol"
  1600  	case shiftROpRotateRight:
  1601  		return "ror"
  1602  	case shiftROpShiftLeft:
  1603  		return "shl"
  1604  	case shiftROpShiftRightLogical:
  1605  		return "shr"
  1606  	case shiftROpShiftRightArithmetic:
  1607  		return "sar"
  1608  	default:
  1609  		panic("BUG")
  1610  	}
  1611  }
  1612  
  1613  type sseOpcode byte
  1614  
  1615  const (
  1616  	sseOpcodeInvalid sseOpcode = iota
  1617  	sseOpcodeAddps
  1618  	sseOpcodeAddpd
  1619  	sseOpcodeAddss
  1620  	sseOpcodeAddsd
  1621  	sseOpcodeAndps
  1622  	sseOpcodeAndpd
  1623  	sseOpcodeAndnps
  1624  	sseOpcodeAndnpd
  1625  	sseOpcodeBlendvps
  1626  	sseOpcodeBlendvpd
  1627  	sseOpcodeComiss
  1628  	sseOpcodeComisd
  1629  	sseOpcodeCmpps
  1630  	sseOpcodeCmppd
  1631  	sseOpcodeCmpss
  1632  	sseOpcodeCmpsd
  1633  	sseOpcodeCvtdq2ps
  1634  	sseOpcodeCvtdq2pd
  1635  	sseOpcodeCvtsd2ss
  1636  	sseOpcodeCvtsd2si
  1637  	sseOpcodeCvtsi2ss
  1638  	sseOpcodeCvtsi2sd
  1639  	sseOpcodeCvtss2si
  1640  	sseOpcodeCvtss2sd
  1641  	sseOpcodeCvttps2dq
  1642  	sseOpcodeCvttss2si
  1643  	sseOpcodeCvttsd2si
  1644  	sseOpcodeDivps
  1645  	sseOpcodeDivpd
  1646  	sseOpcodeDivss
  1647  	sseOpcodeDivsd
  1648  	sseOpcodeInsertps
  1649  	sseOpcodeMaxps
  1650  	sseOpcodeMaxpd
  1651  	sseOpcodeMaxss
  1652  	sseOpcodeMaxsd
  1653  	sseOpcodeMinps
  1654  	sseOpcodeMinpd
  1655  	sseOpcodeMinss
  1656  	sseOpcodeMinsd
  1657  	sseOpcodeMovaps
  1658  	sseOpcodeMovapd
  1659  	sseOpcodeMovd
  1660  	sseOpcodeMovdqa
  1661  	sseOpcodeMovdqu
  1662  	sseOpcodeMovlhps
  1663  	sseOpcodeMovmskps
  1664  	sseOpcodeMovmskpd
  1665  	sseOpcodeMovq
  1666  	sseOpcodeMovss
  1667  	sseOpcodeMovsd
  1668  	sseOpcodeMovups
  1669  	sseOpcodeMovupd
  1670  	sseOpcodeMulps
  1671  	sseOpcodeMulpd
  1672  	sseOpcodeMulss
  1673  	sseOpcodeMulsd
  1674  	sseOpcodeOrps
  1675  	sseOpcodeOrpd
  1676  	sseOpcodePabsb
  1677  	sseOpcodePabsw
  1678  	sseOpcodePabsd
  1679  	sseOpcodePackssdw
  1680  	sseOpcodePacksswb
  1681  	sseOpcodePackusdw
  1682  	sseOpcodePackuswb
  1683  	sseOpcodePaddb
  1684  	sseOpcodePaddd
  1685  	sseOpcodePaddq
  1686  	sseOpcodePaddw
  1687  	sseOpcodePaddsb
  1688  	sseOpcodePaddsw
  1689  	sseOpcodePaddusb
  1690  	sseOpcodePaddusw
  1691  	sseOpcodePalignr
  1692  	sseOpcodePand
  1693  	sseOpcodePandn
  1694  	sseOpcodePavgb
  1695  	sseOpcodePavgw
  1696  	sseOpcodePcmpeqb
  1697  	sseOpcodePcmpeqw
  1698  	sseOpcodePcmpeqd
  1699  	sseOpcodePcmpeqq
  1700  	sseOpcodePcmpgtb
  1701  	sseOpcodePcmpgtw
  1702  	sseOpcodePcmpgtd
  1703  	sseOpcodePcmpgtq
  1704  	sseOpcodePextrb
  1705  	sseOpcodePextrw
  1706  	sseOpcodePextrd
  1707  	sseOpcodePextrq
  1708  	sseOpcodePinsrb
  1709  	sseOpcodePinsrw
  1710  	sseOpcodePinsrd
  1711  	sseOpcodePinsrq
  1712  	sseOpcodePmaddwd
  1713  	sseOpcodePmaxsb
  1714  	sseOpcodePmaxsw
  1715  	sseOpcodePmaxsd
  1716  	sseOpcodePmaxub
  1717  	sseOpcodePmaxuw
  1718  	sseOpcodePmaxud
  1719  	sseOpcodePminsb
  1720  	sseOpcodePminsw
  1721  	sseOpcodePminsd
  1722  	sseOpcodePminub
  1723  	sseOpcodePminuw
  1724  	sseOpcodePminud
  1725  	sseOpcodePmovmskb
  1726  	sseOpcodePmovsxbd
  1727  	sseOpcodePmovsxbw
  1728  	sseOpcodePmovsxbq
  1729  	sseOpcodePmovsxwd
  1730  	sseOpcodePmovsxwq
  1731  	sseOpcodePmovsxdq
  1732  	sseOpcodePmovzxbd
  1733  	sseOpcodePmovzxbw
  1734  	sseOpcodePmovzxbq
  1735  	sseOpcodePmovzxwd
  1736  	sseOpcodePmovzxwq
  1737  	sseOpcodePmovzxdq
  1738  	sseOpcodePmulld
  1739  	sseOpcodePmullw
  1740  	sseOpcodePmuludq
  1741  	sseOpcodePor
  1742  	sseOpcodePshufb
  1743  	sseOpcodePshufd
  1744  	sseOpcodePsllw
  1745  	sseOpcodePslld
  1746  	sseOpcodePsllq
  1747  	sseOpcodePsraw
  1748  	sseOpcodePsrad
  1749  	sseOpcodePsrlw
  1750  	sseOpcodePsrld
  1751  	sseOpcodePsrlq
  1752  	sseOpcodePsubb
  1753  	sseOpcodePsubd
  1754  	sseOpcodePsubq
  1755  	sseOpcodePsubw
  1756  	sseOpcodePsubsb
  1757  	sseOpcodePsubsw
  1758  	sseOpcodePsubusb
  1759  	sseOpcodePsubusw
  1760  	sseOpcodePtest
  1761  	sseOpcodePunpckhbw
  1762  	sseOpcodePunpcklbw
  1763  	sseOpcodePxor
  1764  	sseOpcodeRcpss
  1765  	sseOpcodeRoundps
  1766  	sseOpcodeRoundpd
  1767  	sseOpcodeRoundss
  1768  	sseOpcodeRoundsd
  1769  	sseOpcodeRsqrtss
  1770  	sseOpcodeSqrtps
  1771  	sseOpcodeSqrtpd
  1772  	sseOpcodeSqrtss
  1773  	sseOpcodeSqrtsd
  1774  	sseOpcodeSubps
  1775  	sseOpcodeSubpd
  1776  	sseOpcodeSubss
  1777  	sseOpcodeSubsd
  1778  	sseOpcodeUcomiss
  1779  	sseOpcodeUcomisd
  1780  	sseOpcodeXorps
  1781  	sseOpcodeXorpd
  1782  	sseOpcodePmulhrsw
  1783  	sseOpcodeUnpcklps
  1784  	sseOpcodeCvtps2pd
  1785  	sseOpcodeCvtpd2ps
  1786  	sseOpcodeCvttpd2dq
  1787  	sseOpcodeShufps
  1788  	sseOpcodePmaddubsw
  1789  )
  1790  
  1791  func (s sseOpcode) String() string {
  1792  	switch s {
  1793  	case sseOpcodeInvalid:
  1794  		return "invalid"
  1795  	case sseOpcodeAddps:
  1796  		return "addps"
  1797  	case sseOpcodeAddpd:
  1798  		return "addpd"
  1799  	case sseOpcodeAddss:
  1800  		return "addss"
  1801  	case sseOpcodeAddsd:
  1802  		return "addsd"
  1803  	case sseOpcodeAndps:
  1804  		return "andps"
  1805  	case sseOpcodeAndpd:
  1806  		return "andpd"
  1807  	case sseOpcodeAndnps:
  1808  		return "andnps"
  1809  	case sseOpcodeAndnpd:
  1810  		return "andnpd"
  1811  	case sseOpcodeBlendvps:
  1812  		return "blendvps"
  1813  	case sseOpcodeBlendvpd:
  1814  		return "blendvpd"
  1815  	case sseOpcodeComiss:
  1816  		return "comiss"
  1817  	case sseOpcodeComisd:
  1818  		return "comisd"
  1819  	case sseOpcodeCmpps:
  1820  		return "cmpps"
  1821  	case sseOpcodeCmppd:
  1822  		return "cmppd"
  1823  	case sseOpcodeCmpss:
  1824  		return "cmpss"
  1825  	case sseOpcodeCmpsd:
  1826  		return "cmpsd"
  1827  	case sseOpcodeCvtdq2ps:
  1828  		return "cvtdq2ps"
  1829  	case sseOpcodeCvtdq2pd:
  1830  		return "cvtdq2pd"
  1831  	case sseOpcodeCvtsd2ss:
  1832  		return "cvtsd2ss"
  1833  	case sseOpcodeCvtsd2si:
  1834  		return "cvtsd2si"
  1835  	case sseOpcodeCvtsi2ss:
  1836  		return "cvtsi2ss"
  1837  	case sseOpcodeCvtsi2sd:
  1838  		return "cvtsi2sd"
  1839  	case sseOpcodeCvtss2si:
  1840  		return "cvtss2si"
  1841  	case sseOpcodeCvtss2sd:
  1842  		return "cvtss2sd"
  1843  	case sseOpcodeCvttps2dq:
  1844  		return "cvttps2dq"
  1845  	case sseOpcodeCvttss2si:
  1846  		return "cvttss2si"
  1847  	case sseOpcodeCvttsd2si:
  1848  		return "cvttsd2si"
  1849  	case sseOpcodeDivps:
  1850  		return "divps"
  1851  	case sseOpcodeDivpd:
  1852  		return "divpd"
  1853  	case sseOpcodeDivss:
  1854  		return "divss"
  1855  	case sseOpcodeDivsd:
  1856  		return "divsd"
  1857  	case sseOpcodeInsertps:
  1858  		return "insertps"
  1859  	case sseOpcodeMaxps:
  1860  		return "maxps"
  1861  	case sseOpcodeMaxpd:
  1862  		return "maxpd"
  1863  	case sseOpcodeMaxss:
  1864  		return "maxss"
  1865  	case sseOpcodeMaxsd:
  1866  		return "maxsd"
  1867  	case sseOpcodeMinps:
  1868  		return "minps"
  1869  	case sseOpcodeMinpd:
  1870  		return "minpd"
  1871  	case sseOpcodeMinss:
  1872  		return "minss"
  1873  	case sseOpcodeMinsd:
  1874  		return "minsd"
  1875  	case sseOpcodeMovaps:
  1876  		return "movaps"
  1877  	case sseOpcodeMovapd:
  1878  		return "movapd"
  1879  	case sseOpcodeMovd:
  1880  		return "movd"
  1881  	case sseOpcodeMovdqa:
  1882  		return "movdqa"
  1883  	case sseOpcodeMovdqu:
  1884  		return "movdqu"
  1885  	case sseOpcodeMovlhps:
  1886  		return "movlhps"
  1887  	case sseOpcodeMovmskps:
  1888  		return "movmskps"
  1889  	case sseOpcodeMovmskpd:
  1890  		return "movmskpd"
  1891  	case sseOpcodeMovq:
  1892  		return "movq"
  1893  	case sseOpcodeMovss:
  1894  		return "movss"
  1895  	case sseOpcodeMovsd:
  1896  		return "movsd"
  1897  	case sseOpcodeMovups:
  1898  		return "movups"
  1899  	case sseOpcodeMovupd:
  1900  		return "movupd"
  1901  	case sseOpcodeMulps:
  1902  		return "mulps"
  1903  	case sseOpcodeMulpd:
  1904  		return "mulpd"
  1905  	case sseOpcodeMulss:
  1906  		return "mulss"
  1907  	case sseOpcodeMulsd:
  1908  		return "mulsd"
  1909  	case sseOpcodeOrps:
  1910  		return "orps"
  1911  	case sseOpcodeOrpd:
  1912  		return "orpd"
  1913  	case sseOpcodePabsb:
  1914  		return "pabsb"
  1915  	case sseOpcodePabsw:
  1916  		return "pabsw"
  1917  	case sseOpcodePabsd:
  1918  		return "pabsd"
  1919  	case sseOpcodePackssdw:
  1920  		return "packssdw"
  1921  	case sseOpcodePacksswb:
  1922  		return "packsswb"
  1923  	case sseOpcodePackusdw:
  1924  		return "packusdw"
  1925  	case sseOpcodePackuswb:
  1926  		return "packuswb"
  1927  	case sseOpcodePaddb:
  1928  		return "paddb"
  1929  	case sseOpcodePaddd:
  1930  		return "paddd"
  1931  	case sseOpcodePaddq:
  1932  		return "paddq"
  1933  	case sseOpcodePaddw:
  1934  		return "paddw"
  1935  	case sseOpcodePaddsb:
  1936  		return "paddsb"
  1937  	case sseOpcodePaddsw:
  1938  		return "paddsw"
  1939  	case sseOpcodePaddusb:
  1940  		return "paddusb"
  1941  	case sseOpcodePaddusw:
  1942  		return "paddusw"
  1943  	case sseOpcodePalignr:
  1944  		return "palignr"
  1945  	case sseOpcodePand:
  1946  		return "pand"
  1947  	case sseOpcodePandn:
  1948  		return "pandn"
  1949  	case sseOpcodePavgb:
  1950  		return "pavgb"
  1951  	case sseOpcodePavgw:
  1952  		return "pavgw"
  1953  	case sseOpcodePcmpeqb:
  1954  		return "pcmpeqb"
  1955  	case sseOpcodePcmpeqw:
  1956  		return "pcmpeqw"
  1957  	case sseOpcodePcmpeqd:
  1958  		return "pcmpeqd"
  1959  	case sseOpcodePcmpeqq:
  1960  		return "pcmpeqq"
  1961  	case sseOpcodePcmpgtb:
  1962  		return "pcmpgtb"
  1963  	case sseOpcodePcmpgtw:
  1964  		return "pcmpgtw"
  1965  	case sseOpcodePcmpgtd:
  1966  		return "pcmpgtd"
  1967  	case sseOpcodePcmpgtq:
  1968  		return "pcmpgtq"
  1969  	case sseOpcodePextrb:
  1970  		return "pextrb"
  1971  	case sseOpcodePextrw:
  1972  		return "pextrw"
  1973  	case sseOpcodePextrd:
  1974  		return "pextrd"
  1975  	case sseOpcodePextrq:
  1976  		return "pextrq"
  1977  	case sseOpcodePinsrb:
  1978  		return "pinsrb"
  1979  	case sseOpcodePinsrw:
  1980  		return "pinsrw"
  1981  	case sseOpcodePinsrd:
  1982  		return "pinsrd"
  1983  	case sseOpcodePinsrq:
  1984  		return "pinsrq"
  1985  	case sseOpcodePmaddwd:
  1986  		return "pmaddwd"
  1987  	case sseOpcodePmaxsb:
  1988  		return "pmaxsb"
  1989  	case sseOpcodePmaxsw:
  1990  		return "pmaxsw"
  1991  	case sseOpcodePmaxsd:
  1992  		return "pmaxsd"
  1993  	case sseOpcodePmaxub:
  1994  		return "pmaxub"
  1995  	case sseOpcodePmaxuw:
  1996  		return "pmaxuw"
  1997  	case sseOpcodePmaxud:
  1998  		return "pmaxud"
  1999  	case sseOpcodePminsb:
  2000  		return "pminsb"
  2001  	case sseOpcodePminsw:
  2002  		return "pminsw"
  2003  	case sseOpcodePminsd:
  2004  		return "pminsd"
  2005  	case sseOpcodePminub:
  2006  		return "pminub"
  2007  	case sseOpcodePminuw:
  2008  		return "pminuw"
  2009  	case sseOpcodePminud:
  2010  		return "pminud"
  2011  	case sseOpcodePmovmskb:
  2012  		return "pmovmskb"
  2013  	case sseOpcodePmovsxbd:
  2014  		return "pmovsxbd"
  2015  	case sseOpcodePmovsxbw:
  2016  		return "pmovsxbw"
  2017  	case sseOpcodePmovsxbq:
  2018  		return "pmovsxbq"
  2019  	case sseOpcodePmovsxwd:
  2020  		return "pmovsxwd"
  2021  	case sseOpcodePmovsxwq:
  2022  		return "pmovsxwq"
  2023  	case sseOpcodePmovsxdq:
  2024  		return "pmovsxdq"
  2025  	case sseOpcodePmovzxbd:
  2026  		return "pmovzxbd"
  2027  	case sseOpcodePmovzxbw:
  2028  		return "pmovzxbw"
  2029  	case sseOpcodePmovzxbq:
  2030  		return "pmovzxbq"
  2031  	case sseOpcodePmovzxwd:
  2032  		return "pmovzxwd"
  2033  	case sseOpcodePmovzxwq:
  2034  		return "pmovzxwq"
  2035  	case sseOpcodePmovzxdq:
  2036  		return "pmovzxdq"
  2037  	case sseOpcodePmulld:
  2038  		return "pmulld"
  2039  	case sseOpcodePmullw:
  2040  		return "pmullw"
  2041  	case sseOpcodePmuludq:
  2042  		return "pmuludq"
  2043  	case sseOpcodePor:
  2044  		return "por"
  2045  	case sseOpcodePshufb:
  2046  		return "pshufb"
  2047  	case sseOpcodePshufd:
  2048  		return "pshufd"
  2049  	case sseOpcodePsllw:
  2050  		return "psllw"
  2051  	case sseOpcodePslld:
  2052  		return "pslld"
  2053  	case sseOpcodePsllq:
  2054  		return "psllq"
  2055  	case sseOpcodePsraw:
  2056  		return "psraw"
  2057  	case sseOpcodePsrad:
  2058  		return "psrad"
  2059  	case sseOpcodePsrlw:
  2060  		return "psrlw"
  2061  	case sseOpcodePsrld:
  2062  		return "psrld"
  2063  	case sseOpcodePsrlq:
  2064  		return "psrlq"
  2065  	case sseOpcodePsubb:
  2066  		return "psubb"
  2067  	case sseOpcodePsubd:
  2068  		return "psubd"
  2069  	case sseOpcodePsubq:
  2070  		return "psubq"
  2071  	case sseOpcodePsubw:
  2072  		return "psubw"
  2073  	case sseOpcodePsubsb:
  2074  		return "psubsb"
  2075  	case sseOpcodePsubsw:
  2076  		return "psubsw"
  2077  	case sseOpcodePsubusb:
  2078  		return "psubusb"
  2079  	case sseOpcodePsubusw:
  2080  		return "psubusw"
  2081  	case sseOpcodePtest:
  2082  		return "ptest"
  2083  	case sseOpcodePunpckhbw:
  2084  		return "punpckhbw"
  2085  	case sseOpcodePunpcklbw:
  2086  		return "punpcklbw"
  2087  	case sseOpcodePxor:
  2088  		return "pxor"
  2089  	case sseOpcodeRcpss:
  2090  		return "rcpss"
  2091  	case sseOpcodeRoundps:
  2092  		return "roundps"
  2093  	case sseOpcodeRoundpd:
  2094  		return "roundpd"
  2095  	case sseOpcodeRoundss:
  2096  		return "roundss"
  2097  	case sseOpcodeRoundsd:
  2098  		return "roundsd"
  2099  	case sseOpcodeRsqrtss:
  2100  		return "rsqrtss"
  2101  	case sseOpcodeSqrtps:
  2102  		return "sqrtps"
  2103  	case sseOpcodeSqrtpd:
  2104  		return "sqrtpd"
  2105  	case sseOpcodeSqrtss:
  2106  		return "sqrtss"
  2107  	case sseOpcodeSqrtsd:
  2108  		return "sqrtsd"
  2109  	case sseOpcodeSubps:
  2110  		return "subps"
  2111  	case sseOpcodeSubpd:
  2112  		return "subpd"
  2113  	case sseOpcodeSubss:
  2114  		return "subss"
  2115  	case sseOpcodeSubsd:
  2116  		return "subsd"
  2117  	case sseOpcodeUcomiss:
  2118  		return "ucomiss"
  2119  	case sseOpcodeUcomisd:
  2120  		return "ucomisd"
  2121  	case sseOpcodeXorps:
  2122  		return "xorps"
  2123  	case sseOpcodeXorpd:
  2124  		return "xorpd"
  2125  	case sseOpcodePmulhrsw:
  2126  		return "pmulhrsw"
  2127  	case sseOpcodeUnpcklps:
  2128  		return "unpcklps"
  2129  	case sseOpcodeCvtps2pd:
  2130  		return "cvtps2pd"
  2131  	case sseOpcodeCvtpd2ps:
  2132  		return "cvtpd2ps"
  2133  	case sseOpcodeCvttpd2dq:
  2134  		return "cvttpd2dq"
  2135  	case sseOpcodeShufps:
  2136  		return "shufps"
  2137  	case sseOpcodePmaddubsw:
  2138  		return "pmaddubsw"
  2139  	default:
  2140  		panic("BUG")
  2141  	}
  2142  }
  2143  
  2144  type roundingMode uint8
  2145  
  2146  const (
  2147  	roundingModeNearest roundingMode = iota
  2148  	roundingModeDown
  2149  	roundingModeUp
  2150  	roundingModeZero
  2151  )
  2152  
  2153  func (r roundingMode) String() string {
  2154  	switch r {
  2155  	case roundingModeNearest:
  2156  		return "nearest"
  2157  	case roundingModeDown:
  2158  		return "down"
  2159  	case roundingModeUp:
  2160  		return "up"
  2161  	case roundingModeZero:
  2162  		return "zero"
  2163  	default:
  2164  		panic("BUG")
  2165  	}
  2166  }
  2167  
  2168  // cmpPred is the immediate value for a comparison operation in xmmRmRImm.
  2169  type cmpPred uint8
  2170  
  2171  const (
  2172  	// cmpPredEQ_OQ is Equal (ordered, non-signaling)
  2173  	cmpPredEQ_OQ cmpPred = iota
  2174  	// cmpPredLT_OS is Less-than (ordered, signaling)
  2175  	cmpPredLT_OS
  2176  	// cmpPredLE_OS is Less-than-or-equal (ordered, signaling)
  2177  	cmpPredLE_OS
  2178  	// cmpPredUNORD_Q is Unordered (non-signaling)
  2179  	cmpPredUNORD_Q
  2180  	// cmpPredNEQ_UQ is Not-equal (unordered, non-signaling)
  2181  	cmpPredNEQ_UQ
  2182  	// cmpPredNLT_US is Not-less-than (unordered, signaling)
  2183  	cmpPredNLT_US
  2184  	// cmpPredNLE_US is Not-less-than-or-equal (unordered, signaling)
  2185  	cmpPredNLE_US
  2186  	// cmpPredORD_Q is Ordered (non-signaling)
  2187  	cmpPredORD_Q
  2188  	// cmpPredEQ_UQ is Equal (unordered, non-signaling)
  2189  	cmpPredEQ_UQ
  2190  	// cmpPredNGE_US is Not-greater-than-or-equal (unordered, signaling)
  2191  	cmpPredNGE_US
  2192  	// cmpPredNGT_US is Not-greater-than (unordered, signaling)
  2193  	cmpPredNGT_US
  2194  	// cmpPredFALSE_OQ is False (ordered, non-signaling)
  2195  	cmpPredFALSE_OQ
  2196  	// cmpPredNEQ_OQ is Not-equal (ordered, non-signaling)
  2197  	cmpPredNEQ_OQ
  2198  	// cmpPredGE_OS is Greater-than-or-equal (ordered, signaling)
  2199  	cmpPredGE_OS
  2200  	// cmpPredGT_OS is Greater-than (ordered, signaling)
  2201  	cmpPredGT_OS
  2202  	// cmpPredTRUE_UQ is True (unordered, non-signaling)
  2203  	cmpPredTRUE_UQ
  2204  	// Equal (ordered, signaling)
  2205  	cmpPredEQ_OS
  2206  	// Less-than (ordered, nonsignaling)
  2207  	cmpPredLT_OQ
  2208  	// Less-than-or-equal (ordered, nonsignaling)
  2209  	cmpPredLE_OQ
  2210  	// Unordered (signaling)
  2211  	cmpPredUNORD_S
  2212  	// Not-equal (unordered, signaling)
  2213  	cmpPredNEQ_US
  2214  	// Not-less-than (unordered, nonsignaling)
  2215  	cmpPredNLT_UQ
  2216  	// Not-less-than-or-equal (unordered, nonsignaling)
  2217  	cmpPredNLE_UQ
  2218  	// Ordered (signaling)
  2219  	cmpPredORD_S
  2220  	// Equal (unordered, signaling)
  2221  	cmpPredEQ_US
  2222  	// Not-greater-than-or-equal (unordered, non-signaling)
  2223  	cmpPredNGE_UQ
  2224  	// Not-greater-than (unordered, nonsignaling)
  2225  	cmpPredNGT_UQ
  2226  	// False (ordered, signaling)
  2227  	cmpPredFALSE_OS
  2228  	// Not-equal (ordered, signaling)
  2229  	cmpPredNEQ_OS
  2230  	// Greater-than-or-equal (ordered, nonsignaling)
  2231  	cmpPredGE_OQ
  2232  	// Greater-than (ordered, nonsignaling)
  2233  	cmpPredGT_OQ
  2234  	// True (unordered, signaling)
  2235  	cmpPredTRUE_US
  2236  )
  2237  
  2238  func (r cmpPred) String() string {
  2239  	switch r {
  2240  	case cmpPredEQ_OQ:
  2241  		return "eq_oq"
  2242  	case cmpPredLT_OS:
  2243  		return "lt_os"
  2244  	case cmpPredLE_OS:
  2245  		return "le_os"
  2246  	case cmpPredUNORD_Q:
  2247  		return "unord_q"
  2248  	case cmpPredNEQ_UQ:
  2249  		return "neq_uq"
  2250  	case cmpPredNLT_US:
  2251  		return "nlt_us"
  2252  	case cmpPredNLE_US:
  2253  		return "nle_us"
  2254  	case cmpPredORD_Q:
  2255  		return "ord_q"
  2256  	case cmpPredEQ_UQ:
  2257  		return "eq_uq"
  2258  	case cmpPredNGE_US:
  2259  		return "nge_us"
  2260  	case cmpPredNGT_US:
  2261  		return "ngt_us"
  2262  	case cmpPredFALSE_OQ:
  2263  		return "false_oq"
  2264  	case cmpPredNEQ_OQ:
  2265  		return "neq_oq"
  2266  	case cmpPredGE_OS:
  2267  		return "ge_os"
  2268  	case cmpPredGT_OS:
  2269  		return "gt_os"
  2270  	case cmpPredTRUE_UQ:
  2271  		return "true_uq"
  2272  	case cmpPredEQ_OS:
  2273  		return "eq_os"
  2274  	case cmpPredLT_OQ:
  2275  		return "lt_oq"
  2276  	case cmpPredLE_OQ:
  2277  		return "le_oq"
  2278  	case cmpPredUNORD_S:
  2279  		return "unord_s"
  2280  	case cmpPredNEQ_US:
  2281  		return "neq_us"
  2282  	case cmpPredNLT_UQ:
  2283  		return "nlt_uq"
  2284  	case cmpPredNLE_UQ:
  2285  		return "nle_uq"
  2286  	case cmpPredORD_S:
  2287  		return "ord_s"
  2288  	case cmpPredEQ_US:
  2289  		return "eq_us"
  2290  	case cmpPredNGE_UQ:
  2291  		return "nge_uq"
  2292  	case cmpPredNGT_UQ:
  2293  		return "ngt_uq"
  2294  	case cmpPredFALSE_OS:
  2295  		return "false_os"
  2296  	case cmpPredNEQ_OS:
  2297  		return "neq_os"
  2298  	case cmpPredGE_OQ:
  2299  		return "ge_oq"
  2300  	case cmpPredGT_OQ:
  2301  		return "gt_oq"
  2302  	case cmpPredTRUE_US:
  2303  		return "true_us"
  2304  	default:
  2305  		panic("BUG")
  2306  	}
  2307  }
  2308  
  2309  func linkInstr(prev, next *instruction) *instruction {
  2310  	prev.next = next
  2311  	next.prev = prev
  2312  	return next
  2313  }
  2314  
  2315  type defKind byte
  2316  
  2317  const (
  2318  	defKindNone defKind = iota + 1
  2319  	defKindOp2
  2320  	defKindCall
  2321  	defKindDivRem
  2322  )
  2323  
  2324  var defKinds = [instrMax]defKind{
  2325  	nop0:                   defKindNone,
  2326  	ret:                    defKindNone,
  2327  	movRR:                  defKindOp2,
  2328  	movRM:                  defKindNone,
  2329  	xmmMovRM:               defKindNone,
  2330  	aluRmiR:                defKindNone,
  2331  	shiftR:                 defKindNone,
  2332  	imm:                    defKindOp2,
  2333  	unaryRmR:               defKindOp2,
  2334  	xmmRmiReg:              defKindNone,
  2335  	xmmUnaryRmR:            defKindOp2,
  2336  	xmmUnaryRmRImm:         defKindOp2,
  2337  	xmmCmpRmR:              defKindNone,
  2338  	xmmRmR:                 defKindNone,
  2339  	xmmRmRImm:              defKindNone,
  2340  	mov64MR:                defKindOp2,
  2341  	movsxRmR:               defKindOp2,
  2342  	movzxRmR:               defKindOp2,
  2343  	gprToXmm:               defKindOp2,
  2344  	xmmToGpr:               defKindOp2,
  2345  	cmove:                  defKindNone,
  2346  	call:                   defKindCall,
  2347  	callIndirect:           defKindCall,
  2348  	ud2:                    defKindNone,
  2349  	jmp:                    defKindNone,
  2350  	jmpIf:                  defKindNone,
  2351  	jmpTableIsland:         defKindNone,
  2352  	cmpRmiR:                defKindNone,
  2353  	exitSequence:           defKindNone,
  2354  	lea:                    defKindOp2,
  2355  	setcc:                  defKindOp2,
  2356  	zeros:                  defKindOp2,
  2357  	sourceOffsetInfo:       defKindNone,
  2358  	fcvtToSintSequence:     defKindNone,
  2359  	defineUninitializedReg: defKindOp2,
  2360  	fcvtToUintSequence:     defKindNone,
  2361  	xmmCMov:                defKindOp2,
  2362  	idivRemSequence:        defKindDivRem,
  2363  	blendvpd:               defKindNone,
  2364  	mfence:                 defKindNone,
  2365  	xchg:                   defKindNone,
  2366  	lockcmpxchg:            defKindNone,
  2367  	lockxadd:               defKindNone,
  2368  	neg:                    defKindNone,
  2369  	nopUseReg:              defKindNone,
  2370  }
  2371  
  2372  // String implements fmt.Stringer.
  2373  func (d defKind) String() string {
  2374  	switch d {
  2375  	case defKindNone:
  2376  		return "none"
  2377  	case defKindOp2:
  2378  		return "op2"
  2379  	case defKindCall:
  2380  		return "call"
  2381  	case defKindDivRem:
  2382  		return "divrem"
  2383  	default:
  2384  		return "invalid"
  2385  	}
  2386  }
  2387  
  2388  type useKind byte
  2389  
  2390  const (
  2391  	useKindNone useKind = iota + 1
  2392  	useKindOp1
  2393  	// useKindOp1Op2Reg is Op1 can be any operand, Op2 must be a register.
  2394  	useKindOp1Op2Reg
  2395  	// useKindOp1RegOp2 is Op1 must be a register, Op2 can be any operand.
  2396  	useKindOp1RegOp2
  2397  	// useKindRaxOp1RegOp2 is Op1 must be a register, Op2 can be any operand, and RAX is used.
  2398  	useKindRaxOp1RegOp2
  2399  	useKindDivRem
  2400  	useKindBlendvpd
  2401  	useKindCall
  2402  	useKindCallInd
  2403  	useKindFcvtToSintSequence
  2404  	useKindFcvtToUintSequence
  2405  )
  2406  
  2407  var useKinds = [instrMax]useKind{
  2408  	nop0:                   useKindNone,
  2409  	ret:                    useKindNone,
  2410  	movRR:                  useKindOp1,
  2411  	movRM:                  useKindOp1RegOp2,
  2412  	xmmMovRM:               useKindOp1RegOp2,
  2413  	cmove:                  useKindOp1Op2Reg,
  2414  	aluRmiR:                useKindOp1Op2Reg,
  2415  	shiftR:                 useKindOp1Op2Reg,
  2416  	imm:                    useKindNone,
  2417  	unaryRmR:               useKindOp1,
  2418  	xmmRmiReg:              useKindOp1Op2Reg,
  2419  	xmmUnaryRmR:            useKindOp1,
  2420  	xmmUnaryRmRImm:         useKindOp1,
  2421  	xmmCmpRmR:              useKindOp1Op2Reg,
  2422  	xmmRmR:                 useKindOp1Op2Reg,
  2423  	xmmRmRImm:              useKindOp1Op2Reg,
  2424  	mov64MR:                useKindOp1,
  2425  	movzxRmR:               useKindOp1,
  2426  	movsxRmR:               useKindOp1,
  2427  	gprToXmm:               useKindOp1,
  2428  	xmmToGpr:               useKindOp1,
  2429  	call:                   useKindCall,
  2430  	callIndirect:           useKindCallInd,
  2431  	ud2:                    useKindNone,
  2432  	jmpIf:                  useKindOp1,
  2433  	jmp:                    useKindOp1,
  2434  	cmpRmiR:                useKindOp1Op2Reg,
  2435  	exitSequence:           useKindOp1,
  2436  	lea:                    useKindOp1,
  2437  	jmpTableIsland:         useKindNone,
  2438  	setcc:                  useKindNone,
  2439  	zeros:                  useKindNone,
  2440  	sourceOffsetInfo:       useKindNone,
  2441  	fcvtToSintSequence:     useKindFcvtToSintSequence,
  2442  	defineUninitializedReg: useKindNone,
  2443  	fcvtToUintSequence:     useKindFcvtToUintSequence,
  2444  	xmmCMov:                useKindOp1,
  2445  	idivRemSequence:        useKindDivRem,
  2446  	blendvpd:               useKindBlendvpd,
  2447  	mfence:                 useKindNone,
  2448  	xchg:                   useKindOp1RegOp2,
  2449  	lockcmpxchg:            useKindRaxOp1RegOp2,
  2450  	lockxadd:               useKindOp1RegOp2,
  2451  	neg:                    useKindOp1,
  2452  	nopUseReg:              useKindOp1,
  2453  }
  2454  
  2455  func (u useKind) String() string {
  2456  	switch u {
  2457  	case useKindNone:
  2458  		return "none"
  2459  	case useKindOp1:
  2460  		return "op1"
  2461  	case useKindOp1Op2Reg:
  2462  		return "op1op2Reg"
  2463  	case useKindOp1RegOp2:
  2464  		return "op1RegOp2"
  2465  	case useKindCall:
  2466  		return "call"
  2467  	case useKindCallInd:
  2468  		return "callInd"
  2469  	default:
  2470  		return "invalid"
  2471  	}
  2472  }