Commit 8cc3f4a1 authored by Cherry Zhang's avatar Cherry Zhang

[dev.ssa] cmd/compile: use shifted and indexed ops in SSA for ARM

This CL implements the following optimizations for ARM:
- use shifted ops (e.g. ADD R1<<2, R2) and indexed load/stores
- break up shift ops. Shifts used to be one SSA op that generates
  multiple instructions. We break them up to multiple ops, which
  allows constant folding and CSE for comparisons. Conditional moves
  are introduced for this.
- simplify zero/sign-extension ops.

Updates #15365.

Change-Id: I55e262a776a7ef2a1505d75e04d1208913c35d39
Reviewed-on: https://go-review.googlesource.com/24512
Run-TryBot: Cherry Zhang <cherryyz@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: default avatarDavid Chase <drchase@google.com>
parent 14cf6e20
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
package arm package arm
import ( import (
"fmt"
"math" "math"
"cmd/compile/internal/gc" "cmd/compile/internal/gc"
...@@ -108,6 +109,57 @@ func storeByType(t ssa.Type) obj.As { ...@@ -108,6 +109,57 @@ func storeByType(t ssa.Type) obj.As {
panic("bad store type") panic("bad store type")
} }
// shift type is used as Offset in obj.TYPE_SHIFT operands to encode shifted register operands
type shift int64
// copied from ../../../internal/obj/util.go:/TYPE_SHIFT
func (v shift) String() string {
op := "<<>>->@>"[((v>>5)&3)<<1:]
if v&(1<<4) != 0 {
// register shift
return fmt.Sprintf("R%d%c%cR%d", v&15, op[0], op[1], (v>>8)&15)
} else {
// constant shift
return fmt.Sprintf("R%d%c%c%d", v&15, op[0], op[1], (v>>7)&31)
}
}
// makeshift encodes a register shifted by a constant
func makeshift(reg int16, typ int64, s int64) shift {
return shift(int64(reg&0xf) | typ | (s&31)<<7)
}
// genshift generates a Prog for r = r0 op (r1 shifted by s)
func genshift(as obj.As, r0, r1, r int16, typ int64, s int64) *obj.Prog {
p := gc.Prog(as)
p.From.Type = obj.TYPE_SHIFT
p.From.Offset = int64(makeshift(r1, typ, s))
p.Reg = r0
if r != 0 {
p.To.Type = obj.TYPE_REG
p.To.Reg = r
}
return p
}
// makeregshift encodes a register shifted by a register
func makeregshift(r1 int16, typ int64, r2 int16) shift {
return shift(int64(r1&0xf) | typ | int64(r2&0xf)<<8 | 1<<4)
}
// genregshift generates a Prog for r = r0 op (r1 shifted by r2)
func genregshift(as obj.As, r0, r1, r2, r int16, typ int64) *obj.Prog {
p := gc.Prog(as)
p.From.Type = obj.TYPE_SHIFT
p.From.Offset = int64(makeregshift(r1, typ, r2))
p.Reg = r0
if r != 0 {
p.To.Type = obj.TYPE_REG
p.To.Reg = r
}
return p
}
func ssaGenValue(s *gc.SSAGenState, v *ssa.Value) { func ssaGenValue(s *gc.SSAGenState, v *ssa.Value) {
s.SetLineno(v.Line) s.SetLineno(v.Line)
switch v.Op { switch v.Op {
...@@ -237,45 +289,27 @@ func ssaGenValue(s *gc.SSAGenState, v *ssa.Value) { ...@@ -237,45 +289,27 @@ func ssaGenValue(s *gc.SSAGenState, v *ssa.Value) {
p.To.Type = obj.TYPE_REG p.To.Type = obj.TYPE_REG
p.To.Reg = r p.To.Reg = r
case ssa.OpARMSLL, case ssa.OpARMSLL,
ssa.OpARMSRL: ssa.OpARMSRL,
// ARM shift instructions uses only the low-order byte of the shift amount ssa.OpARMSRA:
// generate conditional instructions to deal with large shifts
// CMP $32, Rarg1
// SLL Rarg1, Rarg0, Rdst
// MOVW.HS $0, Rdst
r := gc.SSARegNum(v) r := gc.SSARegNum(v)
r1 := gc.SSARegNum(v.Args[0]) r1 := gc.SSARegNum(v.Args[0])
r2 := gc.SSARegNum(v.Args[1]) r2 := gc.SSARegNum(v.Args[1])
p := gc.Prog(arm.ACMP) p := gc.Prog(v.Op.Asm())
p.From.Type = obj.TYPE_CONST
p.From.Offset = 32
p.Reg = r2
p = gc.Prog(v.Op.Asm())
p.From.Type = obj.TYPE_REG p.From.Type = obj.TYPE_REG
p.From.Reg = r2 p.From.Reg = r2
p.Reg = r1 p.Reg = r1
p.To.Type = obj.TYPE_REG p.To.Type = obj.TYPE_REG
p.To.Reg = r p.To.Reg = r
p = gc.Prog(arm.AMOVW) case ssa.OpARMSRAcond:
p.Scond = arm.C_SCOND_HS
p.From.Type = obj.TYPE_CONST
p.From.Offset = 0
p.To.Type = obj.TYPE_REG
p.To.Reg = r
case ssa.OpARMSRA:
// ARM shift instructions uses only the low-order byte of the shift amount // ARM shift instructions uses only the low-order byte of the shift amount
// generate conditional instructions to deal with large shifts // generate conditional instructions to deal with large shifts
// CMP $32, Rarg1 // flag is already set
// SRA.HS $31, Rarg0, Rdst // shift 31 bits to get the sign bit // SRA.HS $31, Rarg0, Rdst // shift 31 bits to get the sign bit
// SRA.LO Rarg1, Rarg0, Rdst // SRA.LO Rarg1, Rarg0, Rdst
r := gc.SSARegNum(v) r := gc.SSARegNum(v)
r1 := gc.SSARegNum(v.Args[0]) r1 := gc.SSARegNum(v.Args[0])
r2 := gc.SSARegNum(v.Args[1]) r2 := gc.SSARegNum(v.Args[1])
p := gc.Prog(arm.ACMP) p := gc.Prog(arm.ASRA)
p.From.Type = obj.TYPE_CONST
p.From.Offset = 32
p.Reg = r2
p = gc.Prog(arm.ASRA)
p.Scond = arm.C_SCOND_HS p.Scond = arm.C_SCOND_HS
p.From.Type = obj.TYPE_CONST p.From.Type = obj.TYPE_CONST
p.From.Offset = 31 p.From.Offset = 31
...@@ -319,11 +353,115 @@ func ssaGenValue(s *gc.SSAGenState, v *ssa.Value) { ...@@ -319,11 +353,115 @@ func ssaGenValue(s *gc.SSAGenState, v *ssa.Value) {
p.To.Type = obj.TYPE_REG p.To.Type = obj.TYPE_REG
p.To.Reg = gc.SSARegNum(v) p.To.Reg = gc.SSARegNum(v)
case ssa.OpARMSRRconst: case ssa.OpARMSRRconst:
p := gc.Prog(arm.AMOVW) genshift(arm.AMOVW, 0, gc.SSARegNum(v.Args[0]), gc.SSARegNum(v), arm.SHIFT_RR, v.AuxInt)
p.From.Type = obj.TYPE_SHIFT case ssa.OpARMADDshiftLL,
p.From.Offset = int64(gc.SSARegNum(v.Args[0])&0xf) | arm.SHIFT_RR | (v.AuxInt&31)<<7 ssa.OpARMADCshiftLL,
p.To.Type = obj.TYPE_REG ssa.OpARMSUBshiftLL,
p.To.Reg = gc.SSARegNum(v) ssa.OpARMSBCshiftLL,
ssa.OpARMRSBshiftLL,
ssa.OpARMRSCshiftLL,
ssa.OpARMANDshiftLL,
ssa.OpARMORshiftLL,
ssa.OpARMXORshiftLL,
ssa.OpARMBICshiftLL:
genshift(v.Op.Asm(), gc.SSARegNum(v.Args[0]), gc.SSARegNum(v.Args[1]), gc.SSARegNum(v), arm.SHIFT_LL, v.AuxInt)
case ssa.OpARMADDSshiftLL,
ssa.OpARMSUBSshiftLL,
ssa.OpARMRSBSshiftLL:
p := genshift(v.Op.Asm(), gc.SSARegNum(v.Args[0]), gc.SSARegNum(v.Args[1]), gc.SSARegNum(v), arm.SHIFT_LL, v.AuxInt)
p.Scond = arm.C_SBIT
case ssa.OpARMADDshiftRL,
ssa.OpARMADCshiftRL,
ssa.OpARMSUBshiftRL,
ssa.OpARMSBCshiftRL,
ssa.OpARMRSBshiftRL,
ssa.OpARMRSCshiftRL,
ssa.OpARMANDshiftRL,
ssa.OpARMORshiftRL,
ssa.OpARMXORshiftRL,
ssa.OpARMBICshiftRL:
genshift(v.Op.Asm(), gc.SSARegNum(v.Args[0]), gc.SSARegNum(v.Args[1]), gc.SSARegNum(v), arm.SHIFT_LR, v.AuxInt)
case ssa.OpARMADDSshiftRL,
ssa.OpARMSUBSshiftRL,
ssa.OpARMRSBSshiftRL:
p := genshift(v.Op.Asm(), gc.SSARegNum(v.Args[0]), gc.SSARegNum(v.Args[1]), gc.SSARegNum(v), arm.SHIFT_LR, v.AuxInt)
p.Scond = arm.C_SBIT
case ssa.OpARMADDshiftRA,
ssa.OpARMADCshiftRA,
ssa.OpARMSUBshiftRA,
ssa.OpARMSBCshiftRA,
ssa.OpARMRSBshiftRA,
ssa.OpARMRSCshiftRA,
ssa.OpARMANDshiftRA,
ssa.OpARMORshiftRA,
ssa.OpARMXORshiftRA,
ssa.OpARMBICshiftRA:
genshift(v.Op.Asm(), gc.SSARegNum(v.Args[0]), gc.SSARegNum(v.Args[1]), gc.SSARegNum(v), arm.SHIFT_AR, v.AuxInt)
case ssa.OpARMADDSshiftRA,
ssa.OpARMSUBSshiftRA,
ssa.OpARMRSBSshiftRA:
p := genshift(v.Op.Asm(), gc.SSARegNum(v.Args[0]), gc.SSARegNum(v.Args[1]), gc.SSARegNum(v), arm.SHIFT_AR, v.AuxInt)
p.Scond = arm.C_SBIT
case ssa.OpARMMVNshiftLL:
genshift(v.Op.Asm(), 0, gc.SSARegNum(v.Args[0]), gc.SSARegNum(v), arm.SHIFT_LL, v.AuxInt)
case ssa.OpARMMVNshiftRL:
genshift(v.Op.Asm(), 0, gc.SSARegNum(v.Args[0]), gc.SSARegNum(v), arm.SHIFT_LR, v.AuxInt)
case ssa.OpARMMVNshiftRA:
genshift(v.Op.Asm(), 0, gc.SSARegNum(v.Args[0]), gc.SSARegNum(v), arm.SHIFT_AR, v.AuxInt)
case ssa.OpARMMVNshiftLLreg:
genregshift(v.Op.Asm(), 0, gc.SSARegNum(v.Args[0]), gc.SSARegNum(v.Args[1]), gc.SSARegNum(v), arm.SHIFT_LL)
case ssa.OpARMMVNshiftRLreg:
genregshift(v.Op.Asm(), 0, gc.SSARegNum(v.Args[0]), gc.SSARegNum(v.Args[1]), gc.SSARegNum(v), arm.SHIFT_LR)
case ssa.OpARMMVNshiftRAreg:
genregshift(v.Op.Asm(), 0, gc.SSARegNum(v.Args[0]), gc.SSARegNum(v.Args[1]), gc.SSARegNum(v), arm.SHIFT_AR)
case ssa.OpARMADDshiftLLreg,
ssa.OpARMADCshiftLLreg,
ssa.OpARMSUBshiftLLreg,
ssa.OpARMSBCshiftLLreg,
ssa.OpARMRSBshiftLLreg,
ssa.OpARMRSCshiftLLreg,
ssa.OpARMANDshiftLLreg,
ssa.OpARMORshiftLLreg,
ssa.OpARMXORshiftLLreg,
ssa.OpARMBICshiftLLreg:
genregshift(v.Op.Asm(), gc.SSARegNum(v.Args[0]), gc.SSARegNum(v.Args[1]), gc.SSARegNum(v.Args[2]), gc.SSARegNum(v), arm.SHIFT_LL)
case ssa.OpARMADDSshiftLLreg,
ssa.OpARMSUBSshiftLLreg,
ssa.OpARMRSBSshiftLLreg:
p := genregshift(v.Op.Asm(), gc.SSARegNum(v.Args[0]), gc.SSARegNum(v.Args[1]), gc.SSARegNum(v.Args[2]), gc.SSARegNum(v), arm.SHIFT_LL)
p.Scond = arm.C_SBIT
case ssa.OpARMADDshiftRLreg,
ssa.OpARMADCshiftRLreg,
ssa.OpARMSUBshiftRLreg,
ssa.OpARMSBCshiftRLreg,
ssa.OpARMRSBshiftRLreg,
ssa.OpARMRSCshiftRLreg,
ssa.OpARMANDshiftRLreg,
ssa.OpARMORshiftRLreg,
ssa.OpARMXORshiftRLreg,
ssa.OpARMBICshiftRLreg:
genregshift(v.Op.Asm(), gc.SSARegNum(v.Args[0]), gc.SSARegNum(v.Args[1]), gc.SSARegNum(v.Args[2]), gc.SSARegNum(v), arm.SHIFT_LR)
case ssa.OpARMADDSshiftRLreg,
ssa.OpARMSUBSshiftRLreg,
ssa.OpARMRSBSshiftRLreg:
p := genregshift(v.Op.Asm(), gc.SSARegNum(v.Args[0]), gc.SSARegNum(v.Args[1]), gc.SSARegNum(v.Args[2]), gc.SSARegNum(v), arm.SHIFT_LR)
p.Scond = arm.C_SBIT
case ssa.OpARMADDshiftRAreg,
ssa.OpARMADCshiftRAreg,
ssa.OpARMSUBshiftRAreg,
ssa.OpARMSBCshiftRAreg,
ssa.OpARMRSBshiftRAreg,
ssa.OpARMRSCshiftRAreg,
ssa.OpARMANDshiftRAreg,
ssa.OpARMORshiftRAreg,
ssa.OpARMXORshiftRAreg,
ssa.OpARMBICshiftRAreg:
genregshift(v.Op.Asm(), gc.SSARegNum(v.Args[0]), gc.SSARegNum(v.Args[1]), gc.SSARegNum(v.Args[2]), gc.SSARegNum(v), arm.SHIFT_AR)
case ssa.OpARMADDSshiftRAreg,
ssa.OpARMSUBSshiftRAreg,
ssa.OpARMRSBSshiftRAreg:
p := genregshift(v.Op.Asm(), gc.SSARegNum(v.Args[0]), gc.SSARegNum(v.Args[1]), gc.SSARegNum(v.Args[2]), gc.SSARegNum(v), arm.SHIFT_AR)
p.Scond = arm.C_SBIT
case ssa.OpARMHMUL, case ssa.OpARMHMUL,
ssa.OpARMHMULU: ssa.OpARMHMULU:
// 32-bit high multiplication // 32-bit high multiplication
...@@ -385,6 +523,18 @@ func ssaGenValue(s *gc.SSAGenState, v *ssa.Value) { ...@@ -385,6 +523,18 @@ func ssaGenValue(s *gc.SSAGenState, v *ssa.Value) {
p.From.Type = obj.TYPE_CONST p.From.Type = obj.TYPE_CONST
p.From.Offset = v.AuxInt p.From.Offset = v.AuxInt
p.Reg = gc.SSARegNum(v.Args[0]) p.Reg = gc.SSARegNum(v.Args[0])
case ssa.OpARMCMPshiftLL:
genshift(v.Op.Asm(), gc.SSARegNum(v.Args[0]), gc.SSARegNum(v.Args[1]), 0, arm.SHIFT_LL, v.AuxInt)
case ssa.OpARMCMPshiftRL:
genshift(v.Op.Asm(), gc.SSARegNum(v.Args[0]), gc.SSARegNum(v.Args[1]), 0, arm.SHIFT_LR, v.AuxInt)
case ssa.OpARMCMPshiftRA:
genshift(v.Op.Asm(), gc.SSARegNum(v.Args[0]), gc.SSARegNum(v.Args[1]), 0, arm.SHIFT_AR, v.AuxInt)
case ssa.OpARMCMPshiftLLreg:
genregshift(v.Op.Asm(), gc.SSARegNum(v.Args[0]), gc.SSARegNum(v.Args[1]), gc.SSARegNum(v.Args[2]), 0, arm.SHIFT_LL)
case ssa.OpARMCMPshiftRLreg:
genregshift(v.Op.Asm(), gc.SSARegNum(v.Args[0]), gc.SSARegNum(v.Args[1]), gc.SSARegNum(v.Args[2]), 0, arm.SHIFT_LR)
case ssa.OpARMCMPshiftRAreg:
genregshift(v.Op.Asm(), gc.SSARegNum(v.Args[0]), gc.SSARegNum(v.Args[1]), gc.SSARegNum(v.Args[2]), 0, arm.SHIFT_AR)
case ssa.OpARMMOVWaddr: case ssa.OpARMMOVWaddr:
p := gc.Prog(arm.AMOVW) p := gc.Prog(arm.AMOVW)
p.From.Type = obj.TYPE_ADDR p.From.Type = obj.TYPE_ADDR
...@@ -440,11 +590,72 @@ func ssaGenValue(s *gc.SSAGenState, v *ssa.Value) { ...@@ -440,11 +590,72 @@ func ssaGenValue(s *gc.SSAGenState, v *ssa.Value) {
p.To.Type = obj.TYPE_MEM p.To.Type = obj.TYPE_MEM
p.To.Reg = gc.SSARegNum(v.Args[0]) p.To.Reg = gc.SSARegNum(v.Args[0])
gc.AddAux(&p.To, v) gc.AddAux(&p.To, v)
case ssa.OpARMMOVWloadidx:
// this is just shift 0 bits
fallthrough
case ssa.OpARMMOVWloadshiftLL:
p := genshift(v.Op.Asm(), 0, gc.SSARegNum(v.Args[1]), gc.SSARegNum(v), arm.SHIFT_LL, v.AuxInt)
p.From.Reg = gc.SSARegNum(v.Args[0])
case ssa.OpARMMOVWloadshiftRL:
p := genshift(v.Op.Asm(), 0, gc.SSARegNum(v.Args[1]), gc.SSARegNum(v), arm.SHIFT_LR, v.AuxInt)
p.From.Reg = gc.SSARegNum(v.Args[0])
case ssa.OpARMMOVWloadshiftRA:
p := genshift(v.Op.Asm(), 0, gc.SSARegNum(v.Args[1]), gc.SSARegNum(v), arm.SHIFT_AR, v.AuxInt)
p.From.Reg = gc.SSARegNum(v.Args[0])
case ssa.OpARMMOVWstoreidx:
// this is just shift 0 bits
fallthrough
case ssa.OpARMMOVWstoreshiftLL:
p := gc.Prog(v.Op.Asm())
p.From.Type = obj.TYPE_REG
p.From.Reg = gc.SSARegNum(v.Args[2])
p.To.Type = obj.TYPE_SHIFT
p.To.Reg = gc.SSARegNum(v.Args[0])
p.To.Offset = int64(makeshift(gc.SSARegNum(v.Args[1]), arm.SHIFT_LL, v.AuxInt))
case ssa.OpARMMOVWstoreshiftRL:
p := gc.Prog(v.Op.Asm())
p.From.Type = obj.TYPE_REG
p.From.Reg = gc.SSARegNum(v.Args[2])
p.To.Type = obj.TYPE_SHIFT
p.To.Reg = gc.SSARegNum(v.Args[0])
p.To.Offset = int64(makeshift(gc.SSARegNum(v.Args[1]), arm.SHIFT_LR, v.AuxInt))
case ssa.OpARMMOVWstoreshiftRA:
p := gc.Prog(v.Op.Asm())
p.From.Type = obj.TYPE_REG
p.From.Reg = gc.SSARegNum(v.Args[2])
p.To.Type = obj.TYPE_SHIFT
p.To.Reg = gc.SSARegNum(v.Args[0])
p.To.Offset = int64(makeshift(gc.SSARegNum(v.Args[1]), arm.SHIFT_AR, v.AuxInt))
case ssa.OpARMMOVBreg, case ssa.OpARMMOVBreg,
ssa.OpARMMOVBUreg, ssa.OpARMMOVBUreg,
ssa.OpARMMOVHreg, ssa.OpARMMOVHreg,
ssa.OpARMMOVHUreg, ssa.OpARMMOVHUreg:
ssa.OpARMMVN, a := v.Args[0]
for a.Op == ssa.OpCopy || a.Op == ssa.OpARMMOVWreg {
a = a.Args[0]
}
if a.Op == ssa.OpLoadReg {
t := a.Type
switch {
case v.Op == ssa.OpARMMOVBreg && t.Size() == 1 && t.IsSigned(),
v.Op == ssa.OpARMMOVBUreg && t.Size() == 1 && !t.IsSigned(),
v.Op == ssa.OpARMMOVHreg && t.Size() == 2 && t.IsSigned(),
v.Op == ssa.OpARMMOVHUreg && t.Size() == 2 && !t.IsSigned():
// arg is a proper-typed load, already zero/sign-extended, don't extend again
if gc.SSARegNum(v) == gc.SSARegNum(v.Args[0]) {
return
}
p := gc.Prog(arm.AMOVW)
p.From.Type = obj.TYPE_REG
p.From.Reg = gc.SSARegNum(v.Args[0])
p.To.Type = obj.TYPE_REG
p.To.Reg = gc.SSARegNum(v)
return
default:
}
}
fallthrough
case ssa.OpARMMVN,
ssa.OpARMSQRTD, ssa.OpARMSQRTD,
ssa.OpARMMOVWF, ssa.OpARMMOVWF,
ssa.OpARMMOVWD, ssa.OpARMMOVWD,
...@@ -467,6 +678,20 @@ func ssaGenValue(s *gc.SSAGenState, v *ssa.Value) { ...@@ -467,6 +678,20 @@ func ssaGenValue(s *gc.SSAGenState, v *ssa.Value) {
p.From.Reg = gc.SSARegNum(v.Args[0]) p.From.Reg = gc.SSARegNum(v.Args[0])
p.To.Type = obj.TYPE_REG p.To.Type = obj.TYPE_REG
p.To.Reg = gc.SSARegNum(v) p.To.Reg = gc.SSARegNum(v)
case ssa.OpARMCMOVWHSconst:
p := gc.Prog(arm.AMOVW)
p.Scond = arm.C_SCOND_HS
p.From.Type = obj.TYPE_CONST
p.From.Offset = v.AuxInt
p.To.Type = obj.TYPE_REG
p.To.Reg = gc.SSARegNum(v)
case ssa.OpARMCMOVWLSconst:
p := gc.Prog(arm.AMOVW)
p.Scond = arm.C_SCOND_LS
p.From.Type = obj.TYPE_CONST
p.From.Offset = v.AuxInt
p.To.Type = obj.TYPE_REG
p.To.Reg = gc.SSARegNum(v)
case ssa.OpARMCALLstatic: case ssa.OpARMCALLstatic:
if v.Aux.(*gc.Sym) == gc.Deferreturn.Sym { if v.Aux.(*gc.Sym) == gc.Deferreturn.Sym {
// Deferred calls will appear to be returning to // Deferred calls will appear to be returning to
...@@ -657,24 +882,6 @@ func ssaGenValue(s *gc.SSAGenState, v *ssa.Value) { ...@@ -657,24 +882,6 @@ func ssaGenValue(s *gc.SSAGenState, v *ssa.Value) {
p4 := gc.Prog(arm.ABLT) p4 := gc.Prog(arm.ABLT)
p4.To.Type = obj.TYPE_BRANCH p4.To.Type = obj.TYPE_BRANCH
gc.Patch(p4, p) gc.Patch(p4, p)
case ssa.OpARMLoweredZeromask:
// int32(arg0>>1 - arg0) >> 31
// RSB r0>>1, r0, r
// SRA $31, r, r
r0 := gc.SSARegNum(v.Args[0])
r := gc.SSARegNum(v)
p := gc.Prog(arm.ARSB)
p.From.Type = obj.TYPE_SHIFT
p.From.Offset = int64(r0&0xf) | arm.SHIFT_LR | 1<<7 // unsigned r0>>1
p.Reg = r0
p.To.Type = obj.TYPE_REG
p.To.Reg = r
p = gc.Prog(arm.ASRA)
p.From.Type = obj.TYPE_CONST
p.From.Offset = 31
p.Reg = r
p.To.Type = obj.TYPE_REG
p.To.Reg = r
case ssa.OpVarDef: case ssa.OpVarDef:
gc.Gvardef(v.Aux.(*gc.Node)) gc.Gvardef(v.Aux.(*gc.Node))
case ssa.OpVarKill: case ssa.OpVarKill:
......
...@@ -553,6 +553,445 @@ func testOrPhi() { ...@@ -553,6 +553,445 @@ func testOrPhi() {
} }
} }
//go:noinline
func addshiftLL_ssa(a, b uint32) uint32 {
return a + b<<3
}
//go:noinline
func subshiftLL_ssa(a, b uint32) uint32 {
return a - b<<3
}
//go:noinline
func rsbshiftLL_ssa(a, b uint32) uint32 {
return a<<3 - b
}
//go:noinline
func andshiftLL_ssa(a, b uint32) uint32 {
return a & (b << 3)
}
//go:noinline
func orshiftLL_ssa(a, b uint32) uint32 {
return a | b<<3
}
//go:noinline
func xorshiftLL_ssa(a, b uint32) uint32 {
return a ^ b<<3
}
//go:noinline
func bicshiftLL_ssa(a, b uint32) uint32 {
return a &^ (b << 3)
}
//go:noinline
func notshiftLL_ssa(a uint32) uint32 {
return ^(a << 3)
}
//go:noinline
func addshiftRL_ssa(a, b uint32) uint32 {
return a + b>>3
}
//go:noinline
func subshiftRL_ssa(a, b uint32) uint32 {
return a - b>>3
}
//go:noinline
func rsbshiftRL_ssa(a, b uint32) uint32 {
return a>>3 - b
}
//go:noinline
func andshiftRL_ssa(a, b uint32) uint32 {
return a & (b >> 3)
}
//go:noinline
func orshiftRL_ssa(a, b uint32) uint32 {
return a | b>>3
}
//go:noinline
func xorshiftRL_ssa(a, b uint32) uint32 {
return a ^ b>>3
}
//go:noinline
func bicshiftRL_ssa(a, b uint32) uint32 {
return a &^ (b >> 3)
}
//go:noinline
func notshiftRL_ssa(a uint32) uint32 {
return ^(a >> 3)
}
//go:noinline
func addshiftRA_ssa(a, b int32) int32 {
return a + b>>3
}
//go:noinline
func subshiftRA_ssa(a, b int32) int32 {
return a - b>>3
}
//go:noinline
func rsbshiftRA_ssa(a, b int32) int32 {
return a>>3 - b
}
//go:noinline
func andshiftRA_ssa(a, b int32) int32 {
return a & (b >> 3)
}
//go:noinline
func orshiftRA_ssa(a, b int32) int32 {
return a | b>>3
}
//go:noinline
func xorshiftRA_ssa(a, b int32) int32 {
return a ^ b>>3
}
//go:noinline
func bicshiftRA_ssa(a, b int32) int32 {
return a &^ (b >> 3)
}
//go:noinline
func notshiftRA_ssa(a int32) int32 {
return ^(a >> 3)
}
//go:noinline
func addshiftLLreg_ssa(a, b uint32, s uint8) uint32 {
return a + b<<s
}
//go:noinline
func subshiftLLreg_ssa(a, b uint32, s uint8) uint32 {
return a - b<<s
}
//go:noinline
func rsbshiftLLreg_ssa(a, b uint32, s uint8) uint32 {
return a<<s - b
}
//go:noinline
func andshiftLLreg_ssa(a, b uint32, s uint8) uint32 {
return a & (b << s)
}
//go:noinline
func orshiftLLreg_ssa(a, b uint32, s uint8) uint32 {
return a | b<<s
}
//go:noinline
func xorshiftLLreg_ssa(a, b uint32, s uint8) uint32 {
return a ^ b<<s
}
//go:noinline
func bicshiftLLreg_ssa(a, b uint32, s uint8) uint32 {
return a &^ (b << s)
}
//go:noinline
func notshiftLLreg_ssa(a uint32, s uint8) uint32 {
return ^(a << s)
}
//go:noinline
func addshiftRLreg_ssa(a, b uint32, s uint8) uint32 {
return a + b>>s
}
//go:noinline
func subshiftRLreg_ssa(a, b uint32, s uint8) uint32 {
return a - b>>s
}
//go:noinline
func rsbshiftRLreg_ssa(a, b uint32, s uint8) uint32 {
return a>>s - b
}
//go:noinline
func andshiftRLreg_ssa(a, b uint32, s uint8) uint32 {
return a & (b >> s)
}
//go:noinline
func orshiftRLreg_ssa(a, b uint32, s uint8) uint32 {
return a | b>>s
}
//go:noinline
func xorshiftRLreg_ssa(a, b uint32, s uint8) uint32 {
return a ^ b>>s
}
//go:noinline
func bicshiftRLreg_ssa(a, b uint32, s uint8) uint32 {
return a &^ (b >> s)
}
//go:noinline
func notshiftRLreg_ssa(a uint32, s uint8) uint32 {
return ^(a >> s)
}
//go:noinline
func addshiftRAreg_ssa(a, b int32, s uint8) int32 {
return a + b>>s
}
//go:noinline
func subshiftRAreg_ssa(a, b int32, s uint8) int32 {
return a - b>>s
}
//go:noinline
func rsbshiftRAreg_ssa(a, b int32, s uint8) int32 {
return a>>s - b
}
//go:noinline
func andshiftRAreg_ssa(a, b int32, s uint8) int32 {
return a & (b >> s)
}
//go:noinline
func orshiftRAreg_ssa(a, b int32, s uint8) int32 {
return a | b>>s
}
//go:noinline
func xorshiftRAreg_ssa(a, b int32, s uint8) int32 {
return a ^ b>>s
}
//go:noinline
func bicshiftRAreg_ssa(a, b int32, s uint8) int32 {
return a &^ (b >> s)
}
//go:noinline
func notshiftRAreg_ssa(a int32, s uint8) int32 {
return ^(a >> s)
}
// test ARM shifted ops
func testShiftedOps() {
a, b := uint32(10), uint32(42)
if want, got := a+b<<3, addshiftLL_ssa(a, b); got != want {
println("addshiftLL_ssa(10, 42) =", got, " want ", want)
failed = true
}
if want, got := a-b<<3, subshiftLL_ssa(a, b); got != want {
println("subshiftLL_ssa(10, 42) =", got, " want ", want)
failed = true
}
if want, got := a<<3-b, rsbshiftLL_ssa(a, b); got != want {
println("rsbshiftLL_ssa(10, 42) =", got, " want ", want)
failed = true
}
if want, got := a&(b<<3), andshiftLL_ssa(a, b); got != want {
println("andshiftLL_ssa(10, 42) =", got, " want ", want)
failed = true
}
if want, got := a|b<<3, orshiftLL_ssa(a, b); got != want {
println("orshiftLL_ssa(10, 42) =", got, " want ", want)
failed = true
}
if want, got := a^b<<3, xorshiftLL_ssa(a, b); got != want {
println("xorshiftLL_ssa(10, 42) =", got, " want ", want)
failed = true
}
if want, got := a&^(b<<3), bicshiftLL_ssa(a, b); got != want {
println("bicshiftLL_ssa(10, 42) =", got, " want ", want)
failed = true
}
if want, got := ^(a << 3), notshiftLL_ssa(a); got != want {
println("notshiftLL_ssa(10) =", got, " want ", want)
failed = true
}
if want, got := a+b>>3, addshiftRL_ssa(a, b); got != want {
println("addshiftRL_ssa(10, 42) =", got, " want ", want)
failed = true
}
if want, got := a-b>>3, subshiftRL_ssa(a, b); got != want {
println("subshiftRL_ssa(10, 42) =", got, " want ", want)
failed = true
}
if want, got := a>>3-b, rsbshiftRL_ssa(a, b); got != want {
println("rsbshiftRL_ssa(10, 42) =", got, " want ", want)
failed = true
}
if want, got := a&(b>>3), andshiftRL_ssa(a, b); got != want {
println("andshiftRL_ssa(10, 42) =", got, " want ", want)
failed = true
}
if want, got := a|b>>3, orshiftRL_ssa(a, b); got != want {
println("orshiftRL_ssa(10, 42) =", got, " want ", want)
failed = true
}
if want, got := a^b>>3, xorshiftRL_ssa(a, b); got != want {
println("xorshiftRL_ssa(10, 42) =", got, " want ", want)
failed = true
}
if want, got := a&^(b>>3), bicshiftRL_ssa(a, b); got != want {
println("bicshiftRL_ssa(10, 42) =", got, " want ", want)
failed = true
}
if want, got := ^(a >> 3), notshiftRL_ssa(a); got != want {
println("notshiftRL_ssa(10) =", got, " want ", want)
failed = true
}
c, d := int32(10), int32(-42)
if want, got := c+d>>3, addshiftRA_ssa(c, d); got != want {
println("addshiftRA_ssa(10, -42) =", got, " want ", want)
failed = true
}
if want, got := c-d>>3, subshiftRA_ssa(c, d); got != want {
println("subshiftRA_ssa(10, -42) =", got, " want ", want)
failed = true
}
if want, got := c>>3-d, rsbshiftRA_ssa(c, d); got != want {
println("rsbshiftRA_ssa(10, -42) =", got, " want ", want)
failed = true
}
if want, got := c&(d>>3), andshiftRA_ssa(c, d); got != want {
println("andshiftRA_ssa(10, -42) =", got, " want ", want)
failed = true
}
if want, got := c|d>>3, orshiftRA_ssa(c, d); got != want {
println("orshiftRA_ssa(10, -42) =", got, " want ", want)
failed = true
}
if want, got := c^d>>3, xorshiftRA_ssa(c, d); got != want {
println("xorshiftRA_ssa(10, -42) =", got, " want ", want)
failed = true
}
if want, got := c&^(d>>3), bicshiftRA_ssa(c, d); got != want {
println("bicshiftRA_ssa(10, -42) =", got, " want ", want)
failed = true
}
if want, got := ^(d >> 3), notshiftRA_ssa(d); got != want {
println("notshiftRA_ssa(-42) =", got, " want ", want)
failed = true
}
s := uint8(3)
if want, got := a+b<<s, addshiftLLreg_ssa(a, b, s); got != want {
println("addshiftLLreg_ssa(10, 42, 3) =", got, " want ", want)
failed = true
}
if want, got := a-b<<s, subshiftLLreg_ssa(a, b, s); got != want {
println("subshiftLLreg_ssa(10, 42, 3) =", got, " want ", want)
failed = true
}
if want, got := a<<s-b, rsbshiftLLreg_ssa(a, b, s); got != want {
println("rsbshiftLLreg_ssa(10, 42, 3) =", got, " want ", want)
failed = true
}
if want, got := a&(b<<s), andshiftLLreg_ssa(a, b, s); got != want {
println("andshiftLLreg_ssa(10, 42, 3) =", got, " want ", want)
failed = true
}
if want, got := a|b<<s, orshiftLLreg_ssa(a, b, s); got != want {
println("orshiftLLreg_ssa(10, 42, 3) =", got, " want ", want)
failed = true
}
if want, got := a^b<<s, xorshiftLLreg_ssa(a, b, s); got != want {
println("xorshiftLLreg_ssa(10, 42, 3) =", got, " want ", want)
failed = true
}
if want, got := a&^(b<<s), bicshiftLLreg_ssa(a, b, s); got != want {
println("bicshiftLLreg_ssa(10, 42, 3) =", got, " want ", want)
failed = true
}
if want, got := ^(a << s), notshiftLLreg_ssa(a, s); got != want {
println("notshiftLLreg_ssa(10) =", got, " want ", want)
failed = true
}
if want, got := a+b>>s, addshiftRLreg_ssa(a, b, s); got != want {
println("addshiftRLreg_ssa(10, 42, 3) =", got, " want ", want)
failed = true
}
if want, got := a-b>>s, subshiftRLreg_ssa(a, b, s); got != want {
println("subshiftRLreg_ssa(10, 42, 3) =", got, " want ", want)
failed = true
}
if want, got := a>>s-b, rsbshiftRLreg_ssa(a, b, s); got != want {
println("rsbshiftRLreg_ssa(10, 42, 3) =", got, " want ", want)
failed = true
}
if want, got := a&(b>>s), andshiftRLreg_ssa(a, b, s); got != want {
println("andshiftRLreg_ssa(10, 42, 3) =", got, " want ", want)
failed = true
}
if want, got := a|b>>s, orshiftRLreg_ssa(a, b, s); got != want {
println("orshiftRLreg_ssa(10, 42, 3) =", got, " want ", want)
failed = true
}
if want, got := a^b>>s, xorshiftRLreg_ssa(a, b, s); got != want {
println("xorshiftRLreg_ssa(10, 42, 3) =", got, " want ", want)
failed = true
}
if want, got := a&^(b>>s), bicshiftRLreg_ssa(a, b, s); got != want {
println("bicshiftRLreg_ssa(10, 42, 3) =", got, " want ", want)
failed = true
}
if want, got := ^(a >> s), notshiftRLreg_ssa(a, s); got != want {
println("notshiftRLreg_ssa(10) =", got, " want ", want)
failed = true
}
if want, got := c+d>>s, addshiftRAreg_ssa(c, d, s); got != want {
println("addshiftRAreg_ssa(10, -42, 3) =", got, " want ", want)
failed = true
}
if want, got := c-d>>s, subshiftRAreg_ssa(c, d, s); got != want {
println("subshiftRAreg_ssa(10, -42, 3) =", got, " want ", want)
failed = true
}
if want, got := c>>s-d, rsbshiftRAreg_ssa(c, d, s); got != want {
println("rsbshiftRAreg_ssa(10, -42, 3) =", got, " want ", want)
failed = true
}
if want, got := c&(d>>s), andshiftRAreg_ssa(c, d, s); got != want {
println("andshiftRAreg_ssa(10, -42, 3) =", got, " want ", want)
failed = true
}
if want, got := c|d>>s, orshiftRAreg_ssa(c, d, s); got != want {
println("orshiftRAreg_ssa(10, -42, 3) =", got, " want ", want)
failed = true
}
if want, got := c^d>>s, xorshiftRAreg_ssa(c, d, s); got != want {
println("xorshiftRAreg_ssa(10, -42, 3) =", got, " want ", want)
failed = true
}
if want, got := c&^(d>>s), bicshiftRAreg_ssa(c, d, s); got != want {
println("bicshiftRAreg_ssa(10, -42, 3) =", got, " want ", want)
failed = true
}
if want, got := ^(d >> s), notshiftRAreg_ssa(d, s); got != want {
println("notshiftRAreg_ssa(-42, 3) =", got, " want ", want)
failed = true
}
}
var failed = false var failed = false
func main() { func main() {
...@@ -573,6 +1012,7 @@ func main() { ...@@ -573,6 +1012,7 @@ func main() {
testLoadCombine() testLoadCombine()
testLoadSymCombine() testLoadSymCombine()
testShiftRemoval() testShiftRemoval()
testShiftedOps()
if failed { if failed {
panic("failed") panic("failed")
......
...@@ -87,40 +87,42 @@ ...@@ -87,40 +87,42 @@
(Not x) -> (XORconst [1] x) (Not x) -> (XORconst [1] x)
// shifts // shifts
(Lsh32x32 x y) -> (SLL x y) // hardware instruction uses only the low byte of the shift
(Lsh32x16 x y) -> (SLL x (ZeroExt16to32 y)) // we compare to 256 to ensure Go semantics for large shifts
(Lsh32x32 x y) -> (CMOVWHSconst (SLL <x.Type> x y) (CMPconst [256] y) [0])
(Lsh32x16 x y) -> (CMOVWHSconst (SLL <x.Type> x (ZeroExt16to32 y)) (CMPconst [256] (ZeroExt16to32 y)) [0])
(Lsh32x8 x y) -> (SLL x (ZeroExt8to32 y)) (Lsh32x8 x y) -> (SLL x (ZeroExt8to32 y))
(Lsh16x32 x y) -> (SLL x y) (Lsh16x32 x y) -> (CMOVWHSconst (SLL <x.Type> x y) (CMPconst [256] y) [0])
(Lsh16x16 x y) -> (SLL x (ZeroExt16to32 y)) (Lsh16x16 x y) -> (CMOVWHSconst (SLL <x.Type> x (ZeroExt16to32 y)) (CMPconst [256] (ZeroExt16to32 y)) [0])
(Lsh16x8 x y) -> (SLL x (ZeroExt8to32 y)) (Lsh16x8 x y) -> (SLL x (ZeroExt8to32 y))
(Lsh8x32 x y) -> (SLL x y) (Lsh8x32 x y) -> (CMOVWHSconst (SLL <x.Type> x y) (CMPconst [256] y) [0])
(Lsh8x16 x y) -> (SLL x (ZeroExt16to32 y)) (Lsh8x16 x y) -> (CMOVWHSconst (SLL <x.Type> x (ZeroExt16to32 y)) (CMPconst [256] (ZeroExt16to32 y)) [0])
(Lsh8x8 x y) -> (SLL x (ZeroExt8to32 y)) (Lsh8x8 x y) -> (SLL x (ZeroExt8to32 y))
(Rsh32Ux32 x y) -> (SRL x y) (Rsh32Ux32 x y) -> (CMOVWHSconst (SRL <x.Type> x y) (CMPconst [256] y) [0])
(Rsh32Ux16 x y) -> (SRL x (ZeroExt16to32 y)) (Rsh32Ux16 x y) -> (CMOVWHSconst (SRL <x.Type> x (ZeroExt16to32 y)) (CMPconst [256] (ZeroExt16to32 y)) [0])
(Rsh32Ux8 x y) -> (SRL x (ZeroExt8to32 y)) (Rsh32Ux8 x y) -> (SRL x (ZeroExt8to32 y))
(Rsh16Ux32 x y) -> (SRL (ZeroExt16to32 x) y) (Rsh16Ux32 x y) -> (CMOVWHSconst (SRL <x.Type> (ZeroExt16to32 x) y) (CMPconst [256] y) [0])
(Rsh16Ux16 x y) -> (SRL (ZeroExt16to32 x) (ZeroExt16to32 y)) (Rsh16Ux16 x y) -> (CMOVWHSconst (SRL <x.Type> (ZeroExt16to32 x) (ZeroExt16to32 y)) (CMPconst [256] (ZeroExt16to32 y)) [0])
(Rsh16Ux8 x y) -> (SRL (ZeroExt16to32 x) (ZeroExt8to32 y)) (Rsh16Ux8 x y) -> (SRL (ZeroExt16to32 x) (ZeroExt8to32 y))
(Rsh8Ux32 x y) -> (SRL (ZeroExt8to32 x) y) (Rsh8Ux32 x y) -> (CMOVWHSconst (SRL <x.Type> (ZeroExt8to32 x) y) (CMPconst [256] y) [0])
(Rsh8Ux16 x y) -> (SRL (ZeroExt8to32 x) (ZeroExt16to32 y)) (Rsh8Ux16 x y) -> (CMOVWHSconst (SRL <x.Type> (ZeroExt8to32 x) (ZeroExt16to32 y)) (CMPconst [256] (ZeroExt16to32 y)) [0])
(Rsh8Ux8 x y) -> (SRL (ZeroExt8to32 x) (ZeroExt8to32 y)) (Rsh8Ux8 x y) -> (SRL (ZeroExt8to32 x) (ZeroExt8to32 y))
(Rsh32x32 x y) -> (SRA x y) (Rsh32x32 x y) -> (SRAcond x y (CMPconst [256] y))
(Rsh32x16 x y) -> (SRA x (ZeroExt16to32 y)) (Rsh32x16 x y) -> (SRAcond x (ZeroExt16to32 y) (CMPconst [256] (ZeroExt16to32 y)))
(Rsh32x8 x y) -> (SRA x (ZeroExt8to32 y)) (Rsh32x8 x y) -> (SRA x (ZeroExt8to32 y))
(Rsh16x32 x y) -> (SRA (SignExt16to32 x) y) (Rsh16x32 x y) -> (SRAcond (SignExt16to32 x) y (CMPconst [256] y))
(Rsh16x16 x y) -> (SRA (SignExt16to32 x) (ZeroExt16to32 y)) (Rsh16x16 x y) -> (SRAcond (SignExt16to32 x) (ZeroExt16to32 y) (CMPconst [256] (ZeroExt16to32 y)))
(Rsh16x8 x y) -> (SRA (SignExt16to32 x) (ZeroExt8to32 y)) (Rsh16x8 x y) -> (SRA (SignExt16to32 x) (ZeroExt8to32 y))
(Rsh8x32 x y) -> (SRA (SignExt8to32 x) y) (Rsh8x32 x y) -> (SRAcond (SignExt8to32 x) y (CMPconst [256] y))
(Rsh8x16 x y) -> (SRA (SignExt8to32 x) (ZeroExt16to32 y)) (Rsh8x16 x y) -> (SRAcond (SignExt8to32 x) (ZeroExt16to32 y) (CMPconst [256] (ZeroExt16to32 y)))
(Rsh8x8 x y) -> (SRA (SignExt8to32 x) (ZeroExt8to32 y)) (Rsh8x8 x y) -> (SRA (SignExt8to32 x) (ZeroExt8to32 y))
// constant shifts // constant shifts
...@@ -177,7 +179,7 @@ ...@@ -177,7 +179,7 @@
(SignExt16to32 x) -> (MOVHreg x) (SignExt16to32 x) -> (MOVHreg x)
(Signmask x) -> (SRAconst x [31]) (Signmask x) -> (SRAconst x [31])
(Zeromask x) -> (LoweredZeromask x) (Zeromask x) -> (SRAconst (RSBshiftRL <config.fe.TypeInt32()> x x [1]) [31]) // sign bit of uint32(x)>>1 - x
// float <-> int conversion // float <-> int conversion
(Cvt32to32F x) -> (MOVWF x) (Cvt32to32F x) -> (MOVWF x)
...@@ -452,6 +454,11 @@ ...@@ -452,6 +454,11 @@
(MOVFload [off] {sym} ptr (MOVFstore [off2] {sym2} ptr2 x _)) && sym == sym2 && off == off2 && isSamePtr(ptr, ptr2) -> x (MOVFload [off] {sym} ptr (MOVFstore [off2] {sym2} ptr2 x _)) && sym == sym2 && off == off2 && isSamePtr(ptr, ptr2) -> x
(MOVDload [off] {sym} ptr (MOVDstore [off2] {sym2} ptr2 x _)) && sym == sym2 && off == off2 && isSamePtr(ptr, ptr2) -> x (MOVDload [off] {sym} ptr (MOVDstore [off2] {sym2} ptr2 x _)) && sym == sym2 && off == off2 && isSamePtr(ptr, ptr2) -> x
(MOVWloadidx ptr idx (MOVWstoreidx ptr2 idx x _)) && isSamePtr(ptr, ptr2) -> x
(MOVWloadshiftLL ptr idx [c] (MOVWstoreshiftLL ptr2 idx [d] x _)) && c==d && isSamePtr(ptr, ptr2) -> x
(MOVWloadshiftRL ptr idx [c] (MOVWstoreshiftRL ptr2 idx [d] x _)) && c==d && isSamePtr(ptr, ptr2) -> x
(MOVWloadshiftRA ptr idx [c] (MOVWstoreshiftRA ptr2 idx [d] x _)) && c==d && isSamePtr(ptr, ptr2) -> x
// fold constant into arithmatic ops // fold constant into arithmatic ops
(ADD (MOVWconst [c]) x) -> (ADDconst [c] x) (ADD (MOVWconst [c]) x) -> (ADDconst [c] x)
(ADD x (MOVWconst [c])) -> (ADDconst [c] x) (ADD x (MOVWconst [c])) -> (ADDconst [c] x)
...@@ -485,9 +492,6 @@ ...@@ -485,9 +492,6 @@
(CMP x (MOVWconst [c])) -> (CMPconst [c] x) (CMP x (MOVWconst [c])) -> (CMPconst [c] x)
(CMP (MOVWconst [c]) x) -> (InvertFlags (CMPconst [c] x)) (CMP (MOVWconst [c]) x) -> (InvertFlags (CMPconst [c] x))
(LoweredZeromask (MOVWconst [0])) -> (MOVWconst [0])
(LoweredZeromask (MOVWconst [c])) && c != 0 -> (MOVWconst [0xffffffff])
// don't extend after proper load // don't extend after proper load
// MOVWreg instruction is not emitted if src and dst registers are same, but it ensures the type. // MOVWreg instruction is not emitted if src and dst registers are same, but it ensures the type.
(MOVBreg x:(MOVBload _ _)) -> (MOVWreg x) (MOVBreg x:(MOVBload _ _)) -> (MOVWreg x)
...@@ -504,6 +508,15 @@ ...@@ -504,6 +508,15 @@
(MOVBreg (ANDconst [c] x)) && c & 0x80 == 0 -> (ANDconst [c&0x7f] x) (MOVBreg (ANDconst [c] x)) && c & 0x80 == 0 -> (ANDconst [c&0x7f] x)
(MOVHreg (ANDconst [c] x)) && c & 0x8000 == 0 -> (ANDconst [c&0x7fff] x) (MOVHreg (ANDconst [c] x)) && c & 0x8000 == 0 -> (ANDconst [c&0x7fff] x)
// fold double extensions
(MOVBreg x:(MOVBreg _)) -> (MOVWreg x)
(MOVBUreg x:(MOVBUreg _)) -> (MOVWreg x)
(MOVHreg x:(MOVBreg _)) -> (MOVWreg x)
(MOVHreg x:(MOVBUreg _)) -> (MOVWreg x)
(MOVHreg x:(MOVHreg _)) -> (MOVWreg x)
(MOVHUreg x:(MOVBUreg _)) -> (MOVWreg x)
(MOVHUreg x:(MOVHUreg _)) -> (MOVWreg x)
// don't extend before store // don't extend before store
(MOVBstore [off] {sym} ptr (MOVBreg x) mem) -> (MOVBstore [off] {sym} ptr x mem) (MOVBstore [off] {sym} ptr (MOVBreg x) mem) -> (MOVBstore [off] {sym} ptr x mem)
(MOVBstore [off] {sym} ptr (MOVBUreg x) mem) -> (MOVBstore [off] {sym} ptr x mem) (MOVBstore [off] {sym} ptr (MOVBUreg x) mem) -> (MOVBstore [off] {sym} ptr x mem)
...@@ -513,25 +526,49 @@ ...@@ -513,25 +526,49 @@
(MOVHstore [off] {sym} ptr (MOVHUreg x) mem) -> (MOVHstore [off] {sym} ptr x mem) (MOVHstore [off] {sym} ptr (MOVHUreg x) mem) -> (MOVHstore [off] {sym} ptr x mem)
// mul by constant // mul by constant
(MUL x (MOVWconst [-1])) -> (RSBconst [0] x) (MUL x (MOVWconst [c])) && int32(c) == -1 -> (RSBconst [0] x)
(MUL _ (MOVWconst [0])) -> (MOVWconst [0]) (MUL _ (MOVWconst [0])) -> (MOVWconst [0])
(MUL x (MOVWconst [1])) -> x (MUL x (MOVWconst [1])) -> x
(MUL x (MOVWconst [c])) && isPowerOfTwo(c) -> (SLLconst [log2(c)] x) (MUL x (MOVWconst [c])) && isPowerOfTwo(c) -> (SLLconst [log2(c)] x)
(MUL x (MOVWconst [c])) && isPowerOfTwo(c-1) && int32(c) >= 3 -> (ADDshiftLL x x [log2(c-1)])
(MUL (MOVWconst [-1]) x) -> (RSBconst [0] x) (MUL x (MOVWconst [c])) && isPowerOfTwo(c+1) && int32(c) >= 7 -> (RSBshiftLL x x [log2(c+1)])
(MUL x (MOVWconst [c])) && c%3 == 0 && isPowerOfTwo(c/3) && is32Bit(c) -> (SLLconst [log2(c/3)] (ADDshiftLL <x.Type> x x [1]))
(MUL x (MOVWconst [c])) && c%5 == 0 && isPowerOfTwo(c/5) && is32Bit(c) -> (SLLconst [log2(c/5)] (ADDshiftLL <x.Type> x x [2]))
(MUL x (MOVWconst [c])) && c%7 == 0 && isPowerOfTwo(c/7) && is32Bit(c) -> (SLLconst [log2(c/7)] (RSBshiftLL <x.Type> x x [3]))
(MUL x (MOVWconst [c])) && c%9 == 0 && isPowerOfTwo(c/9) && is32Bit(c) -> (SLLconst [log2(c/9)] (ADDshiftLL <x.Type> x x [3]))
(MUL (MOVWconst [c]) x) && int32(c) == -1 -> (RSBconst [0] x)
(MUL (MOVWconst [0]) _) -> (MOVWconst [0]) (MUL (MOVWconst [0]) _) -> (MOVWconst [0])
(MUL (MOVWconst [1]) x) -> x (MUL (MOVWconst [1]) x) -> x
(MUL (MOVWconst [c]) x) && isPowerOfTwo(c) -> (SLLconst [log2(c)] x) (MUL (MOVWconst [c]) x) && isPowerOfTwo(c) -> (SLLconst [log2(c)] x)
(MUL (MOVWconst [c]) x) && isPowerOfTwo(c-1) && int32(c) >= 3 -> (ADDshiftLL x x [log2(c-1)])
(MULA x (MOVWconst [-1]) a) -> (SUB a x) (MUL (MOVWconst [c]) x) && isPowerOfTwo(c+1) && int32(c) >= 7 -> (RSBshiftLL x x [log2(c+1)])
(MUL (MOVWconst [c]) x) && c%3 == 0 && isPowerOfTwo(c/3) && is32Bit(c) -> (SLLconst [log2(c/3)] (ADDshiftLL <x.Type> x x [1]))
(MUL (MOVWconst [c]) x) && c%5 == 0 && isPowerOfTwo(c/5) && is32Bit(c) -> (SLLconst [log2(c/5)] (ADDshiftLL <x.Type> x x [2]))
(MUL (MOVWconst [c]) x) && c%7 == 0 && isPowerOfTwo(c/7) && is32Bit(c) -> (SLLconst [log2(c/7)] (RSBshiftLL <x.Type> x x [3]))
(MUL (MOVWconst [c]) x) && c%9 == 0 && isPowerOfTwo(c/9) && is32Bit(c) -> (SLLconst [log2(c/9)] (ADDshiftLL <x.Type> x x [3]))
(MULA x (MOVWconst [c]) a) && int32(c) == -1 -> (SUB a x)
(MULA _ (MOVWconst [0]) a) -> a (MULA _ (MOVWconst [0]) a) -> a
(MULA x (MOVWconst [1]) a) -> (ADD x a) (MULA x (MOVWconst [1]) a) -> (ADD x a)
(MULA x (MOVWconst [c]) a) && isPowerOfTwo(c) -> (ADD (SLLconst <x.Type> [log2(c)] x) a) (MULA x (MOVWconst [c]) a) && isPowerOfTwo(c) -> (ADD (SLLconst <x.Type> [log2(c)] x) a)
(MULA x (MOVWconst [c]) a) && isPowerOfTwo(c-1) && int32(c) >= 3 -> (ADD (ADDshiftLL <x.Type> x x [log2(c-1)]) a)
(MULA (MOVWconst [-1]) x a) -> (SUB a x) (MULA x (MOVWconst [c]) a) && isPowerOfTwo(c+1) && int32(c) >= 7 -> (ADD (RSBshiftLL <x.Type> x x [log2(c+1)]) a)
(MULA x (MOVWconst [c]) a) && c%3 == 0 && isPowerOfTwo(c/3) && is32Bit(c) -> (ADD (SLLconst <x.Type> [log2(c/3)] (ADDshiftLL <x.Type> x x [1])) a)
(MULA x (MOVWconst [c]) a) && c%5 == 0 && isPowerOfTwo(c/5) && is32Bit(c) -> (ADD (SLLconst <x.Type> [log2(c/5)] (ADDshiftLL <x.Type> x x [2])) a)
(MULA x (MOVWconst [c]) a) && c%7 == 0 && isPowerOfTwo(c/7) && is32Bit(c) -> (ADD (SLLconst <x.Type> [log2(c/7)] (RSBshiftLL <x.Type> x x [3])) a)
(MULA x (MOVWconst [c]) a) && c%9 == 0 && isPowerOfTwo(c/9) && is32Bit(c) -> (ADD (SLLconst <x.Type> [log2(c/9)] (ADDshiftLL <x.Type> x x [3])) a)
(MULA (MOVWconst [c]) x a) && int32(c) == -1 -> (SUB a x)
(MULA (MOVWconst [0]) _ a) -> a (MULA (MOVWconst [0]) _ a) -> a
(MULA (MOVWconst [1]) x a) -> (ADD x a) (MULA (MOVWconst [1]) x a) -> (ADD x a)
(MULA (MOVWconst [c]) x a) && isPowerOfTwo(c) -> (ADD (SLLconst <x.Type> [log2(c)] x) a) (MULA (MOVWconst [c]) x a) && isPowerOfTwo(c) -> (ADD (SLLconst <x.Type> [log2(c)] x) a)
(MULA (MOVWconst [c]) x a) && isPowerOfTwo(c-1) && int32(c) >= 3 -> (ADD (ADDshiftLL <x.Type> x x [log2(c-1)]) a)
(MULA (MOVWconst [c]) x a) && isPowerOfTwo(c+1) && int32(c) >= 7 -> (ADD (RSBshiftLL <x.Type> x x [log2(c+1)]) a)
(MULA (MOVWconst [c]) x a) && c%3 == 0 && isPowerOfTwo(c/3) && is32Bit(c) -> (ADD (SLLconst <x.Type> [log2(c/3)] (ADDshiftLL <x.Type> x x [1])) a)
(MULA (MOVWconst [c]) x a) && c%5 == 0 && isPowerOfTwo(c/5) && is32Bit(c) -> (ADD (SLLconst <x.Type> [log2(c/5)] (ADDshiftLL <x.Type> x x [2])) a)
(MULA (MOVWconst [c]) x a) && c%7 == 0 && isPowerOfTwo(c/7) && is32Bit(c) -> (ADD (SLLconst <x.Type> [log2(c/7)] (RSBshiftLL <x.Type> x x [3])) a)
(MULA (MOVWconst [c]) x a) && c%9 == 0 && isPowerOfTwo(c/9) && is32Bit(c) -> (ADD (SLLconst <x.Type> [log2(c/9)] (ADDshiftLL <x.Type> x x [3])) a)
// div by constant // div by constant
(DIVU x (MOVWconst [1])) -> x (DIVU x (MOVWconst [1])) -> x
...@@ -696,6 +733,28 @@ ...@@ -696,6 +733,28 @@
(GreaterEqual (InvertFlags x)) -> (LessEqual x) (GreaterEqual (InvertFlags x)) -> (LessEqual x)
(GreaterEqualU (InvertFlags x)) -> (LessEqualU x) (GreaterEqualU (InvertFlags x)) -> (LessEqualU x)
// absorb flag constants into conditional instructions
(CMOVWLSconst _ (FlagEQ) [c]) -> (MOVWconst [c])
(CMOVWLSconst _ (FlagLT_ULT) [c]) -> (MOVWconst [c])
(CMOVWLSconst x (FlagLT_UGT)) -> x
(CMOVWLSconst _ (FlagGT_ULT) [c]) -> (MOVWconst [c])
(CMOVWLSconst x (FlagGT_UGT)) -> x
(CMOVWHSconst _ (FlagEQ) [c]) -> (MOVWconst [c])
(CMOVWHSconst x (FlagLT_ULT)) -> x
(CMOVWHSconst _ (FlagLT_UGT) [c]) -> (MOVWconst [c])
(CMOVWHSconst x (FlagGT_ULT)) -> x
(CMOVWHSconst _ (FlagGT_UGT) [c]) -> (MOVWconst [c])
(CMOVWLSconst x (InvertFlags flags) [c]) -> (CMOVWHSconst x flags [c])
(CMOVWHSconst x (InvertFlags flags) [c]) -> (CMOVWLSconst x flags [c])
(SRAcond x _ (FlagEQ)) -> (SRAconst x [31])
(SRAcond x y (FlagLT_ULT)) -> (SRA x y)
(SRAcond x _ (FlagLT_UGT)) -> (SRAconst x [31])
(SRAcond x y (FlagGT_ULT)) -> (SRA x y)
(SRAcond x _ (FlagGT_UGT)) -> (SRAconst x [31])
// remove redundant *const ops // remove redundant *const ops
(ADDconst [0] x) -> x (ADDconst [0] x) -> x
(SUBconst [0] x) -> x (SUBconst [0] x) -> x
...@@ -741,10 +800,377 @@ ...@@ -741,10 +800,377 @@
(XORconst [c] (XORconst [d] x)) -> (XORconst [c^d] x) (XORconst [c] (XORconst [d] x)) -> (XORconst [c^d] x)
(BICconst [c] (MOVWconst [d])) -> (MOVWconst [d&^c]) (BICconst [c] (MOVWconst [d])) -> (MOVWconst [d&^c])
(MVN (MOVWconst [c])) -> (MOVWconst [^c]) (MVN (MOVWconst [c])) -> (MOVWconst [^c])
(MOVBreg (MOVWconst [c])) -> (MOVWconst [int64(int8(c))])
(MOVBUreg (MOVWconst [c])) -> (MOVWconst [int64(uint8(c))])
(MOVHreg (MOVWconst [c])) -> (MOVWconst [int64(int16(c))])
(MOVHUreg (MOVWconst [c])) -> (MOVWconst [int64(uint16(c))])
(MOVWreg (MOVWconst [c])) -> (MOVWconst [c])
// absorb shifts into ops
(ADD x (SLLconst [c] y)) -> (ADDshiftLL x y [c])
(ADD (SLLconst [c] y) x) -> (ADDshiftLL x y [c])
(ADD x (SRLconst [c] y)) -> (ADDshiftRL x y [c])
(ADD (SRLconst [c] y) x) -> (ADDshiftRL x y [c])
(ADD x (SRAconst [c] y)) -> (ADDshiftRA x y [c])
(ADD (SRAconst [c] y) x) -> (ADDshiftRA x y [c])
(ADD x (SLL y z)) -> (ADDshiftLLreg x y z)
(ADD (SLL y z) x) -> (ADDshiftLLreg x y z)
(ADD x (SRL y z)) -> (ADDshiftRLreg x y z)
(ADD (SRL y z) x) -> (ADDshiftRLreg x y z)
(ADD x (SRA y z)) -> (ADDshiftRAreg x y z)
(ADD (SRA y z) x) -> (ADDshiftRAreg x y z)
(ADC x (SLLconst [c] y) flags) -> (ADCshiftLL x y [c] flags)
(ADC (SLLconst [c] y) x flags) -> (ADCshiftLL x y [c] flags)
(ADC x (SRLconst [c] y) flags) -> (ADCshiftRL x y [c] flags)
(ADC (SRLconst [c] y) x flags) -> (ADCshiftRL x y [c] flags)
(ADC x (SRAconst [c] y) flags) -> (ADCshiftRA x y [c] flags)
(ADC (SRAconst [c] y) x flags) -> (ADCshiftRA x y [c] flags)
(ADC x (SLL y z) flags) -> (ADCshiftLLreg x y z flags)
(ADC (SLL y z) x flags) -> (ADCshiftLLreg x y z flags)
(ADC x (SRL y z) flags) -> (ADCshiftRLreg x y z flags)
(ADC (SRL y z) x flags) -> (ADCshiftRLreg x y z flags)
(ADC x (SRA y z) flags) -> (ADCshiftRAreg x y z flags)
(ADC (SRA y z) x flags) -> (ADCshiftRAreg x y z flags)
(ADDS x (SLLconst [c] y)) -> (ADDSshiftLL x y [c])
(ADDS (SLLconst [c] y) x) -> (ADDSshiftLL x y [c])
(ADDS x (SRLconst [c] y)) -> (ADDSshiftRL x y [c])
(ADDS (SRLconst [c] y) x) -> (ADDSshiftRL x y [c])
(ADDS x (SRAconst [c] y)) -> (ADDSshiftRA x y [c])
(ADDS (SRAconst [c] y) x) -> (ADDSshiftRA x y [c])
(ADDS x (SLL y z)) -> (ADDSshiftLLreg x y z)
(ADDS (SLL y z) x) -> (ADDSshiftLLreg x y z)
(ADDS x (SRL y z)) -> (ADDSshiftRLreg x y z)
(ADDS (SRL y z) x) -> (ADDSshiftRLreg x y z)
(ADDS x (SRA y z)) -> (ADDSshiftRAreg x y z)
(ADDS (SRA y z) x) -> (ADDSshiftRAreg x y z)
(SUB x (SLLconst [c] y)) -> (SUBshiftLL x y [c])
(SUB (SLLconst [c] y) x) -> (RSBshiftLL x y [c])
(SUB x (SRLconst [c] y)) -> (SUBshiftRL x y [c])
(SUB (SRLconst [c] y) x) -> (RSBshiftRL x y [c])
(SUB x (SRAconst [c] y)) -> (SUBshiftRA x y [c])
(SUB (SRAconst [c] y) x) -> (RSBshiftRA x y [c])
(SUB x (SLL y z)) -> (SUBshiftLLreg x y z)
(SUB (SLL y z) x) -> (RSBshiftLLreg x y z)
(SUB x (SRL y z)) -> (SUBshiftRLreg x y z)
(SUB (SRL y z) x) -> (RSBshiftRLreg x y z)
(SUB x (SRA y z)) -> (SUBshiftRAreg x y z)
(SUB (SRA y z) x) -> (RSBshiftRAreg x y z)
(SBC x (SLLconst [c] y) flags) -> (SBCshiftLL x y [c] flags)
(SBC (SLLconst [c] y) x flags) -> (RSCshiftLL x y [c] flags)
(SBC x (SRLconst [c] y) flags) -> (SBCshiftRL x y [c] flags)
(SBC (SRLconst [c] y) x flags) -> (RSCshiftRL x y [c] flags)
(SBC x (SRAconst [c] y) flags) -> (SBCshiftRA x y [c] flags)
(SBC (SRAconst [c] y) x flags) -> (RSCshiftRA x y [c] flags)
(SBC x (SLL y z) flags) -> (SBCshiftLLreg x y z flags)
(SBC (SLL y z) x flags) -> (RSCshiftLLreg x y z flags)
(SBC x (SRL y z) flags) -> (SBCshiftRLreg x y z flags)
(SBC (SRL y z) x flags) -> (RSCshiftRLreg x y z flags)
(SBC x (SRA y z) flags) -> (SBCshiftRAreg x y z flags)
(SBC (SRA y z) x flags) -> (RSCshiftRAreg x y z flags)
(SUBS x (SLLconst [c] y)) -> (SUBSshiftLL x y [c])
(SUBS (SLLconst [c] y) x) -> (RSBSshiftLL x y [c])
(SUBS x (SRLconst [c] y)) -> (SUBSshiftRL x y [c])
(SUBS (SRLconst [c] y) x) -> (RSBSshiftRL x y [c])
(SUBS x (SRAconst [c] y)) -> (SUBSshiftRA x y [c])
(SUBS (SRAconst [c] y) x) -> (RSBSshiftRA x y [c])
(SUBS x (SLL y z)) -> (SUBSshiftLLreg x y z)
(SUBS (SLL y z) x) -> (RSBSshiftLLreg x y z)
(SUBS x (SRL y z)) -> (SUBSshiftRLreg x y z)
(SUBS (SRL y z) x) -> (RSBSshiftRLreg x y z)
(SUBS x (SRA y z)) -> (SUBSshiftRAreg x y z)
(SUBS (SRA y z) x) -> (RSBSshiftRAreg x y z)
(RSB x (SLLconst [c] y)) -> (RSBshiftLL x y [c])
(RSB (SLLconst [c] y) x) -> (SUBshiftLL x y [c])
(RSB x (SRLconst [c] y)) -> (RSBshiftRL x y [c])
(RSB (SRLconst [c] y) x) -> (SUBshiftRL x y [c])
(RSB x (SRAconst [c] y)) -> (RSBshiftRA x y [c])
(RSB (SRAconst [c] y) x) -> (SUBshiftRA x y [c])
(RSB x (SLL y z)) -> (RSBshiftLLreg x y z)
(RSB (SLL y z) x) -> (SUBshiftLLreg x y z)
(RSB x (SRL y z)) -> (RSBshiftRLreg x y z)
(RSB (SRL y z) x) -> (SUBshiftRLreg x y z)
(RSB x (SRA y z)) -> (RSBshiftRAreg x y z)
(RSB (SRA y z) x) -> (SUBshiftRAreg x y z)
(AND x (SLLconst [c] y)) -> (ANDshiftLL x y [c])
(AND (SLLconst [c] y) x) -> (ANDshiftLL x y [c])
(AND x (SRLconst [c] y)) -> (ANDshiftRL x y [c])
(AND (SRLconst [c] y) x) -> (ANDshiftRL x y [c])
(AND x (SRAconst [c] y)) -> (ANDshiftRA x y [c])
(AND (SRAconst [c] y) x) -> (ANDshiftRA x y [c])
(AND x (SLL y z)) -> (ANDshiftLLreg x y z)
(AND (SLL y z) x) -> (ANDshiftLLreg x y z)
(AND x (SRL y z)) -> (ANDshiftRLreg x y z)
(AND (SRL y z) x) -> (ANDshiftRLreg x y z)
(AND x (SRA y z)) -> (ANDshiftRAreg x y z)
(AND (SRA y z) x) -> (ANDshiftRAreg x y z)
(OR x (SLLconst [c] y)) -> (ORshiftLL x y [c])
(OR (SLLconst [c] y) x) -> (ORshiftLL x y [c])
(OR x (SRLconst [c] y)) -> (ORshiftRL x y [c])
(OR (SRLconst [c] y) x) -> (ORshiftRL x y [c])
(OR x (SRAconst [c] y)) -> (ORshiftRA x y [c])
(OR (SRAconst [c] y) x) -> (ORshiftRA x y [c])
(OR x (SLL y z)) -> (ORshiftLLreg x y z)
(OR (SLL y z) x) -> (ORshiftLLreg x y z)
(OR x (SRL y z)) -> (ORshiftRLreg x y z)
(OR (SRL y z) x) -> (ORshiftRLreg x y z)
(OR x (SRA y z)) -> (ORshiftRAreg x y z)
(OR (SRA y z) x) -> (ORshiftRAreg x y z)
(XOR x (SLLconst [c] y)) -> (XORshiftLL x y [c])
(XOR (SLLconst [c] y) x) -> (XORshiftLL x y [c])
(XOR x (SRLconst [c] y)) -> (XORshiftRL x y [c])
(XOR (SRLconst [c] y) x) -> (XORshiftRL x y [c])
(XOR x (SRAconst [c] y)) -> (XORshiftRA x y [c])
(XOR (SRAconst [c] y) x) -> (XORshiftRA x y [c])
(XOR x (SLL y z)) -> (XORshiftLLreg x y z)
(XOR (SLL y z) x) -> (XORshiftLLreg x y z)
(XOR x (SRL y z)) -> (XORshiftRLreg x y z)
(XOR (SRL y z) x) -> (XORshiftRLreg x y z)
(XOR x (SRA y z)) -> (XORshiftRAreg x y z)
(XOR (SRA y z) x) -> (XORshiftRAreg x y z)
(BIC x (SLLconst [c] y)) -> (BICshiftLL x y [c])
(BIC x (SRLconst [c] y)) -> (BICshiftRL x y [c])
(BIC x (SRAconst [c] y)) -> (BICshiftRA x y [c])
(BIC x (SLL y z)) -> (BICshiftLLreg x y z)
(BIC x (SRL y z)) -> (BICshiftRLreg x y z)
(BIC x (SRA y z)) -> (BICshiftRAreg x y z)
(MVN (SLLconst [c] x)) -> (MVNshiftLL x [c])
(MVN (SRLconst [c] x)) -> (MVNshiftRL x [c])
(MVN (SRAconst [c] x)) -> (MVNshiftRA x [c])
(MVN (SLL x y)) -> (MVNshiftLLreg x y)
(MVN (SRL x y)) -> (MVNshiftRLreg x y)
(MVN (SRA x y)) -> (MVNshiftRAreg x y)
(CMP x (SLLconst [c] y)) -> (CMPshiftLL x y [c])
(CMP (SLLconst [c] y) x) -> (InvertFlags (CMPshiftLL x y [c]))
(CMP x (SRLconst [c] y)) -> (CMPshiftRL x y [c])
(CMP (SRLconst [c] y) x) -> (InvertFlags (CMPshiftRL x y [c]))
(CMP x (SRAconst [c] y)) -> (CMPshiftRA x y [c])
(CMP (SRAconst [c] y) x) -> (InvertFlags (CMPshiftRA x y [c]))
(CMP x (SLL y z)) -> (CMPshiftLLreg x y z)
(CMP (SLL y z) x) -> (InvertFlags (CMPshiftLLreg x y z))
(CMP x (SRL y z)) -> (CMPshiftRLreg x y z)
(CMP (SRL y z) x) -> (InvertFlags (CMPshiftRLreg x y z))
(CMP x (SRA y z)) -> (CMPshiftRAreg x y z)
(CMP (SRA y z) x) -> (InvertFlags (CMPshiftRAreg x y z))
// prefer *const ops to *shift ops
(ADDshiftLL (MOVWconst [c]) x [d]) -> (ADDconst [c] (SLLconst <x.Type> x [d]))
(ADDshiftRL (MOVWconst [c]) x [d]) -> (ADDconst [c] (SRLconst <x.Type> x [d]))
(ADDshiftRA (MOVWconst [c]) x [d]) -> (ADDconst [c] (SRAconst <x.Type> x [d]))
(ADCshiftLL (MOVWconst [c]) x [d] flags) -> (ADCconst [c] (SLLconst <x.Type> x [d]) flags)
(ADCshiftRL (MOVWconst [c]) x [d] flags) -> (ADCconst [c] (SRLconst <x.Type> x [d]) flags)
(ADCshiftRA (MOVWconst [c]) x [d] flags) -> (ADCconst [c] (SRAconst <x.Type> x [d]) flags)
(ADDSshiftLL (MOVWconst [c]) x [d]) -> (ADDSconst [c] (SLLconst <x.Type> x [d]))
(ADDSshiftRL (MOVWconst [c]) x [d]) -> (ADDSconst [c] (SRLconst <x.Type> x [d]))
(ADDSshiftRA (MOVWconst [c]) x [d]) -> (ADDSconst [c] (SRAconst <x.Type> x [d]))
(SUBshiftLL (MOVWconst [c]) x [d]) -> (RSBconst [c] (SLLconst <x.Type> x [d]))
(SUBshiftRL (MOVWconst [c]) x [d]) -> (RSBconst [c] (SRLconst <x.Type> x [d]))
(SUBshiftRA (MOVWconst [c]) x [d]) -> (RSBconst [c] (SRAconst <x.Type> x [d]))
(SBCshiftLL (MOVWconst [c]) x [d] flags) -> (RSCconst [c] (SLLconst <x.Type> x [d]) flags)
(SBCshiftRL (MOVWconst [c]) x [d] flags) -> (RSCconst [c] (SRLconst <x.Type> x [d]) flags)
(SBCshiftRA (MOVWconst [c]) x [d] flags) -> (RSCconst [c] (SRAconst <x.Type> x [d]) flags)
(SUBSshiftLL (MOVWconst [c]) x [d]) -> (RSBSconst [c] (SLLconst <x.Type> x [d]))
(SUBSshiftRL (MOVWconst [c]) x [d]) -> (RSBSconst [c] (SRLconst <x.Type> x [d]))
(SUBSshiftRA (MOVWconst [c]) x [d]) -> (RSBSconst [c] (SRAconst <x.Type> x [d]))
(RSBshiftLL (MOVWconst [c]) x [d]) -> (SUBconst [c] (SLLconst <x.Type> x [d]))
(RSBshiftRL (MOVWconst [c]) x [d]) -> (SUBconst [c] (SRLconst <x.Type> x [d]))
(RSBshiftRA (MOVWconst [c]) x [d]) -> (SUBconst [c] (SRAconst <x.Type> x [d]))
(RSCshiftLL (MOVWconst [c]) x [d] flags) -> (SBCconst [c] (SLLconst <x.Type> x [d]) flags)
(RSCshiftRL (MOVWconst [c]) x [d] flags) -> (SBCconst [c] (SRLconst <x.Type> x [d]) flags)
(RSCshiftRA (MOVWconst [c]) x [d] flags) -> (SBCconst [c] (SRAconst <x.Type> x [d]) flags)
(RSBSshiftLL (MOVWconst [c]) x [d]) -> (SUBSconst [c] (SLLconst <x.Type> x [d]))
(RSBSshiftRL (MOVWconst [c]) x [d]) -> (SUBSconst [c] (SRLconst <x.Type> x [d]))
(RSBSshiftRA (MOVWconst [c]) x [d]) -> (SUBSconst [c] (SRAconst <x.Type> x [d]))
(ANDshiftLL (MOVWconst [c]) x [d]) -> (ANDconst [c] (SLLconst <x.Type> x [d]))
(ANDshiftRL (MOVWconst [c]) x [d]) -> (ANDconst [c] (SRLconst <x.Type> x [d]))
(ANDshiftRA (MOVWconst [c]) x [d]) -> (ANDconst [c] (SRAconst <x.Type> x [d]))
(ORshiftLL (MOVWconst [c]) x [d]) -> (ORconst [c] (SLLconst <x.Type> x [d]))
(ORshiftRL (MOVWconst [c]) x [d]) -> (ORconst [c] (SRLconst <x.Type> x [d]))
(ORshiftRA (MOVWconst [c]) x [d]) -> (ORconst [c] (SRAconst <x.Type> x [d]))
(XORshiftLL (MOVWconst [c]) x [d]) -> (XORconst [c] (SLLconst <x.Type> x [d]))
(XORshiftRL (MOVWconst [c]) x [d]) -> (XORconst [c] (SRLconst <x.Type> x [d]))
(XORshiftRA (MOVWconst [c]) x [d]) -> (XORconst [c] (SRAconst <x.Type> x [d]))
(CMPshiftLL (MOVWconst [c]) x [d]) -> (InvertFlags (CMPconst [c] (SLLconst <x.Type> x [d])))
(CMPshiftRL (MOVWconst [c]) x [d]) -> (InvertFlags (CMPconst [c] (SRLconst <x.Type> x [d])))
(CMPshiftRA (MOVWconst [c]) x [d]) -> (InvertFlags (CMPconst [c] (SRAconst <x.Type> x [d])))
(ADDshiftLLreg (MOVWconst [c]) x y) -> (ADDconst [c] (SLL <x.Type> x y))
(ADDshiftRLreg (MOVWconst [c]) x y) -> (ADDconst [c] (SRL <x.Type> x y))
(ADDshiftRAreg (MOVWconst [c]) x y) -> (ADDconst [c] (SRA <x.Type> x y))
(ADCshiftLLreg (MOVWconst [c]) x y flags) -> (ADCconst [c] (SLL <x.Type> x y) flags)
(ADCshiftRLreg (MOVWconst [c]) x y flags) -> (ADCconst [c] (SRL <x.Type> x y) flags)
(ADCshiftRAreg (MOVWconst [c]) x y flags) -> (ADCconst [c] (SRA <x.Type> x y) flags)
(ADDSshiftLLreg (MOVWconst [c]) x y) -> (ADDSconst [c] (SLL <x.Type> x y))
(ADDSshiftRLreg (MOVWconst [c]) x y) -> (ADDSconst [c] (SRL <x.Type> x y))
(ADDSshiftRAreg (MOVWconst [c]) x y) -> (ADDSconst [c] (SRA <x.Type> x y))
(SUBshiftLLreg (MOVWconst [c]) x y) -> (RSBconst [c] (SLL <x.Type> x y))
(SUBshiftRLreg (MOVWconst [c]) x y) -> (RSBconst [c] (SRL <x.Type> x y))
(SUBshiftRAreg (MOVWconst [c]) x y) -> (RSBconst [c] (SRA <x.Type> x y))
(SBCshiftLLreg (MOVWconst [c]) x y flags) -> (RSCconst [c] (SLL <x.Type> x y) flags)
(SBCshiftRLreg (MOVWconst [c]) x y flags) -> (RSCconst [c] (SRL <x.Type> x y) flags)
(SBCshiftRAreg (MOVWconst [c]) x y flags) -> (RSCconst [c] (SRA <x.Type> x y) flags)
(SUBSshiftLLreg (MOVWconst [c]) x y) -> (RSBSconst [c] (SLL <x.Type> x y))
(SUBSshiftRLreg (MOVWconst [c]) x y) -> (RSBSconst [c] (SRL <x.Type> x y))
(SUBSshiftRAreg (MOVWconst [c]) x y) -> (RSBSconst [c] (SRA <x.Type> x y))
(RSBshiftLLreg (MOVWconst [c]) x y) -> (SUBconst [c] (SLL <x.Type> x y))
(RSBshiftRLreg (MOVWconst [c]) x y) -> (SUBconst [c] (SRL <x.Type> x y))
(RSBshiftRAreg (MOVWconst [c]) x y) -> (SUBconst [c] (SRA <x.Type> x y))
(RSCshiftLLreg (MOVWconst [c]) x y flags) -> (SBCconst [c] (SLL <x.Type> x y) flags)
(RSCshiftRLreg (MOVWconst [c]) x y flags) -> (SBCconst [c] (SRL <x.Type> x y) flags)
(RSCshiftRAreg (MOVWconst [c]) x y flags) -> (SBCconst [c] (SRA <x.Type> x y) flags)
(RSBSshiftLLreg (MOVWconst [c]) x y) -> (SUBSconst [c] (SLL <x.Type> x y))
(RSBSshiftRLreg (MOVWconst [c]) x y) -> (SUBSconst [c] (SRL <x.Type> x y))
(RSBSshiftRAreg (MOVWconst [c]) x y) -> (SUBSconst [c] (SRA <x.Type> x y))
(ANDshiftLLreg (MOVWconst [c]) x y) -> (ANDconst [c] (SLL <x.Type> x y))
(ANDshiftRLreg (MOVWconst [c]) x y) -> (ANDconst [c] (SRL <x.Type> x y))
(ANDshiftRAreg (MOVWconst [c]) x y) -> (ANDconst [c] (SRA <x.Type> x y))
(ORshiftLLreg (MOVWconst [c]) x y) -> (ORconst [c] (SLL <x.Type> x y))
(ORshiftRLreg (MOVWconst [c]) x y) -> (ORconst [c] (SRL <x.Type> x y))
(ORshiftRAreg (MOVWconst [c]) x y) -> (ORconst [c] (SRA <x.Type> x y))
(XORshiftLLreg (MOVWconst [c]) x y) -> (XORconst [c] (SLL <x.Type> x y))
(XORshiftRLreg (MOVWconst [c]) x y) -> (XORconst [c] (SRL <x.Type> x y))
(XORshiftRAreg (MOVWconst [c]) x y) -> (XORconst [c] (SRA <x.Type> x y))
(CMPshiftLLreg (MOVWconst [c]) x y) -> (InvertFlags (CMPconst [c] (SLL <x.Type> x y)))
(CMPshiftRLreg (MOVWconst [c]) x y) -> (InvertFlags (CMPconst [c] (SRL <x.Type> x y)))
(CMPshiftRAreg (MOVWconst [c]) x y) -> (InvertFlags (CMPconst [c] (SRA <x.Type> x y)))
// constant folding in *shift ops
(ADDshiftLL x (MOVWconst [c]) [d]) -> (ADDconst x [int64(uint32(c)<<uint64(d))])
(ADDshiftRL x (MOVWconst [c]) [d]) -> (ADDconst x [int64(uint32(c)>>uint64(d))])
(ADDshiftRA x (MOVWconst [c]) [d]) -> (ADDconst x [int64(int32(c)>>uint64(d))])
(ADCshiftLL x (MOVWconst [c]) [d] flags) -> (ADCconst x [int64(uint32(c)<<uint64(d))] flags)
(ADCshiftRL x (MOVWconst [c]) [d] flags) -> (ADCconst x [int64(uint32(c)>>uint64(d))] flags)
(ADCshiftRA x (MOVWconst [c]) [d] flags) -> (ADCconst x [int64(int32(c)>>uint64(d))] flags)
(ADDSshiftLL x (MOVWconst [c]) [d]) -> (ADDSconst x [int64(uint32(c)<<uint64(d))])
(ADDSshiftRL x (MOVWconst [c]) [d]) -> (ADDSconst x [int64(uint32(c)>>uint64(d))])
(ADDSshiftRA x (MOVWconst [c]) [d]) -> (ADDSconst x [int64(int32(c)>>uint64(d))])
(SUBshiftLL x (MOVWconst [c]) [d]) -> (SUBconst x [int64(uint32(c)<<uint64(d))])
(SUBshiftRL x (MOVWconst [c]) [d]) -> (SUBconst x [int64(uint32(c)>>uint64(d))])
(SUBshiftRA x (MOVWconst [c]) [d]) -> (SUBconst x [int64(int32(c)>>uint64(d))])
(SBCshiftLL x (MOVWconst [c]) [d] flags) -> (SBCconst x [int64(uint32(c)<<uint64(d))] flags)
(SBCshiftRL x (MOVWconst [c]) [d] flags) -> (SBCconst x [int64(uint32(c)>>uint64(d))] flags)
(SBCshiftRA x (MOVWconst [c]) [d] flags) -> (SBCconst x [int64(int32(c)>>uint64(d))] flags)
(SUBSshiftLL x (MOVWconst [c]) [d]) -> (SUBSconst x [int64(uint32(c)<<uint64(d))])
(SUBSshiftRL x (MOVWconst [c]) [d]) -> (SUBSconst x [int64(uint32(c)>>uint64(d))])
(SUBSshiftRA x (MOVWconst [c]) [d]) -> (SUBSconst x [int64(int32(c)>>uint64(d))])
(RSBshiftLL x (MOVWconst [c]) [d]) -> (RSBconst x [int64(uint32(c)<<uint64(d))])
(RSBshiftRL x (MOVWconst [c]) [d]) -> (RSBconst x [int64(uint32(c)>>uint64(d))])
(RSBshiftRA x (MOVWconst [c]) [d]) -> (RSBconst x [int64(int32(c)>>uint64(d))])
(RSCshiftLL x (MOVWconst [c]) [d] flags) -> (RSCconst x [int64(uint32(c)<<uint64(d))] flags)
(RSCshiftRL x (MOVWconst [c]) [d] flags) -> (RSCconst x [int64(uint32(c)>>uint64(d))] flags)
(RSCshiftRA x (MOVWconst [c]) [d] flags) -> (RSCconst x [int64(int32(c)>>uint64(d))] flags)
(RSBSshiftLL x (MOVWconst [c]) [d]) -> (RSBSconst x [int64(uint32(c)<<uint64(d))])
(RSBSshiftRL x (MOVWconst [c]) [d]) -> (RSBSconst x [int64(uint32(c)>>uint64(d))])
(RSBSshiftRA x (MOVWconst [c]) [d]) -> (RSBSconst x [int64(int32(c)>>uint64(d))])
(ANDshiftLL x (MOVWconst [c]) [d]) -> (ANDconst x [int64(uint32(c)<<uint64(d))])
(ANDshiftRL x (MOVWconst [c]) [d]) -> (ANDconst x [int64(uint32(c)>>uint64(d))])
(ANDshiftRA x (MOVWconst [c]) [d]) -> (ANDconst x [int64(int32(c)>>uint64(d))])
(ORshiftLL x (MOVWconst [c]) [d]) -> (ORconst x [int64(uint32(c)<<uint64(d))])
(ORshiftRL x (MOVWconst [c]) [d]) -> (ORconst x [int64(uint32(c)>>uint64(d))])
(ORshiftRA x (MOVWconst [c]) [d]) -> (ORconst x [int64(int32(c)>>uint64(d))])
(XORshiftLL x (MOVWconst [c]) [d]) -> (XORconst x [int64(uint32(c)<<uint64(d))])
(XORshiftRL x (MOVWconst [c]) [d]) -> (XORconst x [int64(uint32(c)>>uint64(d))])
(XORshiftRA x (MOVWconst [c]) [d]) -> (XORconst x [int64(int32(c)>>uint64(d))])
(BICshiftLL x (MOVWconst [c]) [d]) -> (BICconst x [int64(uint32(c)<<uint64(d))])
(BICshiftRL x (MOVWconst [c]) [d]) -> (BICconst x [int64(uint32(c)>>uint64(d))])
(BICshiftRA x (MOVWconst [c]) [d]) -> (BICconst x [int64(int32(c)>>uint64(d))])
(MVNshiftLL (MOVWconst [c]) [d]) -> (MOVWconst [^int64(uint32(c)<<uint64(d))])
(MVNshiftRL (MOVWconst [c]) [d]) -> (MOVWconst [^int64(uint32(c)>>uint64(d))])
(MVNshiftRA (MOVWconst [c]) [d]) -> (MOVWconst [^int64(int32(c)>>uint64(d))])
(CMPshiftLL x (MOVWconst [c]) [d]) -> (CMPconst x [int64(uint32(c)<<uint64(d))])
(CMPshiftRL x (MOVWconst [c]) [d]) -> (CMPconst x [int64(uint32(c)>>uint64(d))])
(CMPshiftRA x (MOVWconst [c]) [d]) -> (CMPconst x [int64(int32(c)>>uint64(d))])
(ADDshiftLLreg x y (MOVWconst [c])) -> (ADDshiftLL x y [c])
(ADDshiftRLreg x y (MOVWconst [c])) -> (ADDshiftRL x y [c])
(ADDshiftRAreg x y (MOVWconst [c])) -> (ADDshiftRA x y [c])
(ADCshiftLLreg x y (MOVWconst [c]) flags) -> (ADCshiftLL x y [c] flags)
(ADCshiftRLreg x y (MOVWconst [c]) flags) -> (ADCshiftRL x y [c] flags)
(ADCshiftRAreg x y (MOVWconst [c]) flags) -> (ADCshiftRA x y [c] flags)
(ADDSshiftLLreg x y (MOVWconst [c])) -> (ADDSshiftLL x y [c])
(ADDSshiftRLreg x y (MOVWconst [c])) -> (ADDSshiftRL x y [c])
(ADDSshiftRAreg x y (MOVWconst [c])) -> (ADDSshiftRA x y [c])
(SUBshiftLLreg x y (MOVWconst [c])) -> (SUBshiftLL x y [c])
(SUBshiftRLreg x y (MOVWconst [c])) -> (SUBshiftRL x y [c])
(SUBshiftRAreg x y (MOVWconst [c])) -> (SUBshiftRA x y [c])
(SBCshiftLLreg x y (MOVWconst [c]) flags) -> (SBCshiftLL x y [c] flags)
(SBCshiftRLreg x y (MOVWconst [c]) flags) -> (SBCshiftRL x y [c] flags)
(SBCshiftRAreg x y (MOVWconst [c]) flags) -> (SBCshiftRA x y [c] flags)
(SUBSshiftLLreg x y (MOVWconst [c])) -> (SUBSshiftLL x y [c])
(SUBSshiftRLreg x y (MOVWconst [c])) -> (SUBSshiftRL x y [c])
(SUBSshiftRAreg x y (MOVWconst [c])) -> (SUBSshiftRA x y [c])
(RSBshiftLLreg x y (MOVWconst [c])) -> (RSBshiftLL x y [c])
(RSBshiftRLreg x y (MOVWconst [c])) -> (RSBshiftRL x y [c])
(RSBshiftRAreg x y (MOVWconst [c])) -> (RSBshiftRA x y [c])
(RSCshiftLLreg x y (MOVWconst [c]) flags) -> (RSCshiftLL x y [c] flags)
(RSCshiftRLreg x y (MOVWconst [c]) flags) -> (RSCshiftRL x y [c] flags)
(RSCshiftRAreg x y (MOVWconst [c]) flags) -> (RSCshiftRA x y [c] flags)
(RSBSshiftLLreg x y (MOVWconst [c])) -> (RSBSshiftLL x y [c])
(RSBSshiftRLreg x y (MOVWconst [c])) -> (RSBSshiftRL x y [c])
(RSBSshiftRAreg x y (MOVWconst [c])) -> (RSBSshiftRA x y [c])
(ANDshiftLLreg x y (MOVWconst [c])) -> (ANDshiftLL x y [c])
(ANDshiftRLreg x y (MOVWconst [c])) -> (ANDshiftRL x y [c])
(ANDshiftRAreg x y (MOVWconst [c])) -> (ANDshiftRA x y [c])
(ORshiftLLreg x y (MOVWconst [c])) -> (ORshiftLL x y [c])
(ORshiftRLreg x y (MOVWconst [c])) -> (ORshiftRL x y [c])
(ORshiftRAreg x y (MOVWconst [c])) -> (ORshiftRA x y [c])
(XORshiftLLreg x y (MOVWconst [c])) -> (XORshiftLL x y [c])
(XORshiftRLreg x y (MOVWconst [c])) -> (XORshiftRL x y [c])
(XORshiftRAreg x y (MOVWconst [c])) -> (XORshiftRA x y [c])
(BICshiftLLreg x y (MOVWconst [c])) -> (BICshiftLL x y [c])
(BICshiftRLreg x y (MOVWconst [c])) -> (BICshiftRL x y [c])
(BICshiftRAreg x y (MOVWconst [c])) -> (BICshiftRA x y [c])
(MVNshiftLLreg x (MOVWconst [c])) -> (MVNshiftLL x [c])
(MVNshiftRLreg x (MOVWconst [c])) -> (MVNshiftRL x [c])
(MVNshiftRAreg x (MOVWconst [c])) -> (MVNshiftRA x [c])
(CMPshiftLLreg x y (MOVWconst [c])) -> (CMPshiftLL x y [c])
(CMPshiftRLreg x y (MOVWconst [c])) -> (CMPshiftRL x y [c])
(CMPshiftRAreg x y (MOVWconst [c])) -> (CMPshiftRA x y [c])
// use indexed loads and stores
(MOVWload [0] {sym} (ADD ptr idx) mem) && sym == nil -> (MOVWloadidx ptr idx mem)
(MOVWstore [0] {sym} (ADD ptr idx) val mem) && sym == nil -> (MOVWstoreidx ptr idx val mem)
(MOVWload [0] {sym} (ADDshiftLL ptr idx [c]) mem) && sym == nil -> (MOVWloadshiftLL ptr idx [c] mem)
(MOVWload [0] {sym} (ADDshiftRL ptr idx [c]) mem) && sym == nil -> (MOVWloadshiftRL ptr idx [c] mem)
(MOVWload [0] {sym} (ADDshiftRA ptr idx [c]) mem) && sym == nil -> (MOVWloadshiftRA ptr idx [c] mem)
(MOVWstore [0] {sym} (ADDshiftLL ptr idx [c]) val mem) && sym == nil -> (MOVWstoreshiftLL ptr idx [c] val mem)
(MOVWstore [0] {sym} (ADDshiftRL ptr idx [c]) val mem) && sym == nil -> (MOVWstoreshiftRL ptr idx [c] val mem)
(MOVWstore [0] {sym} (ADDshiftRA ptr idx [c]) val mem) && sym == nil -> (MOVWstoreshiftRA ptr idx [c] val mem)
// constant folding in indexed loads and stores
(MOVWloadidx ptr (MOVWconst [c]) mem) -> (MOVWload [c] ptr mem)
(MOVWloadidx (MOVWconst [c]) ptr mem) -> (MOVWload [c] ptr mem)
(MOVWstoreidx ptr (MOVWconst [c]) val mem) -> (MOVWstore [c] ptr val mem)
(MOVWstoreidx (MOVWconst [c]) ptr val mem) -> (MOVWstore [c] ptr val mem)
(MOVWloadidx ptr (SLLconst idx [c]) mem) -> (MOVWloadshiftLL ptr idx [c] mem)
(MOVWloadidx (SLLconst idx [c]) ptr mem) -> (MOVWloadshiftLL ptr idx [c] mem)
(MOVWloadidx ptr (SRLconst idx [c]) mem) -> (MOVWloadshiftRL ptr idx [c] mem)
(MOVWloadidx (SRLconst idx [c]) ptr mem) -> (MOVWloadshiftRL ptr idx [c] mem)
(MOVWloadidx ptr (SRAconst idx [c]) mem) -> (MOVWloadshiftRA ptr idx [c] mem)
(MOVWloadidx (SRAconst idx [c]) ptr mem) -> (MOVWloadshiftRA ptr idx [c] mem)
(MOVWstoreidx ptr (SLLconst idx [c]) val mem) -> (MOVWstoreshiftLL ptr idx [c] val mem)
(MOVWstoreidx (SLLconst idx [c]) ptr val mem) -> (MOVWstoreshiftLL ptr idx [c] val mem)
(MOVWstoreidx ptr (SRLconst idx [c]) val mem) -> (MOVWstoreshiftRL ptr idx [c] val mem)
(MOVWstoreidx (SRLconst idx [c]) ptr val mem) -> (MOVWstoreshiftRL ptr idx [c] val mem)
(MOVWstoreidx ptr (SRAconst idx [c]) val mem) -> (MOVWstoreshiftRA ptr idx [c] val mem)
(MOVWstoreidx (SRAconst idx [c]) ptr val mem) -> (MOVWstoreshiftRA ptr idx [c] val mem)
(MOVWloadshiftLL ptr (MOVWconst [c]) [d] mem) -> (MOVWload [int64(uint32(c)<<uint64(d))] ptr mem)
(MOVWloadshiftRL ptr (MOVWconst [c]) [d] mem) -> (MOVWload [int64(uint32(c)>>uint64(d))] ptr mem)
(MOVWloadshiftRA ptr (MOVWconst [c]) [d] mem) -> (MOVWload [int64(int32(c)>>uint64(d))] ptr mem)
(MOVWstoreshiftLL ptr (MOVWconst [c]) [d] val mem) -> (MOVWstore [int64(uint32(c)<<uint64(d))] ptr val mem)
(MOVWstoreshiftRL ptr (MOVWconst [c]) [d] val mem) -> (MOVWstore [int64(uint32(c)>>uint64(d))] ptr val mem)
(MOVWstoreshiftRA ptr (MOVWconst [c]) [d] val mem) -> (MOVWstore [int64(int32(c)>>uint64(d))] ptr val mem)
// generic simplifications // generic simplifications
(ADD x (RSBconst [0] y)) -> (SUB x y) (ADD x (RSBconst [0] y)) -> (SUB x y)
(ADD (RSBconst [0] y) x) -> (SUB x y)
(SUB x x) -> (MOVWconst [0]) (SUB x x) -> (MOVWconst [0])
(RSB x x) -> (MOVWconst [0])
(AND x x) -> x (AND x x) -> x
(OR x x) -> x (OR x x) -> x
(XOR x x) -> (MOVWconst [0]) (XOR x x) -> (MOVWconst [0])
...@@ -754,3 +1180,26 @@ ...@@ -754,3 +1180,26 @@
(ADD a (MUL x y)) -> (MULA x y a) (ADD a (MUL x y)) -> (MULA x y a)
(AND x (MVN y)) -> (BIC x y) (AND x (MVN y)) -> (BIC x y)
// simplification with *shift ops
(SUBshiftLL x (SLLconst x [c]) [d]) && c==d -> (MOVWconst [0])
(SUBshiftRL x (SRLconst x [c]) [d]) && c==d -> (MOVWconst [0])
(SUBshiftRA x (SRAconst x [c]) [d]) && c==d -> (MOVWconst [0])
(RSBshiftLL x (SLLconst x [c]) [d]) && c==d -> (MOVWconst [0])
(RSBshiftRL x (SRLconst x [c]) [d]) && c==d -> (MOVWconst [0])
(RSBshiftRA x (SRAconst x [c]) [d]) && c==d -> (MOVWconst [0])
(ANDshiftLL x y:(SLLconst x [c]) [d]) && c==d -> y
(ANDshiftRL x y:(SRLconst x [c]) [d]) && c==d -> y
(ANDshiftRA x y:(SRAconst x [c]) [d]) && c==d -> y
(ORshiftLL x y:(SLLconst x [c]) [d]) && c==d -> y
(ORshiftRL x y:(SRLconst x [c]) [d]) && c==d -> y
(ORshiftRA x y:(SRAconst x [c]) [d]) && c==d -> y
(XORshiftLL x (SLLconst x [c]) [d]) && c==d -> (MOVWconst [0])
(XORshiftRL x (SRLconst x [c]) [d]) && c==d -> (MOVWconst [0])
(XORshiftRA x (SRAconst x [c]) [d]) && c==d -> (MOVWconst [0])
(BICshiftLL x (SLLconst x [c]) [d]) && c==d -> (MOVWconst [0])
(BICshiftRL x (SRLconst x [c]) [d]) && c==d -> (MOVWconst [0])
(BICshiftRA x (SRAconst x [c]) [d]) && c==d -> (MOVWconst [0])
(AND x (MVNshiftLL y [c])) -> (BICshiftLL x y [c])
(AND x (MVNshiftRL y [c])) -> (BICshiftRL x y [c])
(AND x (MVNshiftRA y [c])) -> (BICshiftRA x y [c])
...@@ -110,8 +110,13 @@ func init() { ...@@ -110,8 +110,13 @@ func init() {
gp2flags = regInfo{inputs: []regMask{gpg, gpg}, outputs: []regMask{flags}} gp2flags = regInfo{inputs: []regMask{gpg, gpg}, outputs: []regMask{flags}}
gp2flags1 = regInfo{inputs: []regMask{gp, gp, flags}, outputs: []regMask{gp}} gp2flags1 = regInfo{inputs: []regMask{gp, gp, flags}, outputs: []regMask{gp}}
gp31 = regInfo{inputs: []regMask{gp, gp, gp}, outputs: []regMask{gp}} gp31 = regInfo{inputs: []regMask{gp, gp, gp}, outputs: []regMask{gp}}
gp31cf = regInfo{inputs: []regMask{gp, gp, gp}, outputs: []regMask{gp}, clobbers: flags} // cf: clobbers flags
gp3flags = regInfo{inputs: []regMask{gp, gp, gp}, outputs: []regMask{flags}}
gp3flags1 = regInfo{inputs: []regMask{gp, gp, gp, flags}, outputs: []regMask{gp}}
gpload = regInfo{inputs: []regMask{gpspsbg}, outputs: []regMask{gp}} gpload = regInfo{inputs: []regMask{gpspsbg}, outputs: []regMask{gp}}
gpstore = regInfo{inputs: []regMask{gpspsbg, gpg}, outputs: []regMask{}} gpstore = regInfo{inputs: []regMask{gpspsbg, gpg}, outputs: []regMask{}}
gp2load = regInfo{inputs: []regMask{gpspsbg, gpg}, outputs: []regMask{gp}}
gp2store = regInfo{inputs: []regMask{gpspsbg, gpg, gpg}, outputs: []regMask{}}
fp01 = regInfo{inputs: []regMask{}, outputs: []regMask{fp}} fp01 = regInfo{inputs: []regMask{}, outputs: []regMask{fp}}
fp11 = regInfo{inputs: []regMask{fp}, outputs: []regMask{fp}} fp11 = regInfo{inputs: []regMask{fp}, outputs: []regMask{fp}}
fpgp = regInfo{inputs: []regMask{fp}, outputs: []regMask{gp}} fpgp = regInfo{inputs: []regMask{fp}, outputs: []regMask{gp}}
...@@ -176,14 +181,105 @@ func init() { ...@@ -176,14 +181,105 @@ func init() {
{name: "SQRTD", argLength: 1, reg: fp11, asm: "SQRTD"}, // sqrt(arg0), float64 {name: "SQRTD", argLength: 1, reg: fp11, asm: "SQRTD"}, // sqrt(arg0), float64
// shifts // shifts
{name: "SLL", argLength: 2, reg: gp21cf, asm: "SLL"}, // arg0 << arg1, results 0 for large shift {name: "SLL", argLength: 2, reg: gp21, asm: "SLL"}, // arg0 << arg1, shift amount is mod 256
{name: "SLLconst", argLength: 1, reg: gp11, asm: "SLL", aux: "Int32"}, // arg0 << auxInt {name: "SLLconst", argLength: 1, reg: gp11, asm: "SLL", aux: "Int32"}, // arg0 << auxInt
{name: "SRL", argLength: 2, reg: gp21cf, asm: "SRL"}, // arg0 >> arg1, unsigned, results 0 for large shift {name: "SRL", argLength: 2, reg: gp21, asm: "SRL"}, // arg0 >> arg1, unsigned, shift amount is mod 256
{name: "SRLconst", argLength: 1, reg: gp11, asm: "SRL", aux: "Int32"}, // arg0 >> auxInt, unsigned {name: "SRLconst", argLength: 1, reg: gp11, asm: "SRL", aux: "Int32"}, // arg0 >> auxInt, unsigned
{name: "SRA", argLength: 2, reg: gp21cf, asm: "SRA"}, // arg0 >> arg1, signed, results 0/-1 for large shift {name: "SRA", argLength: 2, reg: gp21cf, asm: "SRA"}, // arg0 >> arg1, signed, shift amount is mod 256
{name: "SRAconst", argLength: 1, reg: gp11, asm: "SRA", aux: "Int32"}, // arg0 >> auxInt, signed {name: "SRAconst", argLength: 1, reg: gp11, asm: "SRA", aux: "Int32"}, // arg0 >> auxInt, signed
{name: "SRRconst", argLength: 1, reg: gp11, aux: "Int32"}, // arg0 right rotate by auxInt bits {name: "SRRconst", argLength: 1, reg: gp11, aux: "Int32"}, // arg0 right rotate by auxInt bits
{name: "ADDshiftLL", argLength: 2, reg: gp21, asm: "ADD", aux: "Int32"}, // arg0 + arg1<<auxInt
{name: "ADDshiftRL", argLength: 2, reg: gp21, asm: "ADD", aux: "Int32"}, // arg0 + arg1>>auxInt, unsigned shift
{name: "ADDshiftRA", argLength: 2, reg: gp21, asm: "ADD", aux: "Int32"}, // arg0 + arg1>>auxInt, signed shift
{name: "SUBshiftLL", argLength: 2, reg: gp21, asm: "SUB", aux: "Int32"}, // arg0 - arg1<<auxInt
{name: "SUBshiftRL", argLength: 2, reg: gp21, asm: "SUB", aux: "Int32"}, // arg0 - arg1>>auxInt, unsigned shift
{name: "SUBshiftRA", argLength: 2, reg: gp21, asm: "SUB", aux: "Int32"}, // arg0 - arg1>>auxInt, signed shift
{name: "RSBshiftLL", argLength: 2, reg: gp21, asm: "RSB", aux: "Int32"}, // arg1<<auxInt - arg0
{name: "RSBshiftRL", argLength: 2, reg: gp21, asm: "RSB", aux: "Int32"}, // arg1>>auxInt - arg0, unsigned shift
{name: "RSBshiftRA", argLength: 2, reg: gp21, asm: "RSB", aux: "Int32"}, // arg1>>auxInt - arg0, signed shift
{name: "ANDshiftLL", argLength: 2, reg: gp21, asm: "AND", aux: "Int32"}, // arg0 & (arg1<<auxInt)
{name: "ANDshiftRL", argLength: 2, reg: gp21, asm: "AND", aux: "Int32"}, // arg0 & (arg1>>auxInt), unsigned shift
{name: "ANDshiftRA", argLength: 2, reg: gp21, asm: "AND", aux: "Int32"}, // arg0 & (arg1>>auxInt), signed shift
{name: "ORshiftLL", argLength: 2, reg: gp21, asm: "ORR", aux: "Int32"}, // arg0 | arg1<<auxInt
{name: "ORshiftRL", argLength: 2, reg: gp21, asm: "ORR", aux: "Int32"}, // arg0 | arg1>>auxInt, unsigned shift
{name: "ORshiftRA", argLength: 2, reg: gp21, asm: "ORR", aux: "Int32"}, // arg0 | arg1>>auxInt, signed shift
{name: "XORshiftLL", argLength: 2, reg: gp21, asm: "EOR", aux: "Int32"}, // arg0 ^ arg1<<auxInt
{name: "XORshiftRL", argLength: 2, reg: gp21, asm: "EOR", aux: "Int32"}, // arg0 ^ arg1>>auxInt, unsigned shift
{name: "XORshiftRA", argLength: 2, reg: gp21, asm: "EOR", aux: "Int32"}, // arg0 ^ arg1>>auxInt, signed shift
{name: "BICshiftLL", argLength: 2, reg: gp21, asm: "BIC", aux: "Int32"}, // arg0 &^ (arg1<<auxInt)
{name: "BICshiftRL", argLength: 2, reg: gp21, asm: "BIC", aux: "Int32"}, // arg0 &^ (arg1>>auxInt), unsigned shift
{name: "BICshiftRA", argLength: 2, reg: gp21, asm: "BIC", aux: "Int32"}, // arg0 &^ (arg1>>auxInt), signed shift
{name: "MVNshiftLL", argLength: 1, reg: gp11, asm: "MVN", aux: "Int32"}, // ^(arg0<<auxInt)
{name: "MVNshiftRL", argLength: 1, reg: gp11, asm: "MVN", aux: "Int32"}, // ^(arg0>>auxInt), unsigned shift
{name: "MVNshiftRA", argLength: 1, reg: gp11, asm: "MVN", aux: "Int32"}, // ^(arg0>>auxInt), signed shift
{name: "ADCshiftLL", argLength: 3, reg: gp2flags1, asm: "ADC", aux: "Int32"}, // arg0 + arg1<<auxInt + carry, arg2=flags
{name: "ADCshiftRL", argLength: 3, reg: gp2flags1, asm: "ADC", aux: "Int32"}, // arg0 + arg1>>auxInt + carry, unsigned shift, arg2=flags
{name: "ADCshiftRA", argLength: 3, reg: gp2flags1, asm: "ADC", aux: "Int32"}, // arg0 + arg1>>auxInt + carry, signed shift, arg2=flags
{name: "SBCshiftLL", argLength: 3, reg: gp2flags1, asm: "SBC", aux: "Int32"}, // arg0 - arg1<<auxInt - carry, arg2=flags
{name: "SBCshiftRL", argLength: 3, reg: gp2flags1, asm: "SBC", aux: "Int32"}, // arg0 - arg1>>auxInt - carry, unsigned shift, arg2=flags
{name: "SBCshiftRA", argLength: 3, reg: gp2flags1, asm: "SBC", aux: "Int32"}, // arg0 - arg1>>auxInt - carry, signed shift, arg2=flags
{name: "RSCshiftLL", argLength: 3, reg: gp2flags1, asm: "RSC", aux: "Int32"}, // arg1<<auxInt - arg0 - carry, arg2=flags
{name: "RSCshiftRL", argLength: 3, reg: gp2flags1, asm: "RSC", aux: "Int32"}, // arg1>>auxInt - arg0 - carry, unsigned shift, arg2=flags
{name: "RSCshiftRA", argLength: 3, reg: gp2flags1, asm: "RSC", aux: "Int32"}, // arg1>>auxInt - arg0 - carry, signed shift, arg2=flags
{name: "ADDSshiftLL", argLength: 2, reg: gp21cf, asm: "ADD", aux: "Int32"}, // arg0 + arg1<<auxInt, set carry flag
{name: "ADDSshiftRL", argLength: 2, reg: gp21cf, asm: "ADD", aux: "Int32"}, // arg0 + arg1>>auxInt, unsigned shift, set carry flag
{name: "ADDSshiftRA", argLength: 2, reg: gp21cf, asm: "ADD", aux: "Int32"}, // arg0 + arg1>>auxInt, signed shift, set carry flag
{name: "SUBSshiftLL", argLength: 2, reg: gp21cf, asm: "SUB", aux: "Int32"}, // arg0 - arg1<<auxInt, set carry flag
{name: "SUBSshiftRL", argLength: 2, reg: gp21cf, asm: "SUB", aux: "Int32"}, // arg0 - arg1>>auxInt, unsigned shift, set carry flag
{name: "SUBSshiftRA", argLength: 2, reg: gp21cf, asm: "SUB", aux: "Int32"}, // arg0 - arg1>>auxInt, signed shift, set carry flag
{name: "RSBSshiftLL", argLength: 2, reg: gp21cf, asm: "RSB", aux: "Int32"}, // arg1<<auxInt - arg0, set carry flag
{name: "RSBSshiftRL", argLength: 2, reg: gp21cf, asm: "RSB", aux: "Int32"}, // arg1>>auxInt - arg0, unsigned shift, set carry flag
{name: "RSBSshiftRA", argLength: 2, reg: gp21cf, asm: "RSB", aux: "Int32"}, // arg1>>auxInt - arg0, signed shift, set carry flag
{name: "ADDshiftLLreg", argLength: 3, reg: gp31, asm: "ADD"}, // arg0 + arg1<<arg2
{name: "ADDshiftRLreg", argLength: 3, reg: gp31, asm: "ADD"}, // arg0 + arg1>>arg2, unsigned shift
{name: "ADDshiftRAreg", argLength: 3, reg: gp31, asm: "ADD"}, // arg0 + arg1>>arg2, signed shift
{name: "SUBshiftLLreg", argLength: 3, reg: gp31, asm: "SUB"}, // arg0 - arg1<<arg2
{name: "SUBshiftRLreg", argLength: 3, reg: gp31, asm: "SUB"}, // arg0 - arg1>>arg2, unsigned shift
{name: "SUBshiftRAreg", argLength: 3, reg: gp31, asm: "SUB"}, // arg0 - arg1>>arg2, signed shift
{name: "RSBshiftLLreg", argLength: 3, reg: gp31, asm: "RSB"}, // arg1<<arg2 - arg0
{name: "RSBshiftRLreg", argLength: 3, reg: gp31, asm: "RSB"}, // arg1>>arg2 - arg0, unsigned shift
{name: "RSBshiftRAreg", argLength: 3, reg: gp31, asm: "RSB"}, // arg1>>arg2 - arg0, signed shift
{name: "ANDshiftLLreg", argLength: 3, reg: gp31, asm: "AND"}, // arg0 & (arg1<<arg2)
{name: "ANDshiftRLreg", argLength: 3, reg: gp31, asm: "AND"}, // arg0 & (arg1>>arg2), unsigned shift
{name: "ANDshiftRAreg", argLength: 3, reg: gp31, asm: "AND"}, // arg0 & (arg1>>arg2), signed shift
{name: "ORshiftLLreg", argLength: 3, reg: gp31, asm: "ORR"}, // arg0 | arg1<<arg2
{name: "ORshiftRLreg", argLength: 3, reg: gp31, asm: "ORR"}, // arg0 | arg1>>arg2, unsigned shift
{name: "ORshiftRAreg", argLength: 3, reg: gp31, asm: "ORR"}, // arg0 | arg1>>arg2, signed shift
{name: "XORshiftLLreg", argLength: 3, reg: gp31, asm: "EOR"}, // arg0 ^ arg1<<arg2
{name: "XORshiftRLreg", argLength: 3, reg: gp31, asm: "EOR"}, // arg0 ^ arg1>>arg2, unsigned shift
{name: "XORshiftRAreg", argLength: 3, reg: gp31, asm: "EOR"}, // arg0 ^ arg1>>arg2, signed shift
{name: "BICshiftLLreg", argLength: 3, reg: gp31, asm: "BIC"}, // arg0 &^ (arg1<<arg2)
{name: "BICshiftRLreg", argLength: 3, reg: gp31, asm: "BIC"}, // arg0 &^ (arg1>>arg2), unsigned shift
{name: "BICshiftRAreg", argLength: 3, reg: gp31, asm: "BIC"}, // arg0 &^ (arg1>>arg2), signed shift
{name: "MVNshiftLLreg", argLength: 2, reg: gp21, asm: "MVN"}, // ^(arg0<<arg1)
{name: "MVNshiftRLreg", argLength: 2, reg: gp21, asm: "MVN"}, // ^(arg0>>arg1), unsigned shift
{name: "MVNshiftRAreg", argLength: 2, reg: gp21, asm: "MVN"}, // ^(arg0>>arg1), signed shift
{name: "ADCshiftLLreg", argLength: 4, reg: gp3flags1, asm: "ADC"}, // arg0 + arg1<<arg2 + carry, arg3=flags
{name: "ADCshiftRLreg", argLength: 4, reg: gp3flags1, asm: "ADC"}, // arg0 + arg1>>arg2 + carry, unsigned shift, arg3=flags
{name: "ADCshiftRAreg", argLength: 4, reg: gp3flags1, asm: "ADC"}, // arg0 + arg1>>arg2 + carry, signed shift, arg3=flags
{name: "SBCshiftLLreg", argLength: 4, reg: gp3flags1, asm: "SBC"}, // arg0 - arg1<<arg2 - carry, arg3=flags
{name: "SBCshiftRLreg", argLength: 4, reg: gp3flags1, asm: "SBC"}, // arg0 - arg1>>arg2 - carry, unsigned shift, arg3=flags
{name: "SBCshiftRAreg", argLength: 4, reg: gp3flags1, asm: "SBC"}, // arg0 - arg1>>arg2 - carry, signed shift, arg3=flags
{name: "RSCshiftLLreg", argLength: 4, reg: gp3flags1, asm: "RSC"}, // arg1<<arg2 - arg0 - carry, arg3=flags
{name: "RSCshiftRLreg", argLength: 4, reg: gp3flags1, asm: "RSC"}, // arg1>>arg2 - arg0 - carry, unsigned shift, arg3=flags
{name: "RSCshiftRAreg", argLength: 4, reg: gp3flags1, asm: "RSC"}, // arg1>>arg2 - arg0 - carry, signed shift, arg3=flags
{name: "ADDSshiftLLreg", argLength: 3, reg: gp31cf, asm: "ADD"}, // arg0 + arg1<<arg2, set carry flag
{name: "ADDSshiftRLreg", argLength: 3, reg: gp31cf, asm: "ADD"}, // arg0 + arg1>>arg2, unsigned shift, set carry flag
{name: "ADDSshiftRAreg", argLength: 3, reg: gp31cf, asm: "ADD"}, // arg0 + arg1>>arg2, signed shift, set carry flag
{name: "SUBSshiftLLreg", argLength: 3, reg: gp31cf, asm: "SUB"}, // arg0 - arg1<<arg2, set carry flag
{name: "SUBSshiftRLreg", argLength: 3, reg: gp31cf, asm: "SUB"}, // arg0 - arg1>>arg2, unsigned shift, set carry flag
{name: "SUBSshiftRAreg", argLength: 3, reg: gp31cf, asm: "SUB"}, // arg0 - arg1>>arg2, signed shift, set carry flag
{name: "RSBSshiftLLreg", argLength: 3, reg: gp31cf, asm: "RSB"}, // arg1<<arg2 - arg0, set carry flag
{name: "RSBSshiftRLreg", argLength: 3, reg: gp31cf, asm: "RSB"}, // arg1>>arg2 - arg0, unsigned shift, set carry flag
{name: "RSBSshiftRAreg", argLength: 3, reg: gp31cf, asm: "RSB"}, // arg1>>arg2 - arg0, signed shift, set carry flag
// comparisons
{name: "CMP", argLength: 2, reg: gp2flags, asm: "CMP", typ: "Flags"}, // arg0 compare to arg1 {name: "CMP", argLength: 2, reg: gp2flags, asm: "CMP", typ: "Flags"}, // arg0 compare to arg1
{name: "CMPconst", argLength: 1, reg: gp1flags, asm: "CMP", aux: "Int32", typ: "Flags"}, // arg0 compare to auxInt {name: "CMPconst", argLength: 1, reg: gp1flags, asm: "CMP", aux: "Int32", typ: "Flags"}, // arg0 compare to auxInt
{name: "CMN", argLength: 2, reg: gp2flags, asm: "CMN", typ: "Flags"}, // arg0 compare to -arg1 {name: "CMN", argLength: 2, reg: gp2flags, asm: "CMN", typ: "Flags"}, // arg0 compare to -arg1
...@@ -195,6 +291,15 @@ func init() { ...@@ -195,6 +291,15 @@ func init() {
{name: "CMPF", argLength: 2, reg: fp2flags, asm: "CMPF", typ: "Flags"}, // arg0 compare to arg1, float32 {name: "CMPF", argLength: 2, reg: fp2flags, asm: "CMPF", typ: "Flags"}, // arg0 compare to arg1, float32
{name: "CMPD", argLength: 2, reg: fp2flags, asm: "CMPD", typ: "Flags"}, // arg0 compare to arg1, float64 {name: "CMPD", argLength: 2, reg: fp2flags, asm: "CMPD", typ: "Flags"}, // arg0 compare to arg1, float64
{name: "CMPshiftLL", argLength: 2, reg: gp2flags, asm: "CMP", aux: "Int32", typ: "Flags"}, // arg0 compare to arg1<<auxInt
{name: "CMPshiftRL", argLength: 2, reg: gp2flags, asm: "CMP", aux: "Int32", typ: "Flags"}, // arg0 compare to arg1>>auxInt, unsigned shift
{name: "CMPshiftRA", argLength: 2, reg: gp2flags, asm: "CMP", aux: "Int32", typ: "Flags"}, // arg0 compare to arg1>>auxInt, signed shift
{name: "CMPshiftLLreg", argLength: 3, reg: gp3flags, asm: "CMP", typ: "Flags"}, // arg0 compare to arg1<<arg2
{name: "CMPshiftRLreg", argLength: 3, reg: gp3flags, asm: "CMP", typ: "Flags"}, // arg0 compare to arg1>>arg2, unsigned shift
{name: "CMPshiftRAreg", argLength: 3, reg: gp3flags, asm: "CMP", typ: "Flags"}, // arg0 compare to arg1>>arg2, signed shift
// moves
{name: "MOVWconst", argLength: 0, reg: gp01, aux: "Int32", asm: "MOVW", typ: "UInt32", rematerializeable: true}, // 32 low bits of auxint {name: "MOVWconst", argLength: 0, reg: gp01, aux: "Int32", asm: "MOVW", typ: "UInt32", rematerializeable: true}, // 32 low bits of auxint
{name: "MOVFconst", argLength: 0, reg: fp01, aux: "Float64", asm: "MOVF", typ: "Float32", rematerializeable: true}, // auxint as 64-bit float, convert to 32-bit float {name: "MOVFconst", argLength: 0, reg: fp01, aux: "Float64", asm: "MOVF", typ: "Float32", rematerializeable: true}, // auxint as 64-bit float, convert to 32-bit float
{name: "MOVDconst", argLength: 0, reg: fp01, aux: "Float64", asm: "MOVD", typ: "Float64", rematerializeable: true}, // auxint as 64-bit float {name: "MOVDconst", argLength: 0, reg: fp01, aux: "Float64", asm: "MOVD", typ: "Float64", rematerializeable: true}, // auxint as 64-bit float
...@@ -215,6 +320,16 @@ func init() { ...@@ -215,6 +320,16 @@ func init() {
{name: "MOVFstore", argLength: 3, reg: fpstore, aux: "SymOff", asm: "MOVF", typ: "Mem"}, // store 4 bytes of arg1 to arg0 + auxInt + aux. arg2=mem. {name: "MOVFstore", argLength: 3, reg: fpstore, aux: "SymOff", asm: "MOVF", typ: "Mem"}, // store 4 bytes of arg1 to arg0 + auxInt + aux. arg2=mem.
{name: "MOVDstore", argLength: 3, reg: fpstore, aux: "SymOff", asm: "MOVD", typ: "Mem"}, // store 8 bytes of arg1 to arg0 + auxInt + aux. arg2=mem. {name: "MOVDstore", argLength: 3, reg: fpstore, aux: "SymOff", asm: "MOVD", typ: "Mem"}, // store 8 bytes of arg1 to arg0 + auxInt + aux. arg2=mem.
{name: "MOVWloadidx", argLength: 3, reg: gp2load, asm: "MOVW"}, // load from arg0 + arg1. arg2=mem
{name: "MOVWloadshiftLL", argLength: 3, reg: gp2load, asm: "MOVW", aux: "Int32"}, // load from arg0 + arg1<<auxInt. arg2=mem
{name: "MOVWloadshiftRL", argLength: 3, reg: gp2load, asm: "MOVW", aux: "Int32"}, // load from arg0 + arg1>>auxInt, unsigned shift. arg2=mem
{name: "MOVWloadshiftRA", argLength: 3, reg: gp2load, asm: "MOVW", aux: "Int32"}, // load from arg0 + arg1>>auxInt, signed shift. arg2=mem
{name: "MOVWstoreidx", argLength: 4, reg: gp2store, asm: "MOVW"}, // store arg2 to arg0 + arg1. arg3=mem
{name: "MOVWstoreshiftLL", argLength: 4, reg: gp2store, asm: "MOVW", aux: "Int32"}, // store arg2 to arg0 + arg1<<auxInt. arg3=mem
{name: "MOVWstoreshiftRL", argLength: 4, reg: gp2store, asm: "MOVW", aux: "Int32"}, // store arg2 to arg0 + arg1>>auxInt, unsigned shift. arg3=mem
{name: "MOVWstoreshiftRA", argLength: 4, reg: gp2store, asm: "MOVW", aux: "Int32"}, // store arg2 to arg0 + arg1>>auxInt, signed shift. arg3=mem
{name: "MOVBreg", argLength: 1, reg: gp11, asm: "MOVBS"}, // move from arg0, sign-extended from byte {name: "MOVBreg", argLength: 1, reg: gp11, asm: "MOVBS"}, // move from arg0, sign-extended from byte
{name: "MOVBUreg", argLength: 1, reg: gp11, asm: "MOVBU"}, // move from arg0, unsign-extended from byte {name: "MOVBUreg", argLength: 1, reg: gp11, asm: "MOVBU"}, // move from arg0, unsign-extended from byte
{name: "MOVHreg", argLength: 1, reg: gp11, asm: "MOVHS"}, // move from arg0, sign-extended from half {name: "MOVHreg", argLength: 1, reg: gp11, asm: "MOVHS"}, // move from arg0, sign-extended from half
...@@ -232,6 +347,12 @@ func init() { ...@@ -232,6 +347,12 @@ func init() {
{name: "MOVFD", argLength: 1, reg: fp11, asm: "MOVFD"}, // float32 -> float64 {name: "MOVFD", argLength: 1, reg: fp11, asm: "MOVFD"}, // float32 -> float64
{name: "MOVDF", argLength: 1, reg: fp11, asm: "MOVDF"}, // float64 -> float32 {name: "MOVDF", argLength: 1, reg: fp11, asm: "MOVDF"}, // float64 -> float32
// conditional instructions, for lowering shifts
{name: "CMOVWHSconst", argLength: 2, reg: gp1flags1, asm: "MOVW", aux: "Int32", resultInArg0: true}, // replace arg0 w/ const if flags indicates HS, arg1=flags
{name: "CMOVWLSconst", argLength: 2, reg: gp1flags1, asm: "MOVW", aux: "Int32", resultInArg0: true}, // replace arg0 w/ const if flags indicates LS, arg1=flags
{name: "SRAcond", argLength: 3, reg: gp2flags1, asm: "SRA"}, // arg0 >> 31 if flags indicates HS, arg0 >> arg1 otherwise, signed shift, arg2=flags
// function calls
{name: "CALLstatic", argLength: 1, reg: regInfo{clobbers: callerSave}, aux: "SymOff"}, // call static function aux.(*gc.Sym). arg0=mem, auxint=argsize, returns mem {name: "CALLstatic", argLength: 1, reg: regInfo{clobbers: callerSave}, aux: "SymOff"}, // call static function aux.(*gc.Sym). arg0=mem, auxint=argsize, returns mem
{name: "CALLclosure", argLength: 3, reg: regInfo{inputs: []regMask{gpsp, buildReg("R7"), 0}, clobbers: callerSave}, aux: "Int64"}, // call function via closure. arg0=codeptr, arg1=closure, arg2=mem, auxint=argsize, returns mem {name: "CALLclosure", argLength: 3, reg: regInfo{inputs: []regMask{gpsp, buildReg("R7"), 0}, clobbers: callerSave}, aux: "Int64"}, // call function via closure. arg0=codeptr, arg1=closure, arg2=mem, auxint=argsize, returns mem
{name: "CALLdefer", argLength: 1, reg: regInfo{clobbers: callerSave}, aux: "Int64"}, // call deferproc. arg0=mem, auxint=argsize, returns mem {name: "CALLdefer", argLength: 1, reg: regInfo{clobbers: callerSave}, aux: "Int64"}, // call deferproc. arg0=mem, auxint=argsize, returns mem
...@@ -256,8 +377,6 @@ func init() { ...@@ -256,8 +377,6 @@ func init() {
{name: "LoweredSelect0", argLength: 1, reg: regInfo{inputs: []regMask{}, outputs: []regMask{buildReg("R0")}}}, // the first component of a tuple, implicitly in R0, arg0=tuple {name: "LoweredSelect0", argLength: 1, reg: regInfo{inputs: []regMask{}, outputs: []regMask{buildReg("R0")}}}, // the first component of a tuple, implicitly in R0, arg0=tuple
{name: "LoweredSelect1", argLength: 1, reg: regInfo{inputs: []regMask{gp}, outputs: []regMask{gp}}, resultInArg0: true}, // the second component of a tuple, arg0=tuple {name: "LoweredSelect1", argLength: 1, reg: regInfo{inputs: []regMask{gp}, outputs: []regMask{gp}}, resultInArg0: true}, // the second component of a tuple, arg0=tuple
{name: "LoweredZeromask", argLength: 1, reg: gp11}, // 0 if arg0 == 1, 0xffffffff if arg0 != 0
// duffzero (must be 4-byte aligned) // duffzero (must be 4-byte aligned)
// arg0 = address of memory to zero (in R1, changed as side effect) // arg0 = address of memory to zero (in R1, changed as side effect)
// arg1 = value to store (always zero) // arg1 = value to store (always zero)
......
...@@ -157,7 +157,13 @@ func (op Op) isTupleGenerator() bool { ...@@ -157,7 +157,13 @@ func (op Op) isTupleGenerator() bool {
switch op { switch op {
case OpAdd32carry, OpSub32carry, OpMul32uhilo, case OpAdd32carry, OpSub32carry, OpMul32uhilo,
OpARMADDS, OpARMSUBS, OpARMMULLU, OpARMADDS, OpARMSUBS, OpARMMULLU,
OpARMADDSconst, OpARMSUBSconst, OpARMRSBSconst: OpARMADDSconst, OpARMSUBSconst, OpARMRSBSconst,
OpARMADDSshiftLL, OpARMSUBSshiftLL, OpARMRSBSshiftLL,
OpARMADDSshiftRL, OpARMSUBSshiftRL, OpARMRSBSshiftRL,
OpARMADDSshiftRA, OpARMSUBSshiftRA, OpARMRSBSshiftRA,
OpARMADDSshiftLLreg, OpARMSUBSshiftLLreg, OpARMRSBSshiftLLreg,
OpARMADDSshiftRLreg, OpARMSUBSshiftRLreg, OpARMRSBSshiftRLreg,
OpARMADDSshiftRAreg, OpARMSUBSshiftRAreg, OpARMRSBSshiftRAreg:
return true return true
} }
return false return false
......
...@@ -596,6 +596,90 @@ const ( ...@@ -596,6 +596,90 @@ const (
OpARMSRA OpARMSRA
OpARMSRAconst OpARMSRAconst
OpARMSRRconst OpARMSRRconst
OpARMADDshiftLL
OpARMADDshiftRL
OpARMADDshiftRA
OpARMSUBshiftLL
OpARMSUBshiftRL
OpARMSUBshiftRA
OpARMRSBshiftLL
OpARMRSBshiftRL
OpARMRSBshiftRA
OpARMANDshiftLL
OpARMANDshiftRL
OpARMANDshiftRA
OpARMORshiftLL
OpARMORshiftRL
OpARMORshiftRA
OpARMXORshiftLL
OpARMXORshiftRL
OpARMXORshiftRA
OpARMBICshiftLL
OpARMBICshiftRL
OpARMBICshiftRA
OpARMMVNshiftLL
OpARMMVNshiftRL
OpARMMVNshiftRA
OpARMADCshiftLL
OpARMADCshiftRL
OpARMADCshiftRA
OpARMSBCshiftLL
OpARMSBCshiftRL
OpARMSBCshiftRA
OpARMRSCshiftLL
OpARMRSCshiftRL
OpARMRSCshiftRA
OpARMADDSshiftLL
OpARMADDSshiftRL
OpARMADDSshiftRA
OpARMSUBSshiftLL
OpARMSUBSshiftRL
OpARMSUBSshiftRA
OpARMRSBSshiftLL
OpARMRSBSshiftRL
OpARMRSBSshiftRA
OpARMADDshiftLLreg
OpARMADDshiftRLreg
OpARMADDshiftRAreg
OpARMSUBshiftLLreg
OpARMSUBshiftRLreg
OpARMSUBshiftRAreg
OpARMRSBshiftLLreg
OpARMRSBshiftRLreg
OpARMRSBshiftRAreg
OpARMANDshiftLLreg
OpARMANDshiftRLreg
OpARMANDshiftRAreg
OpARMORshiftLLreg
OpARMORshiftRLreg
OpARMORshiftRAreg
OpARMXORshiftLLreg
OpARMXORshiftRLreg
OpARMXORshiftRAreg
OpARMBICshiftLLreg
OpARMBICshiftRLreg
OpARMBICshiftRAreg
OpARMMVNshiftLLreg
OpARMMVNshiftRLreg
OpARMMVNshiftRAreg
OpARMADCshiftLLreg
OpARMADCshiftRLreg
OpARMADCshiftRAreg
OpARMSBCshiftLLreg
OpARMSBCshiftRLreg
OpARMSBCshiftRAreg
OpARMRSCshiftLLreg
OpARMRSCshiftRLreg
OpARMRSCshiftRAreg
OpARMADDSshiftLLreg
OpARMADDSshiftRLreg
OpARMADDSshiftRAreg
OpARMSUBSshiftLLreg
OpARMSUBSshiftRLreg
OpARMSUBSshiftRAreg
OpARMRSBSshiftLLreg
OpARMRSBSshiftRLreg
OpARMRSBSshiftRAreg
OpARMCMP OpARMCMP
OpARMCMPconst OpARMCMPconst
OpARMCMN OpARMCMN
...@@ -606,6 +690,12 @@ const ( ...@@ -606,6 +690,12 @@ const (
OpARMTEQconst OpARMTEQconst
OpARMCMPF OpARMCMPF
OpARMCMPD OpARMCMPD
OpARMCMPshiftLL
OpARMCMPshiftRL
OpARMCMPshiftRA
OpARMCMPshiftLLreg
OpARMCMPshiftRLreg
OpARMCMPshiftRAreg
OpARMMOVWconst OpARMMOVWconst
OpARMMOVFconst OpARMMOVFconst
OpARMMOVDconst OpARMMOVDconst
...@@ -622,6 +712,14 @@ const ( ...@@ -622,6 +712,14 @@ const (
OpARMMOVWstore OpARMMOVWstore
OpARMMOVFstore OpARMMOVFstore
OpARMMOVDstore OpARMMOVDstore
OpARMMOVWloadidx
OpARMMOVWloadshiftLL
OpARMMOVWloadshiftRL
OpARMMOVWloadshiftRA
OpARMMOVWstoreidx
OpARMMOVWstoreshiftLL
OpARMMOVWstoreshiftRL
OpARMMOVWstoreshiftRA
OpARMMOVBreg OpARMMOVBreg
OpARMMOVBUreg OpARMMOVBUreg
OpARMMOVHreg OpARMMOVHreg
...@@ -637,6 +735,9 @@ const ( ...@@ -637,6 +735,9 @@ const (
OpARMMOVDWU OpARMMOVDWU
OpARMMOVFD OpARMMOVFD
OpARMMOVDF OpARMMOVDF
OpARMCMOVWHSconst
OpARMCMOVWLSconst
OpARMSRAcond
OpARMCALLstatic OpARMCALLstatic
OpARMCALLclosure OpARMCALLclosure
OpARMCALLdefer OpARMCALLdefer
...@@ -656,7 +757,6 @@ const ( ...@@ -656,7 +757,6 @@ const (
OpARMCarry OpARMCarry
OpARMLoweredSelect0 OpARMLoweredSelect0
OpARMLoweredSelect1 OpARMLoweredSelect1
OpARMLoweredZeromask
OpARMDUFFZERO OpARMDUFFZERO
OpARMDUFFCOPY OpARMDUFFCOPY
OpARMLoweredZero OpARMLoweredZero
...@@ -7155,7 +7255,6 @@ var opcodeTable = [...]opInfo{ ...@@ -7155,7 +7255,6 @@ var opcodeTable = [...]opInfo{
{0, 6143}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12 {0, 6143}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12
{1, 6143}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12 {1, 6143}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12
}, },
clobbers: 4294967296, // FLAGS
outputs: []regMask{ outputs: []regMask{
5119, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 5119, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
}, },
...@@ -7184,7 +7283,6 @@ var opcodeTable = [...]opInfo{ ...@@ -7184,7 +7283,6 @@ var opcodeTable = [...]opInfo{
{0, 6143}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12 {0, 6143}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12
{1, 6143}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12 {1, 6143}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12
}, },
clobbers: 4294967296, // FLAGS
outputs: []regMask{ outputs: []regMask{
5119, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 5119, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
}, },
...@@ -7220,27 +7318,1317 @@ var opcodeTable = [...]opInfo{ ...@@ -7220,27 +7318,1317 @@ var opcodeTable = [...]opInfo{
}, },
}, },
{ {
name: "SRAconst", name: "SRAconst",
auxType: auxInt32, auxType: auxInt32,
argLen: 1, argLen: 1,
asm: arm.ASRA, asm: arm.ASRA,
reg: regInfo{
inputs: []inputInfo{
{0, 6143}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12
},
outputs: []regMask{
5119, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
},
},
},
{
name: "SRRconst",
auxType: auxInt32,
argLen: 1,
reg: regInfo{
inputs: []inputInfo{
{0, 6143}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12
},
outputs: []regMask{
5119, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
},
},
},
{
name: "ADDshiftLL",
auxType: auxInt32,
argLen: 2,
asm: arm.AADD,
reg: regInfo{
inputs: []inputInfo{
{0, 6143}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12
{1, 6143}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12
},
outputs: []regMask{
5119, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
},
},
},
{
name: "ADDshiftRL",
auxType: auxInt32,
argLen: 2,
asm: arm.AADD,
reg: regInfo{
inputs: []inputInfo{
{0, 6143}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12
{1, 6143}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12
},
outputs: []regMask{
5119, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
},
},
},
{
name: "ADDshiftRA",
auxType: auxInt32,
argLen: 2,
asm: arm.AADD,
reg: regInfo{
inputs: []inputInfo{
{0, 6143}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12
{1, 6143}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12
},
outputs: []regMask{
5119, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
},
},
},
{
name: "SUBshiftLL",
auxType: auxInt32,
argLen: 2,
asm: arm.ASUB,
reg: regInfo{
inputs: []inputInfo{
{0, 6143}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12
{1, 6143}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12
},
outputs: []regMask{
5119, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
},
},
},
{
name: "SUBshiftRL",
auxType: auxInt32,
argLen: 2,
asm: arm.ASUB,
reg: regInfo{
inputs: []inputInfo{
{0, 6143}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12
{1, 6143}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12
},
outputs: []regMask{
5119, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
},
},
},
{
name: "SUBshiftRA",
auxType: auxInt32,
argLen: 2,
asm: arm.ASUB,
reg: regInfo{
inputs: []inputInfo{
{0, 6143}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12
{1, 6143}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12
},
outputs: []regMask{
5119, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
},
},
},
{
name: "RSBshiftLL",
auxType: auxInt32,
argLen: 2,
asm: arm.ARSB,
reg: regInfo{
inputs: []inputInfo{
{0, 6143}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12
{1, 6143}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12
},
outputs: []regMask{
5119, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
},
},
},
{
name: "RSBshiftRL",
auxType: auxInt32,
argLen: 2,
asm: arm.ARSB,
reg: regInfo{
inputs: []inputInfo{
{0, 6143}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12
{1, 6143}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12
},
outputs: []regMask{
5119, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
},
},
},
{
name: "RSBshiftRA",
auxType: auxInt32,
argLen: 2,
asm: arm.ARSB,
reg: regInfo{
inputs: []inputInfo{
{0, 6143}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12
{1, 6143}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12
},
outputs: []regMask{
5119, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
},
},
},
{
name: "ANDshiftLL",
auxType: auxInt32,
argLen: 2,
asm: arm.AAND,
reg: regInfo{
inputs: []inputInfo{
{0, 6143}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12
{1, 6143}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12
},
outputs: []regMask{
5119, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
},
},
},
{
name: "ANDshiftRL",
auxType: auxInt32,
argLen: 2,
asm: arm.AAND,
reg: regInfo{
inputs: []inputInfo{
{0, 6143}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12
{1, 6143}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12
},
outputs: []regMask{
5119, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
},
},
},
{
name: "ANDshiftRA",
auxType: auxInt32,
argLen: 2,
asm: arm.AAND,
reg: regInfo{
inputs: []inputInfo{
{0, 6143}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12
{1, 6143}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12
},
outputs: []regMask{
5119, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
},
},
},
{
name: "ORshiftLL",
auxType: auxInt32,
argLen: 2,
asm: arm.AORR,
reg: regInfo{
inputs: []inputInfo{
{0, 6143}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12
{1, 6143}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12
},
outputs: []regMask{
5119, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
},
},
},
{
name: "ORshiftRL",
auxType: auxInt32,
argLen: 2,
asm: arm.AORR,
reg: regInfo{
inputs: []inputInfo{
{0, 6143}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12
{1, 6143}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12
},
outputs: []regMask{
5119, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
},
},
},
{
name: "ORshiftRA",
auxType: auxInt32,
argLen: 2,
asm: arm.AORR,
reg: regInfo{
inputs: []inputInfo{
{0, 6143}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12
{1, 6143}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12
},
outputs: []regMask{
5119, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
},
},
},
{
name: "XORshiftLL",
auxType: auxInt32,
argLen: 2,
asm: arm.AEOR,
reg: regInfo{
inputs: []inputInfo{
{0, 6143}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12
{1, 6143}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12
},
outputs: []regMask{
5119, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
},
},
},
{
name: "XORshiftRL",
auxType: auxInt32,
argLen: 2,
asm: arm.AEOR,
reg: regInfo{
inputs: []inputInfo{
{0, 6143}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12
{1, 6143}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12
},
outputs: []regMask{
5119, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
},
},
},
{
name: "XORshiftRA",
auxType: auxInt32,
argLen: 2,
asm: arm.AEOR,
reg: regInfo{
inputs: []inputInfo{
{0, 6143}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12
{1, 6143}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12
},
outputs: []regMask{
5119, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
},
},
},
{
name: "BICshiftLL",
auxType: auxInt32,
argLen: 2,
asm: arm.ABIC,
reg: regInfo{
inputs: []inputInfo{
{0, 6143}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12
{1, 6143}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12
},
outputs: []regMask{
5119, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
},
},
},
{
name: "BICshiftRL",
auxType: auxInt32,
argLen: 2,
asm: arm.ABIC,
reg: regInfo{
inputs: []inputInfo{
{0, 6143}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12
{1, 6143}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12
},
outputs: []regMask{
5119, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
},
},
},
{
name: "BICshiftRA",
auxType: auxInt32,
argLen: 2,
asm: arm.ABIC,
reg: regInfo{
inputs: []inputInfo{
{0, 6143}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12
{1, 6143}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12
},
outputs: []regMask{
5119, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
},
},
},
{
name: "MVNshiftLL",
auxType: auxInt32,
argLen: 1,
asm: arm.AMVN,
reg: regInfo{
inputs: []inputInfo{
{0, 6143}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12
},
outputs: []regMask{
5119, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
},
},
},
{
name: "MVNshiftRL",
auxType: auxInt32,
argLen: 1,
asm: arm.AMVN,
reg: regInfo{
inputs: []inputInfo{
{0, 6143}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12
},
outputs: []regMask{
5119, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
},
},
},
{
name: "MVNshiftRA",
auxType: auxInt32,
argLen: 1,
asm: arm.AMVN,
reg: regInfo{
inputs: []inputInfo{
{0, 6143}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12
},
outputs: []regMask{
5119, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
},
},
},
{
name: "ADCshiftLL",
auxType: auxInt32,
argLen: 3,
asm: arm.AADC,
reg: regInfo{
inputs: []inputInfo{
{2, 4294967296}, // FLAGS
{0, 5119}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
{1, 5119}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
},
outputs: []regMask{
5119, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
},
},
},
{
name: "ADCshiftRL",
auxType: auxInt32,
argLen: 3,
asm: arm.AADC,
reg: regInfo{
inputs: []inputInfo{
{2, 4294967296}, // FLAGS
{0, 5119}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
{1, 5119}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
},
outputs: []regMask{
5119, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
},
},
},
{
name: "ADCshiftRA",
auxType: auxInt32,
argLen: 3,
asm: arm.AADC,
reg: regInfo{
inputs: []inputInfo{
{2, 4294967296}, // FLAGS
{0, 5119}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
{1, 5119}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
},
outputs: []regMask{
5119, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
},
},
},
{
name: "SBCshiftLL",
auxType: auxInt32,
argLen: 3,
asm: arm.ASBC,
reg: regInfo{
inputs: []inputInfo{
{2, 4294967296}, // FLAGS
{0, 5119}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
{1, 5119}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
},
outputs: []regMask{
5119, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
},
},
},
{
name: "SBCshiftRL",
auxType: auxInt32,
argLen: 3,
asm: arm.ASBC,
reg: regInfo{
inputs: []inputInfo{
{2, 4294967296}, // FLAGS
{0, 5119}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
{1, 5119}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
},
outputs: []regMask{
5119, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
},
},
},
{
name: "SBCshiftRA",
auxType: auxInt32,
argLen: 3,
asm: arm.ASBC,
reg: regInfo{
inputs: []inputInfo{
{2, 4294967296}, // FLAGS
{0, 5119}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
{1, 5119}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
},
outputs: []regMask{
5119, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
},
},
},
{
name: "RSCshiftLL",
auxType: auxInt32,
argLen: 3,
asm: arm.ARSC,
reg: regInfo{
inputs: []inputInfo{
{2, 4294967296}, // FLAGS
{0, 5119}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
{1, 5119}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
},
outputs: []regMask{
5119, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
},
},
},
{
name: "RSCshiftRL",
auxType: auxInt32,
argLen: 3,
asm: arm.ARSC,
reg: regInfo{
inputs: []inputInfo{
{2, 4294967296}, // FLAGS
{0, 5119}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
{1, 5119}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
},
outputs: []regMask{
5119, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
},
},
},
{
name: "RSCshiftRA",
auxType: auxInt32,
argLen: 3,
asm: arm.ARSC,
reg: regInfo{
inputs: []inputInfo{
{2, 4294967296}, // FLAGS
{0, 5119}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
{1, 5119}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
},
outputs: []regMask{
5119, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
},
},
},
{
name: "ADDSshiftLL",
auxType: auxInt32,
argLen: 2,
asm: arm.AADD,
reg: regInfo{
inputs: []inputInfo{
{0, 6143}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12
{1, 6143}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12
},
clobbers: 4294967296, // FLAGS
outputs: []regMask{
5119, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
},
},
},
{
name: "ADDSshiftRL",
auxType: auxInt32,
argLen: 2,
asm: arm.AADD,
reg: regInfo{
inputs: []inputInfo{
{0, 6143}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12
{1, 6143}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12
},
clobbers: 4294967296, // FLAGS
outputs: []regMask{
5119, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
},
},
},
{
name: "ADDSshiftRA",
auxType: auxInt32,
argLen: 2,
asm: arm.AADD,
reg: regInfo{
inputs: []inputInfo{
{0, 6143}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12
{1, 6143}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12
},
clobbers: 4294967296, // FLAGS
outputs: []regMask{
5119, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
},
},
},
{
name: "SUBSshiftLL",
auxType: auxInt32,
argLen: 2,
asm: arm.ASUB,
reg: regInfo{
inputs: []inputInfo{
{0, 6143}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12
{1, 6143}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12
},
clobbers: 4294967296, // FLAGS
outputs: []regMask{
5119, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
},
},
},
{
name: "SUBSshiftRL",
auxType: auxInt32,
argLen: 2,
asm: arm.ASUB,
reg: regInfo{
inputs: []inputInfo{
{0, 6143}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12
{1, 6143}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12
},
clobbers: 4294967296, // FLAGS
outputs: []regMask{
5119, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
},
},
},
{
name: "SUBSshiftRA",
auxType: auxInt32,
argLen: 2,
asm: arm.ASUB,
reg: regInfo{
inputs: []inputInfo{
{0, 6143}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12
{1, 6143}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12
},
clobbers: 4294967296, // FLAGS
outputs: []regMask{
5119, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
},
},
},
{
name: "RSBSshiftLL",
auxType: auxInt32,
argLen: 2,
asm: arm.ARSB,
reg: regInfo{
inputs: []inputInfo{
{0, 6143}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12
{1, 6143}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12
},
clobbers: 4294967296, // FLAGS
outputs: []regMask{
5119, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
},
},
},
{
name: "RSBSshiftRL",
auxType: auxInt32,
argLen: 2,
asm: arm.ARSB,
reg: regInfo{
inputs: []inputInfo{
{0, 6143}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12
{1, 6143}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12
},
clobbers: 4294967296, // FLAGS
outputs: []regMask{
5119, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
},
},
},
{
name: "RSBSshiftRA",
auxType: auxInt32,
argLen: 2,
asm: arm.ARSB,
reg: regInfo{
inputs: []inputInfo{
{0, 6143}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12
{1, 6143}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12
},
clobbers: 4294967296, // FLAGS
outputs: []regMask{
5119, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
},
},
},
{
name: "ADDshiftLLreg",
argLen: 3,
asm: arm.AADD,
reg: regInfo{
inputs: []inputInfo{
{0, 5119}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
{1, 5119}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
{2, 5119}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
},
outputs: []regMask{
5119, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
},
},
},
{
name: "ADDshiftRLreg",
argLen: 3,
asm: arm.AADD,
reg: regInfo{
inputs: []inputInfo{
{0, 5119}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
{1, 5119}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
{2, 5119}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
},
outputs: []regMask{
5119, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
},
},
},
{
name: "ADDshiftRAreg",
argLen: 3,
asm: arm.AADD,
reg: regInfo{
inputs: []inputInfo{
{0, 5119}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
{1, 5119}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
{2, 5119}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
},
outputs: []regMask{
5119, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
},
},
},
{
name: "SUBshiftLLreg",
argLen: 3,
asm: arm.ASUB,
reg: regInfo{
inputs: []inputInfo{
{0, 5119}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
{1, 5119}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
{2, 5119}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
},
outputs: []regMask{
5119, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
},
},
},
{
name: "SUBshiftRLreg",
argLen: 3,
asm: arm.ASUB,
reg: regInfo{
inputs: []inputInfo{
{0, 5119}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
{1, 5119}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
{2, 5119}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
},
outputs: []regMask{
5119, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
},
},
},
{
name: "SUBshiftRAreg",
argLen: 3,
asm: arm.ASUB,
reg: regInfo{
inputs: []inputInfo{
{0, 5119}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
{1, 5119}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
{2, 5119}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
},
outputs: []regMask{
5119, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
},
},
},
{
name: "RSBshiftLLreg",
argLen: 3,
asm: arm.ARSB,
reg: regInfo{
inputs: []inputInfo{
{0, 5119}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
{1, 5119}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
{2, 5119}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
},
outputs: []regMask{
5119, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
},
},
},
{
name: "RSBshiftRLreg",
argLen: 3,
asm: arm.ARSB,
reg: regInfo{
inputs: []inputInfo{
{0, 5119}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
{1, 5119}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
{2, 5119}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
},
outputs: []regMask{
5119, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
},
},
},
{
name: "RSBshiftRAreg",
argLen: 3,
asm: arm.ARSB,
reg: regInfo{
inputs: []inputInfo{
{0, 5119}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
{1, 5119}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
{2, 5119}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
},
outputs: []regMask{
5119, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
},
},
},
{
name: "ANDshiftLLreg",
argLen: 3,
asm: arm.AAND,
reg: regInfo{
inputs: []inputInfo{
{0, 5119}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
{1, 5119}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
{2, 5119}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
},
outputs: []regMask{
5119, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
},
},
},
{
name: "ANDshiftRLreg",
argLen: 3,
asm: arm.AAND,
reg: regInfo{
inputs: []inputInfo{
{0, 5119}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
{1, 5119}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
{2, 5119}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
},
outputs: []regMask{
5119, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
},
},
},
{
name: "ANDshiftRAreg",
argLen: 3,
asm: arm.AAND,
reg: regInfo{
inputs: []inputInfo{
{0, 5119}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
{1, 5119}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
{2, 5119}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
},
outputs: []regMask{
5119, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
},
},
},
{
name: "ORshiftLLreg",
argLen: 3,
asm: arm.AORR,
reg: regInfo{
inputs: []inputInfo{
{0, 5119}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
{1, 5119}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
{2, 5119}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
},
outputs: []regMask{
5119, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
},
},
},
{
name: "ORshiftRLreg",
argLen: 3,
asm: arm.AORR,
reg: regInfo{
inputs: []inputInfo{
{0, 5119}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
{1, 5119}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
{2, 5119}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
},
outputs: []regMask{
5119, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
},
},
},
{
name: "ORshiftRAreg",
argLen: 3,
asm: arm.AORR,
reg: regInfo{
inputs: []inputInfo{
{0, 5119}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
{1, 5119}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
{2, 5119}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
},
outputs: []regMask{
5119, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
},
},
},
{
name: "XORshiftLLreg",
argLen: 3,
asm: arm.AEOR,
reg: regInfo{
inputs: []inputInfo{
{0, 5119}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
{1, 5119}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
{2, 5119}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
},
outputs: []regMask{
5119, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
},
},
},
{
name: "XORshiftRLreg",
argLen: 3,
asm: arm.AEOR,
reg: regInfo{
inputs: []inputInfo{
{0, 5119}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
{1, 5119}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
{2, 5119}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
},
outputs: []regMask{
5119, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
},
},
},
{
name: "XORshiftRAreg",
argLen: 3,
asm: arm.AEOR,
reg: regInfo{
inputs: []inputInfo{
{0, 5119}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
{1, 5119}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
{2, 5119}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
},
outputs: []regMask{
5119, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
},
},
},
{
name: "BICshiftLLreg",
argLen: 3,
asm: arm.ABIC,
reg: regInfo{
inputs: []inputInfo{
{0, 5119}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
{1, 5119}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
{2, 5119}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
},
outputs: []regMask{
5119, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
},
},
},
{
name: "BICshiftRLreg",
argLen: 3,
asm: arm.ABIC,
reg: regInfo{
inputs: []inputInfo{
{0, 5119}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
{1, 5119}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
{2, 5119}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
},
outputs: []regMask{
5119, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
},
},
},
{
name: "BICshiftRAreg",
argLen: 3,
asm: arm.ABIC,
reg: regInfo{
inputs: []inputInfo{
{0, 5119}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
{1, 5119}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
{2, 5119}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
},
outputs: []regMask{
5119, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
},
},
},
{
name: "MVNshiftLLreg",
argLen: 2,
asm: arm.AMVN,
reg: regInfo{
inputs: []inputInfo{
{0, 6143}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12
{1, 6143}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12
},
outputs: []regMask{
5119, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
},
},
},
{
name: "MVNshiftRLreg",
argLen: 2,
asm: arm.AMVN,
reg: regInfo{
inputs: []inputInfo{
{0, 6143}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12
{1, 6143}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12
},
outputs: []regMask{
5119, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
},
},
},
{
name: "MVNshiftRAreg",
argLen: 2,
asm: arm.AMVN,
reg: regInfo{
inputs: []inputInfo{
{0, 6143}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12
{1, 6143}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12
},
outputs: []regMask{
5119, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
},
},
},
{
name: "ADCshiftLLreg",
argLen: 4,
asm: arm.AADC,
reg: regInfo{
inputs: []inputInfo{
{3, 4294967296}, // FLAGS
{0, 5119}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
{1, 5119}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
{2, 5119}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
},
outputs: []regMask{
5119, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
},
},
},
{
name: "ADCshiftRLreg",
argLen: 4,
asm: arm.AADC,
reg: regInfo{
inputs: []inputInfo{
{3, 4294967296}, // FLAGS
{0, 5119}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
{1, 5119}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
{2, 5119}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
},
outputs: []regMask{
5119, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
},
},
},
{
name: "ADCshiftRAreg",
argLen: 4,
asm: arm.AADC,
reg: regInfo{
inputs: []inputInfo{
{3, 4294967296}, // FLAGS
{0, 5119}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
{1, 5119}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
{2, 5119}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
},
outputs: []regMask{
5119, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
},
},
},
{
name: "SBCshiftLLreg",
argLen: 4,
asm: arm.ASBC,
reg: regInfo{
inputs: []inputInfo{
{3, 4294967296}, // FLAGS
{0, 5119}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
{1, 5119}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
{2, 5119}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
},
outputs: []regMask{
5119, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
},
},
},
{
name: "SBCshiftRLreg",
argLen: 4,
asm: arm.ASBC,
reg: regInfo{
inputs: []inputInfo{
{3, 4294967296}, // FLAGS
{0, 5119}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
{1, 5119}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
{2, 5119}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
},
outputs: []regMask{
5119, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
},
},
},
{
name: "SBCshiftRAreg",
argLen: 4,
asm: arm.ASBC,
reg: regInfo{
inputs: []inputInfo{
{3, 4294967296}, // FLAGS
{0, 5119}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
{1, 5119}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
{2, 5119}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
},
outputs: []regMask{
5119, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
},
},
},
{
name: "RSCshiftLLreg",
argLen: 4,
asm: arm.ARSC,
reg: regInfo{
inputs: []inputInfo{
{3, 4294967296}, // FLAGS
{0, 5119}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
{1, 5119}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
{2, 5119}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
},
outputs: []regMask{
5119, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
},
},
},
{
name: "RSCshiftRLreg",
argLen: 4,
asm: arm.ARSC,
reg: regInfo{
inputs: []inputInfo{
{3, 4294967296}, // FLAGS
{0, 5119}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
{1, 5119}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
{2, 5119}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
},
outputs: []regMask{
5119, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
},
},
},
{
name: "RSCshiftRAreg",
argLen: 4,
asm: arm.ARSC,
reg: regInfo{
inputs: []inputInfo{
{3, 4294967296}, // FLAGS
{0, 5119}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
{1, 5119}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
{2, 5119}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
},
outputs: []regMask{
5119, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
},
},
},
{
name: "ADDSshiftLLreg",
argLen: 3,
asm: arm.AADD,
reg: regInfo{
inputs: []inputInfo{
{0, 5119}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
{1, 5119}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
{2, 5119}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
},
clobbers: 4294967296, // FLAGS
outputs: []regMask{
5119, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
},
},
},
{
name: "ADDSshiftRLreg",
argLen: 3,
asm: arm.AADD,
reg: regInfo{
inputs: []inputInfo{
{0, 5119}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
{1, 5119}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
{2, 5119}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
},
clobbers: 4294967296, // FLAGS
outputs: []regMask{
5119, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
},
},
},
{
name: "ADDSshiftRAreg",
argLen: 3,
asm: arm.AADD,
reg: regInfo{
inputs: []inputInfo{
{0, 5119}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
{1, 5119}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
{2, 5119}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
},
clobbers: 4294967296, // FLAGS
outputs: []regMask{
5119, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
},
},
},
{
name: "SUBSshiftLLreg",
argLen: 3,
asm: arm.ASUB,
reg: regInfo{
inputs: []inputInfo{
{0, 5119}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
{1, 5119}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
{2, 5119}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
},
clobbers: 4294967296, // FLAGS
outputs: []regMask{
5119, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
},
},
},
{
name: "SUBSshiftRLreg",
argLen: 3,
asm: arm.ASUB,
reg: regInfo{
inputs: []inputInfo{
{0, 5119}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
{1, 5119}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
{2, 5119}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
},
clobbers: 4294967296, // FLAGS
outputs: []regMask{
5119, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
},
},
},
{
name: "SUBSshiftRAreg",
argLen: 3,
asm: arm.ASUB,
reg: regInfo{
inputs: []inputInfo{
{0, 5119}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
{1, 5119}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
{2, 5119}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
},
clobbers: 4294967296, // FLAGS
outputs: []regMask{
5119, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
},
},
},
{
name: "RSBSshiftLLreg",
argLen: 3,
asm: arm.ARSB,
reg: regInfo{
inputs: []inputInfo{
{0, 5119}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
{1, 5119}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
{2, 5119}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
},
clobbers: 4294967296, // FLAGS
outputs: []regMask{
5119, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
},
},
},
{
name: "RSBSshiftRLreg",
argLen: 3,
asm: arm.ARSB,
reg: regInfo{ reg: regInfo{
inputs: []inputInfo{ inputs: []inputInfo{
{0, 6143}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12 {0, 5119}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
{1, 5119}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
{2, 5119}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
}, },
clobbers: 4294967296, // FLAGS
outputs: []regMask{ outputs: []regMask{
5119, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 5119, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
}, },
}, },
}, },
{ {
name: "SRRconst", name: "RSBSshiftRAreg",
auxType: auxInt32, argLen: 3,
argLen: 1, asm: arm.ARSB,
reg: regInfo{ reg: regInfo{
inputs: []inputInfo{ inputs: []inputInfo{
{0, 6143}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12 {0, 5119}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
{1, 5119}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
{2, 5119}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
}, },
clobbers: 4294967296, // FLAGS
outputs: []regMask{ outputs: []regMask{
5119, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 5119, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
}, },
...@@ -7388,6 +8776,96 @@ var opcodeTable = [...]opInfo{ ...@@ -7388,6 +8776,96 @@ var opcodeTable = [...]opInfo{
}, },
}, },
}, },
{
name: "CMPshiftLL",
auxType: auxInt32,
argLen: 2,
asm: arm.ACMP,
reg: regInfo{
inputs: []inputInfo{
{0, 6143}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12
{1, 6143}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12
},
outputs: []regMask{
4294967296, // FLAGS
},
},
},
{
name: "CMPshiftRL",
auxType: auxInt32,
argLen: 2,
asm: arm.ACMP,
reg: regInfo{
inputs: []inputInfo{
{0, 6143}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12
{1, 6143}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12
},
outputs: []regMask{
4294967296, // FLAGS
},
},
},
{
name: "CMPshiftRA",
auxType: auxInt32,
argLen: 2,
asm: arm.ACMP,
reg: regInfo{
inputs: []inputInfo{
{0, 6143}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12
{1, 6143}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12
},
outputs: []regMask{
4294967296, // FLAGS
},
},
},
{
name: "CMPshiftLLreg",
argLen: 3,
asm: arm.ACMP,
reg: regInfo{
inputs: []inputInfo{
{0, 5119}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
{1, 5119}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
{2, 5119}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
},
outputs: []regMask{
4294967296, // FLAGS
},
},
},
{
name: "CMPshiftRLreg",
argLen: 3,
asm: arm.ACMP,
reg: regInfo{
inputs: []inputInfo{
{0, 5119}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
{1, 5119}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
{2, 5119}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
},
outputs: []regMask{
4294967296, // FLAGS
},
},
},
{
name: "CMPshiftRAreg",
argLen: 3,
asm: arm.ACMP,
reg: regInfo{
inputs: []inputInfo{
{0, 5119}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
{1, 5119}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
{2, 5119}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
},
outputs: []regMask{
4294967296, // FLAGS
},
},
},
{ {
name: "MOVWconst", name: "MOVWconst",
auxType: auxInt32, auxType: auxInt32,
...@@ -7597,6 +9075,116 @@ var opcodeTable = [...]opInfo{ ...@@ -7597,6 +9075,116 @@ var opcodeTable = [...]opInfo{
}, },
}, },
}, },
{
name: "MOVWloadidx",
argLen: 3,
asm: arm.AMOVW,
reg: regInfo{
inputs: []inputInfo{
{1, 6143}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12
{0, 8589948927}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12 SP SB
},
outputs: []regMask{
5119, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
},
},
},
{
name: "MOVWloadshiftLL",
auxType: auxInt32,
argLen: 3,
asm: arm.AMOVW,
reg: regInfo{
inputs: []inputInfo{
{1, 6143}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12
{0, 8589948927}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12 SP SB
},
outputs: []regMask{
5119, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
},
},
},
{
name: "MOVWloadshiftRL",
auxType: auxInt32,
argLen: 3,
asm: arm.AMOVW,
reg: regInfo{
inputs: []inputInfo{
{1, 6143}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12
{0, 8589948927}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12 SP SB
},
outputs: []regMask{
5119, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
},
},
},
{
name: "MOVWloadshiftRA",
auxType: auxInt32,
argLen: 3,
asm: arm.AMOVW,
reg: regInfo{
inputs: []inputInfo{
{1, 6143}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12
{0, 8589948927}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12 SP SB
},
outputs: []regMask{
5119, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
},
},
},
{
name: "MOVWstoreidx",
argLen: 4,
asm: arm.AMOVW,
reg: regInfo{
inputs: []inputInfo{
{1, 6143}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12
{2, 6143}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12
{0, 8589948927}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12 SP SB
},
},
},
{
name: "MOVWstoreshiftLL",
auxType: auxInt32,
argLen: 4,
asm: arm.AMOVW,
reg: regInfo{
inputs: []inputInfo{
{1, 6143}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12
{2, 6143}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12
{0, 8589948927}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12 SP SB
},
},
},
{
name: "MOVWstoreshiftRL",
auxType: auxInt32,
argLen: 4,
asm: arm.AMOVW,
reg: regInfo{
inputs: []inputInfo{
{1, 6143}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12
{2, 6143}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12
{0, 8589948927}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12 SP SB
},
},
},
{
name: "MOVWstoreshiftRA",
auxType: auxInt32,
argLen: 4,
asm: arm.AMOVW,
reg: regInfo{
inputs: []inputInfo{
{1, 6143}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12
{2, 6143}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12
{0, 8589948927}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12 SP SB
},
},
},
{ {
name: "MOVBreg", name: "MOVBreg",
argLen: 1, argLen: 1,
...@@ -7792,6 +9380,53 @@ var opcodeTable = [...]opInfo{ ...@@ -7792,6 +9380,53 @@ var opcodeTable = [...]opInfo{
}, },
}, },
}, },
{
name: "CMOVWHSconst",
auxType: auxInt32,
argLen: 2,
resultInArg0: true,
asm: arm.AMOVW,
reg: regInfo{
inputs: []inputInfo{
{1, 4294967296}, // FLAGS
{0, 5119}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
},
outputs: []regMask{
5119, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
},
},
},
{
name: "CMOVWLSconst",
auxType: auxInt32,
argLen: 2,
resultInArg0: true,
asm: arm.AMOVW,
reg: regInfo{
inputs: []inputInfo{
{1, 4294967296}, // FLAGS
{0, 5119}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
},
outputs: []regMask{
5119, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
},
},
},
{
name: "SRAcond",
argLen: 3,
asm: arm.ASRA,
reg: regInfo{
inputs: []inputInfo{
{2, 4294967296}, // FLAGS
{0, 5119}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
{1, 5119}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
},
outputs: []regMask{
5119, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
},
},
},
{ {
name: "CALLstatic", name: "CALLstatic",
auxType: auxSymOff, auxType: auxSymOff,
...@@ -7999,18 +9634,6 @@ var opcodeTable = [...]opInfo{ ...@@ -7999,18 +9634,6 @@ var opcodeTable = [...]opInfo{
}, },
}, },
}, },
{
name: "LoweredZeromask",
argLen: 1,
reg: regInfo{
inputs: []inputInfo{
{0, 6143}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12
},
outputs: []regMask{
5119, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
},
},
},
{ {
name: "DUFFZERO", name: "DUFFZERO",
auxType: auxInt64, auxType: auxInt64,
......
This source diff could not be displayed because it is too large. You can view the blob instead.
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