mirror of
https://github.com/golang/go
synced 2024-11-12 03:00:22 -07:00
cmd/compile: add math/bits.{Add,Sub}64 intrinsics on s390x
This CL adds intrinsics for the 64-bit addition and subtraction functions in math/bits. These intrinsics use the condition code to propagate the carry or borrow bit. To make the carry chains more efficient I've removed the 'clobberFlags' property from most of the load and store operations. Originally these ops did clobber flags when using offsets that didn't fit in a signed 20-bit integer, however that is no longer true. As with other platforms the intrinsics are faster when executed in a chain rather than a loop because currently we need to spill and restore the carry bit between each loop iteration. We may be able to reduce the need to do this on s390x (e.g. by using compare-and-branch instructions that do not clobber flags) in the future. name old time/op new time/op delta Add64 1.21ns ± 2% 2.03ns ± 2% +67.18% (p=0.000 n=7+10) Add64multiple 2.98ns ± 3% 1.03ns ± 0% -65.39% (p=0.000 n=10+9) Sub64 1.23ns ± 4% 2.03ns ± 1% +64.85% (p=0.000 n=10+10) Sub64multiple 3.73ns ± 4% 1.04ns ± 1% -72.28% (p=0.000 n=10+8) Change-Id: I913bbd5e19e6b95bef52f5bc4f14d6fe40119083 Reviewed-on: https://go-review.googlesource.com/c/go/+/174303 Run-TryBot: Michael Munday <mike.munday@ibm.com> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Cherry Zhang <cherryyz@google.com>
This commit is contained in:
parent
004fb5cb8d
commit
2c1b5130aa
1
src/cmd/asm/internal/asm/testdata/s390x.s
vendored
1
src/cmd/asm/internal/asm/testdata/s390x.s
vendored
@ -66,6 +66,7 @@ TEXT main·foo(SB),DUPOK|NOSPLIT,$16-0 // TEXT main.foo(SB), DUPOK|NOSPLIT, $16-
|
||||
ADD $32768, R1, R2 // b9040021c22800008000
|
||||
ADDC R1, R2 // b9ea1022
|
||||
ADDC $1, R1, R2 // ec21000100db
|
||||
ADDC $-1, R1, R2 // ec21ffff00db
|
||||
ADDC R1, R2, R3 // b9ea1032
|
||||
ADDW R1, R2 // 1a21
|
||||
ADDW R1, R2, R3 // b9f81032
|
||||
|
@ -3575,14 +3575,14 @@ func init() {
|
||||
func(s *state, n *Node, args []*ssa.Value) *ssa.Value {
|
||||
return s.newValue3(ssa.OpAdd64carry, types.NewTuple(types.Types[TUINT64], types.Types[TUINT64]), args[0], args[1], args[2])
|
||||
},
|
||||
sys.AMD64, sys.ARM64, sys.PPC64)
|
||||
alias("math/bits", "Add", "math/bits", "Add64", sys.ArchAMD64, sys.ArchARM64, sys.ArchPPC64)
|
||||
sys.AMD64, sys.ARM64, sys.PPC64, sys.S390X)
|
||||
alias("math/bits", "Add", "math/bits", "Add64", sys.ArchAMD64, sys.ArchARM64, sys.ArchPPC64, sys.ArchS390X)
|
||||
addF("math/bits", "Sub64",
|
||||
func(s *state, n *Node, args []*ssa.Value) *ssa.Value {
|
||||
return s.newValue3(ssa.OpSub64borrow, types.NewTuple(types.Types[TUINT64], types.Types[TUINT64]), args[0], args[1], args[2])
|
||||
},
|
||||
sys.AMD64, sys.ARM64)
|
||||
alias("math/bits", "Sub", "math/bits", "Sub64", sys.ArchAMD64, sys.ArchARM64)
|
||||
sys.AMD64, sys.ARM64, sys.S390X)
|
||||
alias("math/bits", "Sub", "math/bits", "Sub64", sys.ArchAMD64, sys.ArchARM64, sys.ArchS390X)
|
||||
addF("math/bits", "Div64",
|
||||
func(s *state, n *Node, args []*ssa.Value) *ssa.Value {
|
||||
// check for divide-by-zero/overflow and panic with appropriate message
|
||||
|
@ -184,6 +184,37 @@ func ssaGenValue(s *gc.SSAGenState, v *ssa.Value) {
|
||||
if r != r1 {
|
||||
p.Reg = r1
|
||||
}
|
||||
case ssa.OpS390XADDC:
|
||||
r1 := v.Reg0()
|
||||
r2 := v.Args[0].Reg()
|
||||
r3 := v.Args[1].Reg()
|
||||
if r1 == r2 {
|
||||
r2, r3 = r3, r2
|
||||
}
|
||||
p := opregreg(s, v.Op.Asm(), r1, r2)
|
||||
if r3 != r1 {
|
||||
p.Reg = r3
|
||||
}
|
||||
case ssa.OpS390XSUBC:
|
||||
r1 := v.Reg0()
|
||||
r2 := v.Args[0].Reg()
|
||||
r3 := v.Args[1].Reg()
|
||||
p := opregreg(s, v.Op.Asm(), r1, r3)
|
||||
if r1 != r2 {
|
||||
p.Reg = r2
|
||||
}
|
||||
case ssa.OpS390XADDE, ssa.OpS390XSUBE:
|
||||
r1 := v.Reg0()
|
||||
if r1 != v.Args[0].Reg() {
|
||||
v.Fatalf("input[0] and output not in same register %s", v.LongString())
|
||||
}
|
||||
r2 := v.Args[1].Reg()
|
||||
opregreg(s, v.Op.Asm(), r1, r2)
|
||||
case ssa.OpS390XADDCconst:
|
||||
r1 := v.Reg0()
|
||||
r3 := v.Args[0].Reg()
|
||||
i2 := int64(int16(v.AuxInt))
|
||||
opregregimm(s, v.Op.Asm(), r1, r3, i2)
|
||||
// 2-address opcode arithmetic
|
||||
case ssa.OpS390XMULLD, ssa.OpS390XMULLW,
|
||||
ssa.OpS390XMULHD, ssa.OpS390XMULHDU,
|
||||
@ -553,7 +584,7 @@ func ssaGenValue(s *gc.SSAGenState, v *ssa.Value) {
|
||||
p.To.Reg = v.Reg()
|
||||
case ssa.OpS390XInvertFlags:
|
||||
v.Fatalf("InvertFlags should never make it to codegen %v", v.LongString())
|
||||
case ssa.OpS390XFlagEQ, ssa.OpS390XFlagLT, ssa.OpS390XFlagGT:
|
||||
case ssa.OpS390XFlagEQ, ssa.OpS390XFlagLT, ssa.OpS390XFlagGT, ssa.OpS390XFlagOV:
|
||||
v.Fatalf("Flag* ops should never make it to codegen %v", v.LongString())
|
||||
case ssa.OpS390XAddTupleFirst32, ssa.OpS390XAddTupleFirst64:
|
||||
v.Fatalf("AddTupleFirst* should never make it to codegen %v", v.LongString())
|
||||
|
@ -119,6 +119,18 @@
|
||||
(Bswap64 x) -> (MOVDBR x)
|
||||
(Bswap32 x) -> (MOVWBR x)
|
||||
|
||||
// add with carry
|
||||
(Select0 (Add64carry x y c))
|
||||
-> (Select0 <typ.UInt64> (ADDE x y (Select1 <types.TypeFlags> (ADDCconst c [-1]))))
|
||||
(Select1 (Add64carry x y c))
|
||||
-> (Select0 <typ.UInt64> (ADDE (MOVDconst [0]) (MOVDconst [0]) (Select1 <types.TypeFlags> (ADDE x y (Select1 <types.TypeFlags> (ADDCconst c [-1]))))))
|
||||
|
||||
// subtract with borrow
|
||||
(Select0 (Sub64borrow x y c))
|
||||
-> (Select0 <typ.UInt64> (SUBE x y (Select1 <types.TypeFlags> (SUBC (MOVDconst [0]) c))))
|
||||
(Select1 (Sub64borrow x y c))
|
||||
-> (NEG (Select0 <typ.UInt64> (SUBE (MOVDconst [0]) (MOVDconst [0]) (Select1 <types.TypeFlags> (SUBE x y (Select1 <types.TypeFlags> (SUBC (MOVDconst [0]) c)))))))
|
||||
|
||||
// math package intrinsics
|
||||
(Sqrt x) -> (FSQRT x)
|
||||
(Floor x) -> (FIDBR [7] x)
|
||||
@ -1121,6 +1133,43 @@
|
||||
(MOVBreg (ANDWconst [m] x)) && int8(m) >= 0 -> (MOVWZreg (ANDWconst <typ.UInt32> [int64( uint8(m))] x))
|
||||
(MOVHreg (ANDWconst [m] x)) && int16(m) >= 0 -> (MOVWZreg (ANDWconst <typ.UInt32> [int64(uint16(m))] x))
|
||||
|
||||
// carry flag generation
|
||||
// (only constant fold carry of zero)
|
||||
(Select1 (ADDCconst (MOVDconst [c]) [d]))
|
||||
&& uint64(c+d) >= uint64(c) && c+d == 0
|
||||
-> (FlagEQ)
|
||||
(Select1 (ADDCconst (MOVDconst [c]) [d]))
|
||||
&& uint64(c+d) >= uint64(c) && c+d != 0
|
||||
-> (FlagLT)
|
||||
|
||||
// borrow flag generation
|
||||
// (only constant fold borrow of zero)
|
||||
(Select1 (SUBC (MOVDconst [c]) (MOVDconst [d])))
|
||||
&& uint64(d) <= uint64(c) && c-d == 0
|
||||
-> (FlagGT)
|
||||
(Select1 (SUBC (MOVDconst [c]) (MOVDconst [d])))
|
||||
&& uint64(d) <= uint64(c) && c-d != 0
|
||||
-> (FlagOV)
|
||||
|
||||
// add with carry
|
||||
(ADDE x y (FlagEQ)) -> (ADDC x y)
|
||||
(ADDE x y (FlagLT)) -> (ADDC x y)
|
||||
(ADDC x (MOVDconst [c])) && is16Bit(c) -> (ADDCconst x [c])
|
||||
(Select0 (ADDCconst (MOVDconst [c]) [d])) -> (MOVDconst [c+d])
|
||||
|
||||
// subtract with borrow
|
||||
(SUBE x y (FlagGT)) -> (SUBC x y)
|
||||
(SUBE x y (FlagOV)) -> (SUBC x y)
|
||||
(Select0 (SUBC (MOVDconst [c]) (MOVDconst [d]))) -> (MOVDconst [c-d])
|
||||
|
||||
// collapse carry chain
|
||||
(ADDE x y (Select1 (ADDCconst [-1] (Select0 (ADDE (MOVDconst [0]) (MOVDconst [0]) c)))))
|
||||
-> (ADDE x y c)
|
||||
|
||||
// collapse borrow chain
|
||||
(SUBE x y (Select1 (SUBC (MOVDconst [0]) (NEG (Select0 (SUBE (MOVDconst [0]) (MOVDconst [0]) c))))))
|
||||
-> (SUBE x y c)
|
||||
|
||||
// fused multiply-add
|
||||
(FADD (FMUL y z) x) -> (FMADD x y z)
|
||||
(FADDS (FMULS y z) x) -> (FMADDS x y z)
|
||||
|
@ -153,9 +153,12 @@ func init() {
|
||||
addr = regInfo{inputs: []regMask{sp | sb}, outputs: gponly}
|
||||
addridx = regInfo{inputs: []regMask{sp | sb, ptrsp}, outputs: gponly}
|
||||
|
||||
gp2flags = regInfo{inputs: []regMask{gpsp, gpsp}}
|
||||
gp1flags = regInfo{inputs: []regMask{gpsp}}
|
||||
gp2flags1 = regInfo{inputs: []regMask{gp, gp}, outputs: gponly}
|
||||
gp2flags = regInfo{inputs: []regMask{gpsp, gpsp}}
|
||||
gp1flags = regInfo{inputs: []regMask{gpsp}}
|
||||
gp2flags1 = regInfo{inputs: []regMask{gp, gp}, outputs: gponly}
|
||||
gp11flags = regInfo{inputs: []regMask{gp}, outputs: gponly}
|
||||
gp21flags = regInfo{inputs: []regMask{gp, gp}, outputs: gponly}
|
||||
gp2flags1flags = regInfo{inputs: []regMask{gp, gp}, outputs: gponly}
|
||||
|
||||
gpload = regInfo{inputs: []regMask{ptrspsb, 0}, outputs: gponly}
|
||||
gploadidx = regInfo{inputs: []regMask{ptrspsb, ptrsp, 0}, outputs: gponly}
|
||||
@ -294,6 +297,17 @@ func init() {
|
||||
{name: "XORload", argLength: 3, reg: gpopload, asm: "XOR", aux: "SymOff", resultInArg0: true, clobberFlags: true, faultOnNilArg1: true, symEffect: "Read"}, // arg0 ^ *arg1. arg2=mem
|
||||
{name: "XORWload", argLength: 3, reg: gpopload, asm: "XORW", aux: "SymOff", resultInArg0: true, clobberFlags: true, faultOnNilArg1: true, symEffect: "Read"}, // arg0 ^ *arg1. arg2=mem
|
||||
|
||||
// Arithmetic ops with carry/borrow chain.
|
||||
//
|
||||
// A carry is represented by a condition code of 2 or 3 (GT or OV).
|
||||
// A borrow is represented by a condition code of 0 or 1 (EQ or LT).
|
||||
{name: "ADDC", argLength: 2, reg: gp21flags, asm: "ADDC", typ: "(UInt64,Flags)", commutative: true}, // (arg0 + arg1, carry out)
|
||||
{name: "ADDCconst", argLength: 1, reg: gp11flags, asm: "ADDC", typ: "(UInt64,Flags)", aux: "Int16"}, // (arg0 + auxint, carry out)
|
||||
{name: "ADDE", argLength: 3, reg: gp2flags1flags, asm: "ADDE", typ: "(UInt64,Flags)", commutative: true, resultInArg0: true}, // (arg0 + arg1 + arg2 (carry in), carry out)
|
||||
{name: "SUBC", argLength: 2, reg: gp21flags, asm: "SUBC", typ: "(UInt64,Flags)"}, // (arg0 - arg1, borrow out)
|
||||
{name: "SUBE", argLength: 3, reg: gp2flags1flags, asm: "SUBE", typ: "(UInt64,Flags)", resultInArg0: true}, // (arg0 - arg1 - arg2 (borrow in), borrow out)
|
||||
|
||||
// Comparisons.
|
||||
{name: "CMP", argLength: 2, reg: gp2flags, asm: "CMP", typ: "Flags"}, // arg0 compare to arg1
|
||||
{name: "CMPW", argLength: 2, reg: gp2flags, asm: "CMPW", typ: "Flags"}, // arg0 compare to arg1
|
||||
|
||||
@ -380,49 +394,49 @@ func init() {
|
||||
{name: "MOVDaddridx", argLength: 2, reg: addridx, aux: "SymOff", symEffect: "Read"}, // arg0 + arg1 + auxint + aux
|
||||
|
||||
// auxint+aux == add auxint and the offset of the symbol in aux (if any) to the effective address
|
||||
{name: "MOVBZload", argLength: 2, reg: gpload, asm: "MOVBZ", aux: "SymOff", typ: "UInt8", clobberFlags: true, faultOnNilArg0: true, symEffect: "Read"}, // load byte from arg0+auxint+aux. arg1=mem. Zero extend.
|
||||
{name: "MOVBload", argLength: 2, reg: gpload, asm: "MOVB", aux: "SymOff", clobberFlags: true, faultOnNilArg0: true, symEffect: "Read"}, // ditto, sign extend to int64
|
||||
{name: "MOVHZload", argLength: 2, reg: gpload, asm: "MOVHZ", aux: "SymOff", typ: "UInt16", clobberFlags: true, faultOnNilArg0: true, symEffect: "Read"}, // load 2 bytes from arg0+auxint+aux. arg1=mem. Zero extend.
|
||||
{name: "MOVHload", argLength: 2, reg: gpload, asm: "MOVH", aux: "SymOff", clobberFlags: true, faultOnNilArg0: true, symEffect: "Read"}, // ditto, sign extend to int64
|
||||
{name: "MOVWZload", argLength: 2, reg: gpload, asm: "MOVWZ", aux: "SymOff", typ: "UInt32", clobberFlags: true, faultOnNilArg0: true, symEffect: "Read"}, // load 4 bytes from arg0+auxint+aux. arg1=mem. Zero extend.
|
||||
{name: "MOVWload", argLength: 2, reg: gpload, asm: "MOVW", aux: "SymOff", clobberFlags: true, faultOnNilArg0: true, symEffect: "Read"}, // ditto, sign extend to int64
|
||||
{name: "MOVDload", argLength: 2, reg: gpload, asm: "MOVD", aux: "SymOff", typ: "UInt64", clobberFlags: true, faultOnNilArg0: true, symEffect: "Read"}, // load 8 bytes from arg0+auxint+aux. arg1=mem
|
||||
{name: "MOVBZload", argLength: 2, reg: gpload, asm: "MOVBZ", aux: "SymOff", typ: "UInt8", faultOnNilArg0: true, symEffect: "Read"}, // load byte from arg0+auxint+aux. arg1=mem. Zero extend.
|
||||
{name: "MOVBload", argLength: 2, reg: gpload, asm: "MOVB", aux: "SymOff", faultOnNilArg0: true, symEffect: "Read"}, // ditto, sign extend to int64
|
||||
{name: "MOVHZload", argLength: 2, reg: gpload, asm: "MOVHZ", aux: "SymOff", typ: "UInt16", faultOnNilArg0: true, symEffect: "Read"}, // load 2 bytes from arg0+auxint+aux. arg1=mem. Zero extend.
|
||||
{name: "MOVHload", argLength: 2, reg: gpload, asm: "MOVH", aux: "SymOff", faultOnNilArg0: true, symEffect: "Read"}, // ditto, sign extend to int64
|
||||
{name: "MOVWZload", argLength: 2, reg: gpload, asm: "MOVWZ", aux: "SymOff", typ: "UInt32", faultOnNilArg0: true, symEffect: "Read"}, // load 4 bytes from arg0+auxint+aux. arg1=mem. Zero extend.
|
||||
{name: "MOVWload", argLength: 2, reg: gpload, asm: "MOVW", aux: "SymOff", faultOnNilArg0: true, symEffect: "Read"}, // ditto, sign extend to int64
|
||||
{name: "MOVDload", argLength: 2, reg: gpload, asm: "MOVD", aux: "SymOff", typ: "UInt64", faultOnNilArg0: true, symEffect: "Read"}, // load 8 bytes from arg0+auxint+aux. arg1=mem
|
||||
|
||||
{name: "MOVWBR", argLength: 1, reg: gp11, asm: "MOVWBR"}, // arg0 swap bytes
|
||||
{name: "MOVDBR", argLength: 1, reg: gp11, asm: "MOVDBR"}, // arg0 swap bytes
|
||||
|
||||
{name: "MOVHBRload", argLength: 2, reg: gpload, asm: "MOVHBR", aux: "SymOff", typ: "UInt16", clobberFlags: true, faultOnNilArg0: true, symEffect: "Read"}, // load 2 bytes from arg0+auxint+aux. arg1=mem. Reverse bytes.
|
||||
{name: "MOVWBRload", argLength: 2, reg: gpload, asm: "MOVWBR", aux: "SymOff", typ: "UInt32", clobberFlags: true, faultOnNilArg0: true, symEffect: "Read"}, // load 4 bytes from arg0+auxint+aux. arg1=mem. Reverse bytes.
|
||||
{name: "MOVDBRload", argLength: 2, reg: gpload, asm: "MOVDBR", aux: "SymOff", typ: "UInt64", clobberFlags: true, faultOnNilArg0: true, symEffect: "Read"}, // load 8 bytes from arg0+auxint+aux. arg1=mem. Reverse bytes.
|
||||
{name: "MOVHBRload", argLength: 2, reg: gpload, asm: "MOVHBR", aux: "SymOff", typ: "UInt16", faultOnNilArg0: true, symEffect: "Read"}, // load 2 bytes from arg0+auxint+aux. arg1=mem. Reverse bytes.
|
||||
{name: "MOVWBRload", argLength: 2, reg: gpload, asm: "MOVWBR", aux: "SymOff", typ: "UInt32", faultOnNilArg0: true, symEffect: "Read"}, // load 4 bytes from arg0+auxint+aux. arg1=mem. Reverse bytes.
|
||||
{name: "MOVDBRload", argLength: 2, reg: gpload, asm: "MOVDBR", aux: "SymOff", typ: "UInt64", faultOnNilArg0: true, symEffect: "Read"}, // load 8 bytes from arg0+auxint+aux. arg1=mem. Reverse bytes.
|
||||
|
||||
{name: "MOVBstore", argLength: 3, reg: gpstore, asm: "MOVB", aux: "SymOff", typ: "Mem", clobberFlags: true, faultOnNilArg0: true, symEffect: "Write"}, // store byte in arg1 to arg0+auxint+aux. arg2=mem
|
||||
{name: "MOVHstore", argLength: 3, reg: gpstore, asm: "MOVH", aux: "SymOff", typ: "Mem", clobberFlags: true, faultOnNilArg0: true, symEffect: "Write"}, // store 2 bytes in arg1 to arg0+auxint+aux. arg2=mem
|
||||
{name: "MOVWstore", argLength: 3, reg: gpstore, asm: "MOVW", aux: "SymOff", typ: "Mem", clobberFlags: true, faultOnNilArg0: true, symEffect: "Write"}, // store 4 bytes in arg1 to arg0+auxint+aux. arg2=mem
|
||||
{name: "MOVDstore", argLength: 3, reg: gpstore, asm: "MOVD", aux: "SymOff", typ: "Mem", clobberFlags: true, faultOnNilArg0: true, symEffect: "Write"}, // store 8 bytes in arg1 to arg0+auxint+aux. arg2=mem
|
||||
{name: "MOVHBRstore", argLength: 3, reg: gpstorebr, asm: "MOVHBR", aux: "SymOff", typ: "Mem", clobberFlags: true, faultOnNilArg0: true, symEffect: "Write"}, // store 2 bytes in arg1 to arg0+auxint+aux. arg2=mem. Reverse bytes.
|
||||
{name: "MOVWBRstore", argLength: 3, reg: gpstorebr, asm: "MOVWBR", aux: "SymOff", typ: "Mem", clobberFlags: true, faultOnNilArg0: true, symEffect: "Write"}, // store 4 bytes in arg1 to arg0+auxint+aux. arg2=mem. Reverse bytes.
|
||||
{name: "MOVDBRstore", argLength: 3, reg: gpstorebr, asm: "MOVDBR", aux: "SymOff", typ: "Mem", clobberFlags: true, faultOnNilArg0: true, symEffect: "Write"}, // store 8 bytes in arg1 to arg0+auxint+aux. arg2=mem. Reverse bytes.
|
||||
{name: "MOVBstore", argLength: 3, reg: gpstore, asm: "MOVB", aux: "SymOff", typ: "Mem", faultOnNilArg0: true, symEffect: "Write"}, // store byte in arg1 to arg0+auxint+aux. arg2=mem
|
||||
{name: "MOVHstore", argLength: 3, reg: gpstore, asm: "MOVH", aux: "SymOff", typ: "Mem", faultOnNilArg0: true, symEffect: "Write"}, // store 2 bytes in arg1 to arg0+auxint+aux. arg2=mem
|
||||
{name: "MOVWstore", argLength: 3, reg: gpstore, asm: "MOVW", aux: "SymOff", typ: "Mem", faultOnNilArg0: true, symEffect: "Write"}, // store 4 bytes in arg1 to arg0+auxint+aux. arg2=mem
|
||||
{name: "MOVDstore", argLength: 3, reg: gpstore, asm: "MOVD", aux: "SymOff", typ: "Mem", faultOnNilArg0: true, symEffect: "Write"}, // store 8 bytes in arg1 to arg0+auxint+aux. arg2=mem
|
||||
{name: "MOVHBRstore", argLength: 3, reg: gpstorebr, asm: "MOVHBR", aux: "SymOff", typ: "Mem", faultOnNilArg0: true, symEffect: "Write"}, // store 2 bytes in arg1 to arg0+auxint+aux. arg2=mem. Reverse bytes.
|
||||
{name: "MOVWBRstore", argLength: 3, reg: gpstorebr, asm: "MOVWBR", aux: "SymOff", typ: "Mem", faultOnNilArg0: true, symEffect: "Write"}, // store 4 bytes in arg1 to arg0+auxint+aux. arg2=mem. Reverse bytes.
|
||||
{name: "MOVDBRstore", argLength: 3, reg: gpstorebr, asm: "MOVDBR", aux: "SymOff", typ: "Mem", faultOnNilArg0: true, symEffect: "Write"}, // store 8 bytes in arg1 to arg0+auxint+aux. arg2=mem. Reverse bytes.
|
||||
|
||||
{name: "MVC", argLength: 3, reg: gpmvc, asm: "MVC", aux: "SymValAndOff", typ: "Mem", clobberFlags: true, faultOnNilArg0: true, faultOnNilArg1: true, symEffect: "None"}, // arg0=destptr, arg1=srcptr, arg2=mem, auxint=size,off
|
||||
|
||||
// indexed loads/stores
|
||||
{name: "MOVBZloadidx", argLength: 3, reg: gploadidx, commutative: true, asm: "MOVBZ", aux: "SymOff", typ: "UInt8", clobberFlags: true, symEffect: "Read"}, // load a byte from arg0+arg1+auxint+aux. arg2=mem. Zero extend.
|
||||
{name: "MOVBloadidx", argLength: 3, reg: gploadidx, commutative: true, asm: "MOVB", aux: "SymOff", typ: "Int8", clobberFlags: true, symEffect: "Read"}, // load a byte from arg0+arg1+auxint+aux. arg2=mem. Sign extend.
|
||||
{name: "MOVHZloadidx", argLength: 3, reg: gploadidx, commutative: true, asm: "MOVHZ", aux: "SymOff", typ: "UInt16", clobberFlags: true, symEffect: "Read"}, // load 2 bytes from arg0+arg1+auxint+aux. arg2=mem. Zero extend.
|
||||
{name: "MOVHloadidx", argLength: 3, reg: gploadidx, commutative: true, asm: "MOVH", aux: "SymOff", typ: "Int16", clobberFlags: true, symEffect: "Read"}, // load 2 bytes from arg0+arg1+auxint+aux. arg2=mem. Sign extend.
|
||||
{name: "MOVWZloadidx", argLength: 3, reg: gploadidx, commutative: true, asm: "MOVWZ", aux: "SymOff", typ: "UInt32", clobberFlags: true, symEffect: "Read"}, // load 4 bytes from arg0+arg1+auxint+aux. arg2=mem. Zero extend.
|
||||
{name: "MOVWloadidx", argLength: 3, reg: gploadidx, commutative: true, asm: "MOVW", aux: "SymOff", typ: "Int32", clobberFlags: true, symEffect: "Read"}, // load 4 bytes from arg0+arg1+auxint+aux. arg2=mem. Sign extend.
|
||||
{name: "MOVDloadidx", argLength: 3, reg: gploadidx, commutative: true, asm: "MOVD", aux: "SymOff", typ: "UInt64", clobberFlags: true, symEffect: "Read"}, // load 8 bytes from arg0+arg1+auxint+aux. arg2=mem
|
||||
{name: "MOVHBRloadidx", argLength: 3, reg: gploadidx, commutative: true, asm: "MOVHBR", aux: "SymOff", typ: "Int16", clobberFlags: true, symEffect: "Read"}, // load 2 bytes from arg0+arg1+auxint+aux. arg2=mem. Reverse bytes.
|
||||
{name: "MOVWBRloadidx", argLength: 3, reg: gploadidx, commutative: true, asm: "MOVWBR", aux: "SymOff", typ: "Int32", clobberFlags: true, symEffect: "Read"}, // load 4 bytes from arg0+arg1+auxint+aux. arg2=mem. Reverse bytes.
|
||||
{name: "MOVDBRloadidx", argLength: 3, reg: gploadidx, commutative: true, asm: "MOVDBR", aux: "SymOff", typ: "Int64", clobberFlags: true, symEffect: "Read"}, // load 8 bytes from arg0+arg1+auxint+aux. arg2=mem. Reverse bytes.
|
||||
{name: "MOVBstoreidx", argLength: 4, reg: gpstoreidx, commutative: true, asm: "MOVB", aux: "SymOff", clobberFlags: true, symEffect: "Write"}, // store byte in arg2 to arg0+arg1+auxint+aux. arg3=mem
|
||||
{name: "MOVHstoreidx", argLength: 4, reg: gpstoreidx, commutative: true, asm: "MOVH", aux: "SymOff", clobberFlags: true, symEffect: "Write"}, // store 2 bytes in arg2 to arg0+arg1+auxint+aux. arg3=mem
|
||||
{name: "MOVWstoreidx", argLength: 4, reg: gpstoreidx, commutative: true, asm: "MOVW", aux: "SymOff", clobberFlags: true, symEffect: "Write"}, // store 4 bytes in arg2 to arg0+arg1+auxint+aux. arg3=mem
|
||||
{name: "MOVDstoreidx", argLength: 4, reg: gpstoreidx, commutative: true, asm: "MOVD", aux: "SymOff", clobberFlags: true, symEffect: "Write"}, // store 8 bytes in arg2 to arg0+arg1+auxint+aux. arg3=mem
|
||||
{name: "MOVHBRstoreidx", argLength: 4, reg: gpstoreidx, commutative: true, asm: "MOVHBR", aux: "SymOff", clobberFlags: true, symEffect: "Write"}, // store 2 bytes in arg2 to arg0+arg1+auxint+aux. arg3=mem. Reverse bytes.
|
||||
{name: "MOVWBRstoreidx", argLength: 4, reg: gpstoreidx, commutative: true, asm: "MOVWBR", aux: "SymOff", clobberFlags: true, symEffect: "Write"}, // store 4 bytes in arg2 to arg0+arg1+auxint+aux. arg3=mem. Reverse bytes.
|
||||
{name: "MOVDBRstoreidx", argLength: 4, reg: gpstoreidx, commutative: true, asm: "MOVDBR", aux: "SymOff", clobberFlags: true, symEffect: "Write"}, // store 8 bytes in arg2 to arg0+arg1+auxint+aux. arg3=mem. Reverse bytes.
|
||||
{name: "MOVBZloadidx", argLength: 3, reg: gploadidx, commutative: true, asm: "MOVBZ", aux: "SymOff", typ: "UInt8", symEffect: "Read"}, // load a byte from arg0+arg1+auxint+aux. arg2=mem. Zero extend.
|
||||
{name: "MOVBloadidx", argLength: 3, reg: gploadidx, commutative: true, asm: "MOVB", aux: "SymOff", typ: "Int8", symEffect: "Read"}, // load a byte from arg0+arg1+auxint+aux. arg2=mem. Sign extend.
|
||||
{name: "MOVHZloadidx", argLength: 3, reg: gploadidx, commutative: true, asm: "MOVHZ", aux: "SymOff", typ: "UInt16", symEffect: "Read"}, // load 2 bytes from arg0+arg1+auxint+aux. arg2=mem. Zero extend.
|
||||
{name: "MOVHloadidx", argLength: 3, reg: gploadidx, commutative: true, asm: "MOVH", aux: "SymOff", typ: "Int16", symEffect: "Read"}, // load 2 bytes from arg0+arg1+auxint+aux. arg2=mem. Sign extend.
|
||||
{name: "MOVWZloadidx", argLength: 3, reg: gploadidx, commutative: true, asm: "MOVWZ", aux: "SymOff", typ: "UInt32", symEffect: "Read"}, // load 4 bytes from arg0+arg1+auxint+aux. arg2=mem. Zero extend.
|
||||
{name: "MOVWloadidx", argLength: 3, reg: gploadidx, commutative: true, asm: "MOVW", aux: "SymOff", typ: "Int32", symEffect: "Read"}, // load 4 bytes from arg0+arg1+auxint+aux. arg2=mem. Sign extend.
|
||||
{name: "MOVDloadidx", argLength: 3, reg: gploadidx, commutative: true, asm: "MOVD", aux: "SymOff", typ: "UInt64", symEffect: "Read"}, // load 8 bytes from arg0+arg1+auxint+aux. arg2=mem
|
||||
{name: "MOVHBRloadidx", argLength: 3, reg: gploadidx, commutative: true, asm: "MOVHBR", aux: "SymOff", typ: "Int16", symEffect: "Read"}, // load 2 bytes from arg0+arg1+auxint+aux. arg2=mem. Reverse bytes.
|
||||
{name: "MOVWBRloadidx", argLength: 3, reg: gploadidx, commutative: true, asm: "MOVWBR", aux: "SymOff", typ: "Int32", symEffect: "Read"}, // load 4 bytes from arg0+arg1+auxint+aux. arg2=mem. Reverse bytes.
|
||||
{name: "MOVDBRloadidx", argLength: 3, reg: gploadidx, commutative: true, asm: "MOVDBR", aux: "SymOff", typ: "Int64", symEffect: "Read"}, // load 8 bytes from arg0+arg1+auxint+aux. arg2=mem. Reverse bytes.
|
||||
{name: "MOVBstoreidx", argLength: 4, reg: gpstoreidx, commutative: true, asm: "MOVB", aux: "SymOff", symEffect: "Write"}, // store byte in arg2 to arg0+arg1+auxint+aux. arg3=mem
|
||||
{name: "MOVHstoreidx", argLength: 4, reg: gpstoreidx, commutative: true, asm: "MOVH", aux: "SymOff", symEffect: "Write"}, // store 2 bytes in arg2 to arg0+arg1+auxint+aux. arg3=mem
|
||||
{name: "MOVWstoreidx", argLength: 4, reg: gpstoreidx, commutative: true, asm: "MOVW", aux: "SymOff", symEffect: "Write"}, // store 4 bytes in arg2 to arg0+arg1+auxint+aux. arg3=mem
|
||||
{name: "MOVDstoreidx", argLength: 4, reg: gpstoreidx, commutative: true, asm: "MOVD", aux: "SymOff", symEffect: "Write"}, // store 8 bytes in arg2 to arg0+arg1+auxint+aux. arg3=mem
|
||||
{name: "MOVHBRstoreidx", argLength: 4, reg: gpstoreidx, commutative: true, asm: "MOVHBR", aux: "SymOff", symEffect: "Write"}, // store 2 bytes in arg2 to arg0+arg1+auxint+aux. arg3=mem. Reverse bytes.
|
||||
{name: "MOVWBRstoreidx", argLength: 4, reg: gpstoreidx, commutative: true, asm: "MOVWBR", aux: "SymOff", symEffect: "Write"}, // store 4 bytes in arg2 to arg0+arg1+auxint+aux. arg3=mem. Reverse bytes.
|
||||
{name: "MOVDBRstoreidx", argLength: 4, reg: gpstoreidx, commutative: true, asm: "MOVDBR", aux: "SymOff", symEffect: "Write"}, // store 8 bytes in arg2 to arg0+arg1+auxint+aux. arg3=mem. Reverse bytes.
|
||||
|
||||
// For storeconst ops, the AuxInt field encodes both
|
||||
// the value to store and an address offset of the store.
|
||||
@ -473,16 +487,11 @@ func init() {
|
||||
{name: "LoweredPanicBoundsB", argLength: 3, aux: "Int64", reg: regInfo{inputs: []regMask{r1, r2}}, typ: "Mem"}, // arg0=idx, arg1=len, arg2=mem, returns memory. AuxInt contains report code (see PanicBounds in generic.go).
|
||||
{name: "LoweredPanicBoundsC", argLength: 3, aux: "Int64", reg: regInfo{inputs: []regMask{r0, r1}}, typ: "Mem"}, // arg0=idx, arg1=len, arg2=mem, returns memory. AuxInt contains report code (see PanicBounds in generic.go).
|
||||
|
||||
// Constant flag values. For any comparison, there are 5 possible
|
||||
// outcomes: the three from the signed total order (<,==,>) and the
|
||||
// three from the unsigned total order. The == cases overlap.
|
||||
// Note: there's a sixth "unordered" outcome for floating-point
|
||||
// comparisons, but we don't use such a beast yet.
|
||||
// These ops are for temporary use by rewrite rules. They
|
||||
// cannot appear in the generated assembly.
|
||||
{name: "FlagEQ"}, // equal
|
||||
{name: "FlagLT"}, // <
|
||||
{name: "FlagGT"}, // >
|
||||
// Constant conditon code values. The condition code can be 0, 1, 2 or 3.
|
||||
{name: "FlagEQ"}, // CC=0 (equal)
|
||||
{name: "FlagLT"}, // CC=1 (less than)
|
||||
{name: "FlagGT"}, // CC=2 (greater than)
|
||||
{name: "FlagOV"}, // CC=3 (overflow)
|
||||
|
||||
// Atomic loads. These are just normal loads but return <value,memory> tuples
|
||||
// so they can be properly ordered with other loads.
|
||||
|
@ -1922,6 +1922,11 @@ const (
|
||||
OpS390XXORWconst
|
||||
OpS390XXORload
|
||||
OpS390XXORWload
|
||||
OpS390XADDC
|
||||
OpS390XADDCconst
|
||||
OpS390XADDE
|
||||
OpS390XSUBC
|
||||
OpS390XSUBE
|
||||
OpS390XCMP
|
||||
OpS390XCMPW
|
||||
OpS390XCMPU
|
||||
@ -2044,6 +2049,7 @@ const (
|
||||
OpS390XFlagEQ
|
||||
OpS390XFlagLT
|
||||
OpS390XFlagGT
|
||||
OpS390XFlagOV
|
||||
OpS390XMOVWZatomicload
|
||||
OpS390XMOVDatomicload
|
||||
OpS390XMOVWatomicstore
|
||||
@ -25811,6 +25817,80 @@ var opcodeTable = [...]opInfo{
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "ADDC",
|
||||
argLen: 2,
|
||||
commutative: true,
|
||||
asm: s390x.AADDC,
|
||||
reg: regInfo{
|
||||
inputs: []inputInfo{
|
||||
{0, 23551}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14
|
||||
{1, 23551}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14
|
||||
},
|
||||
outputs: []outputInfo{
|
||||
{0, 23551}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "ADDCconst",
|
||||
auxType: auxInt16,
|
||||
argLen: 1,
|
||||
asm: s390x.AADDC,
|
||||
reg: regInfo{
|
||||
inputs: []inputInfo{
|
||||
{0, 23551}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14
|
||||
},
|
||||
outputs: []outputInfo{
|
||||
{0, 23551}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "ADDE",
|
||||
argLen: 3,
|
||||
commutative: true,
|
||||
resultInArg0: true,
|
||||
asm: s390x.AADDE,
|
||||
reg: regInfo{
|
||||
inputs: []inputInfo{
|
||||
{0, 23551}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14
|
||||
{1, 23551}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14
|
||||
},
|
||||
outputs: []outputInfo{
|
||||
{0, 23551}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "SUBC",
|
||||
argLen: 2,
|
||||
asm: s390x.ASUBC,
|
||||
reg: regInfo{
|
||||
inputs: []inputInfo{
|
||||
{0, 23551}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14
|
||||
{1, 23551}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14
|
||||
},
|
||||
outputs: []outputInfo{
|
||||
{0, 23551}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "SUBE",
|
||||
argLen: 3,
|
||||
resultInArg0: true,
|
||||
asm: s390x.ASUBE,
|
||||
reg: regInfo{
|
||||
inputs: []inputInfo{
|
||||
{0, 23551}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14
|
||||
{1, 23551}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14
|
||||
},
|
||||
outputs: []outputInfo{
|
||||
{0, 23551}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "CMP",
|
||||
argLen: 2,
|
||||
@ -26644,7 +26724,6 @@ var opcodeTable = [...]opInfo{
|
||||
name: "MOVBZload",
|
||||
auxType: auxSymOff,
|
||||
argLen: 2,
|
||||
clobberFlags: true,
|
||||
faultOnNilArg0: true,
|
||||
symEffect: SymRead,
|
||||
asm: s390x.AMOVBZ,
|
||||
@ -26661,7 +26740,6 @@ var opcodeTable = [...]opInfo{
|
||||
name: "MOVBload",
|
||||
auxType: auxSymOff,
|
||||
argLen: 2,
|
||||
clobberFlags: true,
|
||||
faultOnNilArg0: true,
|
||||
symEffect: SymRead,
|
||||
asm: s390x.AMOVB,
|
||||
@ -26678,7 +26756,6 @@ var opcodeTable = [...]opInfo{
|
||||
name: "MOVHZload",
|
||||
auxType: auxSymOff,
|
||||
argLen: 2,
|
||||
clobberFlags: true,
|
||||
faultOnNilArg0: true,
|
||||
symEffect: SymRead,
|
||||
asm: s390x.AMOVHZ,
|
||||
@ -26695,7 +26772,6 @@ var opcodeTable = [...]opInfo{
|
||||
name: "MOVHload",
|
||||
auxType: auxSymOff,
|
||||
argLen: 2,
|
||||
clobberFlags: true,
|
||||
faultOnNilArg0: true,
|
||||
symEffect: SymRead,
|
||||
asm: s390x.AMOVH,
|
||||
@ -26712,7 +26788,6 @@ var opcodeTable = [...]opInfo{
|
||||
name: "MOVWZload",
|
||||
auxType: auxSymOff,
|
||||
argLen: 2,
|
||||
clobberFlags: true,
|
||||
faultOnNilArg0: true,
|
||||
symEffect: SymRead,
|
||||
asm: s390x.AMOVWZ,
|
||||
@ -26729,7 +26804,6 @@ var opcodeTable = [...]opInfo{
|
||||
name: "MOVWload",
|
||||
auxType: auxSymOff,
|
||||
argLen: 2,
|
||||
clobberFlags: true,
|
||||
faultOnNilArg0: true,
|
||||
symEffect: SymRead,
|
||||
asm: s390x.AMOVW,
|
||||
@ -26746,7 +26820,6 @@ var opcodeTable = [...]opInfo{
|
||||
name: "MOVDload",
|
||||
auxType: auxSymOff,
|
||||
argLen: 2,
|
||||
clobberFlags: true,
|
||||
faultOnNilArg0: true,
|
||||
symEffect: SymRead,
|
||||
asm: s390x.AMOVD,
|
||||
@ -26789,7 +26862,6 @@ var opcodeTable = [...]opInfo{
|
||||
name: "MOVHBRload",
|
||||
auxType: auxSymOff,
|
||||
argLen: 2,
|
||||
clobberFlags: true,
|
||||
faultOnNilArg0: true,
|
||||
symEffect: SymRead,
|
||||
asm: s390x.AMOVHBR,
|
||||
@ -26806,7 +26878,6 @@ var opcodeTable = [...]opInfo{
|
||||
name: "MOVWBRload",
|
||||
auxType: auxSymOff,
|
||||
argLen: 2,
|
||||
clobberFlags: true,
|
||||
faultOnNilArg0: true,
|
||||
symEffect: SymRead,
|
||||
asm: s390x.AMOVWBR,
|
||||
@ -26823,7 +26894,6 @@ var opcodeTable = [...]opInfo{
|
||||
name: "MOVDBRload",
|
||||
auxType: auxSymOff,
|
||||
argLen: 2,
|
||||
clobberFlags: true,
|
||||
faultOnNilArg0: true,
|
||||
symEffect: SymRead,
|
||||
asm: s390x.AMOVDBR,
|
||||
@ -26840,7 +26910,6 @@ var opcodeTable = [...]opInfo{
|
||||
name: "MOVBstore",
|
||||
auxType: auxSymOff,
|
||||
argLen: 3,
|
||||
clobberFlags: true,
|
||||
faultOnNilArg0: true,
|
||||
symEffect: SymWrite,
|
||||
asm: s390x.AMOVB,
|
||||
@ -26855,7 +26924,6 @@ var opcodeTable = [...]opInfo{
|
||||
name: "MOVHstore",
|
||||
auxType: auxSymOff,
|
||||
argLen: 3,
|
||||
clobberFlags: true,
|
||||
faultOnNilArg0: true,
|
||||
symEffect: SymWrite,
|
||||
asm: s390x.AMOVH,
|
||||
@ -26870,7 +26938,6 @@ var opcodeTable = [...]opInfo{
|
||||
name: "MOVWstore",
|
||||
auxType: auxSymOff,
|
||||
argLen: 3,
|
||||
clobberFlags: true,
|
||||
faultOnNilArg0: true,
|
||||
symEffect: SymWrite,
|
||||
asm: s390x.AMOVW,
|
||||
@ -26885,7 +26952,6 @@ var opcodeTable = [...]opInfo{
|
||||
name: "MOVDstore",
|
||||
auxType: auxSymOff,
|
||||
argLen: 3,
|
||||
clobberFlags: true,
|
||||
faultOnNilArg0: true,
|
||||
symEffect: SymWrite,
|
||||
asm: s390x.AMOVD,
|
||||
@ -26900,7 +26966,6 @@ var opcodeTable = [...]opInfo{
|
||||
name: "MOVHBRstore",
|
||||
auxType: auxSymOff,
|
||||
argLen: 3,
|
||||
clobberFlags: true,
|
||||
faultOnNilArg0: true,
|
||||
symEffect: SymWrite,
|
||||
asm: s390x.AMOVHBR,
|
||||
@ -26915,7 +26980,6 @@ var opcodeTable = [...]opInfo{
|
||||
name: "MOVWBRstore",
|
||||
auxType: auxSymOff,
|
||||
argLen: 3,
|
||||
clobberFlags: true,
|
||||
faultOnNilArg0: true,
|
||||
symEffect: SymWrite,
|
||||
asm: s390x.AMOVWBR,
|
||||
@ -26930,7 +26994,6 @@ var opcodeTable = [...]opInfo{
|
||||
name: "MOVDBRstore",
|
||||
auxType: auxSymOff,
|
||||
argLen: 3,
|
||||
clobberFlags: true,
|
||||
faultOnNilArg0: true,
|
||||
symEffect: SymWrite,
|
||||
asm: s390x.AMOVDBR,
|
||||
@ -26958,13 +27021,12 @@ var opcodeTable = [...]opInfo{
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "MOVBZloadidx",
|
||||
auxType: auxSymOff,
|
||||
argLen: 3,
|
||||
commutative: true,
|
||||
clobberFlags: true,
|
||||
symEffect: SymRead,
|
||||
asm: s390x.AMOVBZ,
|
||||
name: "MOVBZloadidx",
|
||||
auxType: auxSymOff,
|
||||
argLen: 3,
|
||||
commutative: true,
|
||||
symEffect: SymRead,
|
||||
asm: s390x.AMOVBZ,
|
||||
reg: regInfo{
|
||||
inputs: []inputInfo{
|
||||
{1, 56318}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14 SP
|
||||
@ -26976,13 +27038,12 @@ var opcodeTable = [...]opInfo{
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "MOVBloadidx",
|
||||
auxType: auxSymOff,
|
||||
argLen: 3,
|
||||
commutative: true,
|
||||
clobberFlags: true,
|
||||
symEffect: SymRead,
|
||||
asm: s390x.AMOVB,
|
||||
name: "MOVBloadidx",
|
||||
auxType: auxSymOff,
|
||||
argLen: 3,
|
||||
commutative: true,
|
||||
symEffect: SymRead,
|
||||
asm: s390x.AMOVB,
|
||||
reg: regInfo{
|
||||
inputs: []inputInfo{
|
||||
{1, 56318}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14 SP
|
||||
@ -26994,13 +27055,12 @@ var opcodeTable = [...]opInfo{
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "MOVHZloadidx",
|
||||
auxType: auxSymOff,
|
||||
argLen: 3,
|
||||
commutative: true,
|
||||
clobberFlags: true,
|
||||
symEffect: SymRead,
|
||||
asm: s390x.AMOVHZ,
|
||||
name: "MOVHZloadidx",
|
||||
auxType: auxSymOff,
|
||||
argLen: 3,
|
||||
commutative: true,
|
||||
symEffect: SymRead,
|
||||
asm: s390x.AMOVHZ,
|
||||
reg: regInfo{
|
||||
inputs: []inputInfo{
|
||||
{1, 56318}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14 SP
|
||||
@ -27012,13 +27072,12 @@ var opcodeTable = [...]opInfo{
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "MOVHloadidx",
|
||||
auxType: auxSymOff,
|
||||
argLen: 3,
|
||||
commutative: true,
|
||||
clobberFlags: true,
|
||||
symEffect: SymRead,
|
||||
asm: s390x.AMOVH,
|
||||
name: "MOVHloadidx",
|
||||
auxType: auxSymOff,
|
||||
argLen: 3,
|
||||
commutative: true,
|
||||
symEffect: SymRead,
|
||||
asm: s390x.AMOVH,
|
||||
reg: regInfo{
|
||||
inputs: []inputInfo{
|
||||
{1, 56318}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14 SP
|
||||
@ -27030,13 +27089,12 @@ var opcodeTable = [...]opInfo{
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "MOVWZloadidx",
|
||||
auxType: auxSymOff,
|
||||
argLen: 3,
|
||||
commutative: true,
|
||||
clobberFlags: true,
|
||||
symEffect: SymRead,
|
||||
asm: s390x.AMOVWZ,
|
||||
name: "MOVWZloadidx",
|
||||
auxType: auxSymOff,
|
||||
argLen: 3,
|
||||
commutative: true,
|
||||
symEffect: SymRead,
|
||||
asm: s390x.AMOVWZ,
|
||||
reg: regInfo{
|
||||
inputs: []inputInfo{
|
||||
{1, 56318}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14 SP
|
||||
@ -27048,13 +27106,12 @@ var opcodeTable = [...]opInfo{
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "MOVWloadidx",
|
||||
auxType: auxSymOff,
|
||||
argLen: 3,
|
||||
commutative: true,
|
||||
clobberFlags: true,
|
||||
symEffect: SymRead,
|
||||
asm: s390x.AMOVW,
|
||||
name: "MOVWloadidx",
|
||||
auxType: auxSymOff,
|
||||
argLen: 3,
|
||||
commutative: true,
|
||||
symEffect: SymRead,
|
||||
asm: s390x.AMOVW,
|
||||
reg: regInfo{
|
||||
inputs: []inputInfo{
|
||||
{1, 56318}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14 SP
|
||||
@ -27066,13 +27123,12 @@ var opcodeTable = [...]opInfo{
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "MOVDloadidx",
|
||||
auxType: auxSymOff,
|
||||
argLen: 3,
|
||||
commutative: true,
|
||||
clobberFlags: true,
|
||||
symEffect: SymRead,
|
||||
asm: s390x.AMOVD,
|
||||
name: "MOVDloadidx",
|
||||
auxType: auxSymOff,
|
||||
argLen: 3,
|
||||
commutative: true,
|
||||
symEffect: SymRead,
|
||||
asm: s390x.AMOVD,
|
||||
reg: regInfo{
|
||||
inputs: []inputInfo{
|
||||
{1, 56318}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14 SP
|
||||
@ -27084,13 +27140,12 @@ var opcodeTable = [...]opInfo{
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "MOVHBRloadidx",
|
||||
auxType: auxSymOff,
|
||||
argLen: 3,
|
||||
commutative: true,
|
||||
clobberFlags: true,
|
||||
symEffect: SymRead,
|
||||
asm: s390x.AMOVHBR,
|
||||
name: "MOVHBRloadidx",
|
||||
auxType: auxSymOff,
|
||||
argLen: 3,
|
||||
commutative: true,
|
||||
symEffect: SymRead,
|
||||
asm: s390x.AMOVHBR,
|
||||
reg: regInfo{
|
||||
inputs: []inputInfo{
|
||||
{1, 56318}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14 SP
|
||||
@ -27102,13 +27157,12 @@ var opcodeTable = [...]opInfo{
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "MOVWBRloadidx",
|
||||
auxType: auxSymOff,
|
||||
argLen: 3,
|
||||
commutative: true,
|
||||
clobberFlags: true,
|
||||
symEffect: SymRead,
|
||||
asm: s390x.AMOVWBR,
|
||||
name: "MOVWBRloadidx",
|
||||
auxType: auxSymOff,
|
||||
argLen: 3,
|
||||
commutative: true,
|
||||
symEffect: SymRead,
|
||||
asm: s390x.AMOVWBR,
|
||||
reg: regInfo{
|
||||
inputs: []inputInfo{
|
||||
{1, 56318}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14 SP
|
||||
@ -27120,13 +27174,12 @@ var opcodeTable = [...]opInfo{
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "MOVDBRloadidx",
|
||||
auxType: auxSymOff,
|
||||
argLen: 3,
|
||||
commutative: true,
|
||||
clobberFlags: true,
|
||||
symEffect: SymRead,
|
||||
asm: s390x.AMOVDBR,
|
||||
name: "MOVDBRloadidx",
|
||||
auxType: auxSymOff,
|
||||
argLen: 3,
|
||||
commutative: true,
|
||||
symEffect: SymRead,
|
||||
asm: s390x.AMOVDBR,
|
||||
reg: regInfo{
|
||||
inputs: []inputInfo{
|
||||
{1, 56318}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14 SP
|
||||
@ -27138,13 +27191,12 @@ var opcodeTable = [...]opInfo{
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "MOVBstoreidx",
|
||||
auxType: auxSymOff,
|
||||
argLen: 4,
|
||||
commutative: true,
|
||||
clobberFlags: true,
|
||||
symEffect: SymWrite,
|
||||
asm: s390x.AMOVB,
|
||||
name: "MOVBstoreidx",
|
||||
auxType: auxSymOff,
|
||||
argLen: 4,
|
||||
commutative: true,
|
||||
symEffect: SymWrite,
|
||||
asm: s390x.AMOVB,
|
||||
reg: regInfo{
|
||||
inputs: []inputInfo{
|
||||
{0, 56318}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14 SP
|
||||
@ -27154,13 +27206,12 @@ var opcodeTable = [...]opInfo{
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "MOVHstoreidx",
|
||||
auxType: auxSymOff,
|
||||
argLen: 4,
|
||||
commutative: true,
|
||||
clobberFlags: true,
|
||||
symEffect: SymWrite,
|
||||
asm: s390x.AMOVH,
|
||||
name: "MOVHstoreidx",
|
||||
auxType: auxSymOff,
|
||||
argLen: 4,
|
||||
commutative: true,
|
||||
symEffect: SymWrite,
|
||||
asm: s390x.AMOVH,
|
||||
reg: regInfo{
|
||||
inputs: []inputInfo{
|
||||
{0, 56318}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14 SP
|
||||
@ -27170,13 +27221,12 @@ var opcodeTable = [...]opInfo{
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "MOVWstoreidx",
|
||||
auxType: auxSymOff,
|
||||
argLen: 4,
|
||||
commutative: true,
|
||||
clobberFlags: true,
|
||||
symEffect: SymWrite,
|
||||
asm: s390x.AMOVW,
|
||||
name: "MOVWstoreidx",
|
||||
auxType: auxSymOff,
|
||||
argLen: 4,
|
||||
commutative: true,
|
||||
symEffect: SymWrite,
|
||||
asm: s390x.AMOVW,
|
||||
reg: regInfo{
|
||||
inputs: []inputInfo{
|
||||
{0, 56318}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14 SP
|
||||
@ -27186,13 +27236,12 @@ var opcodeTable = [...]opInfo{
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "MOVDstoreidx",
|
||||
auxType: auxSymOff,
|
||||
argLen: 4,
|
||||
commutative: true,
|
||||
clobberFlags: true,
|
||||
symEffect: SymWrite,
|
||||
asm: s390x.AMOVD,
|
||||
name: "MOVDstoreidx",
|
||||
auxType: auxSymOff,
|
||||
argLen: 4,
|
||||
commutative: true,
|
||||
symEffect: SymWrite,
|
||||
asm: s390x.AMOVD,
|
||||
reg: regInfo{
|
||||
inputs: []inputInfo{
|
||||
{0, 56318}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14 SP
|
||||
@ -27202,13 +27251,12 @@ var opcodeTable = [...]opInfo{
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "MOVHBRstoreidx",
|
||||
auxType: auxSymOff,
|
||||
argLen: 4,
|
||||
commutative: true,
|
||||
clobberFlags: true,
|
||||
symEffect: SymWrite,
|
||||
asm: s390x.AMOVHBR,
|
||||
name: "MOVHBRstoreidx",
|
||||
auxType: auxSymOff,
|
||||
argLen: 4,
|
||||
commutative: true,
|
||||
symEffect: SymWrite,
|
||||
asm: s390x.AMOVHBR,
|
||||
reg: regInfo{
|
||||
inputs: []inputInfo{
|
||||
{0, 56318}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14 SP
|
||||
@ -27218,13 +27266,12 @@ var opcodeTable = [...]opInfo{
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "MOVWBRstoreidx",
|
||||
auxType: auxSymOff,
|
||||
argLen: 4,
|
||||
commutative: true,
|
||||
clobberFlags: true,
|
||||
symEffect: SymWrite,
|
||||
asm: s390x.AMOVWBR,
|
||||
name: "MOVWBRstoreidx",
|
||||
auxType: auxSymOff,
|
||||
argLen: 4,
|
||||
commutative: true,
|
||||
symEffect: SymWrite,
|
||||
asm: s390x.AMOVWBR,
|
||||
reg: regInfo{
|
||||
inputs: []inputInfo{
|
||||
{0, 56318}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14 SP
|
||||
@ -27234,13 +27281,12 @@ var opcodeTable = [...]opInfo{
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "MOVDBRstoreidx",
|
||||
auxType: auxSymOff,
|
||||
argLen: 4,
|
||||
commutative: true,
|
||||
clobberFlags: true,
|
||||
symEffect: SymWrite,
|
||||
asm: s390x.AMOVDBR,
|
||||
name: "MOVDBRstoreidx",
|
||||
auxType: auxSymOff,
|
||||
argLen: 4,
|
||||
commutative: true,
|
||||
symEffect: SymWrite,
|
||||
asm: s390x.AMOVDBR,
|
||||
reg: regInfo{
|
||||
inputs: []inputInfo{
|
||||
{0, 56318}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14 SP
|
||||
@ -27499,6 +27545,11 @@ var opcodeTable = [...]opInfo{
|
||||
argLen: 0,
|
||||
reg: regInfo{},
|
||||
},
|
||||
{
|
||||
name: "FlagOV",
|
||||
argLen: 0,
|
||||
reg: regInfo{},
|
||||
},
|
||||
{
|
||||
name: "MOVWZatomicload",
|
||||
auxType: auxSymOff,
|
||||
|
@ -477,6 +477,10 @@ func rewriteValueS390X(v *Value) bool {
|
||||
return rewriteValueS390X_OpRsh8x8_0(v)
|
||||
case OpS390XADD:
|
||||
return rewriteValueS390X_OpS390XADD_0(v) || rewriteValueS390X_OpS390XADD_10(v)
|
||||
case OpS390XADDC:
|
||||
return rewriteValueS390X_OpS390XADDC_0(v)
|
||||
case OpS390XADDE:
|
||||
return rewriteValueS390X_OpS390XADDE_0(v)
|
||||
case OpS390XADDW:
|
||||
return rewriteValueS390X_OpS390XADDW_0(v) || rewriteValueS390X_OpS390XADDW_10(v)
|
||||
case OpS390XADDWconst:
|
||||
@ -705,6 +709,8 @@ func rewriteValueS390X(v *Value) bool {
|
||||
return rewriteValueS390X_OpS390XSTMG2_0(v)
|
||||
case OpS390XSUB:
|
||||
return rewriteValueS390X_OpS390XSUB_0(v)
|
||||
case OpS390XSUBE:
|
||||
return rewriteValueS390X_OpS390XSUBE_0(v)
|
||||
case OpS390XSUBW:
|
||||
return rewriteValueS390X_OpS390XSUBW_0(v)
|
||||
case OpS390XSUBWconst:
|
||||
@ -6849,6 +6855,175 @@ func rewriteValueS390X_OpS390XADD_10(v *Value) bool {
|
||||
}
|
||||
return false
|
||||
}
|
||||
func rewriteValueS390X_OpS390XADDC_0(v *Value) bool {
|
||||
// match: (ADDC x (MOVDconst [c]))
|
||||
// cond: is16Bit(c)
|
||||
// result: (ADDCconst x [c])
|
||||
for {
|
||||
_ = v.Args[1]
|
||||
x := v.Args[0]
|
||||
v_1 := v.Args[1]
|
||||
if v_1.Op != OpS390XMOVDconst {
|
||||
break
|
||||
}
|
||||
c := v_1.AuxInt
|
||||
if !(is16Bit(c)) {
|
||||
break
|
||||
}
|
||||
v.reset(OpS390XADDCconst)
|
||||
v.AuxInt = c
|
||||
v.AddArg(x)
|
||||
return true
|
||||
}
|
||||
// match: (ADDC (MOVDconst [c]) x)
|
||||
// cond: is16Bit(c)
|
||||
// result: (ADDCconst x [c])
|
||||
for {
|
||||
x := v.Args[1]
|
||||
v_0 := v.Args[0]
|
||||
if v_0.Op != OpS390XMOVDconst {
|
||||
break
|
||||
}
|
||||
c := v_0.AuxInt
|
||||
if !(is16Bit(c)) {
|
||||
break
|
||||
}
|
||||
v.reset(OpS390XADDCconst)
|
||||
v.AuxInt = c
|
||||
v.AddArg(x)
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
func rewriteValueS390X_OpS390XADDE_0(v *Value) bool {
|
||||
// match: (ADDE x y (FlagEQ))
|
||||
// cond:
|
||||
// result: (ADDC x y)
|
||||
for {
|
||||
_ = v.Args[2]
|
||||
x := v.Args[0]
|
||||
y := v.Args[1]
|
||||
v_2 := v.Args[2]
|
||||
if v_2.Op != OpS390XFlagEQ {
|
||||
break
|
||||
}
|
||||
v.reset(OpS390XADDC)
|
||||
v.AddArg(x)
|
||||
v.AddArg(y)
|
||||
return true
|
||||
}
|
||||
// match: (ADDE x y (FlagLT))
|
||||
// cond:
|
||||
// result: (ADDC x y)
|
||||
for {
|
||||
_ = v.Args[2]
|
||||
x := v.Args[0]
|
||||
y := v.Args[1]
|
||||
v_2 := v.Args[2]
|
||||
if v_2.Op != OpS390XFlagLT {
|
||||
break
|
||||
}
|
||||
v.reset(OpS390XADDC)
|
||||
v.AddArg(x)
|
||||
v.AddArg(y)
|
||||
return true
|
||||
}
|
||||
// match: (ADDE x y (Select1 (ADDCconst [-1] (Select0 (ADDE (MOVDconst [0]) (MOVDconst [0]) c)))))
|
||||
// cond:
|
||||
// result: (ADDE x y c)
|
||||
for {
|
||||
_ = v.Args[2]
|
||||
x := v.Args[0]
|
||||
y := v.Args[1]
|
||||
v_2 := v.Args[2]
|
||||
if v_2.Op != OpSelect1 {
|
||||
break
|
||||
}
|
||||
v_2_0 := v_2.Args[0]
|
||||
if v_2_0.Op != OpS390XADDCconst {
|
||||
break
|
||||
}
|
||||
if v_2_0.AuxInt != -1 {
|
||||
break
|
||||
}
|
||||
v_2_0_0 := v_2_0.Args[0]
|
||||
if v_2_0_0.Op != OpSelect0 {
|
||||
break
|
||||
}
|
||||
v_2_0_0_0 := v_2_0_0.Args[0]
|
||||
if v_2_0_0_0.Op != OpS390XADDE {
|
||||
break
|
||||
}
|
||||
c := v_2_0_0_0.Args[2]
|
||||
v_2_0_0_0_0 := v_2_0_0_0.Args[0]
|
||||
if v_2_0_0_0_0.Op != OpS390XMOVDconst {
|
||||
break
|
||||
}
|
||||
if v_2_0_0_0_0.AuxInt != 0 {
|
||||
break
|
||||
}
|
||||
v_2_0_0_0_1 := v_2_0_0_0.Args[1]
|
||||
if v_2_0_0_0_1.Op != OpS390XMOVDconst {
|
||||
break
|
||||
}
|
||||
if v_2_0_0_0_1.AuxInt != 0 {
|
||||
break
|
||||
}
|
||||
v.reset(OpS390XADDE)
|
||||
v.AddArg(x)
|
||||
v.AddArg(y)
|
||||
v.AddArg(c)
|
||||
return true
|
||||
}
|
||||
// match: (ADDE x y (Select1 (ADDCconst [-1] (Select0 (ADDE (MOVDconst [0]) (MOVDconst [0]) c)))))
|
||||
// cond:
|
||||
// result: (ADDE x y c)
|
||||
for {
|
||||
_ = v.Args[2]
|
||||
x := v.Args[0]
|
||||
y := v.Args[1]
|
||||
v_2 := v.Args[2]
|
||||
if v_2.Op != OpSelect1 {
|
||||
break
|
||||
}
|
||||
v_2_0 := v_2.Args[0]
|
||||
if v_2_0.Op != OpS390XADDCconst {
|
||||
break
|
||||
}
|
||||
if v_2_0.AuxInt != -1 {
|
||||
break
|
||||
}
|
||||
v_2_0_0 := v_2_0.Args[0]
|
||||
if v_2_0_0.Op != OpSelect0 {
|
||||
break
|
||||
}
|
||||
v_2_0_0_0 := v_2_0_0.Args[0]
|
||||
if v_2_0_0_0.Op != OpS390XADDE {
|
||||
break
|
||||
}
|
||||
c := v_2_0_0_0.Args[2]
|
||||
v_2_0_0_0_0 := v_2_0_0_0.Args[0]
|
||||
if v_2_0_0_0_0.Op != OpS390XMOVDconst {
|
||||
break
|
||||
}
|
||||
if v_2_0_0_0_0.AuxInt != 0 {
|
||||
break
|
||||
}
|
||||
v_2_0_0_0_1 := v_2_0_0_0.Args[1]
|
||||
if v_2_0_0_0_1.Op != OpS390XMOVDconst {
|
||||
break
|
||||
}
|
||||
if v_2_0_0_0_1.AuxInt != 0 {
|
||||
break
|
||||
}
|
||||
v.reset(OpS390XADDE)
|
||||
v.AddArg(x)
|
||||
v.AddArg(y)
|
||||
v.AddArg(c)
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
func rewriteValueS390X_OpS390XADDW_0(v *Value) bool {
|
||||
// match: (ADDW x (MOVDconst [c]))
|
||||
// cond:
|
||||
@ -39017,6 +39192,97 @@ func rewriteValueS390X_OpS390XSUB_0(v *Value) bool {
|
||||
}
|
||||
return false
|
||||
}
|
||||
func rewriteValueS390X_OpS390XSUBE_0(v *Value) bool {
|
||||
// match: (SUBE x y (FlagGT))
|
||||
// cond:
|
||||
// result: (SUBC x y)
|
||||
for {
|
||||
_ = v.Args[2]
|
||||
x := v.Args[0]
|
||||
y := v.Args[1]
|
||||
v_2 := v.Args[2]
|
||||
if v_2.Op != OpS390XFlagGT {
|
||||
break
|
||||
}
|
||||
v.reset(OpS390XSUBC)
|
||||
v.AddArg(x)
|
||||
v.AddArg(y)
|
||||
return true
|
||||
}
|
||||
// match: (SUBE x y (FlagOV))
|
||||
// cond:
|
||||
// result: (SUBC x y)
|
||||
for {
|
||||
_ = v.Args[2]
|
||||
x := v.Args[0]
|
||||
y := v.Args[1]
|
||||
v_2 := v.Args[2]
|
||||
if v_2.Op != OpS390XFlagOV {
|
||||
break
|
||||
}
|
||||
v.reset(OpS390XSUBC)
|
||||
v.AddArg(x)
|
||||
v.AddArg(y)
|
||||
return true
|
||||
}
|
||||
// match: (SUBE x y (Select1 (SUBC (MOVDconst [0]) (NEG (Select0 (SUBE (MOVDconst [0]) (MOVDconst [0]) c))))))
|
||||
// cond:
|
||||
// result: (SUBE x y c)
|
||||
for {
|
||||
_ = v.Args[2]
|
||||
x := v.Args[0]
|
||||
y := v.Args[1]
|
||||
v_2 := v.Args[2]
|
||||
if v_2.Op != OpSelect1 {
|
||||
break
|
||||
}
|
||||
v_2_0 := v_2.Args[0]
|
||||
if v_2_0.Op != OpS390XSUBC {
|
||||
break
|
||||
}
|
||||
_ = v_2_0.Args[1]
|
||||
v_2_0_0 := v_2_0.Args[0]
|
||||
if v_2_0_0.Op != OpS390XMOVDconst {
|
||||
break
|
||||
}
|
||||
if v_2_0_0.AuxInt != 0 {
|
||||
break
|
||||
}
|
||||
v_2_0_1 := v_2_0.Args[1]
|
||||
if v_2_0_1.Op != OpS390XNEG {
|
||||
break
|
||||
}
|
||||
v_2_0_1_0 := v_2_0_1.Args[0]
|
||||
if v_2_0_1_0.Op != OpSelect0 {
|
||||
break
|
||||
}
|
||||
v_2_0_1_0_0 := v_2_0_1_0.Args[0]
|
||||
if v_2_0_1_0_0.Op != OpS390XSUBE {
|
||||
break
|
||||
}
|
||||
c := v_2_0_1_0_0.Args[2]
|
||||
v_2_0_1_0_0_0 := v_2_0_1_0_0.Args[0]
|
||||
if v_2_0_1_0_0_0.Op != OpS390XMOVDconst {
|
||||
break
|
||||
}
|
||||
if v_2_0_1_0_0_0.AuxInt != 0 {
|
||||
break
|
||||
}
|
||||
v_2_0_1_0_0_1 := v_2_0_1_0_0.Args[1]
|
||||
if v_2_0_1_0_0_1.Op != OpS390XMOVDconst {
|
||||
break
|
||||
}
|
||||
if v_2_0_1_0_0_1.AuxInt != 0 {
|
||||
break
|
||||
}
|
||||
v.reset(OpS390XSUBE)
|
||||
v.AddArg(x)
|
||||
v.AddArg(y)
|
||||
v.AddArg(c)
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
func rewriteValueS390X_OpS390XSUBW_0(v *Value) bool {
|
||||
b := v.Block
|
||||
// match: (SUBW x (MOVDconst [c]))
|
||||
@ -40180,6 +40446,59 @@ func rewriteValueS390X_OpS390XXORload_0(v *Value) bool {
|
||||
}
|
||||
func rewriteValueS390X_OpSelect0_0(v *Value) bool {
|
||||
b := v.Block
|
||||
typ := &b.Func.Config.Types
|
||||
// match: (Select0 (Add64carry x y c))
|
||||
// cond:
|
||||
// result: (Select0 <typ.UInt64> (ADDE x y (Select1 <types.TypeFlags> (ADDCconst c [-1]))))
|
||||
for {
|
||||
v_0 := v.Args[0]
|
||||
if v_0.Op != OpAdd64carry {
|
||||
break
|
||||
}
|
||||
c := v_0.Args[2]
|
||||
x := v_0.Args[0]
|
||||
y := v_0.Args[1]
|
||||
v.reset(OpSelect0)
|
||||
v.Type = typ.UInt64
|
||||
v0 := b.NewValue0(v.Pos, OpS390XADDE, types.NewTuple(typ.UInt64, types.TypeFlags))
|
||||
v0.AddArg(x)
|
||||
v0.AddArg(y)
|
||||
v1 := b.NewValue0(v.Pos, OpSelect1, types.TypeFlags)
|
||||
v2 := b.NewValue0(v.Pos, OpS390XADDCconst, types.NewTuple(typ.UInt64, types.TypeFlags))
|
||||
v2.AuxInt = -1
|
||||
v2.AddArg(c)
|
||||
v1.AddArg(v2)
|
||||
v0.AddArg(v1)
|
||||
v.AddArg(v0)
|
||||
return true
|
||||
}
|
||||
// match: (Select0 (Sub64borrow x y c))
|
||||
// cond:
|
||||
// result: (Select0 <typ.UInt64> (SUBE x y (Select1 <types.TypeFlags> (SUBC (MOVDconst [0]) c))))
|
||||
for {
|
||||
v_0 := v.Args[0]
|
||||
if v_0.Op != OpSub64borrow {
|
||||
break
|
||||
}
|
||||
c := v_0.Args[2]
|
||||
x := v_0.Args[0]
|
||||
y := v_0.Args[1]
|
||||
v.reset(OpSelect0)
|
||||
v.Type = typ.UInt64
|
||||
v0 := b.NewValue0(v.Pos, OpS390XSUBE, types.NewTuple(typ.UInt64, types.TypeFlags))
|
||||
v0.AddArg(x)
|
||||
v0.AddArg(y)
|
||||
v1 := b.NewValue0(v.Pos, OpSelect1, types.TypeFlags)
|
||||
v2 := b.NewValue0(v.Pos, OpS390XSUBC, types.NewTuple(typ.UInt64, types.TypeFlags))
|
||||
v3 := b.NewValue0(v.Pos, OpS390XMOVDconst, typ.UInt64)
|
||||
v3.AuxInt = 0
|
||||
v2.AddArg(v3)
|
||||
v2.AddArg(c)
|
||||
v1.AddArg(v2)
|
||||
v0.AddArg(v1)
|
||||
v.AddArg(v0)
|
||||
return true
|
||||
}
|
||||
// match: (Select0 <t> (AddTupleFirst32 val tuple))
|
||||
// cond:
|
||||
// result: (ADDW val (Select0 <t> tuple))
|
||||
@ -40216,9 +40535,125 @@ func rewriteValueS390X_OpSelect0_0(v *Value) bool {
|
||||
v.AddArg(v0)
|
||||
return true
|
||||
}
|
||||
// match: (Select0 (ADDCconst (MOVDconst [c]) [d]))
|
||||
// cond:
|
||||
// result: (MOVDconst [c+d])
|
||||
for {
|
||||
v_0 := v.Args[0]
|
||||
if v_0.Op != OpS390XADDCconst {
|
||||
break
|
||||
}
|
||||
d := v_0.AuxInt
|
||||
v_0_0 := v_0.Args[0]
|
||||
if v_0_0.Op != OpS390XMOVDconst {
|
||||
break
|
||||
}
|
||||
c := v_0_0.AuxInt
|
||||
v.reset(OpS390XMOVDconst)
|
||||
v.AuxInt = c + d
|
||||
return true
|
||||
}
|
||||
// match: (Select0 (SUBC (MOVDconst [c]) (MOVDconst [d])))
|
||||
// cond:
|
||||
// result: (MOVDconst [c-d])
|
||||
for {
|
||||
v_0 := v.Args[0]
|
||||
if v_0.Op != OpS390XSUBC {
|
||||
break
|
||||
}
|
||||
_ = v_0.Args[1]
|
||||
v_0_0 := v_0.Args[0]
|
||||
if v_0_0.Op != OpS390XMOVDconst {
|
||||
break
|
||||
}
|
||||
c := v_0_0.AuxInt
|
||||
v_0_1 := v_0.Args[1]
|
||||
if v_0_1.Op != OpS390XMOVDconst {
|
||||
break
|
||||
}
|
||||
d := v_0_1.AuxInt
|
||||
v.reset(OpS390XMOVDconst)
|
||||
v.AuxInt = c - d
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
func rewriteValueS390X_OpSelect1_0(v *Value) bool {
|
||||
b := v.Block
|
||||
typ := &b.Func.Config.Types
|
||||
// match: (Select1 (Add64carry x y c))
|
||||
// cond:
|
||||
// result: (Select0 <typ.UInt64> (ADDE (MOVDconst [0]) (MOVDconst [0]) (Select1 <types.TypeFlags> (ADDE x y (Select1 <types.TypeFlags> (ADDCconst c [-1]))))))
|
||||
for {
|
||||
v_0 := v.Args[0]
|
||||
if v_0.Op != OpAdd64carry {
|
||||
break
|
||||
}
|
||||
c := v_0.Args[2]
|
||||
x := v_0.Args[0]
|
||||
y := v_0.Args[1]
|
||||
v.reset(OpSelect0)
|
||||
v.Type = typ.UInt64
|
||||
v0 := b.NewValue0(v.Pos, OpS390XADDE, types.NewTuple(typ.UInt64, types.TypeFlags))
|
||||
v1 := b.NewValue0(v.Pos, OpS390XMOVDconst, typ.UInt64)
|
||||
v1.AuxInt = 0
|
||||
v0.AddArg(v1)
|
||||
v2 := b.NewValue0(v.Pos, OpS390XMOVDconst, typ.UInt64)
|
||||
v2.AuxInt = 0
|
||||
v0.AddArg(v2)
|
||||
v3 := b.NewValue0(v.Pos, OpSelect1, types.TypeFlags)
|
||||
v4 := b.NewValue0(v.Pos, OpS390XADDE, types.NewTuple(typ.UInt64, types.TypeFlags))
|
||||
v4.AddArg(x)
|
||||
v4.AddArg(y)
|
||||
v5 := b.NewValue0(v.Pos, OpSelect1, types.TypeFlags)
|
||||
v6 := b.NewValue0(v.Pos, OpS390XADDCconst, types.NewTuple(typ.UInt64, types.TypeFlags))
|
||||
v6.AuxInt = -1
|
||||
v6.AddArg(c)
|
||||
v5.AddArg(v6)
|
||||
v4.AddArg(v5)
|
||||
v3.AddArg(v4)
|
||||
v0.AddArg(v3)
|
||||
v.AddArg(v0)
|
||||
return true
|
||||
}
|
||||
// match: (Select1 (Sub64borrow x y c))
|
||||
// cond:
|
||||
// result: (NEG (Select0 <typ.UInt64> (SUBE (MOVDconst [0]) (MOVDconst [0]) (Select1 <types.TypeFlags> (SUBE x y (Select1 <types.TypeFlags> (SUBC (MOVDconst [0]) c)))))))
|
||||
for {
|
||||
v_0 := v.Args[0]
|
||||
if v_0.Op != OpSub64borrow {
|
||||
break
|
||||
}
|
||||
c := v_0.Args[2]
|
||||
x := v_0.Args[0]
|
||||
y := v_0.Args[1]
|
||||
v.reset(OpS390XNEG)
|
||||
v0 := b.NewValue0(v.Pos, OpSelect0, typ.UInt64)
|
||||
v1 := b.NewValue0(v.Pos, OpS390XSUBE, types.NewTuple(typ.UInt64, types.TypeFlags))
|
||||
v2 := b.NewValue0(v.Pos, OpS390XMOVDconst, typ.UInt64)
|
||||
v2.AuxInt = 0
|
||||
v1.AddArg(v2)
|
||||
v3 := b.NewValue0(v.Pos, OpS390XMOVDconst, typ.UInt64)
|
||||
v3.AuxInt = 0
|
||||
v1.AddArg(v3)
|
||||
v4 := b.NewValue0(v.Pos, OpSelect1, types.TypeFlags)
|
||||
v5 := b.NewValue0(v.Pos, OpS390XSUBE, types.NewTuple(typ.UInt64, types.TypeFlags))
|
||||
v5.AddArg(x)
|
||||
v5.AddArg(y)
|
||||
v6 := b.NewValue0(v.Pos, OpSelect1, types.TypeFlags)
|
||||
v7 := b.NewValue0(v.Pos, OpS390XSUBC, types.NewTuple(typ.UInt64, types.TypeFlags))
|
||||
v8 := b.NewValue0(v.Pos, OpS390XMOVDconst, typ.UInt64)
|
||||
v8.AuxInt = 0
|
||||
v7.AddArg(v8)
|
||||
v7.AddArg(c)
|
||||
v6.AddArg(v7)
|
||||
v5.AddArg(v6)
|
||||
v4.AddArg(v5)
|
||||
v1.AddArg(v4)
|
||||
v0.AddArg(v1)
|
||||
v.AddArg(v0)
|
||||
return true
|
||||
}
|
||||
// match: (Select1 (AddTupleFirst32 _ tuple))
|
||||
// cond:
|
||||
// result: (Select1 tuple)
|
||||
@ -40245,6 +40680,96 @@ func rewriteValueS390X_OpSelect1_0(v *Value) bool {
|
||||
v.AddArg(tuple)
|
||||
return true
|
||||
}
|
||||
// match: (Select1 (ADDCconst (MOVDconst [c]) [d]))
|
||||
// cond: uint64(c+d) >= uint64(c) && c+d == 0
|
||||
// result: (FlagEQ)
|
||||
for {
|
||||
v_0 := v.Args[0]
|
||||
if v_0.Op != OpS390XADDCconst {
|
||||
break
|
||||
}
|
||||
d := v_0.AuxInt
|
||||
v_0_0 := v_0.Args[0]
|
||||
if v_0_0.Op != OpS390XMOVDconst {
|
||||
break
|
||||
}
|
||||
c := v_0_0.AuxInt
|
||||
if !(uint64(c+d) >= uint64(c) && c+d == 0) {
|
||||
break
|
||||
}
|
||||
v.reset(OpS390XFlagEQ)
|
||||
return true
|
||||
}
|
||||
// match: (Select1 (ADDCconst (MOVDconst [c]) [d]))
|
||||
// cond: uint64(c+d) >= uint64(c) && c+d != 0
|
||||
// result: (FlagLT)
|
||||
for {
|
||||
v_0 := v.Args[0]
|
||||
if v_0.Op != OpS390XADDCconst {
|
||||
break
|
||||
}
|
||||
d := v_0.AuxInt
|
||||
v_0_0 := v_0.Args[0]
|
||||
if v_0_0.Op != OpS390XMOVDconst {
|
||||
break
|
||||
}
|
||||
c := v_0_0.AuxInt
|
||||
if !(uint64(c+d) >= uint64(c) && c+d != 0) {
|
||||
break
|
||||
}
|
||||
v.reset(OpS390XFlagLT)
|
||||
return true
|
||||
}
|
||||
// match: (Select1 (SUBC (MOVDconst [c]) (MOVDconst [d])))
|
||||
// cond: uint64(d) <= uint64(c) && c-d == 0
|
||||
// result: (FlagGT)
|
||||
for {
|
||||
v_0 := v.Args[0]
|
||||
if v_0.Op != OpS390XSUBC {
|
||||
break
|
||||
}
|
||||
_ = v_0.Args[1]
|
||||
v_0_0 := v_0.Args[0]
|
||||
if v_0_0.Op != OpS390XMOVDconst {
|
||||
break
|
||||
}
|
||||
c := v_0_0.AuxInt
|
||||
v_0_1 := v_0.Args[1]
|
||||
if v_0_1.Op != OpS390XMOVDconst {
|
||||
break
|
||||
}
|
||||
d := v_0_1.AuxInt
|
||||
if !(uint64(d) <= uint64(c) && c-d == 0) {
|
||||
break
|
||||
}
|
||||
v.reset(OpS390XFlagGT)
|
||||
return true
|
||||
}
|
||||
// match: (Select1 (SUBC (MOVDconst [c]) (MOVDconst [d])))
|
||||
// cond: uint64(d) <= uint64(c) && c-d != 0
|
||||
// result: (FlagOV)
|
||||
for {
|
||||
v_0 := v.Args[0]
|
||||
if v_0.Op != OpS390XSUBC {
|
||||
break
|
||||
}
|
||||
_ = v_0.Args[1]
|
||||
v_0_0 := v_0.Args[0]
|
||||
if v_0_0.Op != OpS390XMOVDconst {
|
||||
break
|
||||
}
|
||||
c := v_0_0.AuxInt
|
||||
v_0_1 := v_0.Args[1]
|
||||
if v_0_1.Op != OpS390XMOVDconst {
|
||||
break
|
||||
}
|
||||
d := v_0_1.AuxInt
|
||||
if !(uint64(d) <= uint64(c) && c-d != 0) {
|
||||
break
|
||||
}
|
||||
v.reset(OpS390XFlagOV)
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
func rewriteValueS390X_OpSignExt16to32_0(v *Value) bool {
|
||||
|
@ -3139,14 +3139,12 @@ func (c *ctxtz) asmout(p *obj.Prog, asm *[]byte) {
|
||||
}
|
||||
r = p.To.Reg
|
||||
}
|
||||
if r == p.To.Reg {
|
||||
if opri != 0 && int64(int16(v)) == v {
|
||||
zRI(opri, uint32(p.To.Reg), uint32(v), asm)
|
||||
} else {
|
||||
zRIL(_a, opril, uint32(p.To.Reg), uint32(v), asm)
|
||||
}
|
||||
} else {
|
||||
if opri != 0 && r == p.To.Reg && int64(int16(v)) == v {
|
||||
zRI(opri, uint32(p.To.Reg), uint32(v), asm)
|
||||
} else if oprie != 0 && int64(int16(v)) == v {
|
||||
zRIE(_d, oprie, uint32(p.To.Reg), uint32(r), uint32(v), 0, 0, 0, 0, asm)
|
||||
} else {
|
||||
zRIL(_a, opril, uint32(p.To.Reg), uint32(v), asm)
|
||||
}
|
||||
|
||||
case 23: // 64-bit logical op $constant reg
|
||||
|
@ -377,32 +377,38 @@ func IterateBits8(n uint8) int {
|
||||
func Add(x, y, ci uint) (r, co uint) {
|
||||
// arm64:"ADDS","ADCS","ADC",-"ADD\t",-"CMP"
|
||||
// amd64:"NEGL","ADCQ","SBBQ","NEGQ"
|
||||
// s390x:"ADDE","ADDC\t[$]-1,"
|
||||
return bits.Add(x, y, ci)
|
||||
}
|
||||
|
||||
func AddC(x, ci uint) (r, co uint) {
|
||||
// arm64:"ADDS","ADCS","ADC",-"ADD\t",-"CMP"
|
||||
// amd64:"NEGL","ADCQ","SBBQ","NEGQ"
|
||||
// s390x:"ADDE","ADDC\t[$]-1,"
|
||||
return bits.Add(x, 7, ci)
|
||||
}
|
||||
|
||||
func AddZ(x, y uint) (r, co uint) {
|
||||
// arm64:"ADDS","ADC",-"ADCS",-"ADD\t",-"CMP"
|
||||
// amd64:"ADDQ","SBBQ","NEGQ",-"NEGL",-"ADCQ"
|
||||
// s390x:"ADDC",-"ADDC\t[$]-1,"
|
||||
return bits.Add(x, y, 0)
|
||||
}
|
||||
|
||||
func AddR(x, y, ci uint) uint {
|
||||
// arm64:"ADDS","ADCS",-"ADD\t",-"CMP"
|
||||
// amd64:"NEGL","ADCQ",-"SBBQ",-"NEGQ"
|
||||
// s390x:"ADDE","ADDC\t[$]-1,"
|
||||
r, _ := bits.Add(x, y, ci)
|
||||
return r
|
||||
}
|
||||
|
||||
func AddM(p, q, r *[3]uint) {
|
||||
var c uint
|
||||
r[0], c = bits.Add(p[0], q[0], c)
|
||||
// arm64:"ADCS",-"ADD\t",-"CMP"
|
||||
// amd64:"ADCQ",-"NEGL",-"SBBQ",-"NEGQ"
|
||||
// s390x:"ADDE",-"ADDC\t[$]-1,"
|
||||
r[1], c = bits.Add(p[1], q[1], c)
|
||||
r[2], c = bits.Add(p[2], q[2], c)
|
||||
}
|
||||
@ -412,6 +418,7 @@ func Add64(x, y, ci uint64) (r, co uint64) {
|
||||
// amd64:"NEGL","ADCQ","SBBQ","NEGQ"
|
||||
// ppc64: "ADDC", "ADDE", "ADDZE"
|
||||
// ppc64le: "ADDC", "ADDE", "ADDZE"
|
||||
// s390x:"ADDE","ADDC\t[$]-1,"
|
||||
return bits.Add64(x, y, ci)
|
||||
}
|
||||
|
||||
@ -420,6 +427,7 @@ func Add64C(x, ci uint64) (r, co uint64) {
|
||||
// amd64:"NEGL","ADCQ","SBBQ","NEGQ"
|
||||
// ppc64: "ADDC", "ADDE", "ADDZE"
|
||||
// ppc64le: "ADDC", "ADDE", "ADDZE"
|
||||
// s390x:"ADDE","ADDC\t[$]-1,"
|
||||
return bits.Add64(x, 7, ci)
|
||||
}
|
||||
|
||||
@ -428,6 +436,7 @@ func Add64Z(x, y uint64) (r, co uint64) {
|
||||
// amd64:"ADDQ","SBBQ","NEGQ",-"NEGL",-"ADCQ"
|
||||
// ppc64: "ADDC", "ADDE", "ADDZE"
|
||||
// ppc64le: "ADDC", "ADDE", "ADDZE"
|
||||
// s390x:"ADDC",-"ADDC\t[$]-1,"
|
||||
return bits.Add64(x, y, 0)
|
||||
}
|
||||
|
||||
@ -436,6 +445,7 @@ func Add64R(x, y, ci uint64) uint64 {
|
||||
// amd64:"NEGL","ADCQ",-"SBBQ",-"NEGQ"
|
||||
// ppc64: "ADDC", "ADDE", "ADDZE"
|
||||
// ppc64le: "ADDC", "ADDE", "ADDZE"
|
||||
// s390x:"ADDE","ADDC\t[$]-1,"
|
||||
r, _ := bits.Add64(x, y, ci)
|
||||
return r
|
||||
}
|
||||
@ -446,6 +456,7 @@ func Add64M(p, q, r *[3]uint64) {
|
||||
// amd64:"ADCQ",-"NEGL",-"SBBQ",-"NEGQ"
|
||||
// ppc64: "ADDC", "ADDE", "ADDZE"
|
||||
// ppc64le: "ADDC", "ADDE", "ADDZE"
|
||||
// s390x:"ADDE",-"ADDC\t[$]-1,"
|
||||
r[1], c = bits.Add64(p[1], q[1], c)
|
||||
r[2], c = bits.Add64(p[2], q[2], c)
|
||||
}
|
||||
@ -457,24 +468,28 @@ func Add64M(p, q, r *[3]uint64) {
|
||||
func Sub(x, y, ci uint) (r, co uint) {
|
||||
// amd64:"NEGL","SBBQ","NEGQ"
|
||||
// arm64:"NEGS","SBCS","NGC","NEG",-"ADD",-"SUB",-"CMP"
|
||||
// s390x:"SUBE"
|
||||
return bits.Sub(x, y, ci)
|
||||
}
|
||||
|
||||
func SubC(x, ci uint) (r, co uint) {
|
||||
// amd64:"NEGL","SBBQ","NEGQ"
|
||||
// arm64:"NEGS","SBCS","NGC","NEG",-"ADD",-"SUB",-"CMP"
|
||||
// s390x:"SUBE"
|
||||
return bits.Sub(x, 7, ci)
|
||||
}
|
||||
|
||||
func SubZ(x, y uint) (r, co uint) {
|
||||
// amd64:"SUBQ","SBBQ","NEGQ",-"NEGL"
|
||||
// arm64:"SUBS","NGC","NEG",-"SBCS",-"ADD",-"SUB\t",-"CMP"
|
||||
// s390x:"SUBC"
|
||||
return bits.Sub(x, y, 0)
|
||||
}
|
||||
|
||||
func SubR(x, y, ci uint) uint {
|
||||
// amd64:"NEGL","SBBQ",-"NEGQ"
|
||||
// arm64:"NEGS","SBCS",-"NGC",-"NEG\t",-"ADD",-"SUB",-"CMP"
|
||||
// s390x:"SUBE"
|
||||
r, _ := bits.Sub(x, y, ci)
|
||||
return r
|
||||
}
|
||||
@ -483,6 +498,7 @@ func SubM(p, q, r *[3]uint) {
|
||||
r[0], c = bits.Sub(p[0], q[0], c)
|
||||
// amd64:"SBBQ",-"NEGL",-"NEGQ"
|
||||
// arm64:"SBCS",-"NEGS",-"NGC",-"NEG",-"ADD",-"SUB",-"CMP"
|
||||
// s390x:"SUBE"
|
||||
r[1], c = bits.Sub(p[1], q[1], c)
|
||||
r[2], c = bits.Sub(p[2], q[2], c)
|
||||
}
|
||||
@ -490,24 +506,28 @@ func SubM(p, q, r *[3]uint) {
|
||||
func Sub64(x, y, ci uint64) (r, co uint64) {
|
||||
// amd64:"NEGL","SBBQ","NEGQ"
|
||||
// arm64:"NEGS","SBCS","NGC","NEG",-"ADD",-"SUB",-"CMP"
|
||||
// s390x:"SUBE"
|
||||
return bits.Sub64(x, y, ci)
|
||||
}
|
||||
|
||||
func Sub64C(x, ci uint64) (r, co uint64) {
|
||||
// amd64:"NEGL","SBBQ","NEGQ"
|
||||
// arm64:"NEGS","SBCS","NGC","NEG",-"ADD",-"SUB",-"CMP"
|
||||
// s390x:"SUBE"
|
||||
return bits.Sub64(x, 7, ci)
|
||||
}
|
||||
|
||||
func Sub64Z(x, y uint64) (r, co uint64) {
|
||||
// amd64:"SUBQ","SBBQ","NEGQ",-"NEGL"
|
||||
// arm64:"SUBS","NGC","NEG",-"SBCS",-"ADD",-"SUB\t",-"CMP"
|
||||
// s390x:"SUBC"
|
||||
return bits.Sub64(x, y, 0)
|
||||
}
|
||||
|
||||
func Sub64R(x, y, ci uint64) uint64 {
|
||||
// amd64:"NEGL","SBBQ",-"NEGQ"
|
||||
// arm64:"NEGS","SBCS",-"NGC",-"NEG\t",-"ADD",-"SUB",-"CMP"
|
||||
// s390x:"SUBE"
|
||||
r, _ := bits.Sub64(x, y, ci)
|
||||
return r
|
||||
}
|
||||
@ -516,6 +536,7 @@ func Sub64M(p, q, r *[3]uint64) {
|
||||
r[0], c = bits.Sub64(p[0], q[0], c)
|
||||
// amd64:"SBBQ",-"NEGL",-"NEGQ"
|
||||
// arm64:"SBCS",-"NEGS",-"NGC",-"NEG",-"ADD",-"SUB",-"CMP"
|
||||
// s390x:"SUBE"
|
||||
r[1], c = bits.Sub64(p[1], q[1], c)
|
||||
r[2], c = bits.Sub64(p[2], q[2], c)
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user