2015-06-06 16:03:33 -07:00
// Copyright 2015 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package main
2015-06-14 11:38:46 -07:00
import "strings"
2015-06-06 16:03:33 -07:00
// copied from ../../amd64/reg.go
var regNamesAMD64 = [ ] string {
".AX" ,
".CX" ,
".DX" ,
".BX" ,
".SP" ,
".BP" ,
".SI" ,
".DI" ,
".R8" ,
".R9" ,
".R10" ,
".R11" ,
".R12" ,
".R13" ,
".R14" ,
".R15" ,
".X0" ,
".X1" ,
".X2" ,
".X3" ,
".X4" ,
".X5" ,
".X6" ,
".X7" ,
".X8" ,
".X9" ,
".X10" ,
".X11" ,
".X12" ,
".X13" ,
".X14" ,
".X15" ,
// pseudo-registers
2015-06-19 21:02:28 -07:00
".SB" ,
2015-06-06 16:03:33 -07:00
".FLAGS" ,
}
func init ( ) {
// Make map from reg names to reg integers.
if len ( regNamesAMD64 ) > 64 {
panic ( "too many registers" )
}
num := map [ string ] int { }
for i , name := range regNamesAMD64 {
if name [ 0 ] != '.' {
panic ( "register name " + name + " does not start with '.'" )
}
num [ name [ 1 : ] ] = i
}
buildReg := func ( s string ) regMask {
m := regMask ( 0 )
for _ , r := range strings . Split ( s , " " ) {
if n , ok := num [ r ] ; ok {
m |= regMask ( 1 ) << uint ( n )
continue
}
panic ( "register " + r + " not found" )
}
return m
}
2015-08-06 09:34:54 -07:00
// Common individual register masks
var (
2015-08-17 17:46:06 -05:00
ax = buildReg ( "AX" )
2015-08-11 12:51:33 -07:00
cx = buildReg ( "CX" )
2015-08-17 17:46:06 -05:00
dx = buildReg ( "DX" )
2015-08-11 12:51:33 -07:00
x15 = buildReg ( "X15" )
gp = buildReg ( "AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15" )
fp = buildReg ( "X0 X1 X2 X3 X4 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15" )
gpsp = gp | buildReg ( "SP" )
gpspsb = gpsp | buildReg ( "SB" )
flags = buildReg ( "FLAGS" )
callerSave = gp | fp | flags
2015-08-06 09:34:54 -07:00
)
// Common slices of register masks
var (
gponly = [ ] regMask { gp }
2015-08-12 16:38:11 -04:00
fponly = [ ] regMask { fp }
2015-08-06 09:34:54 -07:00
flagsonly = [ ] regMask { flags }
)
// Common regInfo
var (
2015-08-11 12:51:33 -07:00
gp01 = regInfo { inputs : [ ] regMask { } , outputs : gponly , clobbers : flags }
gp11 = regInfo { inputs : [ ] regMask { gpsp } , outputs : gponly , clobbers : flags }
gp11sb = regInfo { inputs : [ ] regMask { gpspsb } , outputs : gponly , clobbers : flags }
gp21 = regInfo { inputs : [ ] regMask { gpsp , gpsp } , outputs : gponly , clobbers : flags }
gp21sb = regInfo { inputs : [ ] regMask { gpspsb , gpsp } , outputs : gponly , clobbers : flags }
gp21shift = regInfo { inputs : [ ] regMask { gpsp , cx } , outputs : [ ] regMask { gp &^ cx } , clobbers : flags }
2015-08-17 17:46:06 -05:00
gp11div = regInfo { inputs : [ ] regMask { ax , gpsp &^ dx } , outputs : [ ] regMask { ax } ,
clobbers : dx | flags }
2015-08-06 09:34:54 -07:00
gp2flags = regInfo { inputs : [ ] regMask { gpsp , gpsp } , outputs : flagsonly }
gp1flags = regInfo { inputs : [ ] regMask { gpsp } , outputs : flagsonly }
2015-08-11 12:51:33 -07:00
flagsgp = regInfo { inputs : flagsonly , outputs : gponly , clobbers : flags }
2015-08-06 09:34:54 -07:00
gpload = regInfo { inputs : [ ] regMask { gpspsb , 0 } , outputs : gponly }
gploadidx = regInfo { inputs : [ ] regMask { gpspsb , gpsp , 0 } , outputs : gponly }
gpstore = regInfo { inputs : [ ] regMask { gpspsb , gpsp , 0 } }
gpstoreconst = regInfo { inputs : [ ] regMask { gpspsb , 0 } }
gpstoreidx = regInfo { inputs : [ ] regMask { gpspsb , gpsp , gpsp , 0 } }
2015-08-12 16:38:11 -04:00
// fp11 = regInfo{inputs: fponly, outputs: fponly}
fp01 = regInfo { inputs : [ ] regMask { } , outputs : fponly }
fp21 = regInfo { inputs : [ ] regMask { fp , fp } , outputs : fponly }
fp21x15 = regInfo { inputs : [ ] regMask { fp &^ x15 , fp &^ x15 } ,
clobbers : x15 , outputs : [ ] regMask { fp &^ x15 } }
// fp2flags = regInfo{inputs: []regMask{fp, fp}, outputs: flagsonly}
// fp1flags = regInfo{inputs: fponly, outputs: flagsonly}
fpload = regInfo { inputs : [ ] regMask { gpspsb , 0 } , outputs : fponly }
fploadidx = regInfo { inputs : [ ] regMask { gpspsb , gpsp , 0 } , outputs : fponly }
fpstore = regInfo { inputs : [ ] regMask { gpspsb , fp , 0 } }
fpstoreidx = regInfo { inputs : [ ] regMask { gpspsb , gpsp , fp , 0 } }
2015-08-06 09:34:54 -07:00
)
2015-08-11 12:51:33 -07:00
// TODO: most ops clobber flags
2015-06-06 16:03:33 -07:00
// Suffixes encode the bit width of various instructions.
// Q = 64 bit, L = 32 bit, W = 16 bit, B = 8 bit
// TODO: 2-address instructions. Mark ops as needing matching input/output regs.
var AMD64ops = [ ] opData {
2015-08-12 16:38:11 -04:00
// fp ops
{ name : "ADDSS" , reg : fp21 , asm : "ADDSS" } , // fp32 add
{ name : "ADDSD" , reg : fp21 , asm : "ADDSD" } , // fp64 add
{ name : "SUBSS" , reg : fp21x15 , asm : "SUBSS" } , // fp32 sub
{ name : "SUBSD" , reg : fp21x15 , asm : "SUBSD" } , // fp64 sub
{ name : "MULSS" , reg : fp21 , asm : "MULSS" } , // fp32 mul
{ name : "MULSD" , reg : fp21 , asm : "MULSD" } , // fp64 mul
{ name : "DIVSS" , reg : fp21x15 , asm : "DIVSS" } , // fp32 div
{ name : "DIVSD" , reg : fp21x15 , asm : "DIVSD" } , // fp64 div
{ name : "MOVSSload" , reg : fpload , asm : "MOVSS" } , // fp32 load
{ name : "MOVSDload" , reg : fpload , asm : "MOVSD" } , // fp64 load
{ name : "MOVSSconst" , reg : fp01 , asm : "MOVSS" } , // fp32 constant
{ name : "MOVSDconst" , reg : fp01 , asm : "MOVSD" } , // fp64 constant
{ name : "MOVSSloadidx4" , reg : fploadidx , asm : "MOVSS" } , // fp32 load
{ name : "MOVSDloadidx8" , reg : fploadidx , asm : "MOVSD" } , // fp64 load
{ name : "MOVSSstore" , reg : fpstore , asm : "MOVSS" } , // fp32 store
{ name : "MOVSDstore" , reg : fpstore , asm : "MOVSD" } , // fp64 store
{ name : "MOVSSstoreidx4" , reg : fpstoreidx , asm : "MOVSS" } , // fp32 indexed by 4i store
{ name : "MOVSDstoreidx8" , reg : fpstoreidx , asm : "MOVSD" } , // fp64 indexed by 8i store
2015-07-28 16:04:50 -07:00
// binary ops
{ name : "ADDQ" , reg : gp21 , asm : "ADDQ" } , // arg0 + arg1
{ name : "ADDL" , reg : gp21 , asm : "ADDL" } , // arg0 + arg1
{ name : "ADDW" , reg : gp21 , asm : "ADDW" } , // arg0 + arg1
{ name : "ADDB" , reg : gp21 , asm : "ADDB" } , // arg0 + arg1
{ name : "ADDQconst" , reg : gp11 , asm : "ADDQ" } , // arg0 + auxint
{ name : "ADDLconst" , reg : gp11 , asm : "ADDL" } , // arg0 + auxint
{ name : "ADDWconst" , reg : gp11 , asm : "ADDW" } , // arg0 + auxint
{ name : "ADDBconst" , reg : gp11 , asm : "ADDB" } , // arg0 + auxint
{ name : "SUBQ" , reg : gp21 , asm : "SUBQ" } , // arg0 - arg1
{ name : "SUBL" , reg : gp21 , asm : "SUBL" } , // arg0 - arg1
{ name : "SUBW" , reg : gp21 , asm : "SUBW" } , // arg0 - arg1
{ name : "SUBB" , reg : gp21 , asm : "SUBB" } , // arg0 - arg1
{ name : "SUBQconst" , reg : gp11 , asm : "SUBQ" } , // arg0 - auxint
{ name : "SUBLconst" , reg : gp11 , asm : "SUBL" } , // arg0 - auxint
{ name : "SUBWconst" , reg : gp11 , asm : "SUBW" } , // arg0 - auxint
{ name : "SUBBconst" , reg : gp11 , asm : "SUBB" } , // arg0 - auxint
2015-06-16 13:33:32 -07:00
{ name : "MULQ" , reg : gp21 , asm : "IMULQ" } , // arg0 * arg1
2015-07-28 16:04:50 -07:00
{ name : "MULL" , reg : gp21 , asm : "IMULL" } , // arg0 * arg1
{ name : "MULW" , reg : gp21 , asm : "IMULW" } , // arg0 * arg1
2015-08-14 13:23:11 +02:00
{ name : "MULB" , reg : gp21 , asm : "IMULW" } , // arg0 * arg1
2015-06-16 13:33:32 -07:00
{ name : "MULQconst" , reg : gp11 , asm : "IMULQ" } , // arg0 * auxint
2015-07-28 16:04:50 -07:00
{ name : "MULLconst" , reg : gp11 , asm : "IMULL" } , // arg0 * auxint
{ name : "MULWconst" , reg : gp11 , asm : "IMULW" } , // arg0 * auxint
2015-08-14 13:23:11 +02:00
{ name : "MULBconst" , reg : gp11 , asm : "IMULW" } , // arg0 * auxint
2015-07-28 16:04:50 -07:00
2015-08-17 17:46:06 -05:00
{ name : "DIVQ" , reg : gp11div , asm : "IDIVQ" } , // arg0 / arg1
{ name : "DIVL" , reg : gp11div , asm : "IDIVL" } , // arg0 / arg1
{ name : "DIVW" , reg : gp11div , asm : "IDIVW" } , // arg0 / arg1
{ name : "DIVQU" , reg : gp11div , asm : "DIVQ" } , // arg0 / arg1
{ name : "DIVLU" , reg : gp11div , asm : "DIVL" } , // arg0 / arg1
{ name : "DIVWU" , reg : gp11div , asm : "DIVW" } , // arg0 / arg1
2015-07-28 16:04:50 -07:00
{ name : "ANDQ" , reg : gp21 , asm : "ANDQ" } , // arg0 & arg1
{ name : "ANDL" , reg : gp21 , asm : "ANDL" } , // arg0 & arg1
{ name : "ANDW" , reg : gp21 , asm : "ANDW" } , // arg0 & arg1
{ name : "ANDB" , reg : gp21 , asm : "ANDB" } , // arg0 & arg1
{ name : "ANDQconst" , reg : gp11 , asm : "ANDQ" } , // arg0 & auxint
{ name : "ANDLconst" , reg : gp11 , asm : "ANDL" } , // arg0 & auxint
{ name : "ANDWconst" , reg : gp11 , asm : "ANDW" } , // arg0 & auxint
{ name : "ANDBconst" , reg : gp11 , asm : "ANDB" } , // arg0 & auxint
{ name : "ORQ" , reg : gp21 , asm : "ORQ" } , // arg0 | arg1
{ name : "ORL" , reg : gp21 , asm : "ORL" } , // arg0 | arg1
{ name : "ORW" , reg : gp21 , asm : "ORW" } , // arg0 | arg1
{ name : "ORB" , reg : gp21 , asm : "ORB" } , // arg0 | arg1
{ name : "ORQconst" , reg : gp11 , asm : "ORQ" } , // arg0 | auxint
{ name : "ORLconst" , reg : gp11 , asm : "ORL" } , // arg0 | auxint
{ name : "ORWconst" , reg : gp11 , asm : "ORW" } , // arg0 | auxint
{ name : "ORBconst" , reg : gp11 , asm : "ORB" } , // arg0 | auxint
2015-06-10 10:39:57 -07:00
2015-07-28 16:04:50 -07:00
{ name : "XORQ" , reg : gp21 , asm : "XORQ" } , // arg0 ^ arg1
{ name : "XORL" , reg : gp21 , asm : "XORL" } , // arg0 ^ arg1
{ name : "XORW" , reg : gp21 , asm : "XORW" } , // arg0 ^ arg1
{ name : "XORB" , reg : gp21 , asm : "XORB" } , // arg0 ^ arg1
{ name : "XORQconst" , reg : gp11 , asm : "XORQ" } , // arg0 ^ auxint
{ name : "XORLconst" , reg : gp11 , asm : "XORL" } , // arg0 ^ auxint
{ name : "XORWconst" , reg : gp11 , asm : "XORW" } , // arg0 ^ auxint
{ name : "XORBconst" , reg : gp11 , asm : "XORB" } , // arg0 ^ auxint
2015-06-06 16:03:33 -07:00
2015-06-16 13:33:32 -07:00
{ name : "CMPQ" , reg : gp2flags , asm : "CMPQ" } , // arg0 compare to arg1
2015-07-21 18:06:15 +02:00
{ name : "CMPL" , reg : gp2flags , asm : "CMPL" } , // arg0 compare to arg1
{ name : "CMPW" , reg : gp2flags , asm : "CMPW" } , // arg0 compare to arg1
{ name : "CMPB" , reg : gp2flags , asm : "CMPB" } , // arg0 compare to arg1
2015-07-28 16:04:50 -07:00
{ name : "CMPQconst" , reg : gp1flags , asm : "CMPQ" } , // arg0 compare to auxint
{ name : "CMPLconst" , reg : gp1flags , asm : "CMPL" } , // arg0 compare to auxint
{ name : "CMPWconst" , reg : gp1flags , asm : "CMPW" } , // arg0 compare to auxint
{ name : "CMPBconst" , reg : gp1flags , asm : "CMPB" } , // arg0 compare to auxint
2015-07-21 18:06:15 +02:00
2015-07-28 16:04:50 -07:00
{ name : "TESTQ" , reg : gp2flags , asm : "TESTQ" } , // (arg0 & arg1) compare to 0
{ name : "TESTL" , reg : gp2flags , asm : "TESTL" } , // (arg0 & arg1) compare to 0
{ name : "TESTW" , reg : gp2flags , asm : "TESTW" } , // (arg0 & arg1) compare to 0
{ name : "TESTB" , reg : gp2flags , asm : "TESTB" } , // (arg0 & arg1) compare to 0
{ name : "TESTQconst" , reg : gp1flags , asm : "TESTQ" } , // (arg0 & auxint) compare to 0
{ name : "TESTLconst" , reg : gp1flags , asm : "TESTL" } , // (arg0 & auxint) compare to 0
{ name : "TESTWconst" , reg : gp1flags , asm : "TESTW" } , // (arg0 & auxint) compare to 0
{ name : "TESTBconst" , reg : gp1flags , asm : "TESTB" } , // (arg0 & auxint) compare to 0
{ name : "SHLQ" , reg : gp21shift , asm : "SHLQ" } , // arg0 << arg1, shift amount is mod 64
{ name : "SHLL" , reg : gp21shift , asm : "SHLL" } , // arg0 << arg1, shift amount is mod 32
{ name : "SHLW" , reg : gp21shift , asm : "SHLW" } , // arg0 << arg1, shift amount is mod 32
{ name : "SHLB" , reg : gp21shift , asm : "SHLB" } , // arg0 << arg1, shift amount is mod 32
{ name : "SHLQconst" , reg : gp11 , asm : "SHLQ" } , // arg0 << auxint, shift amount 0-63
{ name : "SHLLconst" , reg : gp11 , asm : "SHLL" } , // arg0 << auxint, shift amount 0-31
{ name : "SHLWconst" , reg : gp11 , asm : "SHLW" } , // arg0 << auxint, shift amount 0-31
{ name : "SHLBconst" , reg : gp11 , asm : "SHLB" } , // arg0 << auxint, shift amount 0-31
// Note: x86 is weird, the 16 and 8 byte shifts still use all 5 bits of shift amount!
{ name : "SHRQ" , reg : gp21shift , asm : "SHRQ" } , // unsigned arg0 >> arg1, shift amount is mod 64
{ name : "SHRL" , reg : gp21shift , asm : "SHRL" } , // unsigned arg0 >> arg1, shift amount is mod 32
{ name : "SHRW" , reg : gp21shift , asm : "SHRW" } , // unsigned arg0 >> arg1, shift amount is mod 32
{ name : "SHRB" , reg : gp21shift , asm : "SHRB" } , // unsigned arg0 >> arg1, shift amount is mod 32
{ name : "SHRQconst" , reg : gp11 , asm : "SHRQ" } , // unsigned arg0 >> auxint, shift amount 0-63
{ name : "SHRLconst" , reg : gp11 , asm : "SHRL" } , // unsigned arg0 >> auxint, shift amount 0-31
{ name : "SHRWconst" , reg : gp11 , asm : "SHRW" } , // unsigned arg0 >> auxint, shift amount 0-31
{ name : "SHRBconst" , reg : gp11 , asm : "SHRB" } , // unsigned arg0 >> auxint, shift amount 0-31
{ name : "SARQ" , reg : gp21shift , asm : "SARQ" } , // signed arg0 >> arg1, shift amount is mod 64
{ name : "SARL" , reg : gp21shift , asm : "SARL" } , // signed arg0 >> arg1, shift amount is mod 32
{ name : "SARW" , reg : gp21shift , asm : "SARW" } , // signed arg0 >> arg1, shift amount is mod 32
{ name : "SARB" , reg : gp21shift , asm : "SARB" } , // signed arg0 >> arg1, shift amount is mod 32
{ name : "SARQconst" , reg : gp11 , asm : "SARQ" } , // signed arg0 >> auxint, shift amount 0-63
{ name : "SARLconst" , reg : gp11 , asm : "SARL" } , // signed arg0 >> auxint, shift amount 0-31
{ name : "SARWconst" , reg : gp11 , asm : "SARW" } , // signed arg0 >> auxint, shift amount 0-31
{ name : "SARBconst" , reg : gp11 , asm : "SARB" } , // signed arg0 >> auxint, shift amount 0-31
2015-08-05 22:11:14 -04:00
{ name : "ROLQconst" , reg : gp11 , asm : "ROLQ" } , // arg0 rotate left auxint, rotate amount 0-63
{ name : "ROLLconst" , reg : gp11 , asm : "ROLL" } , // arg0 rotate left auxint, rotate amount 0-31
{ name : "ROLWconst" , reg : gp11 , asm : "ROLW" } , // arg0 rotate left auxint, rotate amount 0-15
{ name : "ROLBconst" , reg : gp11 , asm : "ROLB" } , // arg0 rotate left auxint, rotate amount 0-7
2015-07-28 16:04:50 -07:00
// unary ops
{ name : "NEGQ" , reg : gp11 , asm : "NEGQ" } , // -arg0
{ name : "NEGL" , reg : gp11 , asm : "NEGL" } , // -arg0
{ name : "NEGW" , reg : gp11 , asm : "NEGW" } , // -arg0
{ name : "NEGB" , reg : gp11 , asm : "NEGB" } , // -arg0
2015-06-06 16:03:33 -07:00
2015-07-29 17:07:09 -07:00
{ name : "NOTQ" , reg : gp11 , asm : "NOTQ" } , // ^arg0
{ name : "NOTL" , reg : gp11 , asm : "NOTL" } , // ^arg0
{ name : "NOTW" , reg : gp11 , asm : "NOTW" } , // ^arg0
{ name : "NOTB" , reg : gp11 , asm : "NOTB" } , // ^arg0
2015-08-06 09:34:54 -07:00
{ name : "SBBQcarrymask" , reg : flagsgp , asm : "SBBQ" } , // (int64)(-1) if carry is set, 0 if carry is clear.
{ name : "SBBLcarrymask" , reg : flagsgp , asm : "SBBL" } , // (int32)(-1) if carry is set, 0 if carry is clear.
2015-07-29 17:07:09 -07:00
// Note: SBBW and SBBB are subsumed by SBBL
2015-06-10 10:39:57 -07:00
2015-07-20 15:21:49 -07:00
{ name : "SETEQ" , reg : flagsgp , asm : "SETEQ" } , // extract == condition from arg0
{ name : "SETNE" , reg : flagsgp , asm : "SETNE" } , // extract != condition from arg0
{ name : "SETL" , reg : flagsgp , asm : "SETLT" } , // extract signed < condition from arg0
{ name : "SETLE" , reg : flagsgp , asm : "SETLE" } , // extract signed <= condition from arg0
{ name : "SETG" , reg : flagsgp , asm : "SETGT" } , // extract signed > condition from arg0
{ name : "SETGE" , reg : flagsgp , asm : "SETGE" } , // extract signed >= condition from arg0
{ name : "SETB" , reg : flagsgp , asm : "SETCS" } , // extract unsigned < condition from arg0
2015-07-24 12:47:00 -07:00
{ name : "SETBE" , reg : flagsgp , asm : "SETLS" } , // extract unsigned <= condition from arg0
{ name : "SETA" , reg : flagsgp , asm : "SETHI" } , // extract unsigned > condition from arg0
{ name : "SETAE" , reg : flagsgp , asm : "SETCC" } , // extract unsigned >= condition from arg0
2015-06-06 16:03:33 -07:00
2015-07-22 13:46:15 -07:00
{ name : "MOVBQSX" , reg : gp11 , asm : "MOVBQSX" } , // sign extend arg0 from int8 to int64
{ name : "MOVBQZX" , reg : gp11 , asm : "MOVBQZX" } , // zero extend arg0 from int8 to int64
{ name : "MOVWQSX" , reg : gp11 , asm : "MOVWQSX" } , // sign extend arg0 from int16 to int64
{ name : "MOVWQZX" , reg : gp11 , asm : "MOVWQZX" } , // zero extend arg0 from int16 to int64
{ name : "MOVLQSX" , reg : gp11 , asm : "MOVLQSX" } , // sign extend arg0 from int32 to int64
{ name : "MOVLQZX" , reg : gp11 , asm : "MOVLQZX" } , // zero extend arg0 from int32 to int64
2015-06-14 11:38:46 -07:00
2015-07-28 14:19:20 -07:00
{ name : "MOVBconst" , reg : gp01 , asm : "MOVB" } , // 8 low bits of auxint
{ name : "MOVWconst" , reg : gp01 , asm : "MOVW" } , // 16 low bits of auxint
{ name : "MOVLconst" , reg : gp01 , asm : "MOVL" } , // 32 low bits of auxint
{ name : "MOVQconst" , reg : gp01 , asm : "MOVQ" } , // auxint
{ name : "LEAQ" , reg : gp11sb } , // arg0 + auxint + offset encoded in aux
{ name : "LEAQ1" , reg : gp21sb } , // arg0 + arg1 + auxint
{ name : "LEAQ2" , reg : gp21sb } , // arg0 + 2*arg1 + auxint
{ name : "LEAQ4" , reg : gp21sb } , // arg0 + 4*arg1 + auxint
{ name : "LEAQ8" , reg : gp21sb } , // arg0 + 8*arg1 + auxint
2015-06-06 16:03:33 -07:00
2015-07-27 16:36:36 -07:00
{ name : "MOVBload" , reg : gpload , asm : "MOVB" } , // load byte from arg0+auxint. arg1=mem
{ name : "MOVBQSXload" , reg : gpload , asm : "MOVBQSX" } , // ditto, extend to int64
{ name : "MOVBQZXload" , reg : gpload , asm : "MOVBQZX" } , // ditto, extend to uint64
{ name : "MOVWload" , reg : gpload , asm : "MOVW" } , // load 2 bytes from arg0+auxint. arg1=mem
{ name : "MOVLload" , reg : gpload , asm : "MOVL" } , // load 4 bytes from arg0+auxint. arg1=mem
{ name : "MOVQload" , reg : gpload , asm : "MOVQ" } , // load 8 bytes from arg0+auxint. arg1=mem
{ name : "MOVQloadidx8" , reg : gploadidx , asm : "MOVQ" } , // load 8 bytes from arg0+8*arg1+auxint. arg2=mem
{ name : "MOVBstore" , reg : gpstore , asm : "MOVB" } , // store byte in arg1 to arg0+auxint. arg2=mem
{ name : "MOVWstore" , reg : gpstore , asm : "MOVW" } , // store 2 bytes in arg1 to arg0+auxint. arg2=mem
{ name : "MOVLstore" , reg : gpstore , asm : "MOVL" } , // store 4 bytes in arg1 to arg0+auxint. arg2=mem
{ name : "MOVQstore" , reg : gpstore , asm : "MOVQ" } , // store 8 bytes in arg1 to arg0+auxint. arg2=mem
{ name : "MOVQstoreidx8" , reg : gpstoreidx , asm : "MOVQ" } , // store 8 bytes in arg2 to arg0+8*arg1+auxint. arg3=mem
2015-06-06 16:03:33 -07:00
2015-06-27 15:45:20 +01:00
{ name : "MOVXzero" , reg : gpstoreconst } , // store auxint 0 bytes into arg0 using a series of MOV instructions. arg1=mem.
// TODO: implement this when register clobbering works
{ name : "REPSTOSQ" , reg : regInfo { [ ] regMask { buildReg ( "DI" ) , buildReg ( "CX" ) } , buildReg ( "DI AX CX" ) , nil } } , // store arg1 8-byte words containing zero into arg0 using STOSQ. arg2=mem.
2015-06-10 15:03:06 -07:00
//TODO: set register clobber to everything?
2015-08-11 12:51:33 -07:00
{ name : "CALLstatic" , reg : regInfo { clobbers : callerSave } } , // call static function aux.(*gc.Sym). arg0=mem, returns mem
{ name : "CALLclosure" , reg : regInfo { [ ] regMask { gpsp , buildReg ( "DX" ) , 0 } , callerSave , nil } } , // call function via closure. arg0=codeptr, arg1=closure, arg2=mem returns mem
2015-06-10 15:03:06 -07:00
2015-06-06 16:03:33 -07:00
{ name : "REPMOVSB" , reg : regInfo { [ ] regMask { buildReg ( "DI" ) , buildReg ( "SI" ) , buildReg ( "CX" ) } , buildReg ( "DI SI CX" ) , nil } } , // move arg2 bytes from arg1 to arg0. arg3=mem, returns memory
// (InvertFlags (CMPQ a b)) == (CMPQ b a)
// So if we want (SETL (CMPQ a b)) but we can't do that because a is a constant,
// then we do (SETL (InvertFlags (CMPQ b a))) instead.
// Rewrites will convert this to (SETG (CMPQ b a)).
// InvertFlags is a pseudo-op which can't appear in assembly output.
{ name : "InvertFlags" } , // reverse direction of arg0
2015-08-11 09:47:45 -07:00
2015-08-12 11:22:16 -07:00
// Pseudo-ops
2015-08-11 09:47:45 -07:00
{ name : "LoweredPanicNilCheck" } ,
2015-08-13 13:12:17 -07:00
{ name : "LoweredGetG" , reg : gp01 } ,
2015-06-06 16:03:33 -07:00
}
var AMD64blocks = [ ] blockData {
{ name : "EQ" } ,
{ name : "NE" } ,
{ name : "LT" } ,
{ name : "LE" } ,
{ name : "GT" } ,
{ name : "GE" } ,
{ name : "ULT" } ,
{ name : "ULE" } ,
{ name : "UGT" } ,
{ name : "UGE" } ,
}
2015-06-11 15:52:08 -07:00
archs = append ( archs , arch { "AMD64" , AMD64ops , AMD64blocks , regNamesAMD64 } )
2015-06-06 16:03:33 -07:00
}