Commit 59e11d78 authored by Cherry Zhang's avatar Cherry Zhang

[dev.ssa] cmd/compile: handle floating point on ARM

Machine supports (or the runtime simulates in soft float mode)
(u)int32<->float conversions. The frontend rewrites int64<->float
conversions to call to runtime function.

For int64->float32 conversion, the frontend generates

.   .   AS u(100) l(10) tc(1)
.   .   .   NAME-main.~r1 u(1) a(true) g(1) l(9) x(8+0) class(PPARAMOUT) f(1) float32
.   .   .   CALLFUNC u(100) l(10) tc(1) float32
.   .   .   .   NAME-runtime.int64tofloat64 u(1) a(true) x(0+0) class(PFUNC) tc(1) used(true) FUNC-func(int64) float64

The CALLFUNC node has type float32, whereas runtime.int64tofloat64
returns float64. The legacy backend implicitly makes a float64->float32
conversion. The SSA backend does not do implicit conversion, so we
insert an explicit CONV here.

All cmd/compile/internal/gc/testdata/*_ssa.go tests passed.

Progress on SSA for ARM. Still not complete.

Update #15365.

Change-Id: I30937c8ff977271246b068f48224693776804339
Reviewed-on: https://go-review.googlesource.com/23652Reviewed-by: default avatarKeith Randall <khr@golang.org>
parent e78d90be
...@@ -5,6 +5,8 @@ ...@@ -5,6 +5,8 @@
package arm package arm
import ( import (
"math"
"cmd/compile/internal/gc" "cmd/compile/internal/gc"
"cmd/compile/internal/ssa" "cmd/compile/internal/ssa"
"cmd/internal/obj" "cmd/internal/obj"
...@@ -29,6 +31,23 @@ var ssaRegToReg = []int16{ ...@@ -29,6 +31,23 @@ var ssaRegToReg = []int16{
arm.REG_R14, arm.REG_R14,
arm.REG_R15, arm.REG_R15,
arm.REG_F0,
arm.REG_F1,
arm.REG_F2,
arm.REG_F3,
arm.REG_F4,
arm.REG_F5,
arm.REG_F6,
arm.REG_F7,
arm.REG_F8,
arm.REG_F9,
arm.REG_F10,
arm.REG_F11,
arm.REG_F12,
arm.REG_F13,
arm.REG_F14,
arm.REG_F15,
arm.REG_CPSR, // flag arm.REG_CPSR, // flag
0, // SB isn't a real register. We fill an Addr.Reg field with 0 in this case. 0, // SB isn't a real register. We fill an Addr.Reg field with 0 in this case.
} }
...@@ -36,7 +55,12 @@ var ssaRegToReg = []int16{ ...@@ -36,7 +55,12 @@ var ssaRegToReg = []int16{
// loadByType returns the load instruction of the given type. // loadByType returns the load instruction of the given type.
func loadByType(t ssa.Type) obj.As { func loadByType(t ssa.Type) obj.As {
if t.IsFloat() { if t.IsFloat() {
panic("load floating point register is not implemented") switch t.Size() {
case 4:
return arm.AMOVF
case 8:
return arm.AMOVD
}
} else { } else {
switch t.Size() { switch t.Size() {
case 1: case 1:
...@@ -61,7 +85,12 @@ func loadByType(t ssa.Type) obj.As { ...@@ -61,7 +85,12 @@ func loadByType(t ssa.Type) obj.As {
// storeByType returns the store instruction of the given type. // storeByType returns the store instruction of the given type.
func storeByType(t ssa.Type) obj.As { func storeByType(t ssa.Type) obj.As {
if t.IsFloat() { if t.IsFloat() {
panic("store floating point register is not implemented") switch t.Size() {
case 4:
return arm.AMOVF
case 8:
return arm.AMOVD
}
} else { } else {
switch t.Size() { switch t.Size() {
case 1: case 1:
...@@ -93,7 +122,18 @@ func ssaGenValue(s *gc.SSAGenState, v *ssa.Value) { ...@@ -93,7 +122,18 @@ func ssaGenValue(s *gc.SSAGenState, v *ssa.Value) {
if x == y { if x == y {
return return
} }
p := gc.Prog(arm.AMOVW) as := arm.AMOVW
if v.Type.IsFloat() {
switch v.Type.Size() {
case 4:
as = arm.AMOVF
case 8:
as = arm.AMOVD
default:
panic("bad float size")
}
}
p := gc.Prog(as)
p.From.Type = obj.TYPE_REG p.From.Type = obj.TYPE_REG
p.From.Reg = x p.From.Reg = x
p.To.Type = obj.TYPE_REG p.To.Type = obj.TYPE_REG
...@@ -172,7 +212,15 @@ func ssaGenValue(s *gc.SSAGenState, v *ssa.Value) { ...@@ -172,7 +212,15 @@ func ssaGenValue(s *gc.SSAGenState, v *ssa.Value) {
ssa.OpARMOR, ssa.OpARMOR,
ssa.OpARMXOR, ssa.OpARMXOR,
ssa.OpARMBIC, ssa.OpARMBIC,
ssa.OpARMMUL: ssa.OpARMMUL,
ssa.OpARMADDF,
ssa.OpARMADDD,
ssa.OpARMSUBF,
ssa.OpARMSUBD,
ssa.OpARMMULF,
ssa.OpARMMULD,
ssa.OpARMDIVF,
ssa.OpARMDIVD:
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])
...@@ -331,10 +379,19 @@ func ssaGenValue(s *gc.SSAGenState, v *ssa.Value) { ...@@ -331,10 +379,19 @@ func ssaGenValue(s *gc.SSAGenState, v *ssa.Value) {
p.From.Offset = v.AuxInt p.From.Offset = v.AuxInt
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.OpARMMOVFconst,
ssa.OpARMMOVDconst:
p := gc.Prog(v.Op.Asm())
p.From.Type = obj.TYPE_FCONST
p.From.Val = math.Float64frombits(uint64(v.AuxInt))
p.To.Type = obj.TYPE_REG
p.To.Reg = gc.SSARegNum(v)
case ssa.OpARMCMP, case ssa.OpARMCMP,
ssa.OpARMCMN, ssa.OpARMCMN,
ssa.OpARMTST, ssa.OpARMTST,
ssa.OpARMTEQ: ssa.OpARMTEQ,
ssa.OpARMCMPF,
ssa.OpARMCMPD:
p := gc.Prog(v.Op.Asm()) p := gc.Prog(v.Op.Asm())
p.From.Type = obj.TYPE_REG p.From.Type = obj.TYPE_REG
// Special layout in ARM assembly // Special layout in ARM assembly
...@@ -354,7 +411,9 @@ func ssaGenValue(s *gc.SSAGenState, v *ssa.Value) { ...@@ -354,7 +411,9 @@ func ssaGenValue(s *gc.SSAGenState, v *ssa.Value) {
ssa.OpARMMOVBUload, ssa.OpARMMOVBUload,
ssa.OpARMMOVHload, ssa.OpARMMOVHload,
ssa.OpARMMOVHUload, ssa.OpARMMOVHUload,
ssa.OpARMMOVWload: ssa.OpARMMOVWload,
ssa.OpARMMOVFload,
ssa.OpARMMOVDload:
p := gc.Prog(v.Op.Asm()) p := gc.Prog(v.Op.Asm())
p.From.Type = obj.TYPE_MEM p.From.Type = obj.TYPE_MEM
p.From.Reg = gc.SSARegNum(v.Args[0]) p.From.Reg = gc.SSARegNum(v.Args[0])
...@@ -363,7 +422,9 @@ func ssaGenValue(s *gc.SSAGenState, v *ssa.Value) { ...@@ -363,7 +422,9 @@ func ssaGenValue(s *gc.SSAGenState, v *ssa.Value) {
p.To.Reg = gc.SSARegNum(v) p.To.Reg = gc.SSARegNum(v)
case ssa.OpARMMOVBstore, case ssa.OpARMMOVBstore,
ssa.OpARMMOVHstore, ssa.OpARMMOVHstore,
ssa.OpARMMOVWstore: ssa.OpARMMOVWstore,
ssa.OpARMMOVFstore,
ssa.OpARMMOVDstore:
p := gc.Prog(v.Op.Asm()) p := gc.Prog(v.Op.Asm())
p.From.Type = obj.TYPE_REG p.From.Type = obj.TYPE_REG
p.From.Reg = gc.SSARegNum(v.Args[1]) p.From.Reg = gc.SSARegNum(v.Args[1])
...@@ -374,11 +435,25 @@ func ssaGenValue(s *gc.SSAGenState, v *ssa.Value) { ...@@ -374,11 +435,25 @@ func ssaGenValue(s *gc.SSAGenState, v *ssa.Value) {
ssa.OpARMMOVBUreg, ssa.OpARMMOVBUreg,
ssa.OpARMMOVHreg, ssa.OpARMMOVHreg,
ssa.OpARMMOVHUreg, ssa.OpARMMOVHUreg,
ssa.OpARMMVN: ssa.OpARMMVN,
if v.Type.IsMemory() { ssa.OpARMSQRTD,
v.Fatalf("memory operand for %s", v.LongString()) ssa.OpARMMOVWF,
} ssa.OpARMMOVWD,
ssa.OpARMMOVFW,
ssa.OpARMMOVDW,
ssa.OpARMMOVFD,
ssa.OpARMMOVDF:
p := gc.Prog(v.Op.Asm())
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)
case ssa.OpARMMOVWUF,
ssa.OpARMMOVWUD,
ssa.OpARMMOVFWU,
ssa.OpARMMOVDWU:
p := gc.Prog(v.Op.Asm()) p := gc.Prog(v.Op.Asm())
p.Scond = arm.C_UBIT
p.From.Type = obj.TYPE_REG p.From.Type = obj.TYPE_REG
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
......
...@@ -1323,6 +1323,15 @@ var fpConvOpToSSA = map[twoTypes]twoOpsAndType{ ...@@ -1323,6 +1323,15 @@ var fpConvOpToSSA = map[twoTypes]twoOpsAndType{
twoTypes{TFLOAT32, TFLOAT64}: twoOpsAndType{ssa.OpCvt32Fto64F, ssa.OpCopy, TFLOAT64}, twoTypes{TFLOAT32, TFLOAT64}: twoOpsAndType{ssa.OpCvt32Fto64F, ssa.OpCopy, TFLOAT64},
} }
// this map is used only for 32-bit arch, and only includes the difference
// on 32-bit arch, don't use int64<->float conversion for uint32
var fpConvOpToSSA32 = map[twoTypes]twoOpsAndType{
twoTypes{TUINT32, TFLOAT32}: twoOpsAndType{ssa.OpCopy, ssa.OpCvt32Uto32F, TUINT32},
twoTypes{TUINT32, TFLOAT64}: twoOpsAndType{ssa.OpCopy, ssa.OpCvt32Uto64F, TUINT32},
twoTypes{TFLOAT32, TUINT32}: twoOpsAndType{ssa.OpCvt32Fto32U, ssa.OpCopy, TUINT32},
twoTypes{TFLOAT64, TUINT32}: twoOpsAndType{ssa.OpCvt64Fto32U, ssa.OpCopy, TUINT32},
}
var shiftOpToSSA = map[opAndTwoTypes]ssa.Op{ var shiftOpToSSA = map[opAndTwoTypes]ssa.Op{
opAndTwoTypes{OLSH, TINT8, TUINT8}: ssa.OpLsh8x8, opAndTwoTypes{OLSH, TINT8, TUINT8}: ssa.OpLsh8x8,
opAndTwoTypes{OLSH, TUINT8, TUINT8}: ssa.OpLsh8x8, opAndTwoTypes{OLSH, TUINT8, TUINT8}: ssa.OpLsh8x8,
...@@ -1639,6 +1648,11 @@ func (s *state) expr(n *Node) *ssa.Value { ...@@ -1639,6 +1648,11 @@ func (s *state) expr(n *Node) *ssa.Value {
if ft.IsFloat() || tt.IsFloat() { if ft.IsFloat() || tt.IsFloat() {
conv, ok := fpConvOpToSSA[twoTypes{s.concreteEtype(ft), s.concreteEtype(tt)}] conv, ok := fpConvOpToSSA[twoTypes{s.concreteEtype(ft), s.concreteEtype(tt)}]
if s.config.IntSize == 4 {
if conv1, ok1 := fpConvOpToSSA32[twoTypes{s.concreteEtype(ft), s.concreteEtype(tt)}]; ok1 {
conv = conv1
}
}
if !ok { if !ok {
s.Fatalf("weird float conversion %s -> %s", ft, tt) s.Fatalf("weird float conversion %s -> %s", ft, tt)
} }
......
...@@ -1094,12 +1094,12 @@ opswitch: ...@@ -1094,12 +1094,12 @@ opswitch:
if n.Type.IsFloat() { if n.Type.IsFloat() {
if n.Left.Type.Etype == TINT64 { if n.Left.Type.Etype == TINT64 {
n = mkcall("int64tofloat64", n.Type, init, conv(n.Left, Types[TINT64])) n = conv(mkcall("int64tofloat64", Types[TFLOAT64], init, conv(n.Left, Types[TINT64])), n.Type)
break break
} }
if n.Left.Type.Etype == TUINT64 { if n.Left.Type.Etype == TUINT64 {
n = mkcall("uint64tofloat64", n.Type, init, conv(n.Left, Types[TUINT64])) n = conv(mkcall("uint64tofloat64", Types[TFLOAT64], init, conv(n.Left, Types[TUINT64])), n.Type)
break break
} }
} }
......
...@@ -94,6 +94,8 @@ func decomposeBuiltIn(f *Func) { ...@@ -94,6 +94,8 @@ func decomposeBuiltIn(f *Func) {
f.NamedValues[dataName] = append(f.NamedValues[dataName], data) f.NamedValues[dataName] = append(f.NamedValues[dataName], data)
} }
delete(f.NamedValues, name) delete(f.NamedValues, name)
case t.IsFloat():
// floats are never decomposed, even ones bigger than IntSize
case t.Size() > f.Config.IntSize: case t.Size() > f.Config.IntSize:
f.Unimplementedf("undecomposed named type %s %s", name, t) f.Unimplementedf("undecomposed named type %s %s", name, t)
default: default:
...@@ -115,6 +117,8 @@ func decomposeBuiltInPhi(v *Value) { ...@@ -115,6 +117,8 @@ func decomposeBuiltInPhi(v *Value) {
decomposeSlicePhi(v) decomposeSlicePhi(v)
case v.Type.IsInterface(): case v.Type.IsInterface():
decomposeInterfacePhi(v) decomposeInterfacePhi(v)
case v.Type.IsFloat():
// floats are never decomposed, even ones bigger than IntSize
case v.Type.Size() > v.Block.Func.Config.IntSize: case v.Type.Size() > v.Block.Func.Config.IntSize:
v.Unimplementedf("undecomposed type %s", v.Type) v.Unimplementedf("undecomposed type %s", v.Type)
} }
......
...@@ -6,6 +6,8 @@ ...@@ -6,6 +6,8 @@
(Add32 x y) -> (ADD x y) (Add32 x y) -> (ADD x y)
(Add16 x y) -> (ADD x y) (Add16 x y) -> (ADD x y)
(Add8 x y) -> (ADD x y) (Add8 x y) -> (ADD x y)
(Add32F x y) -> (ADDF x y)
(Add64F x y) -> (ADDD x y)
(Add32carry x y) -> (ADDS x y) (Add32carry x y) -> (ADDS x y)
(Add32withcarry x y c) -> (ADC x y c) (Add32withcarry x y c) -> (ADC x y c)
...@@ -14,6 +16,8 @@ ...@@ -14,6 +16,8 @@
(Sub32 x y) -> (SUB x y) (Sub32 x y) -> (SUB x y)
(Sub16 x y) -> (SUB x y) (Sub16 x y) -> (SUB x y)
(Sub8 x y) -> (SUB x y) (Sub8 x y) -> (SUB x y)
(Sub32F x y) -> (SUBF x y)
(Sub64F x y) -> (SUBD x y)
(Sub32carry x y) -> (SUBS x y) (Sub32carry x y) -> (SUBS x y)
(Sub32withcarry x y c) -> (SBC x y c) (Sub32withcarry x y c) -> (SBC x y c)
...@@ -21,6 +25,8 @@ ...@@ -21,6 +25,8 @@
(Mul32 x y) -> (MUL x y) (Mul32 x y) -> (MUL x y)
(Mul16 x y) -> (MUL x y) (Mul16 x y) -> (MUL x y)
(Mul8 x y) -> (MUL x y) (Mul8 x y) -> (MUL x y)
(Mul32F x y) -> (MULF x y)
(Mul64F x y) -> (MULD x y)
(Hmul32 x y) -> (HMUL x y) (Hmul32 x y) -> (HMUL x y)
(Hmul32u x y) -> (HMULU x y) (Hmul32u x y) -> (HMULU x y)
...@@ -37,6 +43,8 @@ ...@@ -37,6 +43,8 @@
(Div16u x y) -> (DIVU (ZeroExt16to32 x) (ZeroExt16to32 y)) (Div16u x y) -> (DIVU (ZeroExt16to32 x) (ZeroExt16to32 y))
(Div8 x y) -> (DIV (SignExt8to32 x) (SignExt8to32 y)) (Div8 x y) -> (DIV (SignExt8to32 x) (SignExt8to32 y))
(Div8u x y) -> (DIVU (ZeroExt8to32 x) (ZeroExt8to32 y)) (Div8u x y) -> (DIVU (ZeroExt8to32 x) (ZeroExt8to32 y))
(Div32F x y) -> (DIVF x y)
(Div64F x y) -> (DIVD x y)
(Mod32 x y) -> (MOD x y) (Mod32 x y) -> (MOD x y)
(Mod32u x y) -> (MODU x y) (Mod32u x y) -> (MODU x y)
...@@ -61,11 +69,16 @@ ...@@ -61,11 +69,16 @@
(Neg32 x) -> (RSBconst [0] x) (Neg32 x) -> (RSBconst [0] x)
(Neg16 x) -> (RSBconst [0] x) (Neg16 x) -> (RSBconst [0] x)
(Neg8 x) -> (RSBconst [0] x) (Neg8 x) -> (RSBconst [0] x)
//TODO: implement NEGF, NEGD in assembler and soft float simulator, and use them.
(Neg32F x) -> (MULF (MOVFconst [int64(math.Float64bits(-1))]) x)
(Neg64F x) -> (MULD (MOVDconst [int64(math.Float64bits(-1))]) x)
(Com32 x) -> (MVN x) (Com32 x) -> (MVN x)
(Com16 x) -> (MVN x) (Com16 x) -> (MVN x)
(Com8 x) -> (MVN x) (Com8 x) -> (MVN x)
(Sqrt x) -> (SQRTD x)
// boolean ops -- booleans are represented with 0=false, 1=true // boolean ops -- booleans are represented with 0=false, 1=true
(AndB x y) -> (AND x y) (AndB x y) -> (AND x y)
(OrB x y) -> (OR x y) (OrB x y) -> (OR x y)
...@@ -143,6 +156,8 @@ ...@@ -143,6 +156,8 @@
(Const8 [val]) -> (MOVWconst [val]) (Const8 [val]) -> (MOVWconst [val])
(Const16 [val]) -> (MOVWconst [val]) (Const16 [val]) -> (MOVWconst [val])
(Const32 [val]) -> (MOVWconst [val]) (Const32 [val]) -> (MOVWconst [val])
(Const32F [val]) -> (MOVFconst [val])
(Const64F [val]) -> (MOVDconst [val])
(ConstNil) -> (MOVWconst [0]) (ConstNil) -> (MOVWconst [0])
(ConstBool [b]) -> (MOVWconst [b]) (ConstBool [b]) -> (MOVWconst [b])
...@@ -164,20 +179,38 @@ ...@@ -164,20 +179,38 @@
(Signmask x) -> (SRAconst x [31]) (Signmask x) -> (SRAconst x [31])
(Zeromask x) -> (LoweredZeromask x) (Zeromask x) -> (LoweredZeromask x)
// float <-> int conversion
(Cvt32to32F x) -> (MOVWF x)
(Cvt32to64F x) -> (MOVWD x)
(Cvt32Uto32F x) -> (MOVWUF x)
(Cvt32Uto64F x) -> (MOVWUD x)
(Cvt32Fto32 x) -> (MOVFW x)
(Cvt64Fto32 x) -> (MOVDW x)
(Cvt32Fto32U x) -> (MOVFWU x)
(Cvt64Fto32U x) -> (MOVDWU x)
(Cvt32Fto64F x) -> (MOVFD x)
(Cvt64Fto32F x) -> (MOVDF x)
// comparisons // comparisons
(Eq8 x y) -> (Equal (CMP (ZeroExt8to32 x) (ZeroExt8to32 y))) (Eq8 x y) -> (Equal (CMP (ZeroExt8to32 x) (ZeroExt8to32 y)))
(Eq16 x y) -> (Equal (CMP (ZeroExt16to32 x) (ZeroExt16to32 y))) (Eq16 x y) -> (Equal (CMP (ZeroExt16to32 x) (ZeroExt16to32 y)))
(Eq32 x y) -> (Equal (CMP x y)) (Eq32 x y) -> (Equal (CMP x y))
(EqPtr x y) -> (Equal (CMP x y)) (EqPtr x y) -> (Equal (CMP x y))
(Eq32F x y) -> (Equal (CMPF x y))
(Eq64F x y) -> (Equal (CMPD x y))
(Neq8 x y) -> (NotEqual (CMP (ZeroExt8to32 x) (ZeroExt8to32 y))) (Neq8 x y) -> (NotEqual (CMP (ZeroExt8to32 x) (ZeroExt8to32 y)))
(Neq16 x y) -> (NotEqual (CMP (ZeroExt16to32 x) (ZeroExt16to32 y))) (Neq16 x y) -> (NotEqual (CMP (ZeroExt16to32 x) (ZeroExt16to32 y)))
(Neq32 x y) -> (NotEqual (CMP x y)) (Neq32 x y) -> (NotEqual (CMP x y))
(NeqPtr x y) -> (NotEqual (CMP x y)) (NeqPtr x y) -> (NotEqual (CMP x y))
(Neq32F x y) -> (NotEqual (CMPF x y))
(Neq64F x y) -> (NotEqual (CMPD x y))
(Less8 x y) -> (LessThan (CMP (SignExt8to32 x) (SignExt8to32 y))) (Less8 x y) -> (LessThan (CMP (SignExt8to32 x) (SignExt8to32 y)))
(Less16 x y) -> (LessThan (CMP (SignExt16to32 x) (SignExt16to32 y))) (Less16 x y) -> (LessThan (CMP (SignExt16to32 x) (SignExt16to32 y)))
(Less32 x y) -> (LessThan (CMP x y)) (Less32 x y) -> (LessThan (CMP x y))
(Less32F x y) -> (GreaterThan (CMPF y x)) // reverse operands to work around NaN
(Less64F x y) -> (GreaterThan (CMPD y x)) // reverse operands to work around NaN
(Less8U x y) -> (LessThanU (CMP (ZeroExt8to32 x) (ZeroExt8to32 y))) (Less8U x y) -> (LessThanU (CMP (ZeroExt8to32 x) (ZeroExt8to32 y)))
(Less16U x y) -> (LessThanU (CMP (ZeroExt16to32 x) (ZeroExt16to32 y))) (Less16U x y) -> (LessThanU (CMP (ZeroExt16to32 x) (ZeroExt16to32 y)))
...@@ -186,6 +219,8 @@ ...@@ -186,6 +219,8 @@
(Leq8 x y) -> (LessEqual (CMP (SignExt8to32 x) (SignExt8to32 y))) (Leq8 x y) -> (LessEqual (CMP (SignExt8to32 x) (SignExt8to32 y)))
(Leq16 x y) -> (LessEqual (CMP (SignExt16to32 x) (SignExt16to32 y))) (Leq16 x y) -> (LessEqual (CMP (SignExt16to32 x) (SignExt16to32 y)))
(Leq32 x y) -> (LessEqual (CMP x y)) (Leq32 x y) -> (LessEqual (CMP x y))
(Leq32F x y) -> (GreaterEqual (CMPF y x)) // reverse operands to work around NaN
(Leq64F x y) -> (GreaterEqual (CMPD y x)) // reverse operands to work around NaN
(Leq8U x y) -> (LessEqualU (CMP (ZeroExt8to32 x) (ZeroExt8to32 y))) (Leq8U x y) -> (LessEqualU (CMP (ZeroExt8to32 x) (ZeroExt8to32 y)))
(Leq16U x y) -> (LessEqualU (CMP (ZeroExt16to32 x) (ZeroExt16to32 y))) (Leq16U x y) -> (LessEqualU (CMP (ZeroExt16to32 x) (ZeroExt16to32 y)))
...@@ -194,6 +229,8 @@ ...@@ -194,6 +229,8 @@
(Greater8 x y) -> (GreaterThan (CMP (SignExt8to32 x) (SignExt8to32 y))) (Greater8 x y) -> (GreaterThan (CMP (SignExt8to32 x) (SignExt8to32 y)))
(Greater16 x y) -> (GreaterThan (CMP (SignExt16to32 x) (SignExt16to32 y))) (Greater16 x y) -> (GreaterThan (CMP (SignExt16to32 x) (SignExt16to32 y)))
(Greater32 x y) -> (GreaterThan (CMP x y)) (Greater32 x y) -> (GreaterThan (CMP x y))
(Greater32F x y) -> (GreaterThan (CMPF x y))
(Greater64F x y) -> (GreaterThan (CMPD x y))
(Greater8U x y) -> (GreaterThanU (CMP (ZeroExt8to32 x) (ZeroExt8to32 y))) (Greater8U x y) -> (GreaterThanU (CMP (ZeroExt8to32 x) (ZeroExt8to32 y)))
(Greater16U x y) -> (GreaterThanU (CMP (ZeroExt16to32 x) (ZeroExt16to32 y))) (Greater16U x y) -> (GreaterThanU (CMP (ZeroExt16to32 x) (ZeroExt16to32 y)))
...@@ -202,6 +239,8 @@ ...@@ -202,6 +239,8 @@
(Geq8 x y) -> (GreaterEqual (CMP (SignExt8to32 x) (SignExt8to32 y))) (Geq8 x y) -> (GreaterEqual (CMP (SignExt8to32 x) (SignExt8to32 y)))
(Geq16 x y) -> (GreaterEqual (CMP (SignExt16to32 x) (SignExt16to32 y))) (Geq16 x y) -> (GreaterEqual (CMP (SignExt16to32 x) (SignExt16to32 y)))
(Geq32 x y) -> (GreaterEqual (CMP x y)) (Geq32 x y) -> (GreaterEqual (CMP x y))
(Geq32F x y) -> (GreaterEqual (CMPF x y))
(Geq64F x y) -> (GreaterEqual (CMPD x y))
(Geq8U x y) -> (GreaterEqualU (CMP (ZeroExt8to32 x) (ZeroExt8to32 y))) (Geq8U x y) -> (GreaterEqualU (CMP (ZeroExt8to32 x) (ZeroExt8to32 y)))
(Geq16U x y) -> (GreaterEqualU (CMP (ZeroExt16to32 x) (ZeroExt16to32 y))) (Geq16U x y) -> (GreaterEqualU (CMP (ZeroExt16to32 x) (ZeroExt16to32 y)))
...@@ -218,11 +257,15 @@ ...@@ -218,11 +257,15 @@
(Load <t> ptr mem) && (is16BitInt(t) && isSigned(t)) -> (MOVHload ptr mem) (Load <t> ptr mem) && (is16BitInt(t) && isSigned(t)) -> (MOVHload ptr mem)
(Load <t> ptr mem) && (is16BitInt(t) && !isSigned(t)) -> (MOVHUload ptr mem) (Load <t> ptr mem) && (is16BitInt(t) && !isSigned(t)) -> (MOVHUload ptr mem)
(Load <t> ptr mem) && (is32BitInt(t) || isPtr(t)) -> (MOVWload ptr mem) (Load <t> ptr mem) && (is32BitInt(t) || isPtr(t)) -> (MOVWload ptr mem)
(Load <t> ptr mem) && is32BitFloat(t) -> (MOVFload ptr mem)
(Load <t> ptr mem) && is64BitFloat(t) -> (MOVDload ptr mem)
// stores // stores
(Store [1] ptr val mem) -> (MOVBstore ptr val mem) (Store [1] ptr val mem) -> (MOVBstore ptr val mem)
(Store [2] ptr val mem) -> (MOVHstore ptr val mem) (Store [2] ptr val mem) -> (MOVHstore ptr val mem)
(Store [4] ptr val mem) -> (MOVWstore ptr val mem) (Store [4] ptr val mem) && !is32BitFloat(val.Type) -> (MOVWstore ptr val mem)
(Store [4] ptr val mem) && is32BitFloat(val.Type) -> (MOVFstore ptr val mem)
(Store [8] ptr val mem) && is64BitFloat(val.Type) -> (MOVDstore ptr val mem)
// zero instructions // zero instructions
//TODO: check alignment? //TODO: check alignment?
...@@ -336,6 +379,10 @@ ...@@ -336,6 +379,10 @@
(MOVHUload [off1+off2] {mergeSym(sym1,sym2)} ptr mem) (MOVHUload [off1+off2] {mergeSym(sym1,sym2)} ptr mem)
(MOVWload [off1] {sym1} (ADDconst [off2] {sym2} ptr) mem) && canMergeSym(sym1,sym2) -> (MOVWload [off1] {sym1} (ADDconst [off2] {sym2} ptr) mem) && canMergeSym(sym1,sym2) ->
(MOVWload [off1+off2] {mergeSym(sym1,sym2)} ptr mem) (MOVWload [off1+off2] {mergeSym(sym1,sym2)} ptr mem)
(MOVFload [off1] {sym1} (ADDconst [off2] {sym2} ptr) mem) && canMergeSym(sym1,sym2) ->
(MOVFload [off1+off2] {mergeSym(sym1,sym2)} ptr mem)
(MOVDload [off1] {sym1} (ADDconst [off2] {sym2} ptr) mem) && canMergeSym(sym1,sym2) ->
(MOVDload [off1+off2] {mergeSym(sym1,sym2)} ptr mem)
(MOVBstore [off1] {sym1} (ADDconst [off2] {sym2} ptr) val mem) && canMergeSym(sym1,sym2) -> (MOVBstore [off1] {sym1} (ADDconst [off2] {sym2} ptr) val mem) && canMergeSym(sym1,sym2) ->
(MOVBstore [off1+off2] {mergeSym(sym1,sym2)} ptr val mem) (MOVBstore [off1+off2] {mergeSym(sym1,sym2)} ptr val mem)
...@@ -343,6 +390,10 @@ ...@@ -343,6 +390,10 @@
(MOVHstore [off1+off2] {mergeSym(sym1,sym2)} ptr val mem) (MOVHstore [off1+off2] {mergeSym(sym1,sym2)} ptr val mem)
(MOVWstore [off1] {sym1} (ADDconst [off2] {sym2} ptr) val mem) && canMergeSym(sym1,sym2) -> (MOVWstore [off1] {sym1} (ADDconst [off2] {sym2} ptr) val mem) && canMergeSym(sym1,sym2) ->
(MOVWstore [off1+off2] {mergeSym(sym1,sym2)} ptr val mem) (MOVWstore [off1+off2] {mergeSym(sym1,sym2)} ptr val mem)
(MOVFstore [off1] {sym1} (ADDconst [off2] {sym2} ptr) val mem) && canMergeSym(sym1,sym2) ->
(MOVFstore [off1+off2] {mergeSym(sym1,sym2)} ptr val mem)
(MOVDstore [off1] {sym1} (ADDconst [off2] {sym2} ptr) val mem) && canMergeSym(sym1,sym2) ->
(MOVDstore [off1+off2] {mergeSym(sym1,sym2)} ptr val mem)
(ADD (MUL x y) a) -> (MULA x y a) (ADD (MUL x y) a) -> (MULA x y a)
(ADD a (MUL x y)) -> (MULA x y a) (ADD a (MUL x y)) -> (MULA x y a)
...@@ -22,6 +22,8 @@ import "strings" ...@@ -22,6 +22,8 @@ import "strings"
// HU = 16 bit unsigned // HU = 16 bit unsigned
// B (byte) = 8 bit // B (byte) = 8 bit
// BU = 8 bit unsigned // BU = 8 bit unsigned
// F (float) = 32 bit float
// D (double) = 64 bit float
var regNamesARM = []string{ var regNamesARM = []string{
"R0", "R0",
...@@ -41,6 +43,23 @@ var regNamesARM = []string{ ...@@ -41,6 +43,23 @@ var regNamesARM = []string{
"R14", // link "R14", // link
"R15", // pc "R15", // pc
"F0",
"F1",
"F2",
"F3",
"F4",
"F5",
"F6",
"F7",
"F8",
"F9",
"F10",
"F11",
"F12",
"F13",
"F14",
"F15", // tmp
// pseudo-registers // pseudo-registers
"FLAGS", "FLAGS",
"SB", "SB",
...@@ -73,7 +92,8 @@ func init() { ...@@ -73,7 +92,8 @@ func init() {
gpsp = gp | buildReg("SP") gpsp = gp | buildReg("SP")
gpspsb = gpsp | buildReg("SB") gpspsb = gpsp | buildReg("SB")
flags = buildReg("FLAGS") flags = buildReg("FLAGS")
callerSave = gp | flags fp = buildReg("F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15")
callerSave = gp | fp | flags
) )
// Common regInfo // Common regInfo
var ( var (
...@@ -88,6 +108,14 @@ func init() { ...@@ -88,6 +108,14 @@ func init() {
gp31 = regInfo{inputs: []regMask{gp, gp, gp}, outputs: []regMask{gp}} gp31 = regInfo{inputs: []regMask{gp, gp, gp}, outputs: []regMask{gp}}
gpload = regInfo{inputs: []regMask{gpspsb}, outputs: []regMask{gp}} gpload = regInfo{inputs: []regMask{gpspsb}, outputs: []regMask{gp}}
gpstore = regInfo{inputs: []regMask{gpspsb, gp}, outputs: []regMask{}} gpstore = regInfo{inputs: []regMask{gpspsb, gp}, outputs: []regMask{}}
fp01 = regInfo{inputs: []regMask{}, outputs: []regMask{fp}}
fp11 = regInfo{inputs: []regMask{fp}, outputs: []regMask{fp}}
fpgp = regInfo{inputs: []regMask{fp}, outputs: []regMask{gp}}
gpfp = regInfo{inputs: []regMask{gp}, outputs: []regMask{fp}}
fp21 = regInfo{inputs: []regMask{fp, fp}, outputs: []regMask{fp}}
fp2flags = regInfo{inputs: []regMask{fp, fp}, outputs: []regMask{flags}}
fpload = regInfo{inputs: []regMask{gpspsb}, outputs: []regMask{fp}}
fpstore = regInfo{inputs: []regMask{gpspsb, fp}, outputs: []regMask{}}
readflags = regInfo{inputs: []regMask{flags}, outputs: []regMask{gp}} readflags = regInfo{inputs: []regMask{flags}, outputs: []regMask{gp}}
) )
ops := []opData{ ops := []opData{
...@@ -114,6 +142,15 @@ func init() { ...@@ -114,6 +142,15 @@ func init() {
{name: "MULLU", argLength: 2, reg: regInfo{inputs: []regMask{gp, gp}, outputs: []regMask{gp &^ buildReg("R0")}, clobbers: buildReg("R0")}, asm: "MULLU", commutative: true}, // arg0 * arg1, results 64-bit, high 32-bit in R0 {name: "MULLU", argLength: 2, reg: regInfo{inputs: []regMask{gp, gp}, outputs: []regMask{gp &^ buildReg("R0")}, clobbers: buildReg("R0")}, asm: "MULLU", commutative: true}, // arg0 * arg1, results 64-bit, high 32-bit in R0
{name: "MULA", argLength: 3, reg: gp31, asm: "MULA"}, // arg0 * arg1 + arg2 {name: "MULA", argLength: 3, reg: gp31, asm: "MULA"}, // arg0 * arg1 + arg2
{name: "ADDF", argLength: 2, reg: fp21, asm: "ADDF", commutative: true}, // arg0 + arg1
{name: "ADDD", argLength: 2, reg: fp21, asm: "ADDD", commutative: true}, // arg0 + arg1
{name: "SUBF", argLength: 2, reg: fp21, asm: "SUBF"}, // arg0 - arg1
{name: "SUBD", argLength: 2, reg: fp21, asm: "SUBD"}, // arg0 - arg1
{name: "MULF", argLength: 2, reg: fp21, asm: "MULF", commutative: true}, // arg0 * arg1
{name: "MULD", argLength: 2, reg: fp21, asm: "MULD", commutative: true}, // arg0 * arg1
{name: "DIVF", argLength: 2, reg: fp21, asm: "DIVF"}, // arg0 / arg1
{name: "DIVD", argLength: 2, reg: fp21, asm: "DIVD"}, // arg0 / arg1
{name: "AND", argLength: 2, reg: gp21, asm: "AND", commutative: true}, // arg0 & arg1 {name: "AND", argLength: 2, reg: gp21, asm: "AND", commutative: true}, // arg0 & arg1
{name: "ANDconst", argLength: 1, reg: gp11, asm: "AND", aux: "Int32"}, // arg0 & auxInt {name: "ANDconst", argLength: 1, reg: gp11, asm: "AND", aux: "Int32"}, // arg0 & auxInt
{name: "OR", argLength: 2, reg: gp21, asm: "ORR", commutative: true}, // arg0 | arg1 {name: "OR", argLength: 2, reg: gp21, asm: "ORR", commutative: true}, // arg0 | arg1
...@@ -126,6 +163,8 @@ func init() { ...@@ -126,6 +163,8 @@ func init() {
// unary ops // unary ops
{name: "MVN", argLength: 1, reg: gp11, asm: "MVN"}, // ^arg0 {name: "MVN", argLength: 1, reg: gp11, asm: "MVN"}, // ^arg0
{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: gp21cf, asm: "SLL"}, // arg0 << arg1, results 0 for large shift
{name: "SLLconst", argLength: 1, reg: gp11, asm: "SLL", aux: "Int32"}, // arg0 << auxInt {name: "SLLconst", argLength: 1, reg: gp11, asm: "SLL", aux: "Int32"}, // arg0 << auxInt
...@@ -143,24 +182,43 @@ func init() { ...@@ -143,24 +182,43 @@ func init() {
{name: "TSTconst", argLength: 1, reg: gp1flags, asm: "TST", aux: "Int32", typ: "Flags"}, // arg0 & auxInt compare to 0 {name: "TSTconst", argLength: 1, reg: gp1flags, asm: "TST", aux: "Int32", typ: "Flags"}, // arg0 & auxInt compare to 0
{name: "TEQ", argLength: 2, reg: gp2flags, asm: "TEQ", typ: "Flags", commutative: true}, // arg0 ^ arg1 compare to 0 {name: "TEQ", argLength: 2, reg: gp2flags, asm: "TEQ", typ: "Flags", commutative: true}, // arg0 ^ arg1 compare to 0
{name: "TEQconst", argLength: 1, reg: gp1flags, asm: "TEQ", aux: "Int32", typ: "Flags"}, // arg0 ^ auxInt compare to 0 {name: "TEQconst", argLength: 1, reg: gp1flags, asm: "TEQ", aux: "Int32", typ: "Flags"}, // arg0 ^ auxInt compare to 0
{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: "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: "MOVDconst", argLength: 0, reg: fp01, aux: "Float64", asm: "MOVD", typ: "Float64", rematerializeable: true}, // auxint as 64-bit float
{name: "MOVBload", argLength: 2, reg: gpload, aux: "SymOff", asm: "MOVB", typ: "Int8"}, // load from arg0 + auxInt + aux. arg1=mem. {name: "MOVBload", argLength: 2, reg: gpload, aux: "SymOff", asm: "MOVB", typ: "Int8"}, // load from arg0 + auxInt + aux. arg1=mem.
{name: "MOVBUload", argLength: 2, reg: gpload, aux: "SymOff", asm: "MOVBU", typ: "UInt8"}, // load from arg0 + auxInt + aux. arg1=mem. {name: "MOVBUload", argLength: 2, reg: gpload, aux: "SymOff", asm: "MOVBU", typ: "UInt8"}, // load from arg0 + auxInt + aux. arg1=mem.
{name: "MOVHload", argLength: 2, reg: gpload, aux: "SymOff", asm: "MOVH", typ: "Int16"}, // load from arg0 + auxInt + aux. arg1=mem. {name: "MOVHload", argLength: 2, reg: gpload, aux: "SymOff", asm: "MOVH", typ: "Int16"}, // load from arg0 + auxInt + aux. arg1=mem.
{name: "MOVHUload", argLength: 2, reg: gpload, aux: "SymOff", asm: "MOVHU", typ: "UInt16"}, // load from arg0 + auxInt + aux. arg1=mem. {name: "MOVHUload", argLength: 2, reg: gpload, aux: "SymOff", asm: "MOVHU", typ: "UInt16"}, // load from arg0 + auxInt + aux. arg1=mem.
{name: "MOVWload", argLength: 2, reg: gpload, aux: "SymOff", asm: "MOVW", typ: "UInt32"}, // load from arg0 + auxInt + aux. arg1=mem. {name: "MOVWload", argLength: 2, reg: gpload, aux: "SymOff", asm: "MOVW", typ: "UInt32"}, // load from arg0 + auxInt + aux. arg1=mem.
{name: "MOVFload", argLength: 2, reg: fpload, aux: "SymOff", asm: "MOVF", typ: "Float32"}, // load from arg0 + auxInt + aux. arg1=mem.
{name: "MOVDload", argLength: 2, reg: fpload, aux: "SymOff", asm: "MOVD", typ: "Float64"}, // load from arg0 + auxInt + aux. arg1=mem.
{name: "MOVBstore", argLength: 3, reg: gpstore, aux: "SymOff", asm: "MOVB", typ: "Mem"}, // store 1 byte of arg1 to arg0 + auxInt + aux. arg2=mem. {name: "MOVBstore", argLength: 3, reg: gpstore, aux: "SymOff", asm: "MOVB", typ: "Mem"}, // store 1 byte of arg1 to arg0 + auxInt + aux. arg2=mem.
{name: "MOVHstore", argLength: 3, reg: gpstore, aux: "SymOff", asm: "MOVH", typ: "Mem"}, // store 2 bytes of arg1 to arg0 + auxInt + aux. arg2=mem. {name: "MOVHstore", argLength: 3, reg: gpstore, aux: "SymOff", asm: "MOVH", typ: "Mem"}, // store 2 bytes of arg1 to arg0 + auxInt + aux. arg2=mem.
{name: "MOVWstore", argLength: 3, reg: gpstore, aux: "SymOff", asm: "MOVW", typ: "Mem"}, // store 4 bytes of arg1 to arg0 + auxInt + aux. arg2=mem. {name: "MOVWstore", argLength: 3, reg: gpstore, aux: "SymOff", asm: "MOVW", 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: "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
{name: "MOVHUreg", argLength: 1, reg: gp11, asm: "MOVHU"}, // move from arg0, unsign-extended from half {name: "MOVHUreg", argLength: 1, reg: gp11, asm: "MOVHU"}, // move from arg0, unsign-extended from half
{name: "MOVWF", argLength: 1, reg: gpfp, asm: "MOVWF"}, // int32 -> float32
{name: "MOVWD", argLength: 1, reg: gpfp, asm: "MOVWD"}, // int32 -> float64
{name: "MOVWUF", argLength: 1, reg: gpfp, asm: "MOVWF"}, // uint32 -> float32, set U bit in the instruction
{name: "MOVWUD", argLength: 1, reg: gpfp, asm: "MOVWD"}, // uint32 -> float64, set U bit in the instruction
{name: "MOVFW", argLength: 1, reg: fpgp, asm: "MOVFW"}, // float32 -> int32
{name: "MOVDW", argLength: 1, reg: fpgp, asm: "MOVDW"}, // float64 -> int32
{name: "MOVFWU", argLength: 1, reg: fpgp, asm: "MOVFW"}, // float32 -> uint32, set U bit in the instruction
{name: "MOVDWU", argLength: 1, reg: fpgp, asm: "MOVDW"}, // float64 -> uint32, set U bit in the instruction
{name: "MOVFD", argLength: 1, reg: fp11, asm: "MOVFD"}, // float32 -> float64
{name: "MOVDF", argLength: 1, reg: fp11, asm: "MOVDF"}, // float64 -> float32
{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{[]regMask{gpsp, buildReg("R7"), 0}, callerSave, nil}, aux: "Int64"}, // call function via closure. arg0=codeptr, arg1=closure, arg2=mem, auxint=argsize, returns mem {name: "CALLclosure", argLength: 3, reg: regInfo{[]regMask{gpsp, buildReg("R7"), 0}, callerSave, nil}, 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
...@@ -290,7 +348,7 @@ func init() { ...@@ -290,7 +348,7 @@ func init() {
blocks: blocks, blocks: blocks,
regnames: regNamesARM, regnames: regNamesARM,
gpregmask: gp, gpregmask: gp,
fpregmask: 0, // fp not implemented yet fpregmask: fp,
flagmask: flags, flagmask: flags,
framepointerreg: -1, // not used framepointerreg: -1, // not used
}) })
......
...@@ -433,6 +433,11 @@ var genericOps = []opData{ ...@@ -433,6 +433,11 @@ var genericOps = []opData{
{name: "Signmask", argLength: 1, typ: "Int32"}, // 0 if arg0 >= 0, -1 if arg0 < 0 {name: "Signmask", argLength: 1, typ: "Int32"}, // 0 if arg0 >= 0, -1 if arg0 < 0
{name: "Zeromask", argLength: 1, typ: "UInt32"}, // 0 if arg0 == 0, 0xffffffff if arg0 != 0 {name: "Zeromask", argLength: 1, typ: "UInt32"}, // 0 if arg0 == 0, 0xffffffff if arg0 != 0
{name: "Cvt32Uto32F", argLength: 1}, // uint32 -> float32, only used on 32-bit arch
{name: "Cvt32Uto64F", argLength: 1}, // uint32 -> float64, only used on 32-bit arch
{name: "Cvt32Fto32U", argLength: 1}, // float32 -> uint32, only used on 32-bit arch
{name: "Cvt64Fto32U", argLength: 1}, // float64 -> uint32, only used on 32-bit arch
// pseudo-ops for breaking Tuple // pseudo-ops for breaking Tuple
{name: "Select0", argLength: 1}, // the first component of a tuple {name: "Select0", argLength: 1}, // the first component of a tuple
{name: "Select1", argLength: 1}, // the second component of a tuple {name: "Select1", argLength: 1}, // the second component of a tuple
......
...@@ -342,6 +342,14 @@ const ( ...@@ -342,6 +342,14 @@ const (
OpARMSBC OpARMSBC
OpARMMULLU OpARMMULLU
OpARMMULA OpARMMULA
OpARMADDF
OpARMADDD
OpARMSUBF
OpARMSUBD
OpARMMULF
OpARMMULD
OpARMDIVF
OpARMDIVD
OpARMAND OpARMAND
OpARMANDconst OpARMANDconst
OpARMOR OpARMOR
...@@ -351,6 +359,7 @@ const ( ...@@ -351,6 +359,7 @@ const (
OpARMBIC OpARMBIC
OpARMBICconst OpARMBICconst
OpARMMVN OpARMMVN
OpARMSQRTD
OpARMSLL OpARMSLL
OpARMSLLconst OpARMSLLconst
OpARMSRL OpARMSRL
...@@ -366,19 +375,37 @@ const ( ...@@ -366,19 +375,37 @@ const (
OpARMTSTconst OpARMTSTconst
OpARMTEQ OpARMTEQ
OpARMTEQconst OpARMTEQconst
OpARMCMPF
OpARMCMPD
OpARMMOVWconst OpARMMOVWconst
OpARMMOVFconst
OpARMMOVDconst
OpARMMOVBload OpARMMOVBload
OpARMMOVBUload OpARMMOVBUload
OpARMMOVHload OpARMMOVHload
OpARMMOVHUload OpARMMOVHUload
OpARMMOVWload OpARMMOVWload
OpARMMOVFload
OpARMMOVDload
OpARMMOVBstore OpARMMOVBstore
OpARMMOVHstore OpARMMOVHstore
OpARMMOVWstore OpARMMOVWstore
OpARMMOVFstore
OpARMMOVDstore
OpARMMOVBreg OpARMMOVBreg
OpARMMOVBUreg OpARMMOVBUreg
OpARMMOVHreg OpARMMOVHreg
OpARMMOVHUreg OpARMMOVHUreg
OpARMMOVWF
OpARMMOVWD
OpARMMOVWUF
OpARMMOVWUD
OpARMMOVFW
OpARMMOVDW
OpARMMOVFWU
OpARMMOVDWU
OpARMMOVFD
OpARMMOVDF
OpARMCALLstatic OpARMCALLstatic
OpARMCALLclosure OpARMCALLclosure
OpARMCALLdefer OpARMCALLdefer
...@@ -702,6 +729,10 @@ const ( ...@@ -702,6 +729,10 @@ const (
OpMul32uhilo OpMul32uhilo
OpSignmask OpSignmask
OpZeromask OpZeromask
OpCvt32Uto32F
OpCvt32Uto64F
OpCvt32Fto32U
OpCvt64Fto32U
OpSelect0 OpSelect0
OpSelect1 OpSelect1
) )
...@@ -3906,7 +3937,7 @@ var opcodeTable = [...]opInfo{ ...@@ -3906,7 +3937,7 @@ var opcodeTable = [...]opInfo{
asm: arm.AADD, asm: arm.AADD,
reg: regInfo{ reg: regInfo{
inputs: []inputInfo{ inputs: []inputInfo{
{0, 144383}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 SP SB {0, 8589947903}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 SP SB
}, },
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
...@@ -4023,7 +4054,7 @@ var opcodeTable = [...]opInfo{ ...@@ -4023,7 +4054,7 @@ var opcodeTable = [...]opInfo{
{0, 5119}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 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 {1, 5119}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
}, },
clobbers: 65536, // FLAGS 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
}, },
...@@ -4038,7 +4069,7 @@ var opcodeTable = [...]opInfo{ ...@@ -4038,7 +4069,7 @@ var opcodeTable = [...]opInfo{
{0, 5119}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 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 {1, 5119}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
}, },
clobbers: 65536, // FLAGS 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
}, },
...@@ -4053,7 +4084,7 @@ var opcodeTable = [...]opInfo{ ...@@ -4053,7 +4084,7 @@ var opcodeTable = [...]opInfo{
{0, 5119}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 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 {1, 5119}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
}, },
clobbers: 65536, // FLAGS 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
}, },
...@@ -4068,7 +4099,7 @@ var opcodeTable = [...]opInfo{ ...@@ -4068,7 +4099,7 @@ var opcodeTable = [...]opInfo{
{0, 5119}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 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 {1, 5119}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
}, },
clobbers: 65536, // FLAGS 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
}, },
...@@ -4084,7 +4115,7 @@ var opcodeTable = [...]opInfo{ ...@@ -4084,7 +4115,7 @@ var opcodeTable = [...]opInfo{
{0, 5119}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 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 {1, 5119}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
}, },
clobbers: 65536, // FLAGS 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
}, },
...@@ -4097,9 +4128,9 @@ var opcodeTable = [...]opInfo{ ...@@ -4097,9 +4128,9 @@ var opcodeTable = [...]opInfo{
asm: arm.AADC, asm: arm.AADC,
reg: regInfo{ reg: regInfo{
inputs: []inputInfo{ inputs: []inputInfo{
{2, 65536}, // FLAGS {2, 4294967296}, // FLAGS
{0, 5119}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 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 {1, 5119}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
}, },
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
...@@ -4115,7 +4146,7 @@ var opcodeTable = [...]opInfo{ ...@@ -4115,7 +4146,7 @@ var opcodeTable = [...]opInfo{
{0, 5119}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 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 {1, 5119}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
}, },
clobbers: 65536, // FLAGS 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
}, },
...@@ -4127,9 +4158,9 @@ var opcodeTable = [...]opInfo{ ...@@ -4127,9 +4158,9 @@ var opcodeTable = [...]opInfo{
asm: arm.ASBC, asm: arm.ASBC,
reg: regInfo{ reg: regInfo{
inputs: []inputInfo{ inputs: []inputInfo{
{2, 65536}, // FLAGS {2, 4294967296}, // FLAGS
{0, 5119}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 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 {1, 5119}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
}, },
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
...@@ -4167,6 +4198,122 @@ var opcodeTable = [...]opInfo{ ...@@ -4167,6 +4198,122 @@ var opcodeTable = [...]opInfo{
}, },
}, },
}, },
{
name: "ADDF",
argLen: 2,
commutative: true,
asm: arm.AADDF,
reg: regInfo{
inputs: []inputInfo{
{0, 4294901760}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15
{1, 4294901760}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15
},
outputs: []regMask{
4294901760, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15
},
},
},
{
name: "ADDD",
argLen: 2,
commutative: true,
asm: arm.AADDD,
reg: regInfo{
inputs: []inputInfo{
{0, 4294901760}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15
{1, 4294901760}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15
},
outputs: []regMask{
4294901760, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15
},
},
},
{
name: "SUBF",
argLen: 2,
asm: arm.ASUBF,
reg: regInfo{
inputs: []inputInfo{
{0, 4294901760}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15
{1, 4294901760}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15
},
outputs: []regMask{
4294901760, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15
},
},
},
{
name: "SUBD",
argLen: 2,
asm: arm.ASUBD,
reg: regInfo{
inputs: []inputInfo{
{0, 4294901760}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15
{1, 4294901760}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15
},
outputs: []regMask{
4294901760, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15
},
},
},
{
name: "MULF",
argLen: 2,
commutative: true,
asm: arm.AMULF,
reg: regInfo{
inputs: []inputInfo{
{0, 4294901760}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15
{1, 4294901760}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15
},
outputs: []regMask{
4294901760, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15
},
},
},
{
name: "MULD",
argLen: 2,
commutative: true,
asm: arm.AMULD,
reg: regInfo{
inputs: []inputInfo{
{0, 4294901760}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15
{1, 4294901760}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15
},
outputs: []regMask{
4294901760, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15
},
},
},
{
name: "DIVF",
argLen: 2,
asm: arm.ADIVF,
reg: regInfo{
inputs: []inputInfo{
{0, 4294901760}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15
{1, 4294901760}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15
},
outputs: []regMask{
4294901760, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15
},
},
},
{
name: "DIVD",
argLen: 2,
asm: arm.ADIVD,
reg: regInfo{
inputs: []inputInfo{
{0, 4294901760}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15
{1, 4294901760}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15
},
outputs: []regMask{
4294901760, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15
},
},
},
{ {
name: "AND", name: "AND",
argLen: 2, argLen: 2,
...@@ -4295,6 +4442,19 @@ var opcodeTable = [...]opInfo{ ...@@ -4295,6 +4442,19 @@ var opcodeTable = [...]opInfo{
}, },
}, },
}, },
{
name: "SQRTD",
argLen: 1,
asm: arm.ASQRTD,
reg: regInfo{
inputs: []inputInfo{
{0, 4294901760}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15
},
outputs: []regMask{
4294901760, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15
},
},
},
{ {
name: "SLL", name: "SLL",
argLen: 2, argLen: 2,
...@@ -4304,7 +4464,7 @@ var opcodeTable = [...]opInfo{ ...@@ -4304,7 +4464,7 @@ var opcodeTable = [...]opInfo{
{0, 5119}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 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 {1, 5119}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
}, },
clobbers: 65536, // FLAGS 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
}, },
...@@ -4333,7 +4493,7 @@ var opcodeTable = [...]opInfo{ ...@@ -4333,7 +4493,7 @@ var opcodeTable = [...]opInfo{
{0, 5119}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 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 {1, 5119}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
}, },
clobbers: 65536, // FLAGS 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
}, },
...@@ -4362,7 +4522,7 @@ var opcodeTable = [...]opInfo{ ...@@ -4362,7 +4522,7 @@ var opcodeTable = [...]opInfo{
{0, 5119}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 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 {1, 5119}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
}, },
clobbers: 65536, // FLAGS 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
}, },
...@@ -4405,7 +4565,7 @@ var opcodeTable = [...]opInfo{ ...@@ -4405,7 +4565,7 @@ var opcodeTable = [...]opInfo{
{1, 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{ outputs: []regMask{
65536, // FLAGS 4294967296, // FLAGS
}, },
}, },
}, },
...@@ -4419,7 +4579,7 @@ var opcodeTable = [...]opInfo{ ...@@ -4419,7 +4579,7 @@ var opcodeTable = [...]opInfo{
{0, 5119}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 {0, 5119}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
}, },
outputs: []regMask{ outputs: []regMask{
65536, // FLAGS 4294967296, // FLAGS
}, },
}, },
}, },
...@@ -4433,7 +4593,7 @@ var opcodeTable = [...]opInfo{ ...@@ -4433,7 +4593,7 @@ var opcodeTable = [...]opInfo{
{1, 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{ outputs: []regMask{
65536, // FLAGS 4294967296, // FLAGS
}, },
}, },
}, },
...@@ -4447,7 +4607,7 @@ var opcodeTable = [...]opInfo{ ...@@ -4447,7 +4607,7 @@ var opcodeTable = [...]opInfo{
{0, 5119}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 {0, 5119}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
}, },
outputs: []regMask{ outputs: []regMask{
65536, // FLAGS 4294967296, // FLAGS
}, },
}, },
}, },
...@@ -4462,7 +4622,7 @@ var opcodeTable = [...]opInfo{ ...@@ -4462,7 +4622,7 @@ var opcodeTable = [...]opInfo{
{1, 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{ outputs: []regMask{
65536, // FLAGS 4294967296, // FLAGS
}, },
}, },
}, },
...@@ -4476,7 +4636,7 @@ var opcodeTable = [...]opInfo{ ...@@ -4476,7 +4636,7 @@ var opcodeTable = [...]opInfo{
{0, 5119}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 {0, 5119}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
}, },
outputs: []regMask{ outputs: []regMask{
65536, // FLAGS 4294967296, // FLAGS
}, },
}, },
}, },
...@@ -4491,7 +4651,7 @@ var opcodeTable = [...]opInfo{ ...@@ -4491,7 +4651,7 @@ var opcodeTable = [...]opInfo{
{1, 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{ outputs: []regMask{
65536, // FLAGS 4294967296, // FLAGS
}, },
}, },
}, },
...@@ -4505,7 +4665,35 @@ var opcodeTable = [...]opInfo{ ...@@ -4505,7 +4665,35 @@ var opcodeTable = [...]opInfo{
{0, 5119}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 {0, 5119}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
}, },
outputs: []regMask{ outputs: []regMask{
65536, // FLAGS 4294967296, // FLAGS
},
},
},
{
name: "CMPF",
argLen: 2,
asm: arm.ACMPF,
reg: regInfo{
inputs: []inputInfo{
{0, 4294901760}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15
{1, 4294901760}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15
},
outputs: []regMask{
4294967296, // FLAGS
},
},
},
{
name: "CMPD",
argLen: 2,
asm: arm.ACMPD,
reg: regInfo{
inputs: []inputInfo{
{0, 4294901760}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15
{1, 4294901760}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15
},
outputs: []regMask{
4294967296, // FLAGS
}, },
}, },
}, },
...@@ -4521,6 +4709,30 @@ var opcodeTable = [...]opInfo{ ...@@ -4521,6 +4709,30 @@ var opcodeTable = [...]opInfo{
}, },
}, },
}, },
{
name: "MOVFconst",
auxType: auxFloat64,
argLen: 0,
rematerializeable: true,
asm: arm.AMOVF,
reg: regInfo{
outputs: []regMask{
4294901760, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15
},
},
},
{
name: "MOVDconst",
auxType: auxFloat64,
argLen: 0,
rematerializeable: true,
asm: arm.AMOVD,
reg: regInfo{
outputs: []regMask{
4294901760, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15
},
},
},
{ {
name: "MOVBload", name: "MOVBload",
auxType: auxSymOff, auxType: auxSymOff,
...@@ -4528,7 +4740,7 @@ var opcodeTable = [...]opInfo{ ...@@ -4528,7 +4740,7 @@ var opcodeTable = [...]opInfo{
asm: arm.AMOVB, asm: arm.AMOVB,
reg: regInfo{ reg: regInfo{
inputs: []inputInfo{ inputs: []inputInfo{
{0, 144383}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 SP SB {0, 8589947903}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 SP SB
}, },
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
...@@ -4542,7 +4754,7 @@ var opcodeTable = [...]opInfo{ ...@@ -4542,7 +4754,7 @@ var opcodeTable = [...]opInfo{
asm: arm.AMOVBU, asm: arm.AMOVBU,
reg: regInfo{ reg: regInfo{
inputs: []inputInfo{ inputs: []inputInfo{
{0, 144383}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 SP SB {0, 8589947903}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 SP SB
}, },
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
...@@ -4556,7 +4768,7 @@ var opcodeTable = [...]opInfo{ ...@@ -4556,7 +4768,7 @@ var opcodeTable = [...]opInfo{
asm: arm.AMOVH, asm: arm.AMOVH,
reg: regInfo{ reg: regInfo{
inputs: []inputInfo{ inputs: []inputInfo{
{0, 144383}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 SP SB {0, 8589947903}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 SP SB
}, },
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
...@@ -4570,7 +4782,7 @@ var opcodeTable = [...]opInfo{ ...@@ -4570,7 +4782,7 @@ var opcodeTable = [...]opInfo{
asm: arm.AMOVHU, asm: arm.AMOVHU,
reg: regInfo{ reg: regInfo{
inputs: []inputInfo{ inputs: []inputInfo{
{0, 144383}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 SP SB {0, 8589947903}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 SP SB
}, },
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
...@@ -4584,13 +4796,41 @@ var opcodeTable = [...]opInfo{ ...@@ -4584,13 +4796,41 @@ var opcodeTable = [...]opInfo{
asm: arm.AMOVW, asm: arm.AMOVW,
reg: regInfo{ reg: regInfo{
inputs: []inputInfo{ inputs: []inputInfo{
{0, 144383}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 SP SB {0, 8589947903}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 SP SB
}, },
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: "MOVFload",
auxType: auxSymOff,
argLen: 2,
asm: arm.AMOVF,
reg: regInfo{
inputs: []inputInfo{
{0, 8589947903}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 SP SB
},
outputs: []regMask{
4294901760, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15
},
},
},
{
name: "MOVDload",
auxType: auxSymOff,
argLen: 2,
asm: arm.AMOVD,
reg: regInfo{
inputs: []inputInfo{
{0, 8589947903}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 SP SB
},
outputs: []regMask{
4294901760, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15
},
},
},
{ {
name: "MOVBstore", name: "MOVBstore",
auxType: auxSymOff, auxType: auxSymOff,
...@@ -4598,8 +4838,8 @@ var opcodeTable = [...]opInfo{ ...@@ -4598,8 +4838,8 @@ var opcodeTable = [...]opInfo{
asm: arm.AMOVB, asm: arm.AMOVB,
reg: regInfo{ reg: regInfo{
inputs: []inputInfo{ inputs: []inputInfo{
{1, 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
{0, 144383}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 SP SB {0, 8589947903}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 SP SB
}, },
}, },
}, },
...@@ -4610,8 +4850,8 @@ var opcodeTable = [...]opInfo{ ...@@ -4610,8 +4850,8 @@ var opcodeTable = [...]opInfo{
asm: arm.AMOVH, asm: arm.AMOVH,
reg: regInfo{ reg: regInfo{
inputs: []inputInfo{ inputs: []inputInfo{
{1, 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
{0, 144383}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 SP SB {0, 8589947903}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 SP SB
}, },
}, },
}, },
...@@ -4622,8 +4862,32 @@ var opcodeTable = [...]opInfo{ ...@@ -4622,8 +4862,32 @@ var opcodeTable = [...]opInfo{
asm: arm.AMOVW, asm: arm.AMOVW,
reg: regInfo{ reg: regInfo{
inputs: []inputInfo{ inputs: []inputInfo{
{1, 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
{0, 144383}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 SP SB {0, 8589947903}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 SP SB
},
},
},
{
name: "MOVFstore",
auxType: auxSymOff,
argLen: 3,
asm: arm.AMOVF,
reg: regInfo{
inputs: []inputInfo{
{0, 8589947903}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 SP SB
{1, 4294901760}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15
},
},
},
{
name: "MOVDstore",
auxType: auxSymOff,
argLen: 3,
asm: arm.AMOVD,
reg: regInfo{
inputs: []inputInfo{
{0, 8589947903}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 SP SB
{1, 4294901760}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15
}, },
}, },
}, },
...@@ -4679,12 +4943,142 @@ var opcodeTable = [...]opInfo{ ...@@ -4679,12 +4943,142 @@ var opcodeTable = [...]opInfo{
}, },
}, },
}, },
{
name: "MOVWF",
argLen: 1,
asm: arm.AMOVWF,
reg: regInfo{
inputs: []inputInfo{
{0, 5119}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
},
outputs: []regMask{
4294901760, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15
},
},
},
{
name: "MOVWD",
argLen: 1,
asm: arm.AMOVWD,
reg: regInfo{
inputs: []inputInfo{
{0, 5119}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
},
outputs: []regMask{
4294901760, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15
},
},
},
{
name: "MOVWUF",
argLen: 1,
asm: arm.AMOVWF,
reg: regInfo{
inputs: []inputInfo{
{0, 5119}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
},
outputs: []regMask{
4294901760, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15
},
},
},
{
name: "MOVWUD",
argLen: 1,
asm: arm.AMOVWD,
reg: regInfo{
inputs: []inputInfo{
{0, 5119}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
},
outputs: []regMask{
4294901760, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15
},
},
},
{
name: "MOVFW",
argLen: 1,
asm: arm.AMOVFW,
reg: regInfo{
inputs: []inputInfo{
{0, 4294901760}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15
},
outputs: []regMask{
5119, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
},
},
},
{
name: "MOVDW",
argLen: 1,
asm: arm.AMOVDW,
reg: regInfo{
inputs: []inputInfo{
{0, 4294901760}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15
},
outputs: []regMask{
5119, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
},
},
},
{
name: "MOVFWU",
argLen: 1,
asm: arm.AMOVFW,
reg: regInfo{
inputs: []inputInfo{
{0, 4294901760}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15
},
outputs: []regMask{
5119, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
},
},
},
{
name: "MOVDWU",
argLen: 1,
asm: arm.AMOVDW,
reg: regInfo{
inputs: []inputInfo{
{0, 4294901760}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15
},
outputs: []regMask{
5119, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
},
},
},
{
name: "MOVFD",
argLen: 1,
asm: arm.AMOVFD,
reg: regInfo{
inputs: []inputInfo{
{0, 4294901760}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15
},
outputs: []regMask{
4294901760, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15
},
},
},
{
name: "MOVDF",
argLen: 1,
asm: arm.AMOVDF,
reg: regInfo{
inputs: []inputInfo{
{0, 4294901760}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15
},
outputs: []regMask{
4294901760, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15
},
},
},
{ {
name: "CALLstatic", name: "CALLstatic",
auxType: auxSymOff, auxType: auxSymOff,
argLen: 1, argLen: 1,
reg: regInfo{ reg: regInfo{
clobbers: 70655, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 FLAGS clobbers: 8589874175, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 FLAGS
}, },
}, },
{ {
...@@ -4696,7 +5090,7 @@ var opcodeTable = [...]opInfo{ ...@@ -4696,7 +5090,7 @@ var opcodeTable = [...]opInfo{
{1, 128}, // R7 {1, 128}, // R7
{0, 13311}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 SP {0, 13311}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 SP
}, },
clobbers: 70655, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 FLAGS clobbers: 8589874175, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 FLAGS
}, },
}, },
{ {
...@@ -4704,7 +5098,7 @@ var opcodeTable = [...]opInfo{ ...@@ -4704,7 +5098,7 @@ var opcodeTable = [...]opInfo{
auxType: auxInt64, auxType: auxInt64,
argLen: 1, argLen: 1,
reg: regInfo{ reg: regInfo{
clobbers: 70655, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 FLAGS clobbers: 8589874175, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 FLAGS
}, },
}, },
{ {
...@@ -4712,7 +5106,7 @@ var opcodeTable = [...]opInfo{ ...@@ -4712,7 +5106,7 @@ var opcodeTable = [...]opInfo{
auxType: auxInt64, auxType: auxInt64,
argLen: 1, argLen: 1,
reg: regInfo{ reg: regInfo{
clobbers: 70655, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 FLAGS clobbers: 8589874175, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 FLAGS
}, },
}, },
{ {
...@@ -4723,7 +5117,7 @@ var opcodeTable = [...]opInfo{ ...@@ -4723,7 +5117,7 @@ var opcodeTable = [...]opInfo{
inputs: []inputInfo{ inputs: []inputInfo{
{0, 5119}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 {0, 5119}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
}, },
clobbers: 70655, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 FLAGS clobbers: 8589874175, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 FLAGS
}, },
}, },
{ {
...@@ -4733,7 +5127,7 @@ var opcodeTable = [...]opInfo{ ...@@ -4733,7 +5127,7 @@ var opcodeTable = [...]opInfo{
inputs: []inputInfo{ inputs: []inputInfo{
{0, 13311}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 SP {0, 13311}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 SP
}, },
clobbers: 65536, // FLAGS clobbers: 4294967296, // FLAGS
}, },
}, },
{ {
...@@ -4741,7 +5135,7 @@ var opcodeTable = [...]opInfo{ ...@@ -4741,7 +5135,7 @@ var opcodeTable = [...]opInfo{
argLen: 1, argLen: 1,
reg: regInfo{ reg: regInfo{
inputs: []inputInfo{ inputs: []inputInfo{
{0, 65536}, // FLAGS {0, 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
...@@ -4753,7 +5147,7 @@ var opcodeTable = [...]opInfo{ ...@@ -4753,7 +5147,7 @@ var opcodeTable = [...]opInfo{
argLen: 1, argLen: 1,
reg: regInfo{ reg: regInfo{
inputs: []inputInfo{ inputs: []inputInfo{
{0, 65536}, // FLAGS {0, 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
...@@ -4765,7 +5159,7 @@ var opcodeTable = [...]opInfo{ ...@@ -4765,7 +5159,7 @@ var opcodeTable = [...]opInfo{
argLen: 1, argLen: 1,
reg: regInfo{ reg: regInfo{
inputs: []inputInfo{ inputs: []inputInfo{
{0, 65536}, // FLAGS {0, 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
...@@ -4777,7 +5171,7 @@ var opcodeTable = [...]opInfo{ ...@@ -4777,7 +5171,7 @@ var opcodeTable = [...]opInfo{
argLen: 1, argLen: 1,
reg: regInfo{ reg: regInfo{
inputs: []inputInfo{ inputs: []inputInfo{
{0, 65536}, // FLAGS {0, 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
...@@ -4789,7 +5183,7 @@ var opcodeTable = [...]opInfo{ ...@@ -4789,7 +5183,7 @@ var opcodeTable = [...]opInfo{
argLen: 1, argLen: 1,
reg: regInfo{ reg: regInfo{
inputs: []inputInfo{ inputs: []inputInfo{
{0, 65536}, // FLAGS {0, 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
...@@ -4801,7 +5195,7 @@ var opcodeTable = [...]opInfo{ ...@@ -4801,7 +5195,7 @@ var opcodeTable = [...]opInfo{
argLen: 1, argLen: 1,
reg: regInfo{ reg: regInfo{
inputs: []inputInfo{ inputs: []inputInfo{
{0, 65536}, // FLAGS {0, 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
...@@ -4813,7 +5207,7 @@ var opcodeTable = [...]opInfo{ ...@@ -4813,7 +5207,7 @@ var opcodeTable = [...]opInfo{
argLen: 1, argLen: 1,
reg: regInfo{ reg: regInfo{
inputs: []inputInfo{ inputs: []inputInfo{
{0, 65536}, // FLAGS {0, 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
...@@ -4825,7 +5219,7 @@ var opcodeTable = [...]opInfo{ ...@@ -4825,7 +5219,7 @@ var opcodeTable = [...]opInfo{
argLen: 1, argLen: 1,
reg: regInfo{ reg: regInfo{
inputs: []inputInfo{ inputs: []inputInfo{
{0, 65536}, // FLAGS {0, 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
...@@ -4837,7 +5231,7 @@ var opcodeTable = [...]opInfo{ ...@@ -4837,7 +5231,7 @@ var opcodeTable = [...]opInfo{
argLen: 1, argLen: 1,
reg: regInfo{ reg: regInfo{
inputs: []inputInfo{ inputs: []inputInfo{
{0, 65536}, // FLAGS {0, 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
...@@ -4849,7 +5243,7 @@ var opcodeTable = [...]opInfo{ ...@@ -4849,7 +5243,7 @@ var opcodeTable = [...]opInfo{
argLen: 1, argLen: 1,
reg: regInfo{ reg: regInfo{
inputs: []inputInfo{ inputs: []inputInfo{
{0, 65536}, // FLAGS {0, 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
...@@ -4861,7 +5255,7 @@ var opcodeTable = [...]opInfo{ ...@@ -4861,7 +5255,7 @@ var opcodeTable = [...]opInfo{
argLen: 1, argLen: 1,
reg: regInfo{ reg: regInfo{
outputs: []regMask{ outputs: []regMask{
65536, // FLAGS 4294967296, // FLAGS
}, },
}, },
}, },
...@@ -4932,7 +5326,7 @@ var opcodeTable = [...]opInfo{ ...@@ -4932,7 +5326,7 @@ var opcodeTable = [...]opInfo{
{1, 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 {2, 5119}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
}, },
clobbers: 65538, // R1 FLAGS clobbers: 4294967298, // R1 FLAGS
}, },
}, },
{ {
...@@ -4944,7 +5338,7 @@ var opcodeTable = [...]opInfo{ ...@@ -4944,7 +5338,7 @@ var opcodeTable = [...]opInfo{
{1, 2}, // R1 {1, 2}, // R1
{2, 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: 65542, // R1 R2 FLAGS clobbers: 4294967302, // R1 R2 FLAGS
}, },
}, },
{ {
...@@ -6512,6 +6906,26 @@ var opcodeTable = [...]opInfo{ ...@@ -6512,6 +6906,26 @@ var opcodeTable = [...]opInfo{
argLen: 1, argLen: 1,
generic: true, generic: true,
}, },
{
name: "Cvt32Uto32F",
argLen: 1,
generic: true,
},
{
name: "Cvt32Uto64F",
argLen: 1,
generic: true,
},
{
name: "Cvt32Fto32U",
argLen: 1,
generic: true,
},
{
name: "Cvt64Fto32U",
argLen: 1,
generic: true,
},
{ {
name: "Select0", name: "Select0",
argLen: 1, argLen: 1,
...@@ -6584,10 +6998,26 @@ var registersARM = [...]Register{ ...@@ -6584,10 +6998,26 @@ var registersARM = [...]Register{
{13, "SP"}, {13, "SP"},
{14, "R14"}, {14, "R14"},
{15, "R15"}, {15, "R15"},
{16, "FLAGS"}, {16, "F0"},
{17, "SB"}, {17, "F1"},
{18, "F2"},
{19, "F3"},
{20, "F4"},
{21, "F5"},
{22, "F6"},
{23, "F7"},
{24, "F8"},
{25, "F9"},
{26, "F10"},
{27, "F11"},
{28, "F12"},
{29, "F13"},
{30, "F14"},
{31, "F15"},
{32, "FLAGS"},
{33, "SB"},
} }
var gpRegMaskARM = regMask(5119) var gpRegMaskARM = regMask(5119)
var fpRegMaskARM = regMask(0) var fpRegMaskARM = regMask(4294901760)
var flagRegMaskARM = regMask(65536) var flagRegMaskARM = regMask(4294967296)
var framepointerRegARM = int8(-1) var framepointerRegARM = int8(-1)
...@@ -14,10 +14,14 @@ func rewriteValueARM(v *Value, config *Config) bool { ...@@ -14,10 +14,14 @@ func rewriteValueARM(v *Value, config *Config) bool {
return rewriteValueARM_OpAdd16(v, config) return rewriteValueARM_OpAdd16(v, config)
case OpAdd32: case OpAdd32:
return rewriteValueARM_OpAdd32(v, config) return rewriteValueARM_OpAdd32(v, config)
case OpAdd32F:
return rewriteValueARM_OpAdd32F(v, config)
case OpAdd32carry: case OpAdd32carry:
return rewriteValueARM_OpAdd32carry(v, config) return rewriteValueARM_OpAdd32carry(v, config)
case OpAdd32withcarry: case OpAdd32withcarry:
return rewriteValueARM_OpAdd32withcarry(v, config) return rewriteValueARM_OpAdd32withcarry(v, config)
case OpAdd64F:
return rewriteValueARM_OpAdd64F(v, config)
case OpAdd8: case OpAdd8:
return rewriteValueARM_OpAdd8(v, config) return rewriteValueARM_OpAdd8(v, config)
case OpAddPtr: case OpAddPtr:
...@@ -44,6 +48,10 @@ func rewriteValueARM(v *Value, config *Config) bool { ...@@ -44,6 +48,10 @@ func rewriteValueARM(v *Value, config *Config) bool {
return rewriteValueARM_OpConst16(v, config) return rewriteValueARM_OpConst16(v, config)
case OpConst32: case OpConst32:
return rewriteValueARM_OpConst32(v, config) return rewriteValueARM_OpConst32(v, config)
case OpConst32F:
return rewriteValueARM_OpConst32F(v, config)
case OpConst64F:
return rewriteValueARM_OpConst64F(v, config)
case OpConst8: case OpConst8:
return rewriteValueARM_OpConst8(v, config) return rewriteValueARM_OpConst8(v, config)
case OpConstBool: case OpConstBool:
...@@ -52,6 +60,26 @@ func rewriteValueARM(v *Value, config *Config) bool { ...@@ -52,6 +60,26 @@ func rewriteValueARM(v *Value, config *Config) bool {
return rewriteValueARM_OpConstNil(v, config) return rewriteValueARM_OpConstNil(v, config)
case OpConvert: case OpConvert:
return rewriteValueARM_OpConvert(v, config) return rewriteValueARM_OpConvert(v, config)
case OpCvt32Fto32:
return rewriteValueARM_OpCvt32Fto32(v, config)
case OpCvt32Fto32U:
return rewriteValueARM_OpCvt32Fto32U(v, config)
case OpCvt32Fto64F:
return rewriteValueARM_OpCvt32Fto64F(v, config)
case OpCvt32Uto32F:
return rewriteValueARM_OpCvt32Uto32F(v, config)
case OpCvt32Uto64F:
return rewriteValueARM_OpCvt32Uto64F(v, config)
case OpCvt32to32F:
return rewriteValueARM_OpCvt32to32F(v, config)
case OpCvt32to64F:
return rewriteValueARM_OpCvt32to64F(v, config)
case OpCvt64Fto32:
return rewriteValueARM_OpCvt64Fto32(v, config)
case OpCvt64Fto32F:
return rewriteValueARM_OpCvt64Fto32F(v, config)
case OpCvt64Fto32U:
return rewriteValueARM_OpCvt64Fto32U(v, config)
case OpDeferCall: case OpDeferCall:
return rewriteValueARM_OpDeferCall(v, config) return rewriteValueARM_OpDeferCall(v, config)
case OpDiv16: case OpDiv16:
...@@ -60,8 +88,12 @@ func rewriteValueARM(v *Value, config *Config) bool { ...@@ -60,8 +88,12 @@ func rewriteValueARM(v *Value, config *Config) bool {
return rewriteValueARM_OpDiv16u(v, config) return rewriteValueARM_OpDiv16u(v, config)
case OpDiv32: case OpDiv32:
return rewriteValueARM_OpDiv32(v, config) return rewriteValueARM_OpDiv32(v, config)
case OpDiv32F:
return rewriteValueARM_OpDiv32F(v, config)
case OpDiv32u: case OpDiv32u:
return rewriteValueARM_OpDiv32u(v, config) return rewriteValueARM_OpDiv32u(v, config)
case OpDiv64F:
return rewriteValueARM_OpDiv64F(v, config)
case OpDiv8: case OpDiv8:
return rewriteValueARM_OpDiv8(v, config) return rewriteValueARM_OpDiv8(v, config)
case OpDiv8u: case OpDiv8u:
...@@ -70,6 +102,10 @@ func rewriteValueARM(v *Value, config *Config) bool { ...@@ -70,6 +102,10 @@ func rewriteValueARM(v *Value, config *Config) bool {
return rewriteValueARM_OpEq16(v, config) return rewriteValueARM_OpEq16(v, config)
case OpEq32: case OpEq32:
return rewriteValueARM_OpEq32(v, config) return rewriteValueARM_OpEq32(v, config)
case OpEq32F:
return rewriteValueARM_OpEq32F(v, config)
case OpEq64F:
return rewriteValueARM_OpEq64F(v, config)
case OpEq8: case OpEq8:
return rewriteValueARM_OpEq8(v, config) return rewriteValueARM_OpEq8(v, config)
case OpEqB: case OpEqB:
...@@ -82,8 +118,12 @@ func rewriteValueARM(v *Value, config *Config) bool { ...@@ -82,8 +118,12 @@ func rewriteValueARM(v *Value, config *Config) bool {
return rewriteValueARM_OpGeq16U(v, config) return rewriteValueARM_OpGeq16U(v, config)
case OpGeq32: case OpGeq32:
return rewriteValueARM_OpGeq32(v, config) return rewriteValueARM_OpGeq32(v, config)
case OpGeq32F:
return rewriteValueARM_OpGeq32F(v, config)
case OpGeq32U: case OpGeq32U:
return rewriteValueARM_OpGeq32U(v, config) return rewriteValueARM_OpGeq32U(v, config)
case OpGeq64F:
return rewriteValueARM_OpGeq64F(v, config)
case OpGeq8: case OpGeq8:
return rewriteValueARM_OpGeq8(v, config) return rewriteValueARM_OpGeq8(v, config)
case OpGeq8U: case OpGeq8U:
...@@ -98,8 +138,12 @@ func rewriteValueARM(v *Value, config *Config) bool { ...@@ -98,8 +138,12 @@ func rewriteValueARM(v *Value, config *Config) bool {
return rewriteValueARM_OpGreater16U(v, config) return rewriteValueARM_OpGreater16U(v, config)
case OpGreater32: case OpGreater32:
return rewriteValueARM_OpGreater32(v, config) return rewriteValueARM_OpGreater32(v, config)
case OpGreater32F:
return rewriteValueARM_OpGreater32F(v, config)
case OpGreater32U: case OpGreater32U:
return rewriteValueARM_OpGreater32U(v, config) return rewriteValueARM_OpGreater32U(v, config)
case OpGreater64F:
return rewriteValueARM_OpGreater64F(v, config)
case OpGreater8: case OpGreater8:
return rewriteValueARM_OpGreater8(v, config) return rewriteValueARM_OpGreater8(v, config)
case OpGreater8U: case OpGreater8U:
...@@ -130,8 +174,12 @@ func rewriteValueARM(v *Value, config *Config) bool { ...@@ -130,8 +174,12 @@ func rewriteValueARM(v *Value, config *Config) bool {
return rewriteValueARM_OpLeq16U(v, config) return rewriteValueARM_OpLeq16U(v, config)
case OpLeq32: case OpLeq32:
return rewriteValueARM_OpLeq32(v, config) return rewriteValueARM_OpLeq32(v, config)
case OpLeq32F:
return rewriteValueARM_OpLeq32F(v, config)
case OpLeq32U: case OpLeq32U:
return rewriteValueARM_OpLeq32U(v, config) return rewriteValueARM_OpLeq32U(v, config)
case OpLeq64F:
return rewriteValueARM_OpLeq64F(v, config)
case OpLeq8: case OpLeq8:
return rewriteValueARM_OpLeq8(v, config) return rewriteValueARM_OpLeq8(v, config)
case OpLeq8U: case OpLeq8U:
...@@ -142,8 +190,12 @@ func rewriteValueARM(v *Value, config *Config) bool { ...@@ -142,8 +190,12 @@ func rewriteValueARM(v *Value, config *Config) bool {
return rewriteValueARM_OpLess16U(v, config) return rewriteValueARM_OpLess16U(v, config)
case OpLess32: case OpLess32:
return rewriteValueARM_OpLess32(v, config) return rewriteValueARM_OpLess32(v, config)
case OpLess32F:
return rewriteValueARM_OpLess32F(v, config)
case OpLess32U: case OpLess32U:
return rewriteValueARM_OpLess32U(v, config) return rewriteValueARM_OpLess32U(v, config)
case OpLess64F:
return rewriteValueARM_OpLess64F(v, config)
case OpLess8: case OpLess8:
return rewriteValueARM_OpLess8(v, config) return rewriteValueARM_OpLess8(v, config)
case OpLess8U: case OpLess8U:
...@@ -186,6 +238,14 @@ func rewriteValueARM(v *Value, config *Config) bool { ...@@ -186,6 +238,14 @@ func rewriteValueARM(v *Value, config *Config) bool {
return rewriteValueARM_OpARMMOVBload(v, config) return rewriteValueARM_OpARMMOVBload(v, config)
case OpARMMOVBstore: case OpARMMOVBstore:
return rewriteValueARM_OpARMMOVBstore(v, config) return rewriteValueARM_OpARMMOVBstore(v, config)
case OpARMMOVDload:
return rewriteValueARM_OpARMMOVDload(v, config)
case OpARMMOVDstore:
return rewriteValueARM_OpARMMOVDstore(v, config)
case OpARMMOVFload:
return rewriteValueARM_OpARMMOVFload(v, config)
case OpARMMOVFstore:
return rewriteValueARM_OpARMMOVFstore(v, config)
case OpARMMOVHUload: case OpARMMOVHUload:
return rewriteValueARM_OpARMMOVHUload(v, config) return rewriteValueARM_OpARMMOVHUload(v, config)
case OpARMMOVHload: case OpARMMOVHload:
...@@ -214,20 +274,32 @@ func rewriteValueARM(v *Value, config *Config) bool { ...@@ -214,20 +274,32 @@ func rewriteValueARM(v *Value, config *Config) bool {
return rewriteValueARM_OpMul16(v, config) return rewriteValueARM_OpMul16(v, config)
case OpMul32: case OpMul32:
return rewriteValueARM_OpMul32(v, config) return rewriteValueARM_OpMul32(v, config)
case OpMul32F:
return rewriteValueARM_OpMul32F(v, config)
case OpMul32uhilo: case OpMul32uhilo:
return rewriteValueARM_OpMul32uhilo(v, config) return rewriteValueARM_OpMul32uhilo(v, config)
case OpMul64F:
return rewriteValueARM_OpMul64F(v, config)
case OpMul8: case OpMul8:
return rewriteValueARM_OpMul8(v, config) return rewriteValueARM_OpMul8(v, config)
case OpNeg16: case OpNeg16:
return rewriteValueARM_OpNeg16(v, config) return rewriteValueARM_OpNeg16(v, config)
case OpNeg32: case OpNeg32:
return rewriteValueARM_OpNeg32(v, config) return rewriteValueARM_OpNeg32(v, config)
case OpNeg32F:
return rewriteValueARM_OpNeg32F(v, config)
case OpNeg64F:
return rewriteValueARM_OpNeg64F(v, config)
case OpNeg8: case OpNeg8:
return rewriteValueARM_OpNeg8(v, config) return rewriteValueARM_OpNeg8(v, config)
case OpNeq16: case OpNeq16:
return rewriteValueARM_OpNeq16(v, config) return rewriteValueARM_OpNeq16(v, config)
case OpNeq32: case OpNeq32:
return rewriteValueARM_OpNeq32(v, config) return rewriteValueARM_OpNeq32(v, config)
case OpNeq32F:
return rewriteValueARM_OpNeq32F(v, config)
case OpNeq64F:
return rewriteValueARM_OpNeq64F(v, config)
case OpNeq8: case OpNeq8:
return rewriteValueARM_OpNeq8(v, config) return rewriteValueARM_OpNeq8(v, config)
case OpNeqB: case OpNeqB:
...@@ -308,6 +380,8 @@ func rewriteValueARM(v *Value, config *Config) bool { ...@@ -308,6 +380,8 @@ func rewriteValueARM(v *Value, config *Config) bool {
return rewriteValueARM_OpSignExt8to32(v, config) return rewriteValueARM_OpSignExt8to32(v, config)
case OpSignmask: case OpSignmask:
return rewriteValueARM_OpSignmask(v, config) return rewriteValueARM_OpSignmask(v, config)
case OpSqrt:
return rewriteValueARM_OpSqrt(v, config)
case OpStaticCall: case OpStaticCall:
return rewriteValueARM_OpStaticCall(v, config) return rewriteValueARM_OpStaticCall(v, config)
case OpStore: case OpStore:
...@@ -316,10 +390,14 @@ func rewriteValueARM(v *Value, config *Config) bool { ...@@ -316,10 +390,14 @@ func rewriteValueARM(v *Value, config *Config) bool {
return rewriteValueARM_OpSub16(v, config) return rewriteValueARM_OpSub16(v, config)
case OpSub32: case OpSub32:
return rewriteValueARM_OpSub32(v, config) return rewriteValueARM_OpSub32(v, config)
case OpSub32F:
return rewriteValueARM_OpSub32F(v, config)
case OpSub32carry: case OpSub32carry:
return rewriteValueARM_OpSub32carry(v, config) return rewriteValueARM_OpSub32carry(v, config)
case OpSub32withcarry: case OpSub32withcarry:
return rewriteValueARM_OpSub32withcarry(v, config) return rewriteValueARM_OpSub32withcarry(v, config)
case OpSub64F:
return rewriteValueARM_OpSub64F(v, config)
case OpSub8: case OpSub8:
return rewriteValueARM_OpSub8(v, config) return rewriteValueARM_OpSub8(v, config)
case OpSubPtr: case OpSubPtr:
...@@ -448,6 +526,21 @@ func rewriteValueARM_OpAdd32(v *Value, config *Config) bool { ...@@ -448,6 +526,21 @@ func rewriteValueARM_OpAdd32(v *Value, config *Config) bool {
return true return true
} }
} }
func rewriteValueARM_OpAdd32F(v *Value, config *Config) bool {
b := v.Block
_ = b
// match: (Add32F x y)
// cond:
// result: (ADDF x y)
for {
x := v.Args[0]
y := v.Args[1]
v.reset(OpARMADDF)
v.AddArg(x)
v.AddArg(y)
return true
}
}
func rewriteValueARM_OpAdd32carry(v *Value, config *Config) bool { func rewriteValueARM_OpAdd32carry(v *Value, config *Config) bool {
b := v.Block b := v.Block
_ = b _ = b
...@@ -480,6 +573,21 @@ func rewriteValueARM_OpAdd32withcarry(v *Value, config *Config) bool { ...@@ -480,6 +573,21 @@ func rewriteValueARM_OpAdd32withcarry(v *Value, config *Config) bool {
return true return true
} }
} }
func rewriteValueARM_OpAdd64F(v *Value, config *Config) bool {
b := v.Block
_ = b
// match: (Add64F x y)
// cond:
// result: (ADDD x y)
for {
x := v.Args[0]
y := v.Args[1]
v.reset(OpARMADDD)
v.AddArg(x)
v.AddArg(y)
return true
}
}
func rewriteValueARM_OpAdd8(v *Value, config *Config) bool { func rewriteValueARM_OpAdd8(v *Value, config *Config) bool {
b := v.Block b := v.Block
_ = b _ = b
...@@ -669,6 +777,32 @@ func rewriteValueARM_OpConst32(v *Value, config *Config) bool { ...@@ -669,6 +777,32 @@ func rewriteValueARM_OpConst32(v *Value, config *Config) bool {
return true return true
} }
} }
func rewriteValueARM_OpConst32F(v *Value, config *Config) bool {
b := v.Block
_ = b
// match: (Const32F [val])
// cond:
// result: (MOVFconst [val])
for {
val := v.AuxInt
v.reset(OpARMMOVFconst)
v.AuxInt = val
return true
}
}
func rewriteValueARM_OpConst64F(v *Value, config *Config) bool {
b := v.Block
_ = b
// match: (Const64F [val])
// cond:
// result: (MOVDconst [val])
for {
val := v.AuxInt
v.reset(OpARMMOVDconst)
v.AuxInt = val
return true
}
}
func rewriteValueARM_OpConst8(v *Value, config *Config) bool { func rewriteValueARM_OpConst8(v *Value, config *Config) bool {
b := v.Block b := v.Block
_ = b _ = b
...@@ -722,6 +856,136 @@ func rewriteValueARM_OpConvert(v *Value, config *Config) bool { ...@@ -722,6 +856,136 @@ func rewriteValueARM_OpConvert(v *Value, config *Config) bool {
return true return true
} }
} }
func rewriteValueARM_OpCvt32Fto32(v *Value, config *Config) bool {
b := v.Block
_ = b
// match: (Cvt32Fto32 x)
// cond:
// result: (MOVFW x)
for {
x := v.Args[0]
v.reset(OpARMMOVFW)
v.AddArg(x)
return true
}
}
func rewriteValueARM_OpCvt32Fto32U(v *Value, config *Config) bool {
b := v.Block
_ = b
// match: (Cvt32Fto32U x)
// cond:
// result: (MOVFWU x)
for {
x := v.Args[0]
v.reset(OpARMMOVFWU)
v.AddArg(x)
return true
}
}
func rewriteValueARM_OpCvt32Fto64F(v *Value, config *Config) bool {
b := v.Block
_ = b
// match: (Cvt32Fto64F x)
// cond:
// result: (MOVFD x)
for {
x := v.Args[0]
v.reset(OpARMMOVFD)
v.AddArg(x)
return true
}
}
func rewriteValueARM_OpCvt32Uto32F(v *Value, config *Config) bool {
b := v.Block
_ = b
// match: (Cvt32Uto32F x)
// cond:
// result: (MOVWUF x)
for {
x := v.Args[0]
v.reset(OpARMMOVWUF)
v.AddArg(x)
return true
}
}
func rewriteValueARM_OpCvt32Uto64F(v *Value, config *Config) bool {
b := v.Block
_ = b
// match: (Cvt32Uto64F x)
// cond:
// result: (MOVWUD x)
for {
x := v.Args[0]
v.reset(OpARMMOVWUD)
v.AddArg(x)
return true
}
}
func rewriteValueARM_OpCvt32to32F(v *Value, config *Config) bool {
b := v.Block
_ = b
// match: (Cvt32to32F x)
// cond:
// result: (MOVWF x)
for {
x := v.Args[0]
v.reset(OpARMMOVWF)
v.AddArg(x)
return true
}
}
func rewriteValueARM_OpCvt32to64F(v *Value, config *Config) bool {
b := v.Block
_ = b
// match: (Cvt32to64F x)
// cond:
// result: (MOVWD x)
for {
x := v.Args[0]
v.reset(OpARMMOVWD)
v.AddArg(x)
return true
}
}
func rewriteValueARM_OpCvt64Fto32(v *Value, config *Config) bool {
b := v.Block
_ = b
// match: (Cvt64Fto32 x)
// cond:
// result: (MOVDW x)
for {
x := v.Args[0]
v.reset(OpARMMOVDW)
v.AddArg(x)
return true
}
}
func rewriteValueARM_OpCvt64Fto32F(v *Value, config *Config) bool {
b := v.Block
_ = b
// match: (Cvt64Fto32F x)
// cond:
// result: (MOVDF x)
for {
x := v.Args[0]
v.reset(OpARMMOVDF)
v.AddArg(x)
return true
}
}
func rewriteValueARM_OpCvt64Fto32U(v *Value, config *Config) bool {
b := v.Block
_ = b
// match: (Cvt64Fto32U x)
// cond:
// result: (MOVDWU x)
for {
x := v.Args[0]
v.reset(OpARMMOVDWU)
v.AddArg(x)
return true
}
}
func rewriteValueARM_OpDeferCall(v *Value, config *Config) bool { func rewriteValueARM_OpDeferCall(v *Value, config *Config) bool {
b := v.Block b := v.Block
_ = b _ = b
...@@ -790,6 +1054,21 @@ func rewriteValueARM_OpDiv32(v *Value, config *Config) bool { ...@@ -790,6 +1054,21 @@ func rewriteValueARM_OpDiv32(v *Value, config *Config) bool {
return true return true
} }
} }
func rewriteValueARM_OpDiv32F(v *Value, config *Config) bool {
b := v.Block
_ = b
// match: (Div32F x y)
// cond:
// result: (DIVF x y)
for {
x := v.Args[0]
y := v.Args[1]
v.reset(OpARMDIVF)
v.AddArg(x)
v.AddArg(y)
return true
}
}
func rewriteValueARM_OpDiv32u(v *Value, config *Config) bool { func rewriteValueARM_OpDiv32u(v *Value, config *Config) bool {
b := v.Block b := v.Block
_ = b _ = b
...@@ -805,6 +1084,21 @@ func rewriteValueARM_OpDiv32u(v *Value, config *Config) bool { ...@@ -805,6 +1084,21 @@ func rewriteValueARM_OpDiv32u(v *Value, config *Config) bool {
return true return true
} }
} }
func rewriteValueARM_OpDiv64F(v *Value, config *Config) bool {
b := v.Block
_ = b
// match: (Div64F x y)
// cond:
// result: (DIVD x y)
for {
x := v.Args[0]
y := v.Args[1]
v.reset(OpARMDIVD)
v.AddArg(x)
v.AddArg(y)
return true
}
}
func rewriteValueARM_OpDiv8(v *Value, config *Config) bool { func rewriteValueARM_OpDiv8(v *Value, config *Config) bool {
b := v.Block b := v.Block
_ = b _ = b
...@@ -881,6 +1175,40 @@ func rewriteValueARM_OpEq32(v *Value, config *Config) bool { ...@@ -881,6 +1175,40 @@ func rewriteValueARM_OpEq32(v *Value, config *Config) bool {
return true return true
} }
} }
func rewriteValueARM_OpEq32F(v *Value, config *Config) bool {
b := v.Block
_ = b
// match: (Eq32F x y)
// cond:
// result: (Equal (CMPF x y))
for {
x := v.Args[0]
y := v.Args[1]
v.reset(OpARMEqual)
v0 := b.NewValue0(v.Line, OpARMCMPF, TypeFlags)
v0.AddArg(x)
v0.AddArg(y)
v.AddArg(v0)
return true
}
}
func rewriteValueARM_OpEq64F(v *Value, config *Config) bool {
b := v.Block
_ = b
// match: (Eq64F x y)
// cond:
// result: (Equal (CMPD x y))
for {
x := v.Args[0]
y := v.Args[1]
v.reset(OpARMEqual)
v0 := b.NewValue0(v.Line, OpARMCMPD, TypeFlags)
v0.AddArg(x)
v0.AddArg(y)
v.AddArg(v0)
return true
}
}
func rewriteValueARM_OpEq8(v *Value, config *Config) bool { func rewriteValueARM_OpEq8(v *Value, config *Config) bool {
b := v.Block b := v.Block
_ = b _ = b
...@@ -996,6 +1324,23 @@ func rewriteValueARM_OpGeq32(v *Value, config *Config) bool { ...@@ -996,6 +1324,23 @@ func rewriteValueARM_OpGeq32(v *Value, config *Config) bool {
return true return true
} }
} }
func rewriteValueARM_OpGeq32F(v *Value, config *Config) bool {
b := v.Block
_ = b
// match: (Geq32F x y)
// cond:
// result: (GreaterEqual (CMPF x y))
for {
x := v.Args[0]
y := v.Args[1]
v.reset(OpARMGreaterEqual)
v0 := b.NewValue0(v.Line, OpARMCMPF, TypeFlags)
v0.AddArg(x)
v0.AddArg(y)
v.AddArg(v0)
return true
}
}
func rewriteValueARM_OpGeq32U(v *Value, config *Config) bool { func rewriteValueARM_OpGeq32U(v *Value, config *Config) bool {
b := v.Block b := v.Block
_ = b _ = b
...@@ -1013,6 +1358,23 @@ func rewriteValueARM_OpGeq32U(v *Value, config *Config) bool { ...@@ -1013,6 +1358,23 @@ func rewriteValueARM_OpGeq32U(v *Value, config *Config) bool {
return true return true
} }
} }
func rewriteValueARM_OpGeq64F(v *Value, config *Config) bool {
b := v.Block
_ = b
// match: (Geq64F x y)
// cond:
// result: (GreaterEqual (CMPD x y))
for {
x := v.Args[0]
y := v.Args[1]
v.reset(OpARMGreaterEqual)
v0 := b.NewValue0(v.Line, OpARMCMPD, TypeFlags)
v0.AddArg(x)
v0.AddArg(y)
v.AddArg(v0)
return true
}
}
func rewriteValueARM_OpGeq8(v *Value, config *Config) bool { func rewriteValueARM_OpGeq8(v *Value, config *Config) bool {
b := v.Block b := v.Block
_ = b _ = b
...@@ -1140,6 +1502,23 @@ func rewriteValueARM_OpGreater32(v *Value, config *Config) bool { ...@@ -1140,6 +1502,23 @@ func rewriteValueARM_OpGreater32(v *Value, config *Config) bool {
return true return true
} }
} }
func rewriteValueARM_OpGreater32F(v *Value, config *Config) bool {
b := v.Block
_ = b
// match: (Greater32F x y)
// cond:
// result: (GreaterThan (CMPF x y))
for {
x := v.Args[0]
y := v.Args[1]
v.reset(OpARMGreaterThan)
v0 := b.NewValue0(v.Line, OpARMCMPF, TypeFlags)
v0.AddArg(x)
v0.AddArg(y)
v.AddArg(v0)
return true
}
}
func rewriteValueARM_OpGreater32U(v *Value, config *Config) bool { func rewriteValueARM_OpGreater32U(v *Value, config *Config) bool {
b := v.Block b := v.Block
_ = b _ = b
...@@ -1157,6 +1536,23 @@ func rewriteValueARM_OpGreater32U(v *Value, config *Config) bool { ...@@ -1157,6 +1536,23 @@ func rewriteValueARM_OpGreater32U(v *Value, config *Config) bool {
return true return true
} }
} }
func rewriteValueARM_OpGreater64F(v *Value, config *Config) bool {
b := v.Block
_ = b
// match: (Greater64F x y)
// cond:
// result: (GreaterThan (CMPD x y))
for {
x := v.Args[0]
y := v.Args[1]
v.reset(OpARMGreaterThan)
v0 := b.NewValue0(v.Line, OpARMCMPD, TypeFlags)
v0.AddArg(x)
v0.AddArg(y)
v.AddArg(v0)
return true
}
}
func rewriteValueARM_OpGreater8(v *Value, config *Config) bool { func rewriteValueARM_OpGreater8(v *Value, config *Config) bool {
b := v.Block b := v.Block
_ = b _ = b
...@@ -1443,6 +1839,23 @@ func rewriteValueARM_OpLeq32(v *Value, config *Config) bool { ...@@ -1443,6 +1839,23 @@ func rewriteValueARM_OpLeq32(v *Value, config *Config) bool {
return true return true
} }
} }
func rewriteValueARM_OpLeq32F(v *Value, config *Config) bool {
b := v.Block
_ = b
// match: (Leq32F x y)
// cond:
// result: (GreaterEqual (CMPF y x))
for {
x := v.Args[0]
y := v.Args[1]
v.reset(OpARMGreaterEqual)
v0 := b.NewValue0(v.Line, OpARMCMPF, TypeFlags)
v0.AddArg(y)
v0.AddArg(x)
v.AddArg(v0)
return true
}
}
func rewriteValueARM_OpLeq32U(v *Value, config *Config) bool { func rewriteValueARM_OpLeq32U(v *Value, config *Config) bool {
b := v.Block b := v.Block
_ = b _ = b
...@@ -1460,6 +1873,23 @@ func rewriteValueARM_OpLeq32U(v *Value, config *Config) bool { ...@@ -1460,6 +1873,23 @@ func rewriteValueARM_OpLeq32U(v *Value, config *Config) bool {
return true return true
} }
} }
func rewriteValueARM_OpLeq64F(v *Value, config *Config) bool {
b := v.Block
_ = b
// match: (Leq64F x y)
// cond:
// result: (GreaterEqual (CMPD y x))
for {
x := v.Args[0]
y := v.Args[1]
v.reset(OpARMGreaterEqual)
v0 := b.NewValue0(v.Line, OpARMCMPD, TypeFlags)
v0.AddArg(y)
v0.AddArg(x)
v.AddArg(v0)
return true
}
}
func rewriteValueARM_OpLeq8(v *Value, config *Config) bool { func rewriteValueARM_OpLeq8(v *Value, config *Config) bool {
b := v.Block b := v.Block
_ = b _ = b
...@@ -1561,6 +1991,23 @@ func rewriteValueARM_OpLess32(v *Value, config *Config) bool { ...@@ -1561,6 +1991,23 @@ func rewriteValueARM_OpLess32(v *Value, config *Config) bool {
return true return true
} }
} }
func rewriteValueARM_OpLess32F(v *Value, config *Config) bool {
b := v.Block
_ = b
// match: (Less32F x y)
// cond:
// result: (GreaterThan (CMPF y x))
for {
x := v.Args[0]
y := v.Args[1]
v.reset(OpARMGreaterThan)
v0 := b.NewValue0(v.Line, OpARMCMPF, TypeFlags)
v0.AddArg(y)
v0.AddArg(x)
v.AddArg(v0)
return true
}
}
func rewriteValueARM_OpLess32U(v *Value, config *Config) bool { func rewriteValueARM_OpLess32U(v *Value, config *Config) bool {
b := v.Block b := v.Block
_ = b _ = b
...@@ -1578,6 +2025,23 @@ func rewriteValueARM_OpLess32U(v *Value, config *Config) bool { ...@@ -1578,6 +2025,23 @@ func rewriteValueARM_OpLess32U(v *Value, config *Config) bool {
return true return true
} }
} }
func rewriteValueARM_OpLess64F(v *Value, config *Config) bool {
b := v.Block
_ = b
// match: (Less64F x y)
// cond:
// result: (GreaterThan (CMPD y x))
for {
x := v.Args[0]
y := v.Args[1]
v.reset(OpARMGreaterThan)
v0 := b.NewValue0(v.Line, OpARMCMPD, TypeFlags)
v0.AddArg(y)
v0.AddArg(x)
v.AddArg(v0)
return true
}
}
func rewriteValueARM_OpLess8(v *Value, config *Config) bool { func rewriteValueARM_OpLess8(v *Value, config *Config) bool {
b := v.Block b := v.Block
_ = b _ = b
...@@ -1713,6 +2177,36 @@ func rewriteValueARM_OpLoad(v *Value, config *Config) bool { ...@@ -1713,6 +2177,36 @@ func rewriteValueARM_OpLoad(v *Value, config *Config) bool {
v.AddArg(mem) v.AddArg(mem)
return true return true
} }
// match: (Load <t> ptr mem)
// cond: is32BitFloat(t)
// result: (MOVFload ptr mem)
for {
t := v.Type
ptr := v.Args[0]
mem := v.Args[1]
if !(is32BitFloat(t)) {
break
}
v.reset(OpARMMOVFload)
v.AddArg(ptr)
v.AddArg(mem)
return true
}
// match: (Load <t> ptr mem)
// cond: is64BitFloat(t)
// result: (MOVDload ptr mem)
for {
t := v.Type
ptr := v.Args[0]
mem := v.Args[1]
if !(is64BitFloat(t)) {
break
}
v.reset(OpARMMOVDload)
v.AddArg(ptr)
v.AddArg(mem)
return true
}
return false return false
} }
func rewriteValueARM_OpLrot16(v *Value, config *Config) bool { func rewriteValueARM_OpLrot16(v *Value, config *Config) bool {
...@@ -2127,6 +2621,126 @@ func rewriteValueARM_OpARMMOVBstore(v *Value, config *Config) bool { ...@@ -2127,6 +2621,126 @@ func rewriteValueARM_OpARMMOVBstore(v *Value, config *Config) bool {
} }
return false return false
} }
func rewriteValueARM_OpARMMOVDload(v *Value, config *Config) bool {
b := v.Block
_ = b
// match: (MOVDload [off1] {sym1} (ADDconst [off2] {sym2} ptr) mem)
// cond: canMergeSym(sym1,sym2)
// result: (MOVDload [off1+off2] {mergeSym(sym1,sym2)} ptr mem)
for {
off1 := v.AuxInt
sym1 := v.Aux
v_0 := v.Args[0]
if v_0.Op != OpARMADDconst {
break
}
off2 := v_0.AuxInt
sym2 := v_0.Aux
ptr := v_0.Args[0]
mem := v.Args[1]
if !(canMergeSym(sym1, sym2)) {
break
}
v.reset(OpARMMOVDload)
v.AuxInt = off1 + off2
v.Aux = mergeSym(sym1, sym2)
v.AddArg(ptr)
v.AddArg(mem)
return true
}
return false
}
func rewriteValueARM_OpARMMOVDstore(v *Value, config *Config) bool {
b := v.Block
_ = b
// match: (MOVDstore [off1] {sym1} (ADDconst [off2] {sym2} ptr) val mem)
// cond: canMergeSym(sym1,sym2)
// result: (MOVDstore [off1+off2] {mergeSym(sym1,sym2)} ptr val mem)
for {
off1 := v.AuxInt
sym1 := v.Aux
v_0 := v.Args[0]
if v_0.Op != OpARMADDconst {
break
}
off2 := v_0.AuxInt
sym2 := v_0.Aux
ptr := v_0.Args[0]
val := v.Args[1]
mem := v.Args[2]
if !(canMergeSym(sym1, sym2)) {
break
}
v.reset(OpARMMOVDstore)
v.AuxInt = off1 + off2
v.Aux = mergeSym(sym1, sym2)
v.AddArg(ptr)
v.AddArg(val)
v.AddArg(mem)
return true
}
return false
}
func rewriteValueARM_OpARMMOVFload(v *Value, config *Config) bool {
b := v.Block
_ = b
// match: (MOVFload [off1] {sym1} (ADDconst [off2] {sym2} ptr) mem)
// cond: canMergeSym(sym1,sym2)
// result: (MOVFload [off1+off2] {mergeSym(sym1,sym2)} ptr mem)
for {
off1 := v.AuxInt
sym1 := v.Aux
v_0 := v.Args[0]
if v_0.Op != OpARMADDconst {
break
}
off2 := v_0.AuxInt
sym2 := v_0.Aux
ptr := v_0.Args[0]
mem := v.Args[1]
if !(canMergeSym(sym1, sym2)) {
break
}
v.reset(OpARMMOVFload)
v.AuxInt = off1 + off2
v.Aux = mergeSym(sym1, sym2)
v.AddArg(ptr)
v.AddArg(mem)
return true
}
return false
}
func rewriteValueARM_OpARMMOVFstore(v *Value, config *Config) bool {
b := v.Block
_ = b
// match: (MOVFstore [off1] {sym1} (ADDconst [off2] {sym2} ptr) val mem)
// cond: canMergeSym(sym1,sym2)
// result: (MOVFstore [off1+off2] {mergeSym(sym1,sym2)} ptr val mem)
for {
off1 := v.AuxInt
sym1 := v.Aux
v_0 := v.Args[0]
if v_0.Op != OpARMADDconst {
break
}
off2 := v_0.AuxInt
sym2 := v_0.Aux
ptr := v_0.Args[0]
val := v.Args[1]
mem := v.Args[2]
if !(canMergeSym(sym1, sym2)) {
break
}
v.reset(OpARMMOVFstore)
v.AuxInt = off1 + off2
v.Aux = mergeSym(sym1, sym2)
v.AddArg(ptr)
v.AddArg(val)
v.AddArg(mem)
return true
}
return false
}
func rewriteValueARM_OpARMMOVHUload(v *Value, config *Config) bool { func rewriteValueARM_OpARMMOVHUload(v *Value, config *Config) bool {
b := v.Block b := v.Block
_ = b _ = b
...@@ -2583,6 +3197,21 @@ func rewriteValueARM_OpMul32(v *Value, config *Config) bool { ...@@ -2583,6 +3197,21 @@ func rewriteValueARM_OpMul32(v *Value, config *Config) bool {
return true return true
} }
} }
func rewriteValueARM_OpMul32F(v *Value, config *Config) bool {
b := v.Block
_ = b
// match: (Mul32F x y)
// cond:
// result: (MULF x y)
for {
x := v.Args[0]
y := v.Args[1]
v.reset(OpARMMULF)
v.AddArg(x)
v.AddArg(y)
return true
}
}
func rewriteValueARM_OpMul32uhilo(v *Value, config *Config) bool { func rewriteValueARM_OpMul32uhilo(v *Value, config *Config) bool {
b := v.Block b := v.Block
_ = b _ = b
...@@ -2598,6 +3227,21 @@ func rewriteValueARM_OpMul32uhilo(v *Value, config *Config) bool { ...@@ -2598,6 +3227,21 @@ func rewriteValueARM_OpMul32uhilo(v *Value, config *Config) bool {
return true return true
} }
} }
func rewriteValueARM_OpMul64F(v *Value, config *Config) bool {
b := v.Block
_ = b
// match: (Mul64F x y)
// cond:
// result: (MULD x y)
for {
x := v.Args[0]
y := v.Args[1]
v.reset(OpARMMULD)
v.AddArg(x)
v.AddArg(y)
return true
}
}
func rewriteValueARM_OpMul8(v *Value, config *Config) bool { func rewriteValueARM_OpMul8(v *Value, config *Config) bool {
b := v.Block b := v.Block
_ = b _ = b
...@@ -2641,6 +3285,38 @@ func rewriteValueARM_OpNeg32(v *Value, config *Config) bool { ...@@ -2641,6 +3285,38 @@ func rewriteValueARM_OpNeg32(v *Value, config *Config) bool {
return true return true
} }
} }
func rewriteValueARM_OpNeg32F(v *Value, config *Config) bool {
b := v.Block
_ = b
// match: (Neg32F x)
// cond:
// result: (MULF (MOVFconst [int64(math.Float64bits(-1))]) x)
for {
x := v.Args[0]
v.reset(OpARMMULF)
v0 := b.NewValue0(v.Line, OpARMMOVFconst, config.fe.TypeFloat32())
v0.AuxInt = int64(math.Float64bits(-1))
v.AddArg(v0)
v.AddArg(x)
return true
}
}
func rewriteValueARM_OpNeg64F(v *Value, config *Config) bool {
b := v.Block
_ = b
// match: (Neg64F x)
// cond:
// result: (MULD (MOVDconst [int64(math.Float64bits(-1))]) x)
for {
x := v.Args[0]
v.reset(OpARMMULD)
v0 := b.NewValue0(v.Line, OpARMMOVDconst, config.fe.TypeFloat64())
v0.AuxInt = int64(math.Float64bits(-1))
v.AddArg(v0)
v.AddArg(x)
return true
}
}
func rewriteValueARM_OpNeg8(v *Value, config *Config) bool { func rewriteValueARM_OpNeg8(v *Value, config *Config) bool {
b := v.Block b := v.Block
_ = b _ = b
...@@ -2693,6 +3369,40 @@ func rewriteValueARM_OpNeq32(v *Value, config *Config) bool { ...@@ -2693,6 +3369,40 @@ func rewriteValueARM_OpNeq32(v *Value, config *Config) bool {
return true return true
} }
} }
func rewriteValueARM_OpNeq32F(v *Value, config *Config) bool {
b := v.Block
_ = b
// match: (Neq32F x y)
// cond:
// result: (NotEqual (CMPF x y))
for {
x := v.Args[0]
y := v.Args[1]
v.reset(OpARMNotEqual)
v0 := b.NewValue0(v.Line, OpARMCMPF, TypeFlags)
v0.AddArg(x)
v0.AddArg(y)
v.AddArg(v0)
return true
}
}
func rewriteValueARM_OpNeq64F(v *Value, config *Config) bool {
b := v.Block
_ = b
// match: (Neq64F x y)
// cond:
// result: (NotEqual (CMPD x y))
for {
x := v.Args[0]
y := v.Args[1]
v.reset(OpARMNotEqual)
v0 := b.NewValue0(v.Line, OpARMCMPD, TypeFlags)
v0.AddArg(x)
v0.AddArg(y)
v.AddArg(v0)
return true
}
}
func rewriteValueARM_OpNeq8(v *Value, config *Config) bool { func rewriteValueARM_OpNeq8(v *Value, config *Config) bool {
b := v.Block b := v.Block
_ = b _ = b
...@@ -3531,6 +4241,19 @@ func rewriteValueARM_OpSignmask(v *Value, config *Config) bool { ...@@ -3531,6 +4241,19 @@ func rewriteValueARM_OpSignmask(v *Value, config *Config) bool {
return true return true
} }
} }
func rewriteValueARM_OpSqrt(v *Value, config *Config) bool {
b := v.Block
_ = b
// match: (Sqrt x)
// cond:
// result: (SQRTD x)
for {
x := v.Args[0]
v.reset(OpARMSQRTD)
v.AddArg(x)
return true
}
}
func rewriteValueARM_OpStaticCall(v *Value, config *Config) bool { func rewriteValueARM_OpStaticCall(v *Value, config *Config) bool {
b := v.Block b := v.Block
_ = b _ = b
...@@ -3584,7 +4307,7 @@ func rewriteValueARM_OpStore(v *Value, config *Config) bool { ...@@ -3584,7 +4307,7 @@ func rewriteValueARM_OpStore(v *Value, config *Config) bool {
return true return true
} }
// match: (Store [4] ptr val mem) // match: (Store [4] ptr val mem)
// cond: // cond: !is32BitFloat(val.Type)
// result: (MOVWstore ptr val mem) // result: (MOVWstore ptr val mem)
for { for {
if v.AuxInt != 4 { if v.AuxInt != 4 {
...@@ -3593,12 +4316,53 @@ func rewriteValueARM_OpStore(v *Value, config *Config) bool { ...@@ -3593,12 +4316,53 @@ func rewriteValueARM_OpStore(v *Value, config *Config) bool {
ptr := v.Args[0] ptr := v.Args[0]
val := v.Args[1] val := v.Args[1]
mem := v.Args[2] mem := v.Args[2]
if !(!is32BitFloat(val.Type)) {
break
}
v.reset(OpARMMOVWstore) v.reset(OpARMMOVWstore)
v.AddArg(ptr) v.AddArg(ptr)
v.AddArg(val) v.AddArg(val)
v.AddArg(mem) v.AddArg(mem)
return true return true
} }
// match: (Store [4] ptr val mem)
// cond: is32BitFloat(val.Type)
// result: (MOVFstore ptr val mem)
for {
if v.AuxInt != 4 {
break
}
ptr := v.Args[0]
val := v.Args[1]
mem := v.Args[2]
if !(is32BitFloat(val.Type)) {
break
}
v.reset(OpARMMOVFstore)
v.AddArg(ptr)
v.AddArg(val)
v.AddArg(mem)
return true
}
// match: (Store [8] ptr val mem)
// cond: is64BitFloat(val.Type)
// result: (MOVDstore ptr val mem)
for {
if v.AuxInt != 8 {
break
}
ptr := v.Args[0]
val := v.Args[1]
mem := v.Args[2]
if !(is64BitFloat(val.Type)) {
break
}
v.reset(OpARMMOVDstore)
v.AddArg(ptr)
v.AddArg(val)
v.AddArg(mem)
return true
}
return false return false
} }
func rewriteValueARM_OpSub16(v *Value, config *Config) bool { func rewriteValueARM_OpSub16(v *Value, config *Config) bool {
...@@ -3631,6 +4395,21 @@ func rewriteValueARM_OpSub32(v *Value, config *Config) bool { ...@@ -3631,6 +4395,21 @@ func rewriteValueARM_OpSub32(v *Value, config *Config) bool {
return true return true
} }
} }
func rewriteValueARM_OpSub32F(v *Value, config *Config) bool {
b := v.Block
_ = b
// match: (Sub32F x y)
// cond:
// result: (SUBF x y)
for {
x := v.Args[0]
y := v.Args[1]
v.reset(OpARMSUBF)
v.AddArg(x)
v.AddArg(y)
return true
}
}
func rewriteValueARM_OpSub32carry(v *Value, config *Config) bool { func rewriteValueARM_OpSub32carry(v *Value, config *Config) bool {
b := v.Block b := v.Block
_ = b _ = b
...@@ -3663,6 +4442,21 @@ func rewriteValueARM_OpSub32withcarry(v *Value, config *Config) bool { ...@@ -3663,6 +4442,21 @@ func rewriteValueARM_OpSub32withcarry(v *Value, config *Config) bool {
return true return true
} }
} }
func rewriteValueARM_OpSub64F(v *Value, config *Config) bool {
b := v.Block
_ = b
// match: (Sub64F x y)
// cond:
// result: (SUBD x y)
for {
x := v.Args[0]
y := v.Args[1]
v.reset(OpARMSUBD)
v.AddArg(x)
v.AddArg(y)
return true
}
}
func rewriteValueARM_OpSub8(v *Value, config *Config) bool { func rewriteValueARM_OpSub8(v *Value, config *Config) bool {
b := v.Block b := v.Block
_ = b _ = b
......
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