p.From.Reg = x
p.To.Type = obj.TYPE_REG
p.To.Reg = y
+ case ssa.OpARMMOVWnop:
+ if gc.SSARegNum(v) != gc.SSARegNum(v.Args[0]) {
+ v.Fatalf("input[0] and output not in same register %s", v.LongString())
+ }
+ // nothing to do
case ssa.OpLoadReg:
if v.Type.IsFlags() {
v.Unimplementedf("load flags not implemented: %v", v.LongString())
ssa.OpARMMOVHreg,
ssa.OpARMMOVHUreg:
a := v.Args[0]
- for a.Op == ssa.OpCopy || a.Op == ssa.OpARMMOVWreg {
+ for a.Op == ssa.OpCopy || a.Op == ssa.OpARMMOVWreg || a.Op == ssa.OpARMMOVWnop {
a = a.Args[0]
}
if a.Op == ssa.OpLoadReg {
(MOVHstore [off] {sym} ptr (MOVHreg x) mem) -> (MOVHstore [off] {sym} ptr x mem)
(MOVHstore [off] {sym} ptr (MOVHUreg x) mem) -> (MOVHstore [off] {sym} ptr x mem)
+// if a register move has only 1 use, just use the same register without emitting instruction
+// MOVWnop doesn't emit instruction, only for ensuring the type.
+(MOVWreg x) && x.Uses == 1 -> (MOVWnop x)
+
// mul by constant
(MUL x (MOVWconst [c])) && int32(c) == -1 -> (RSBconst [0] x)
(MUL _ (MOVWconst [0])) -> (MOVWconst [0])
{name: "MOVHUreg", argLength: 1, reg: gp11, asm: "MOVHU"}, // move from arg0, unsign-extended from half
{name: "MOVWreg", argLength: 1, reg: gp11, asm: "MOVW"}, // move from arg0
+ {name: "MOVWnop", argLength: 1, reg: regInfo{inputs: []regMask{gp}, outputs: []regMask{gp}}, resultInArg0: true}, // nop, return arg0 in same register
+
{name: "MOVWF", argLength: 1, reg: gpfp, asm: "MOVWF"}, // int32 -> float32
{name: "MOVWD", argLength: 1, reg: gpfp, asm: "MOVWD"}, // int32 -> float64
{name: "MOVWUF", argLength: 1, reg: gpfp, asm: "MOVWF"}, // uint32 -> float32, set U bit in the instruction
OpARMMOVHreg
OpARMMOVHUreg
OpARMMOVWreg
+ OpARMMOVWnop
OpARMMOVWF
OpARMMOVWD
OpARMMOVWUF
},
},
},
+ {
+ name: "MOVWnop",
+ argLen: 1,
+ resultInArg0: true,
+ reg: regInfo{
+ inputs: []inputInfo{
+ {0, 5119}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
+ },
+ outputs: []outputInfo{
+ {0, 5119}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
+ },
+ },
+ },
{
name: "MOVWF",
argLen: 1,
func rewriteValueARM_OpARMMOVWreg(v *Value, config *Config) bool {
b := v.Block
_ = b
+ // match: (MOVWreg x)
+ // cond: x.Uses == 1
+ // result: (MOVWnop x)
+ for {
+ x := v.Args[0]
+ if !(x.Uses == 1) {
+ break
+ }
+ v.reset(OpARMMOVWnop)
+ v.AddArg(x)
+ return true
+ }
// match: (MOVWreg (MOVWconst [c]))
// cond:
// result: (MOVWconst [c])