{name:"SBBLcarrymask",argLength:1,reg:flagsgp,asm:"SBBL"},// (int32)(-1) if carry is set, 0 if carry is clear.
// Note: SBBW and SBBB are subsumed by SBBL
{name:"SETEQ",argLength:1,reg:readflags,asm:"SETEQ"},// extract == condition from arg0
{name:"SETNE",argLength:1,reg:readflags,asm:"SETNE"},// extract != condition from arg0
{name:"SETL",argLength:1,reg:readflags,asm:"SETLT"},// extract signed < condition from arg0
{name:"SETLE",argLength:1,reg:readflags,asm:"SETLE"},// extract signed <= condition from arg0
{name:"SETG",argLength:1,reg:readflags,asm:"SETGT"},// extract signed > condition from arg0
{name:"SETGE",argLength:1,reg:readflags,asm:"SETGE"},// extract signed >= condition from arg0
{name:"SETB",argLength:1,reg:readflags,asm:"SETCS"},// extract unsigned < condition from arg0
{name:"SETBE",argLength:1,reg:readflags,asm:"SETLS"},// extract unsigned <= condition from arg0
{name:"SETA",argLength:1,reg:readflags,asm:"SETHI"},// extract unsigned > condition from arg0
{name:"SETAE",argLength:1,reg:readflags,asm:"SETCC"},// extract unsigned >= condition from arg0
// Need different opcodes for floating point conditions because
// any comparison involving a NaN is always FALSE and thus
// the patterns for inverting conditions cannot be used.
{name:"SETEQF",argLength:1,reg:flagsgpax,asm:"SETEQ"},// extract == condition from arg0
{name:"SETNEF",argLength:1,reg:flagsgpax,asm:"SETNE"},// extract != condition from arg0
{name:"SETORD",argLength:1,reg:flagsgp,asm:"SETPC"},// extract "ordered" (No Nan present) condition from arg0
{name:"SETNAN",argLength:1,reg:flagsgp,asm:"SETPS"},// extract "unordered" (Nan present) condition from arg0
{name:"SETGF",argLength:1,reg:flagsgp,asm:"SETHI"},// extract floating > condition from arg0
{name:"SETGEF",argLength:1,reg:flagsgp,asm:"SETCC"},// extract floating >= condition from arg0
{name:"MOVBLSX",argLength:1,reg:gp11nf,asm:"MOVBLSX"},// sign extend arg0 from int8 to int32
{name:"MOVBLZX",argLength:1,reg:gp11nf,asm:"MOVBLZX"},// zero extend arg0 from int8 to int32
{name:"MOVWLSX",argLength:1,reg:gp11nf,asm:"MOVWLSX"},// sign extend arg0 from int16 to int32
{name:"MOVWLZX",argLength:1,reg:gp11nf,asm:"MOVWLZX"},// zero extend arg0 from int16 to int32
{name:"MOVLconst",reg:gp01,asm:"MOVL",typ:"UInt32",aux:"Int32",rematerializeable:true},// 32 low bits of auxint
{name:"CVTTSD2SL",argLength:1,reg:fpgp,asm:"CVTTSD2SL"},// convert float64 to int32
{name:"CVTTSS2SL",argLength:1,reg:fpgp,asm:"CVTTSS2SL"},// convert float32 to int32
{name:"CVTSL2SS",argLength:1,reg:gpfp,asm:"CVTSL2SS"},// convert int32 to float32
{name:"CVTSL2SD",argLength:1,reg:gpfp,asm:"CVTSL2SD"},// convert int32 to float64
{name:"CVTSD2SS",argLength:1,reg:fp11,asm:"CVTSD2SS"},// convert float64 to float32
{name:"CVTSS2SD",argLength:1,reg:fp11,asm:"CVTSS2SD"},// convert float32 to float64
{name:"PXOR",argLength:2,reg:fp21,asm:"PXOR",commutative:true,resultInArg0:true},// exclusive or, applied to X regs for float negation.
{name:"LEAL",argLength:1,reg:gp11sb,aux:"SymOff",rematerializeable:true},// arg0 + auxint + offset encoded in aux
{name:"LEAL1",argLength:2,reg:gp21sb,aux:"SymOff"},// arg0 + arg1 + auxint + aux
{name:"LEAL2",argLength:2,reg:gp21sb,aux:"SymOff"},// arg0 + 2*arg1 + auxint + aux
{name:"LEAL4",argLength:2,reg:gp21sb,aux:"SymOff"},// arg0 + 4*arg1 + auxint + aux
{name:"LEAL8",argLength:2,reg:gp21sb,aux:"SymOff"},// arg0 + 8*arg1 + auxint + aux
// Note: LEAL{1,2,4,8} must not have OpSB as either argument.
// auxint+aux == add auxint and the offset of the symbol in aux (if any) to the effective address
{name:"MOVBload",argLength:2,reg:gpload,asm:"MOVBLZX",aux:"SymOff",typ:"UInt8"},// load byte from arg0+auxint+aux. arg1=mem. Zero extend.
{name:"MOVBLSXload",argLength:2,reg:gpload,asm:"MOVBLSX",aux:"SymOff"},// ditto, sign extend to int32
{name:"MOVWload",argLength:2,reg:gpload,asm:"MOVWLZX",aux:"SymOff",typ:"UInt16"},// load 2 bytes from arg0+auxint+aux. arg1=mem. Zero extend.
{name:"MOVWLSXload",argLength:2,reg:gpload,asm:"MOVWLSX",aux:"SymOff"},// ditto, sign extend to int32
{name:"MOVLload",argLength:2,reg:gpload,asm:"MOVL",aux:"SymOff",typ:"UInt32"},// load 4 bytes from arg0+auxint+aux. arg1=mem. Zero extend.
{name:"MOVBstore",argLength:3,reg:gpstore,asm:"MOVB",aux:"SymOff",typ:"Mem"},// store byte in arg1 to arg0+auxint+aux. arg2=mem
{name:"MOVWstore",argLength:3,reg:gpstore,asm:"MOVW",aux:"SymOff",typ:"Mem"},// store 2 bytes in arg1 to arg0+auxint+aux. arg2=mem
{name:"MOVLstore",argLength:3,reg:gpstore,asm:"MOVL",aux:"SymOff",typ:"Mem"},// store 4 bytes in arg1 to arg0+auxint+aux. arg2=mem
{name:"MOVOload",argLength:2,reg:fpload,asm:"MOVUPS",aux:"SymOff",typ:"Int128"},// load 16 bytes from arg0+auxint+aux. arg1=mem
{name:"MOVOstore",argLength:3,reg:fpstore,asm:"MOVUPS",aux:"SymOff",typ:"Mem"},// store 16 bytes in arg1 to arg0+auxint+aux. arg2=mem
// indexed loads/stores
{name:"MOVBloadidx1",argLength:3,reg:gploadidx,asm:"MOVBLZX",aux:"SymOff"},// load a byte from arg0+arg1+auxint+aux. arg2=mem
{name:"MOVWloadidx1",argLength:3,reg:gploadidx,asm:"MOVWLZX",aux:"SymOff"},// load 2 bytes from arg0+arg1+auxint+aux. arg2=mem
{name:"MOVWloadidx2",argLength:3,reg:gploadidx,asm:"MOVWLZX",aux:"SymOff"},// load 2 bytes from arg0+2*arg1+auxint+aux. arg2=mem
{name:"MOVLloadidx1",argLength:3,reg:gploadidx,asm:"MOVL",aux:"SymOff"},// load 4 bytes from arg0+arg1+auxint+aux. arg2=mem
{name:"MOVLloadidx4",argLength:3,reg:gploadidx,asm:"MOVL",aux:"SymOff"},// load 4 bytes from arg0+4*arg1+auxint+aux. arg2=mem
// TODO: sign-extending indexed loads
{name:"MOVBstoreidx1",argLength:4,reg:gpstoreidx,asm:"MOVB",aux:"SymOff"},// store byte in arg2 to arg0+arg1+auxint+aux. arg3=mem
{name:"MOVWstoreidx1",argLength:4,reg:gpstoreidx,asm:"MOVW",aux:"SymOff"},// store 2 bytes in arg2 to arg0+arg1+auxint+aux. arg3=mem
{name:"MOVWstoreidx2",argLength:4,reg:gpstoreidx,asm:"MOVW",aux:"SymOff"},// store 2 bytes in arg2 to arg0+2*arg1+auxint+aux. arg3=mem
{name:"MOVLstoreidx1",argLength:4,reg:gpstoreidx,asm:"MOVL",aux:"SymOff"},// store 4 bytes in arg2 to arg0+arg1+auxint+aux. arg3=mem
{name:"MOVLstoreidx4",argLength:4,reg:gpstoreidx,asm:"MOVL",aux:"SymOff"},// store 4 bytes in arg2 to arg0+4*arg1+auxint+aux. arg3=mem
// TODO: add size-mismatched indexed loads, like MOVBstoreidx4.
// For storeconst ops, the AuxInt field encodes both
// the value to store and an address offset of the store.
// Cast AuxInt to a ValAndOff to extract Val and Off fields.
{name:"MOVBstoreconst",argLength:2,reg:gpstoreconst,asm:"MOVB",aux:"SymValAndOff",typ:"Mem"},// store low byte of ValAndOff(AuxInt).Val() to arg0+ValAndOff(AuxInt).Off()+aux. arg1=mem
{name:"MOVWstoreconst",argLength:2,reg:gpstoreconst,asm:"MOVW",aux:"SymValAndOff",typ:"Mem"},// store low 2 bytes of ...
{name:"MOVLstoreconst",argLength:2,reg:gpstoreconst,asm:"MOVL",aux:"SymValAndOff",typ:"Mem"},// store low 4 bytes of ...
{name:"MOVBstoreconstidx1",argLength:3,reg:gpstoreconstidx,asm:"MOVB",aux:"SymValAndOff",typ:"Mem"},// store low byte of ValAndOff(AuxInt).Val() to arg0+1*arg1+ValAndOff(AuxInt).Off()+aux. arg2=mem
{name:"MOVWstoreconstidx1",argLength:3,reg:gpstoreconstidx,asm:"MOVW",aux:"SymValAndOff",typ:"Mem"},// store low 2 bytes of ... arg1 ...
{name:"MOVWstoreconstidx2",argLength:3,reg:gpstoreconstidx,asm:"MOVW",aux:"SymValAndOff",typ:"Mem"},// store low 2 bytes of ... 2*arg1 ...
{name:"MOVLstoreconstidx1",argLength:3,reg:gpstoreconstidx,asm:"MOVL",aux:"SymValAndOff",typ:"Mem"},// store low 4 bytes of ... arg1 ...
{name:"MOVLstoreconstidx4",argLength:3,reg:gpstoreconstidx,asm:"MOVL",aux:"SymValAndOff",typ:"Mem"},// store low 4 bytes of ... 4*arg1 ...
// arg0 = (duff-adjusted) pointer to start of memory to zero
// arg1 = value to store (will always be zero)
// arg2 = mem
// auxint = offset into duffzero code to start executing
{name:"CALLstatic",argLength:1,reg:regInfo{clobbers:callerSave},aux:"SymOff"},// call static function aux.(*gc.Sym). arg0=mem, auxint=argsize, returns mem
{name:"CALLclosure",argLength:3,reg:regInfo{[]regMask{gpsp,buildReg("DX"),0},callerSave,nil},aux:"Int64"},// call function via closure. arg0=codeptr, arg1=closure, arg2=mem, auxint=argsize, returns mem
{name:"CALLdefer",argLength:1,reg:regInfo{clobbers:callerSave},aux:"Int64"},// call deferproc. arg0=mem, auxint=argsize, returns mem
{name:"CALLgo",argLength:1,reg:regInfo{clobbers:callerSave},aux:"Int64"},// call newproc. arg0=mem, auxint=argsize, returns mem
{name:"CALLinter",argLength:2,reg:regInfo{inputs:[]regMask{gp},clobbers:callerSave},aux:"Int64"},// call fn by pointer. arg0=codeptr, arg1=mem, auxint=argsize, returns mem
// arg0 = destination pointer
// arg1 = source pointer
// arg2 = mem
// auxint = offset from duffcopy symbol to call
// returns memory
{
name:"DUFFCOPY",
aux:"Int64",
argLength:3,
reg:regInfo{
inputs:[]regMask{buildReg("DI"),buildReg("SI")},
clobbers:buildReg("DI SI X0 FLAGS"),// uses X0 as a temporary