p.From.Offset = v.AuxInt
p.To.Type = obj.TYPE_REG
p.To.Reg = r
- case ssa.OpAMD64SHLQ:
+ case ssa.OpAMD64SHLQ, ssa.OpAMD64SHRQ, ssa.OpAMD64SARQ:
x := regnum(v.Args[0])
r := regnum(v)
if x != r {
p.To.Reg = r
x = r
}
- p := Prog(x86.ASHLQ)
+ p := Prog(v.Op.Asm())
p.From.Type = obj.TYPE_REG
p.From.Reg = regnum(v.Args[1]) // should be CX
p.To.Type = obj.TYPE_REG
p.To.Reg = r
- case ssa.OpAMD64SHRQ:
- x := regnum(v.Args[0])
- r := regnum(v)
- if x != r {
- if r == x86.REG_CX {
- log.Fatalf("can't implement %s, target and shift both in CX", v.LongString())
- }
- p := Prog(x86.AMOVQ)
- p.From.Type = obj.TYPE_REG
- p.From.Reg = x
- p.To.Type = obj.TYPE_REG
- p.To.Reg = r
- x = r
- }
- p := Prog(x86.ASHRQ)
- p.From.Type = obj.TYPE_REG
- p.From.Reg = regnum(v.Args[1]) // should be CX
- p.To.Type = obj.TYPE_REG
- p.To.Reg = r
- case ssa.OpAMD64SARQ:
- x := regnum(v.Args[0])
- r := regnum(v)
- if x != r {
- if r == x86.REG_CX {
- log.Fatalf("can't implement %s, target and shift both in CX", v.LongString())
- }
- p := Prog(x86.AMOVQ)
- p.From.Type = obj.TYPE_REG
- p.From.Reg = x
- p.To.Type = obj.TYPE_REG
- p.To.Reg = r
- x = r
- }
- p := Prog(x86.ASARQ)
- p.From.Type = obj.TYPE_REG
- p.From.Reg = regnum(v.Args[1]) // should be CX
- p.To.Type = obj.TYPE_REG
- p.To.Reg = r
- case ssa.OpAMD64SHLQconst:
- x := regnum(v.Args[0])
- r := regnum(v)
- if x != r {
- p := Prog(x86.AMOVQ)
- p.From.Type = obj.TYPE_REG
- p.From.Reg = x
- p.To.Type = obj.TYPE_REG
- p.To.Reg = r
- x = r
- }
- p := Prog(x86.ASHLQ)
- p.From.Type = obj.TYPE_CONST
- p.From.Offset = v.AuxInt
- p.To.Type = obj.TYPE_REG
- p.To.Reg = r
- case ssa.OpAMD64SHRQconst:
+ case ssa.OpAMD64SHLQconst, ssa.OpAMD64SHRQconst, ssa.OpAMD64SARQconst:
x := regnum(v.Args[0])
r := regnum(v)
if x != r {
p.To.Reg = r
x = r
}
- p := Prog(x86.ASHRQ)
+ p := Prog(v.Op.Asm())
p.From.Type = obj.TYPE_CONST
p.From.Offset = v.AuxInt
p.To.Type = obj.TYPE_REG
- p.To.Reg = r
- case ssa.OpAMD64SARQconst:
- x := regnum(v.Args[0])
- r := regnum(v)
- if x != r {
- p := Prog(x86.AMOVQ)
- p.From.Type = obj.TYPE_REG
- p.From.Reg = x
- p.To.Type = obj.TYPE_REG
- p.To.Reg = r
- x = r
- }
- p := Prog(x86.ASARQ)
- p.From.Type = obj.TYPE_CONST
- p.From.Offset = v.AuxInt
- p.To.Type = obj.TYPE_REG
- p.To.Reg = r
case ssa.OpAMD64SBBQcarrymask:
r := regnum(v)
p := Prog(x86.ASBBQ)
p.From.Offset = v.AuxInt
p.To.Type = obj.TYPE_REG
p.To.Reg = regnum(v)
- case ssa.OpAMD64CMPQ:
- p := Prog(x86.ACMPQ)
+ case ssa.OpAMD64CMPQ, ssa.OpAMD64TESTB, ssa.OpAMD64TESTQ:
+ p := Prog(v.Op.Asm())
p.From.Type = obj.TYPE_REG
p.From.Reg = regnum(v.Args[0])
p.To.Type = obj.TYPE_REG
p.From.Reg = regnum(v.Args[0])
p.To.Type = obj.TYPE_CONST
p.To.Offset = v.AuxInt
- case ssa.OpAMD64TESTB:
- p := Prog(x86.ATESTB)
- p.From.Type = obj.TYPE_REG
- p.From.Reg = regnum(v.Args[0])
- p.To.Type = obj.TYPE_REG
- p.To.Reg = regnum(v.Args[1])
- case ssa.OpAMD64TESTQ:
- p := Prog(x86.ATESTQ)
- p.From.Type = obj.TYPE_REG
- p.From.Reg = regnum(v.Args[0])
- p.To.Type = obj.TYPE_REG
- p.To.Reg = regnum(v.Args[1])
case ssa.OpAMD64MOVQconst:
x := regnum(v)
p := Prog(x86.AMOVQ)
p.From.Offset = v.AuxInt
p.To.Type = obj.TYPE_REG
p.To.Reg = x
- case ssa.OpAMD64MOVQload:
- p := Prog(x86.AMOVQ)
- p.From.Type = obj.TYPE_MEM
- p.From.Reg = regnum(v.Args[0])
- p.From.Offset = v.AuxInt
- p.To.Type = obj.TYPE_REG
- p.To.Reg = regnum(v)
- case ssa.OpAMD64MOVBload:
- p := Prog(x86.AMOVB)
+ case ssa.OpAMD64MOVQload, ssa.OpAMD64MOVBload:
+ p := Prog(v.Op.Asm())
p.From.Type = obj.TYPE_MEM
p.From.Reg = regnum(v.Args[0])
p.From.Offset = v.AuxInt
package main
-import "strings"
+import (
+ "cmd/internal/obj/x86"
+ "strings"
+)
// copied from ../../amd64/reg.go
var regNamesAMD64 = []string{
// TODO: 2-address instructions. Mark ops as needing matching input/output regs.
var AMD64ops = []opData{
- {name: "ADDQ", reg: gp21}, // arg0 + arg1
- {name: "ADDQconst", reg: gp11}, // arg0 + auxint
- {name: "SUBQ", reg: gp21}, // arg0 - arg1
- {name: "SUBQconst", reg: gp11}, // arg0 - auxint
- {name: "MULQ", reg: gp21}, // arg0 * arg1
- {name: "MULQconst", reg: gp11}, // arg0 * auxint
- {name: "ANDQ", reg: gp21}, // arg0 & arg1
- {name: "ANDQconst", reg: gp11}, // arg0 & auxint
- {name: "SHLQ", reg: gp21shift}, // arg0 << arg1, shift amount is mod 64
- {name: "SHLQconst", reg: gp11}, // arg0 << auxint, shift amount 0-63
- {name: "SHRQ", reg: gp21shift}, // unsigned arg0 >> arg1, shift amount is mod 64
- {name: "SHRQconst", reg: gp11}, // unsigned arg0 >> auxint, shift amount 0-63
- {name: "SARQ", reg: gp21shift}, // signed arg0 >> arg1, shift amount is mod 64
- {name: "SARQconst", reg: gp11}, // signed arg0 >> auxint, shift amount 0-63
+ {name: "ADDQ", reg: gp21}, // arg0 + arg1
+ {name: "ADDQconst", reg: gp11}, // arg0 + auxint
+ {name: "SUBQ", reg: gp21, asm: x86.ASUBQ}, // arg0 - arg1
+ {name: "SUBQconst", reg: gp11, asm: x86.ASUBQ}, // arg0 - auxint
+ {name: "MULQ", reg: gp21, asm: x86.AIMULQ}, // arg0 * arg1
+ {name: "MULQconst", reg: gp11, asm: x86.AIMULQ}, // arg0 * auxint
+ {name: "ANDQ", reg: gp21, asm: x86.AANDQ}, // arg0 & arg1
+ {name: "ANDQconst", reg: gp11, asm: x86.AANDQ}, // arg0 & auxint
+ {name: "SHLQ", reg: gp21shift, asm: x86.ASHLQ}, // arg0 << arg1, shift amount is mod 64
+ {name: "SHLQconst", reg: gp11, asm: x86.ASHLQ}, // arg0 << auxint, shift amount 0-63
+ {name: "SHRQ", reg: gp21shift, asm: x86.ASHRQ}, // unsigned arg0 >> arg1, shift amount is mod 64
+ {name: "SHRQconst", reg: gp11, asm: x86.ASHRQ}, // unsigned arg0 >> auxint, shift amount 0-63
+ {name: "SARQ", reg: gp21shift, asm: x86.ASARQ}, // signed arg0 >> arg1, shift amount is mod 64
+ {name: "SARQconst", reg: gp11, asm: x86.ASARQ}, // signed arg0 >> auxint, shift amount 0-63
{name: "NEGQ", reg: gp11}, // -arg0
- {name: "CMPQ", reg: gp2flags}, // arg0 compare to arg1
- {name: "CMPQconst", reg: gp1flags}, // arg0 compare to auxint
- {name: "TESTQ", reg: gp2flags}, // (arg0 & arg1) compare to 0
- {name: "TESTB", reg: gp2flags}, // (arg0 & arg1) compare to 0
+ {name: "CMPQ", reg: gp2flags, asm: x86.ACMPQ}, // arg0 compare to arg1
+ {name: "CMPQconst", reg: gp1flags, asm: x86.ACMPQ}, // arg0 compare to auxint
+ {name: "TESTQ", reg: gp2flags, asm: x86.ATESTQ}, // (arg0 & arg1) compare to 0
+ {name: "TESTB", reg: gp2flags, asm: x86.ATESTB}, // (arg0 & arg1) compare to 0
- {name: "SBBQcarrymask", reg: flagsgp1}, // (int64)(-1) if carry is set, 0 if carry is clear.
+ {name: "SBBQcarrymask", reg: flagsgp1, asm: x86.ASBBQ}, // (int64)(-1) if carry is set, 0 if carry is clear.
{name: "SETEQ", reg: flagsgp}, // extract == condition from arg0
{name: "SETNE", reg: flagsgp}, // extract != condition from arg0
{name: "LEAQ8", reg: gp21}, // arg0 + 8*arg1 + auxint
{name: "LEAQglobal", reg: gp01}, // no args. address of aux.(*gc.Sym)
- {name: "MOVBload", reg: gpload}, // load byte from arg0+auxint. arg1=mem
- {name: "MOVBQZXload", reg: gpload}, // ditto, extend to uint64
- {name: "MOVBQSXload", reg: gpload}, // ditto, extend to int64
- {name: "MOVQload", reg: gpload}, // load 8 bytes from arg0+auxint. arg1=mem
- {name: "MOVQloadidx8", reg: gploadidx}, // load 8 bytes from arg0+8*arg1+auxint. arg2=mem
- {name: "MOVBstore", reg: gpstore}, // store byte in arg1 to arg0+auxint. arg2=mem
- {name: "MOVQstore", reg: gpstore}, // store 8 bytes in arg1 to arg0+auxint. arg2=mem
- {name: "MOVQstoreidx8", reg: gpstoreidx}, // store 8 bytes in arg2 to arg0+8*arg1+auxint. arg3=mem
+ {name: "MOVBload", reg: gpload}, // load byte from arg0+auxint. arg1=mem
+ {name: "MOVBQZXload", reg: gpload}, // ditto, extend to uint64
+ {name: "MOVBQSXload", reg: gpload}, // ditto, extend to int64
+ {name: "MOVQload", reg: gpload}, // load 8 bytes from arg0+auxint. arg1=mem
+ {name: "MOVQloadidx8", reg: gploadidx}, // load 8 bytes from arg0+8*arg1+auxint. arg2=mem
+ {name: "MOVBstore", reg: gpstore, asm: x86.AMOVB}, // store byte in arg1 to arg0+auxint. arg2=mem
+ {name: "MOVQstore", reg: gpstore, asm: x86.AMOVQ}, // store 8 bytes in arg1 to arg0+auxint. arg2=mem
+ {name: "MOVQstoreidx8", reg: gpstoreidx}, // store 8 bytes in arg2 to arg0+8*arg1+auxint. arg3=mem
// Load/store from global. Same as the above loads, but arg0 is missing and
// aux is a GlobalOffset instead of an int64.
{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
- {name: "ADDL", reg: gp21}, // arg0+arg1
+ {name: "ADDL", reg: gp21, asm: x86.AADDL}, // arg0+arg1
// (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,
// generated from gen/*Ops.go
package ssa
+import "cmd/internal/obj/x86"
+
const (
blockInvalid BlockKind = iota
},
{
name: "SUBQ",
+ asm: x86.ASUBQ,
reg: regInfo{
inputs: []regMask{
4295032831, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 .FP
},
{
name: "SUBQconst",
+ asm: x86.ASUBQ,
reg: regInfo{
inputs: []regMask{
4295032831, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 .FP
},
{
name: "MULQ",
+ asm: x86.AIMULQ,
reg: regInfo{
inputs: []regMask{
4295032831, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 .FP
},
{
name: "MULQconst",
+ asm: x86.AIMULQ,
reg: regInfo{
inputs: []regMask{
4295032831, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 .FP
},
{
name: "ANDQ",
+ asm: x86.AANDQ,
reg: regInfo{
inputs: []regMask{
4295032831, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 .FP
},
{
name: "ANDQconst",
+ asm: x86.AANDQ,
reg: regInfo{
inputs: []regMask{
4295032831, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 .FP
},
{
name: "SHLQ",
+ asm: x86.ASHLQ,
reg: regInfo{
inputs: []regMask{
4295032831, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 .FP
},
{
name: "SHLQconst",
+ asm: x86.ASHLQ,
reg: regInfo{
inputs: []regMask{
4295032831, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 .FP
},
{
name: "SHRQ",
+ asm: x86.ASHRQ,
reg: regInfo{
inputs: []regMask{
4295032831, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 .FP
},
{
name: "SHRQconst",
+ asm: x86.ASHRQ,
reg: regInfo{
inputs: []regMask{
4295032831, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 .FP
},
{
name: "SARQ",
+ asm: x86.ASARQ,
reg: regInfo{
inputs: []regMask{
4295032831, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 .FP
},
{
name: "SARQconst",
+ asm: x86.ASARQ,
reg: regInfo{
inputs: []regMask{
4295032831, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 .FP
},
{
name: "CMPQ",
+ asm: x86.ACMPQ,
reg: regInfo{
inputs: []regMask{
4295032831, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 .FP
},
{
name: "CMPQconst",
+ asm: x86.ACMPQ,
reg: regInfo{
inputs: []regMask{
4295032831, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 .FP
},
{
name: "TESTQ",
+ asm: x86.ATESTQ,
reg: regInfo{
inputs: []regMask{
4295032831, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 .FP
},
{
name: "TESTB",
+ asm: x86.ATESTB,
reg: regInfo{
inputs: []regMask{
4295032831, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 .FP
},
{
name: "SBBQcarrymask",
+ asm: x86.ASBBQ,
reg: regInfo{
inputs: []regMask{
8589934592, // .FLAGS
},
{
name: "MOVBstore",
+ asm: x86.AMOVB,
reg: regInfo{
inputs: []regMask{
4295032831, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 .FP
},
{
name: "MOVQstore",
+ asm: x86.AMOVQ,
reg: regInfo{
inputs: []regMask{
4295032831, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 .FP
},
{
name: "ADDL",
+ asm: x86.AADDL,
reg: regInfo{
inputs: []regMask{
4295032831, // .AX .CX .DX .BX .SP .BP .SI .DI .R8 .R9 .R10 .R11 .R12 .R13 .R14 .R15 .FP
},
}
+func (o Op) Asm() int { return opcodeTable[o].asm }
func (o Op) String() string { return opcodeTable[o].name }