Commit e71e1fe8 authored by Cherry Zhang's avatar Cherry Zhang

cmd/compile: get MIPS64 SSA working

- implement *, /, %, shifts, Zero, Move.
- fix mistakes in comparison.
- fix floating point rounding.
- handle RetJmp in assembler (which was not handled, as a consequence
  Duff's device was disabled in the old backend.)

all.bash now passes with SSA on.

Updates #16359.

Change-Id: Ia14eed0ed1176b5d800592080c8f53dded7fe73f
Reviewed-on: https://go-review.googlesource.com/27592Reviewed-by: default avatarDavid Chase <drchase@google.com>
Run-TryBot: Cherry Zhang <cherryyz@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
parent e90ae90b
......@@ -90,9 +90,19 @@ var ssaRegToReg = []int16{
// see ../../../../runtime/mheap.go:/minPhysPageSize
const minZeroPage = 4096
// isFPreg returns whether r is an FP register
func isFPreg(r int16) bool {
return mips.REG_F0 <= r && r <= mips.REG_F31
}
// isHILO returns whether r is HI or LO register
func isHILO(r int16) bool {
return r == mips.REG_HI || r == mips.REG_LO
}
// loadByType returns the load instruction of the given type.
func loadByType(t ssa.Type, r int16) obj.As {
if mips.REG_F0 <= r && r <= mips.REG_F31 {
if isFPreg(r) {
if t.IsFloat() && t.Size() == 4 { // float32
return mips.AMOVF
} else { // float64 or integer in FP register
......@@ -127,7 +137,7 @@ func loadByType(t ssa.Type, r int16) obj.As {
// storeByType returns the store instruction of the given type.
func storeByType(t ssa.Type, r int16) obj.As {
if mips.REG_F0 <= r && r <= mips.REG_F31 {
if isFPreg(r) {
if t.IsFloat() && t.Size() == 4 { // float32
return mips.AMOVF
} else { // float64 or integer in FP register
......@@ -167,21 +177,23 @@ func ssaGenValue(s *gc.SSAGenState, v *ssa.Value) {
return
}
as := mips.AMOVV
if v.Type.IsFloat() {
switch v.Type.Size() {
case 4:
as = mips.AMOVF
case 8:
as = mips.AMOVD
default:
panic("bad float size")
}
if isFPreg(x) && isFPreg(y) {
as = mips.AMOVD
}
p := gc.Prog(as)
p.From.Type = obj.TYPE_REG
p.From.Reg = x
p.To.Type = obj.TYPE_REG
p.To.Reg = y
if isHILO(x) && isHILO(y) || isHILO(x) && isFPreg(y) || isFPreg(x) && isHILO(y) {
// cannot move between special registers, use TMP as intermediate
p.To.Reg = mips.REGTMP
p = gc.Prog(mips.AMOVV)
p.From.Type = obj.TYPE_REG
p.From.Reg = mips.REGTMP
p.To.Type = obj.TYPE_REG
p.To.Reg = y
}
case ssa.OpMIPS64MOVVnop:
if gc.SSARegNum(v) != gc.SSARegNum(v.Args[0]) {
v.Fatalf("input[0] and output not in same register %s", v.LongString())
......@@ -207,6 +219,15 @@ func ssaGenValue(s *gc.SSAGenState, v *ssa.Value) {
}
p.To.Type = obj.TYPE_REG
p.To.Reg = r
if isHILO(r) {
// cannot directly load, load to TMP and move
p.To.Reg = mips.REGTMP
p = gc.Prog(mips.AMOVV)
p.From.Type = obj.TYPE_REG
p.From.Reg = mips.REGTMP
p.To.Type = obj.TYPE_REG
p.To.Reg = r
}
case ssa.OpPhi:
gc.CheckLoweredPhi(v)
case ssa.OpStoreReg:
......@@ -215,6 +236,15 @@ func ssaGenValue(s *gc.SSAGenState, v *ssa.Value) {
return
}
r := gc.SSARegNum(v.Args[0])
if isHILO(r) {
// cannot directly store, move to TMP and store
p := gc.Prog(mips.AMOVV)
p.From.Type = obj.TYPE_REG
p.From.Reg = r
p.To.Type = obj.TYPE_REG
p.To.Reg = mips.REGTMP
r = mips.REGTMP
}
p := gc.Prog(storeByType(v.Type, r))
p.From.Type = obj.TYPE_REG
p.From.Reg = r
......@@ -287,11 +317,21 @@ func ssaGenValue(s *gc.SSAGenState, v *ssa.Value) {
p.From.Reg = gc.SSARegNum(v.Args[1])
p.Reg = gc.SSARegNum(v.Args[0])
case ssa.OpMIPS64MOVVconst:
r := gc.SSARegNum(v)
p := gc.Prog(v.Op.Asm())
p.From.Type = obj.TYPE_CONST
p.From.Offset = v.AuxInt
p.To.Type = obj.TYPE_REG
p.To.Reg = gc.SSARegNum(v)
p.To.Reg = r
if isFPreg(r) || isHILO(r) {
// cannot move into FP or special registers, use TMP as intermediate
p.To.Reg = mips.REGTMP
p = gc.Prog(mips.AMOVV)
p.From.Type = obj.TYPE_REG
p.From.Reg = mips.REGTMP
p.To.Type = obj.TYPE_REG
p.To.Reg = r
}
case ssa.OpMIPS64MOVFconst,
ssa.OpMIPS64MOVDconst:
p := gc.Prog(v.Op.Asm())
......@@ -312,9 +352,6 @@ func ssaGenValue(s *gc.SSAGenState, v *ssa.Value) {
case ssa.OpMIPS64MOVVaddr:
p := gc.Prog(mips.AMOVV)
p.From.Type = obj.TYPE_ADDR
p.To.Type = obj.TYPE_REG
p.To.Reg = gc.SSARegNum(v)
var wantreg string
// MOVV $sym+off(base), R
// the assembler expands it as the following:
......@@ -339,6 +376,8 @@ func ssaGenValue(s *gc.SSAGenState, v *ssa.Value) {
if reg := gc.SSAReg(v.Args[0]); reg.Name() != wantreg {
v.Fatalf("bad reg %s for symbol type %T, want %s", reg.Name(), v.Aux, wantreg)
}
p.To.Type = obj.TYPE_REG
p.To.Reg = gc.SSARegNum(v)
case ssa.OpMIPS64MOVBload,
ssa.OpMIPS64MOVBUload,
ssa.OpMIPS64MOVHload,
......@@ -386,12 +425,12 @@ func ssaGenValue(s *gc.SSAGenState, v *ssa.Value) {
fallthrough
case ssa.OpMIPS64MOVWF,
ssa.OpMIPS64MOVWD,
ssa.OpMIPS64MOVFW,
ssa.OpMIPS64MOVDW,
ssa.OpMIPS64TRUNCFW,
ssa.OpMIPS64TRUNCDW,
ssa.OpMIPS64MOVVF,
ssa.OpMIPS64MOVVD,
ssa.OpMIPS64MOVFV,
ssa.OpMIPS64MOVDV,
ssa.OpMIPS64TRUNCFV,
ssa.OpMIPS64TRUNCDV,
ssa.OpMIPS64MOVFD,
ssa.OpMIPS64MOVDF,
ssa.OpMIPS64NEGF,
......@@ -409,6 +448,119 @@ func ssaGenValue(s *gc.SSAGenState, v *ssa.Value) {
p.Reg = mips.REGZERO
p.To.Type = obj.TYPE_REG
p.To.Reg = gc.SSARegNum(v)
case ssa.OpMIPS64DUFFZERO:
// runtime.duffzero expects start address - 8 in R1
p := gc.Prog(mips.ASUBVU)
p.From.Type = obj.TYPE_CONST
p.From.Offset = 8
p.Reg = gc.SSARegNum(v.Args[0])
p.To.Type = obj.TYPE_REG
p.To.Reg = mips.REG_R1
p = gc.Prog(obj.ADUFFZERO)
p.To.Type = obj.TYPE_MEM
p.To.Name = obj.NAME_EXTERN
p.To.Sym = gc.Linksym(gc.Pkglookup("duffzero", gc.Runtimepkg))
p.To.Offset = v.AuxInt
case ssa.OpMIPS64LoweredZero:
// SUBV $8, R1
// MOVV R0, 8(R1)
// ADDV $8, R1
// BNE Rarg1, R1, -2(PC)
// arg1 is the address of the last element to zero
var sz int64
var mov obj.As
switch {
case v.AuxInt%8 == 0:
sz = 8
mov = mips.AMOVV
case v.AuxInt%4 == 0:
sz = 4
mov = mips.AMOVW
case v.AuxInt%2 == 0:
sz = 2
mov = mips.AMOVH
default:
sz = 1
mov = mips.AMOVB
}
p := gc.Prog(mips.ASUBVU)
p.From.Type = obj.TYPE_CONST
p.From.Offset = sz
p.To.Type = obj.TYPE_REG
p.To.Reg = mips.REG_R1
p2 := gc.Prog(mov)
p2.From.Type = obj.TYPE_REG
p2.From.Reg = mips.REGZERO
p2.To.Type = obj.TYPE_MEM
p2.To.Reg = mips.REG_R1
p2.To.Offset = sz
p3 := gc.Prog(mips.AADDVU)
p3.From.Type = obj.TYPE_CONST
p3.From.Offset = sz
p3.To.Type = obj.TYPE_REG
p3.To.Reg = mips.REG_R1
p4 := gc.Prog(mips.ABNE)
p4.From.Type = obj.TYPE_REG
p4.From.Reg = gc.SSARegNum(v.Args[1])
p4.Reg = mips.REG_R1
p4.To.Type = obj.TYPE_BRANCH
gc.Patch(p4, p2)
case ssa.OpMIPS64LoweredMove:
// SUBV $8, R1
// MOVV 8(R1), Rtmp
// MOVV Rtmp, (R2)
// ADDV $8, R1
// ADDV $8, R2
// BNE Rarg2, R1, -4(PC)
// arg2 is the address of the last element of src
var sz int64
var mov obj.As
switch {
case v.AuxInt%8 == 0:
sz = 8
mov = mips.AMOVV
case v.AuxInt%4 == 0:
sz = 4
mov = mips.AMOVW
case v.AuxInt%2 == 0:
sz = 2
mov = mips.AMOVH
default:
sz = 1
mov = mips.AMOVB
}
p := gc.Prog(mips.ASUBVU)
p.From.Type = obj.TYPE_CONST
p.From.Offset = sz
p.To.Type = obj.TYPE_REG
p.To.Reg = mips.REG_R1
p2 := gc.Prog(mov)
p2.From.Type = obj.TYPE_MEM
p2.From.Reg = mips.REG_R1
p2.From.Offset = sz
p2.To.Type = obj.TYPE_REG
p2.To.Reg = mips.REGTMP
p3 := gc.Prog(mov)
p3.From.Type = obj.TYPE_REG
p3.From.Reg = mips.REGTMP
p3.To.Type = obj.TYPE_MEM
p3.To.Reg = mips.REG_R2
p4 := gc.Prog(mips.AADDVU)
p4.From.Type = obj.TYPE_CONST
p4.From.Offset = sz
p4.To.Type = obj.TYPE_REG
p4.To.Reg = mips.REG_R1
p5 := gc.Prog(mips.AADDVU)
p5.From.Type = obj.TYPE_CONST
p5.From.Offset = sz
p5.To.Type = obj.TYPE_REG
p5.To.Reg = mips.REG_R2
p6 := gc.Prog(mips.ABNE)
p6.From.Type = obj.TYPE_REG
p6.From.Reg = gc.SSARegNum(v.Args[2])
p6.Reg = mips.REG_R1
p6.To.Type = obj.TYPE_BRANCH
gc.Patch(p6, p2)
case ssa.OpMIPS64CALLstatic:
if v.Aux.(*gc.Sym) == gc.Deferreturn.Sym {
// Deferred calls will appear to be returning to
......@@ -468,7 +620,7 @@ func ssaGenValue(s *gc.SSAGenState, v *ssa.Value) {
p.From.Reg = gc.SSARegNum(v.Args[0])
gc.AddAux(&p.From, v)
p.To.Type = obj.TYPE_REG
p.To.Reg = mips.REGZERO
p.To.Reg = mips.REGTMP
if gc.Debug_checknil != 0 && v.Line > 1 { // v.Line==1 in generated wrappers
gc.Warnl(v.Line, "generated nil check")
}
......
......@@ -22,6 +22,7 @@ type Config struct {
registers []Register // machine registers
gpRegMask regMask // general purpose integer register mask
fpRegMask regMask // floating point register mask
specialRegMask regMask // special register mask
FPReg int8 // register number of frame pointer, -1 if not used
hasGReg bool // has hardware g register
fe Frontend // callbacks into compiler frontend
......@@ -202,6 +203,7 @@ func NewConfig(arch string, fe Frontend, ctxt *obj.Link, optimize bool) *Config
c.registers = registersMIPS64[:]
c.gpRegMask = gpRegMaskMIPS64
c.fpRegMask = fpRegMaskMIPS64
c.specialRegMask = specialRegMaskMIPS64
c.FPReg = framepointerRegMIPS64
c.hasGReg = true
default:
......
......@@ -160,14 +160,14 @@ func init() {
)
ops := []opData{
// binary ops
{name: "ADDV", argLength: 2, reg: gp21, asm: "ADDVU", commutative: true}, // arg0 + arg1
{name: "ADDVconst", argLength: 1, reg: gp11sp, asm: "ADDVU", aux: "Int64"}, // arg0 + auxInt
{name: "SUBV", argLength: 2, reg: gp21, asm: "SUBVU"}, // arg0 - arg1
{name: "SUBVconst", argLength: 1, reg: gp11, asm: "SUBVU", aux: "Int64"}, // arg0 - auxInt
{name: "MULV", argLength: 2, reg: gp2hilo, asm: "MULV", commutative: true}, // arg0 * arg1, signed, results hi,lo
{name: "MULVU", argLength: 2, reg: gp2hilo, asm: "MULVU", commutative: true}, // arg0 * arg1, unsigned, results hi,lo
{name: "DIVV", argLength: 2, reg: gp2hilo, asm: "DIVV"}, // arg0 / arg1, signed, results hi=arg0%arg1,lo=arg0/arg1
{name: "DIVVU", argLength: 2, reg: gp2hilo, asm: "DIVVU"}, // arg0 / arg1, signed, results hi=arg0%arg1,lo=arg0/arg1
{name: "ADDV", argLength: 2, reg: gp21, asm: "ADDVU", commutative: true}, // arg0 + arg1
{name: "ADDVconst", argLength: 1, reg: gp11sp, asm: "ADDVU", aux: "Int64"}, // arg0 + auxInt
{name: "SUBV", argLength: 2, reg: gp21, asm: "SUBVU"}, // arg0 - arg1
{name: "SUBVconst", argLength: 1, reg: gp11, asm: "SUBVU", aux: "Int64"}, // arg0 - auxInt
{name: "MULV", argLength: 2, reg: gp2hilo, asm: "MULV", commutative: true, typ: "(Int64,Int64)"}, // arg0 * arg1, signed, results hi,lo
{name: "MULVU", argLength: 2, reg: gp2hilo, asm: "MULVU", commutative: true, typ: "(UInt64,UInt64)"}, // arg0 * arg1, unsigned, results hi,lo
{name: "DIVV", argLength: 2, reg: gp2hilo, asm: "DIVV", typ: "(Int64,Int64)"}, // arg0 / arg1, signed, results hi=arg0%arg1,lo=arg0/arg1
{name: "DIVVU", argLength: 2, reg: gp2hilo, asm: "DIVVU", typ: "(UInt64,UInt64)"}, // arg0 / arg1, signed, results hi=arg0%arg1,lo=arg0/arg1
{name: "ADDF", argLength: 2, reg: fp21, asm: "ADDF", commutative: true}, // arg0 + arg1
{name: "ADDD", argLength: 2, reg: fp21, asm: "ADDD", commutative: true}, // arg0 + arg1
......@@ -252,16 +252,16 @@ func init() {
{name: "MOVVnop", argLength: 1, reg: regInfo{inputs: []regMask{gp}, outputs: []regMask{gp}}, resultInArg0: true}, // nop, return arg0 in same register
{name: "MOVWF", argLength: 1, reg: fp11, asm: "MOVWF"}, // int32 -> float32
{name: "MOVWD", argLength: 1, reg: fp11, asm: "MOVWD"}, // int32 -> float64
{name: "MOVVF", argLength: 1, reg: fp11, asm: "MOVVF"}, // int64 -> float32
{name: "MOVVD", argLength: 1, reg: fp11, asm: "MOVVD"}, // int64 -> float64
{name: "MOVFW", argLength: 1, reg: fp11, asm: "MOVFW"}, // float32 -> int32
{name: "MOVDW", argLength: 1, reg: fp11, asm: "MOVDW"}, // float64 -> int32
{name: "MOVFV", argLength: 1, reg: fp11, asm: "MOVFV"}, // float32 -> int64
{name: "MOVDV", argLength: 1, reg: fp11, asm: "MOVDV"}, // float64 -> int64
{name: "MOVFD", argLength: 1, reg: fp11, asm: "MOVFD"}, // float32 -> float64
{name: "MOVDF", argLength: 1, reg: fp11, asm: "MOVDF"}, // float64 -> float32
{name: "MOVWF", argLength: 1, reg: fp11, asm: "MOVWF"}, // int32 -> float32
{name: "MOVWD", argLength: 1, reg: fp11, asm: "MOVWD"}, // int32 -> float64
{name: "MOVVF", argLength: 1, reg: fp11, asm: "MOVVF"}, // int64 -> float32
{name: "MOVVD", argLength: 1, reg: fp11, asm: "MOVVD"}, // int64 -> float64
{name: "TRUNCFW", argLength: 1, reg: fp11, asm: "TRUNCFW"}, // float32 -> int32
{name: "TRUNCDW", argLength: 1, reg: fp11, asm: "TRUNCDW"}, // float64 -> int32
{name: "TRUNCFV", argLength: 1, reg: fp11, asm: "TRUNCFV"}, // float32 -> int64
{name: "TRUNCDV", argLength: 1, reg: fp11, asm: "TRUNCDV"}, // float64 -> int64
{name: "MOVFD", argLength: 1, reg: fp11, asm: "MOVFD"}, // float32 -> float64
{name: "MOVDF", argLength: 1, reg: fp11, asm: "MOVDF"}, // float64 -> float32
// function calls
{name: "CALLstatic", argLength: 1, reg: regInfo{clobbers: callerSave}, aux: "SymOff", clobberFlags: true}, // call static function aux.(*gc.Sym). arg0=mem, auxint=argsize, returns mem
......@@ -270,6 +270,67 @@ func init() {
{name: "CALLgo", argLength: 1, reg: regInfo{clobbers: callerSave}, aux: "Int64", clobberFlags: true}, // call newproc. arg0=mem, auxint=argsize, returns mem
{name: "CALLinter", argLength: 2, reg: regInfo{inputs: []regMask{gp}, clobbers: callerSave}, aux: "Int64", clobberFlags: true}, // call fn by pointer. arg0=codeptr, arg1=mem, auxint=argsize, returns mem
// duffzero
// arg0 = address of memory to zero
// arg1 = mem
// auxint = offset into duffzero code to start executing
// returns mem
// R1 aka mips.REGRT1 changed as side effect
{
name: "DUFFZERO",
aux: "Int64",
argLength: 2,
reg: regInfo{
inputs: []regMask{gp},
clobbers: buildReg("R1"),
},
},
// large or unaligned zeroing
// arg0 = address of memory to zero (in R1, changed as side effect)
// arg1 = address of the last element to zero
// arg2 = mem
// auxint = alignment
// returns mem
// SUBV $8, R1
// MOVV R0, 8(R1)
// ADDV $8, R1
// BNE Rarg1, R1, -2(PC)
{
name: "LoweredZero",
aux: "Int64",
argLength: 3,
reg: regInfo{
inputs: []regMask{buildReg("R1"), gp},
clobbers: buildReg("R1"),
},
clobberFlags: true,
},
// large or unaligned move
// arg0 = address of dst memory (in R2, changed as side effect)
// arg1 = address of src memory (in R1, changed as side effect)
// arg2 = address of the last element of src
// arg3 = mem
// auxint = alignment
// returns mem
// SUBV $8, R1
// MOVV 8(R1), Rtmp
// MOVV Rtmp, (R2)
// ADDV $8, R1
// ADDV $8, R2
// BNE Rarg2, R1, -4(PC)
{
name: "LoweredMove",
aux: "Int64",
argLength: 4,
reg: regInfo{
inputs: []regMask{buildReg("R2"), buildReg("R1"), gp},
clobbers: buildReg("R1 R2"),
},
clobberFlags: true,
},
// pseudo-ops
{name: "LoweredNilCheck", argLength: 2, reg: regInfo{inputs: []regMask{gpg}}}, // panic if arg0 is nil. arg1=mem.
......@@ -309,6 +370,7 @@ func init() {
regnames: regNamesMIPS64,
gpregmask: gp,
fpregmask: fp,
specialregmask: hi | lo,
framepointerreg: -1, // not used
})
}
......@@ -29,6 +29,7 @@ type arch struct {
regnames []string
gpregmask regMask
fpregmask regMask
specialregmask regMask
framepointerreg int8
generic bool
}
......@@ -241,6 +242,7 @@ func genOp() {
fmt.Fprintln(w, "}")
fmt.Fprintf(w, "var gpRegMask%s = regMask(%d)\n", a.name, a.gpregmask)
fmt.Fprintf(w, "var fpRegMask%s = regMask(%d)\n", a.name, a.fpregmask)
fmt.Fprintf(w, "var specialRegMask%s = regMask(%d)\n", a.name, a.specialregmask)
fmt.Fprintf(w, "var framepointerReg%s = int8(%d)\n", a.name, a.framepointerreg)
}
......
......@@ -1051,10 +1051,10 @@ const (
OpMIPS64MOVWD
OpMIPS64MOVVF
OpMIPS64MOVVD
OpMIPS64MOVFW
OpMIPS64MOVDW
OpMIPS64MOVFV
OpMIPS64MOVDV
OpMIPS64TRUNCFW
OpMIPS64TRUNCDW
OpMIPS64TRUNCFV
OpMIPS64TRUNCDV
OpMIPS64MOVFD
OpMIPS64MOVDF
OpMIPS64CALLstatic
......@@ -1062,6 +1062,9 @@ const (
OpMIPS64CALLdefer
OpMIPS64CALLgo
OpMIPS64CALLinter
OpMIPS64DUFFZERO
OpMIPS64LoweredZero
OpMIPS64LoweredMove
OpMIPS64LoweredNilCheck
OpMIPS64FPFlagTrue
OpMIPS64FPFlagFalse
......@@ -12905,9 +12908,9 @@ var opcodeTable = [...]opInfo{
},
},
{
name: "MOVFW",
name: "TRUNCFW",
argLen: 1,
asm: mips.AMOVFW,
asm: mips.ATRUNCFW,
reg: regInfo{
inputs: []inputInfo{
{0, 385057768005959680}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F25 F27 F29 F31
......@@ -12918,9 +12921,9 @@ var opcodeTable = [...]opInfo{
},
},
{
name: "MOVDW",
name: "TRUNCDW",
argLen: 1,
asm: mips.AMOVDW,
asm: mips.ATRUNCDW,
reg: regInfo{
inputs: []inputInfo{
{0, 385057768005959680}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F25 F27 F29 F31
......@@ -12931,9 +12934,9 @@ var opcodeTable = [...]opInfo{
},
},
{
name: "MOVFV",
name: "TRUNCFV",
argLen: 1,
asm: mips.AMOVFV,
asm: mips.ATRUNCFV,
reg: regInfo{
inputs: []inputInfo{
{0, 385057768005959680}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F25 F27 F29 F31
......@@ -12944,9 +12947,9 @@ var opcodeTable = [...]opInfo{
},
},
{
name: "MOVDV",
name: "TRUNCDV",
argLen: 1,
asm: mips.AMOVDV,
asm: mips.ATRUNCDV,
reg: regInfo{
inputs: []inputInfo{
{0, 385057768005959680}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F25 F27 F29 F31
......@@ -13034,6 +13037,44 @@ var opcodeTable = [...]opInfo{
clobbers: 2114440025016893438, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 g F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F25 F27 F29 F31 HI LO
},
},
{
name: "DUFFZERO",
auxType: auxInt64,
argLen: 2,
reg: regInfo{
inputs: []inputInfo{
{0, 33554430}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25
},
clobbers: 2, // R1
},
},
{
name: "LoweredZero",
auxType: auxInt64,
argLen: 3,
clobberFlags: true,
reg: regInfo{
inputs: []inputInfo{
{0, 2}, // R1
{1, 33554430}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25
},
clobbers: 2, // R1
},
},
{
name: "LoweredMove",
auxType: auxInt64,
argLen: 4,
clobberFlags: true,
reg: regInfo{
inputs: []inputInfo{
{0, 4}, // R2
{1, 2}, // R1
{2, 33554430}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25
},
clobbers: 6, // R1 R2
},
},
{
name: "LoweredNilCheck",
argLen: 2,
......@@ -16141,6 +16182,7 @@ var registers386 = [...]Register{
}
var gpRegMask386 = regMask(239)
var fpRegMask386 = regMask(65280)
var specialRegMask386 = regMask(0)
var framepointerReg386 = int8(5)
var registersAMD64 = [...]Register{
{0, "AX"},
......@@ -16179,6 +16221,7 @@ var registersAMD64 = [...]Register{
}
var gpRegMaskAMD64 = regMask(65519)
var fpRegMaskAMD64 = regMask(4294901760)
var specialRegMaskAMD64 = regMask(0)
var framepointerRegAMD64 = int8(5)
var registersARM = [...]Register{
{0, "R0"},
......@@ -16217,6 +16260,7 @@ var registersARM = [...]Register{
}
var gpRegMaskARM = regMask(5119)
var fpRegMaskARM = regMask(4294901760)
var specialRegMaskARM = regMask(0)
var framepointerRegARM = int8(-1)
var registersARM64 = [...]Register{
{0, "R0"},
......@@ -16285,6 +16329,7 @@ var registersARM64 = [...]Register{
}
var gpRegMaskARM64 = regMask(133955583)
var fpRegMaskARM64 = regMask(288230375077969920)
var specialRegMaskARM64 = regMask(0)
var framepointerRegARM64 = int8(-1)
var registersMIPS64 = [...]Register{
{0, "R0"},
......@@ -16352,6 +16397,7 @@ var registersMIPS64 = [...]Register{
}
var gpRegMaskMIPS64 = regMask(33554430)
var fpRegMaskMIPS64 = regMask(385057768005959680)
var specialRegMaskMIPS64 = regMask(1729382256910270464)
var framepointerRegMIPS64 = int8(-1)
var registersPPC64 = [...]Register{
{0, "SP"},
......@@ -16415,4 +16461,5 @@ var registersPPC64 = [...]Register{
}
var gpRegMaskPPC64 = regMask(536866812)
var fpRegMaskPPC64 = regMask(288230371856744448)
var specialRegMaskPPC64 = regMask(0)
var framepointerRegPPC64 = int8(0)
......@@ -471,7 +471,7 @@ func (s *regAllocState) init(f *Func) {
}
// Figure out which registers we're allowed to use.
s.allocatable = s.f.Config.gpRegMask | s.f.Config.fpRegMask
s.allocatable = s.f.Config.gpRegMask | s.f.Config.fpRegMask | s.f.Config.specialRegMask
s.allocatable &^= 1 << s.SPReg
s.allocatable &^= 1 << s.SBReg
if s.f.Config.hasGReg {
......@@ -1302,7 +1302,7 @@ func (s *regAllocState) regalloc(f *Func) {
// We assume that a control input can be passed in any
// type-compatible register. If this turns out not to be true,
// we'll need to introduce a regspec for a block's control value.
s.allocValToReg(v, s.compatRegs(v.Type), false, b.Line)
b.Control = s.allocValToReg(v, s.compatRegs(v.Type), false, b.Line)
// Remove this use from the uses list.
vi := &s.values[v.ID]
u := vi.uses
......
This source diff could not be displayed because it is too large. You can view the blob instead.
......@@ -84,7 +84,7 @@ func schedule(f *Func) {
// Compute score. Larger numbers are scheduled closer to the end of the block.
for _, v := range b.Values {
switch {
case v.Op == OpAMD64LoweredGetClosurePtr || v.Op == OpPPC64LoweredGetClosurePtr || v.Op == OpARMLoweredGetClosurePtr || v.Op == OpARM64LoweredGetClosurePtr || v.Op == Op386LoweredGetClosurePtr:
case v.Op == OpAMD64LoweredGetClosurePtr || v.Op == OpPPC64LoweredGetClosurePtr || v.Op == OpARMLoweredGetClosurePtr || v.Op == OpARM64LoweredGetClosurePtr || v.Op == Op386LoweredGetClosurePtr || v.Op == OpMIPS64LoweredGetClosurePtr:
// We also score GetLoweredClosurePtr as early as possible to ensure that the
// context register is not stomped. GetLoweredClosurePtr should only appear
// in the entry block where there are no phi functions, so there is no
......
......@@ -400,19 +400,23 @@ func preprocess(ctxt *obj.Link, cursym *obj.LSym) {
break
}
if p.To.Sym != nil { // retjmp
p.As = AJMP
p.To.Type = obj.TYPE_BRANCH
break
}
retSym := p.To.Sym
p.To.Name = obj.NAME_NONE // clear fields as we may modify p to other instruction
p.To.Sym = nil
if cursym.Text.Mark&LEAF != 0 {
if autosize == 0 {
p.As = AJMP
p.From = obj.Addr{}
p.To.Type = obj.TYPE_MEM
p.To.Offset = 0
p.To.Reg = REGLINK
if retSym != nil { // retjmp
p.To.Type = obj.TYPE_BRANCH
p.To.Name = obj.NAME_EXTERN
p.To.Sym = retSym
} else {
p.To.Type = obj.TYPE_MEM
p.To.Reg = REGLINK
p.To.Offset = 0
}
p.Mark |= BRANCH
break
}
......@@ -444,22 +448,8 @@ func preprocess(ctxt *obj.Link, cursym *obj.LSym) {
p.From.Reg = REGSP
p.To.Type = obj.TYPE_REG
p.To.Reg = REG_R4
if false {
// Debug bad returns
q = ctxt.NewProg()
q.As = AMOVV
q.Lineno = p.Lineno
q.From.Type = obj.TYPE_MEM
q.From.Offset = 0
q.From.Reg = REG_R4
q.To.Type = obj.TYPE_REG
q.To.Reg = REGTMP
q.Link = p.Link
p.Link = q
p = q
if retSym != nil { // retjmp from non-leaf, need to restore LINK register
p.To.Reg = REGLINK
}
if autosize != 0 {
......@@ -479,9 +469,15 @@ func preprocess(ctxt *obj.Link, cursym *obj.LSym) {
q1 = ctxt.NewProg()
q1.As = AJMP
q1.Lineno = p.Lineno
q1.To.Type = obj.TYPE_MEM
q1.To.Offset = 0
q1.To.Reg = REG_R4
if retSym != nil { // retjmp
q1.To.Type = obj.TYPE_BRANCH
q1.To.Name = obj.NAME_EXTERN
q1.To.Sym = retSym
} else {
q1.To.Type = obj.TYPE_MEM
q1.To.Offset = 0
q1.To.Reg = REG_R4
}
q1.Mark |= BRANCH
q1.Spadj = +autosize
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment