2016-03-21 22:57:26 -07:00
|
|
|
// Copyright 2016 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 arm
|
|
|
|
|
|
|
|
|
|
import (
|
|
|
|
|
"cmd/compile/internal/gc"
|
|
|
|
|
"cmd/compile/internal/ssa"
|
|
|
|
|
"cmd/internal/obj"
|
|
|
|
|
"cmd/internal/obj/arm"
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
var ssaRegToReg = []int16{
|
|
|
|
|
arm.REG_R0,
|
|
|
|
|
arm.REG_R1,
|
|
|
|
|
arm.REG_R2,
|
|
|
|
|
arm.REG_R3,
|
|
|
|
|
arm.REGSP, // aka R13
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func ssaGenValue(s *gc.SSAGenState, v *ssa.Value) {
|
|
|
|
|
s.SetLineno(v.Line)
|
|
|
|
|
switch v.Op {
|
|
|
|
|
case ssa.OpInitMem:
|
|
|
|
|
// memory arg needs no code
|
|
|
|
|
case ssa.OpArg:
|
|
|
|
|
// input args need no code
|
|
|
|
|
case ssa.OpSP, ssa.OpSB:
|
|
|
|
|
// nothing to do
|
|
|
|
|
case ssa.OpCopy:
|
|
|
|
|
case ssa.OpLoadReg:
|
|
|
|
|
// TODO: by type
|
|
|
|
|
p := gc.Prog(arm.AMOVW)
|
|
|
|
|
n, off := gc.AutoVar(v.Args[0])
|
|
|
|
|
p.From.Type = obj.TYPE_MEM
|
|
|
|
|
p.From.Node = n
|
|
|
|
|
p.From.Sym = gc.Linksym(n.Sym)
|
|
|
|
|
p.From.Offset = off
|
|
|
|
|
if n.Class == gc.PPARAM || n.Class == gc.PPARAMOUT {
|
|
|
|
|
p.From.Name = obj.NAME_PARAM
|
|
|
|
|
p.From.Offset += n.Xoffset
|
|
|
|
|
} else {
|
|
|
|
|
p.From.Name = obj.NAME_AUTO
|
|
|
|
|
}
|
|
|
|
|
p.To.Type = obj.TYPE_REG
|
|
|
|
|
p.To.Reg = gc.SSARegNum(v)
|
|
|
|
|
|
|
|
|
|
case ssa.OpStoreReg:
|
|
|
|
|
// TODO: by type
|
|
|
|
|
p := gc.Prog(arm.AMOVW)
|
|
|
|
|
p.From.Type = obj.TYPE_REG
|
|
|
|
|
p.From.Reg = gc.SSARegNum(v.Args[0])
|
|
|
|
|
n, off := gc.AutoVar(v)
|
|
|
|
|
p.To.Type = obj.TYPE_MEM
|
|
|
|
|
p.To.Node = n
|
|
|
|
|
p.To.Sym = gc.Linksym(n.Sym)
|
|
|
|
|
p.To.Offset = off
|
|
|
|
|
if n.Class == gc.PPARAM || n.Class == gc.PPARAMOUT {
|
|
|
|
|
p.To.Name = obj.NAME_PARAM
|
|
|
|
|
p.To.Offset += n.Xoffset
|
|
|
|
|
} else {
|
|
|
|
|
p.To.Name = obj.NAME_AUTO
|
|
|
|
|
}
|
|
|
|
|
case ssa.OpARMADD:
|
|
|
|
|
r := gc.SSARegNum(v)
|
|
|
|
|
r1 := gc.SSARegNum(v.Args[0])
|
|
|
|
|
r2 := gc.SSARegNum(v.Args[1])
|
|
|
|
|
p := gc.Prog(v.Op.Asm())
|
|
|
|
|
p.From.Type = obj.TYPE_REG
|
|
|
|
|
p.From.Reg = r1
|
|
|
|
|
p.Reg = r2
|
|
|
|
|
p.To.Type = obj.TYPE_REG
|
|
|
|
|
p.To.Reg = r
|
|
|
|
|
case ssa.OpARMADDconst:
|
|
|
|
|
p := gc.Prog(v.Op.Asm())
|
|
|
|
|
p.From.Type = obj.TYPE_CONST
|
|
|
|
|
p.From.Offset = v.AuxInt
|
|
|
|
|
if v.Aux != nil {
|
|
|
|
|
panic("can't handle symbolic constant yet")
|
|
|
|
|
}
|
|
|
|
|
p.Reg = gc.SSARegNum(v.Args[0])
|
|
|
|
|
p.To.Type = obj.TYPE_REG
|
|
|
|
|
p.To.Reg = gc.SSARegNum(v)
|
|
|
|
|
case ssa.OpARMMOVWconst:
|
|
|
|
|
p := gc.Prog(v.Op.Asm())
|
|
|
|
|
p.From.Type = obj.TYPE_CONST
|
2016-03-29 16:39:53 -07:00
|
|
|
p.From.Offset = v.AuxInt
|
2016-03-21 22:57:26 -07:00
|
|
|
p.To.Type = obj.TYPE_REG
|
|
|
|
|
p.To.Reg = gc.SSARegNum(v)
|
|
|
|
|
case ssa.OpARMCMP:
|
|
|
|
|
p := gc.Prog(v.Op.Asm())
|
|
|
|
|
p.From.Type = obj.TYPE_REG
|
|
|
|
|
p.From.Reg = gc.SSARegNum(v.Args[0])
|
|
|
|
|
p.Reg = gc.SSARegNum(v.Args[1])
|
|
|
|
|
case ssa.OpARMMOVWload:
|
|
|
|
|
p := gc.Prog(v.Op.Asm())
|
|
|
|
|
p.From.Type = obj.TYPE_MEM
|
|
|
|
|
p.From.Reg = gc.SSARegNum(v.Args[0])
|
|
|
|
|
gc.AddAux(&p.From, v)
|
|
|
|
|
p.To.Type = obj.TYPE_REG
|
|
|
|
|
p.To.Reg = gc.SSARegNum(v)
|
|
|
|
|
case ssa.OpARMMOVWstore:
|
|
|
|
|
p := gc.Prog(v.Op.Asm())
|
|
|
|
|
p.From.Type = obj.TYPE_REG
|
|
|
|
|
p.From.Reg = gc.SSARegNum(v.Args[1])
|
|
|
|
|
p.To.Type = obj.TYPE_MEM
|
|
|
|
|
p.To.Reg = gc.SSARegNum(v.Args[0])
|
|
|
|
|
gc.AddAux(&p.To, v)
|
|
|
|
|
case ssa.OpARMCALLstatic:
|
|
|
|
|
// TODO: deferreturn
|
|
|
|
|
p := gc.Prog(obj.ACALL)
|
|
|
|
|
p.To.Type = obj.TYPE_MEM
|
|
|
|
|
p.To.Name = obj.NAME_EXTERN
|
|
|
|
|
p.To.Sym = gc.Linksym(v.Aux.(*gc.Sym))
|
|
|
|
|
if gc.Maxarg < v.AuxInt {
|
|
|
|
|
gc.Maxarg = v.AuxInt
|
|
|
|
|
}
|
|
|
|
|
case ssa.OpVarDef:
|
|
|
|
|
gc.Gvardef(v.Aux.(*gc.Node))
|
|
|
|
|
case ssa.OpVarKill:
|
|
|
|
|
gc.Gvarkill(v.Aux.(*gc.Node))
|
|
|
|
|
case ssa.OpVarLive:
|
|
|
|
|
gc.Gvarlive(v.Aux.(*gc.Node))
|
|
|
|
|
case ssa.OpARMLessThan:
|
|
|
|
|
v.Fatalf("pseudo-op made it to output: %s", v.LongString())
|
|
|
|
|
default:
|
|
|
|
|
v.Unimplementedf("genValue not implemented: %s", v.LongString())
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func ssaGenBlock(s *gc.SSAGenState, b, next *ssa.Block) {
|
|
|
|
|
s.SetLineno(b.Line)
|
|
|
|
|
|
|
|
|
|
switch b.Kind {
|
|
|
|
|
case ssa.BlockCall:
|
|
|
|
|
if b.Succs[0] != next {
|
|
|
|
|
p := gc.Prog(obj.AJMP)
|
|
|
|
|
p.To.Type = obj.TYPE_BRANCH
|
|
|
|
|
s.Branches = append(s.Branches, gc.Branch{p, b.Succs[0]})
|
|
|
|
|
}
|
|
|
|
|
case ssa.BlockRet:
|
|
|
|
|
gc.Prog(obj.ARET)
|
|
|
|
|
case ssa.BlockARMLT:
|
|
|
|
|
p := gc.Prog(arm.ABGE)
|
|
|
|
|
p.To.Type = obj.TYPE_BRANCH
|
|
|
|
|
s.Branches = append(s.Branches, gc.Branch{p, b.Succs[0]})
|
|
|
|
|
p = gc.Prog(obj.AJMP)
|
|
|
|
|
p.To.Type = obj.TYPE_BRANCH
|
|
|
|
|
s.Branches = append(s.Branches, gc.Branch{p, b.Succs[1]})
|
|
|
|
|
}
|
|
|
|
|
}
|