mirror of
https://github.com/golang/go
synced 2024-11-19 02:44:44 -07:00
cmd/compile: use numeric condition code masks on s390x
Prior to this CL conditional branches on s390x always used an extended mnemonic such as BNE, BLT and so on to represent branch instructions with different condition code masks. This CL adds support for numeric condition code masks to the s390x SSA backend so that we can encode the condition under which a Block's successor is chosen as a field in that Block rather than in its type. This change will be useful as we come to add support for combined compare-and-branch instructions. Rather than trying to add extended mnemonics for every possible combination of mask and compare-and- branch instruction we can instead use a single mnemonic for each instruction. Change-Id: Idb7458f187b50906877d683695c291dff5279553 Reviewed-on: https://go-review.googlesource.com/c/go/+/197178 Reviewed-by: Keith Randall <khr@golang.org>
This commit is contained in:
parent
8506b7d42f
commit
cf03238020
@ -571,17 +571,15 @@ func ssaGenValue(s *gc.SSAGenState, v *ssa.Value) {
|
|||||||
v.Fatalf("NOT/NOTW generated %s", v.LongString())
|
v.Fatalf("NOT/NOTW generated %s", v.LongString())
|
||||||
case ssa.OpS390XSumBytes2, ssa.OpS390XSumBytes4, ssa.OpS390XSumBytes8:
|
case ssa.OpS390XSumBytes2, ssa.OpS390XSumBytes4, ssa.OpS390XSumBytes8:
|
||||||
v.Fatalf("SumBytes generated %s", v.LongString())
|
v.Fatalf("SumBytes generated %s", v.LongString())
|
||||||
case ssa.OpS390XMOVDEQ, ssa.OpS390XMOVDNE,
|
case ssa.OpS390XLOCGR:
|
||||||
ssa.OpS390XMOVDLT, ssa.OpS390XMOVDLE,
|
|
||||||
ssa.OpS390XMOVDGT, ssa.OpS390XMOVDGE,
|
|
||||||
ssa.OpS390XMOVDGTnoinv, ssa.OpS390XMOVDGEnoinv:
|
|
||||||
r := v.Reg()
|
r := v.Reg()
|
||||||
if r != v.Args[0].Reg() {
|
if r != v.Args[0].Reg() {
|
||||||
v.Fatalf("input[0] and output not in same register %s", v.LongString())
|
v.Fatalf("input[0] and output not in same register %s", v.LongString())
|
||||||
}
|
}
|
||||||
p := s.Prog(v.Op.Asm())
|
p := s.Prog(v.Op.Asm())
|
||||||
p.From.Type = obj.TYPE_REG
|
p.From.Type = obj.TYPE_CONST
|
||||||
p.From.Reg = v.Args[1].Reg()
|
p.From.Offset = int64(v.Aux.(s390x.CCMask))
|
||||||
|
p.Reg = v.Args[1].Reg()
|
||||||
p.To.Type = obj.TYPE_REG
|
p.To.Type = obj.TYPE_REG
|
||||||
p.To.Reg = r
|
p.To.Reg = r
|
||||||
case ssa.OpS390XFSQRT:
|
case ssa.OpS390XFSQRT:
|
||||||
@ -817,19 +815,6 @@ func ssaGenValue(s *gc.SSAGenState, v *ssa.Value) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var blockJump = [...]struct {
|
|
||||||
asm, invasm obj.As
|
|
||||||
}{
|
|
||||||
ssa.BlockS390XEQ: {s390x.ABEQ, s390x.ABNE},
|
|
||||||
ssa.BlockS390XNE: {s390x.ABNE, s390x.ABEQ},
|
|
||||||
ssa.BlockS390XLT: {s390x.ABLT, s390x.ABGE},
|
|
||||||
ssa.BlockS390XGE: {s390x.ABGE, s390x.ABLT},
|
|
||||||
ssa.BlockS390XLE: {s390x.ABLE, s390x.ABGT},
|
|
||||||
ssa.BlockS390XGT: {s390x.ABGT, s390x.ABLE},
|
|
||||||
ssa.BlockS390XGTF: {s390x.ABGT, s390x.ABLEU},
|
|
||||||
ssa.BlockS390XGEF: {s390x.ABGE, s390x.ABLTU},
|
|
||||||
}
|
|
||||||
|
|
||||||
func ssaGenBlock(s *gc.SSAGenState, b, next *ssa.Block) {
|
func ssaGenBlock(s *gc.SSAGenState, b, next *ssa.Block) {
|
||||||
switch b.Kind {
|
switch b.Kind {
|
||||||
case ssa.BlockPlain:
|
case ssa.BlockPlain:
|
||||||
@ -863,24 +848,20 @@ func ssaGenBlock(s *gc.SSAGenState, b, next *ssa.Block) {
|
|||||||
p.To.Type = obj.TYPE_MEM
|
p.To.Type = obj.TYPE_MEM
|
||||||
p.To.Name = obj.NAME_EXTERN
|
p.To.Name = obj.NAME_EXTERN
|
||||||
p.To.Sym = b.Aux.(*obj.LSym)
|
p.To.Sym = b.Aux.(*obj.LSym)
|
||||||
case ssa.BlockS390XEQ, ssa.BlockS390XNE,
|
case ssa.BlockS390XBRC:
|
||||||
ssa.BlockS390XLT, ssa.BlockS390XGE,
|
succs := [...]*ssa.Block{b.Succs[0].Block(), b.Succs[1].Block()}
|
||||||
ssa.BlockS390XLE, ssa.BlockS390XGT,
|
mask := b.Aux.(s390x.CCMask)
|
||||||
ssa.BlockS390XGEF, ssa.BlockS390XGTF:
|
if next == succs[0] {
|
||||||
jmp := blockJump[b.Kind]
|
succs[0], succs[1] = succs[1], succs[0]
|
||||||
switch next {
|
mask = mask.Inverse()
|
||||||
case b.Succs[0].Block():
|
}
|
||||||
s.Br(jmp.invasm, b.Succs[1].Block())
|
// TODO: take into account Likely property for forward/backward
|
||||||
case b.Succs[1].Block():
|
// branches.
|
||||||
s.Br(jmp.asm, b.Succs[0].Block())
|
p := s.Br(s390x.ABRC, succs[0])
|
||||||
default:
|
p.From.Type = obj.TYPE_CONST
|
||||||
if b.Likely != ssa.BranchUnlikely {
|
p.From.Offset = int64(mask)
|
||||||
s.Br(jmp.asm, b.Succs[0].Block())
|
if next != succs[1] {
|
||||||
s.Br(s390x.ABR, b.Succs[1].Block())
|
s.Br(s390x.ABR, succs[1])
|
||||||
} else {
|
|
||||||
s.Br(jmp.invasm, b.Succs[1].Block())
|
|
||||||
s.Br(s390x.ABR, b.Succs[0].Block())
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
b.Fatalf("branch not implemented: %s. Control: %s", b.LongString(), b.Control.LongString())
|
b.Fatalf("branch not implemented: %s. Control: %s", b.LongString(), b.Control.LongString())
|
||||||
|
@ -150,7 +150,7 @@ func checkFunc(f *Func) {
|
|||||||
if !isExactFloat32(v.AuxFloat()) {
|
if !isExactFloat32(v.AuxFloat()) {
|
||||||
f.Fatalf("value %v has an AuxInt value that is not an exact float32", v)
|
f.Fatalf("value %v has an AuxInt value that is not an exact float32", v)
|
||||||
}
|
}
|
||||||
case auxString, auxSym, auxTyp:
|
case auxString, auxSym, auxTyp, auxArchSpecific:
|
||||||
canHaveAux = true
|
canHaveAux = true
|
||||||
case auxSymOff, auxSymValAndOff, auxTypSize:
|
case auxSymOff, auxSymValAndOff, auxTypSize:
|
||||||
canHaveAuxInt = true
|
canHaveAuxInt = true
|
||||||
|
@ -218,33 +218,33 @@
|
|||||||
|
|
||||||
// Unsigned shifts need to return 0 if shift amount is >= width of shifted value.
|
// Unsigned shifts need to return 0 if shift amount is >= width of shifted value.
|
||||||
// result = shift >= 64 ? 0 : arg << shift
|
// result = shift >= 64 ? 0 : arg << shift
|
||||||
(Lsh(64|32|16|8)x64 <t> x y) -> (MOVDGE <t> (SL(D|W|W|W) <t> x y) (MOVDconst [0]) (CMPUconst y [64]))
|
(Lsh(64|32|16|8)x64 <t> x y) -> (LOCGR {s390x.GreaterOrEqual} <t> (SL(D|W|W|W) <t> x y) (MOVDconst [0]) (CMPUconst y [64]))
|
||||||
(Lsh(64|32|16|8)x32 <t> x y) -> (MOVDGE <t> (SL(D|W|W|W) <t> x y) (MOVDconst [0]) (CMPWUconst y [64]))
|
(Lsh(64|32|16|8)x32 <t> x y) -> (LOCGR {s390x.GreaterOrEqual} <t> (SL(D|W|W|W) <t> x y) (MOVDconst [0]) (CMPWUconst y [64]))
|
||||||
(Lsh(64|32|16|8)x16 <t> x y) -> (MOVDGE <t> (SL(D|W|W|W) <t> x y) (MOVDconst [0]) (CMPWUconst (MOVHZreg y) [64]))
|
(Lsh(64|32|16|8)x16 <t> x y) -> (LOCGR {s390x.GreaterOrEqual} <t> (SL(D|W|W|W) <t> x y) (MOVDconst [0]) (CMPWUconst (MOVHZreg y) [64]))
|
||||||
(Lsh(64|32|16|8)x8 <t> x y) -> (MOVDGE <t> (SL(D|W|W|W) <t> x y) (MOVDconst [0]) (CMPWUconst (MOVBZreg y) [64]))
|
(Lsh(64|32|16|8)x8 <t> x y) -> (LOCGR {s390x.GreaterOrEqual} <t> (SL(D|W|W|W) <t> x y) (MOVDconst [0]) (CMPWUconst (MOVBZreg y) [64]))
|
||||||
|
|
||||||
(Rsh(64|32)Ux64 <t> x y) -> (MOVDGE <t> (SR(D|W) <t> x y) (MOVDconst [0]) (CMPUconst y [64]))
|
(Rsh(64|32)Ux64 <t> x y) -> (LOCGR {s390x.GreaterOrEqual} <t> (SR(D|W) <t> x y) (MOVDconst [0]) (CMPUconst y [64]))
|
||||||
(Rsh(64|32)Ux32 <t> x y) -> (MOVDGE <t> (SR(D|W) <t> x y) (MOVDconst [0]) (CMPWUconst y [64]))
|
(Rsh(64|32)Ux32 <t> x y) -> (LOCGR {s390x.GreaterOrEqual} <t> (SR(D|W) <t> x y) (MOVDconst [0]) (CMPWUconst y [64]))
|
||||||
(Rsh(64|32)Ux16 <t> x y) -> (MOVDGE <t> (SR(D|W) <t> x y) (MOVDconst [0]) (CMPWUconst (MOVHZreg y) [64]))
|
(Rsh(64|32)Ux16 <t> x y) -> (LOCGR {s390x.GreaterOrEqual} <t> (SR(D|W) <t> x y) (MOVDconst [0]) (CMPWUconst (MOVHZreg y) [64]))
|
||||||
(Rsh(64|32)Ux8 <t> x y) -> (MOVDGE <t> (SR(D|W) <t> x y) (MOVDconst [0]) (CMPWUconst (MOVBZreg y) [64]))
|
(Rsh(64|32)Ux8 <t> x y) -> (LOCGR {s390x.GreaterOrEqual} <t> (SR(D|W) <t> x y) (MOVDconst [0]) (CMPWUconst (MOVBZreg y) [64]))
|
||||||
|
|
||||||
(Rsh(16|8)Ux64 <t> x y) -> (MOVDGE <t> (SRW <t> (MOV(H|B)Zreg x) y) (MOVDconst [0]) (CMPUconst y [64]))
|
(Rsh(16|8)Ux64 <t> x y) -> (LOCGR {s390x.GreaterOrEqual} <t> (SRW <t> (MOV(H|B)Zreg x) y) (MOVDconst [0]) (CMPUconst y [64]))
|
||||||
(Rsh(16|8)Ux32 <t> x y) -> (MOVDGE <t> (SRW <t> (MOV(H|B)Zreg x) y) (MOVDconst [0]) (CMPWUconst y [64]))
|
(Rsh(16|8)Ux32 <t> x y) -> (LOCGR {s390x.GreaterOrEqual} <t> (SRW <t> (MOV(H|B)Zreg x) y) (MOVDconst [0]) (CMPWUconst y [64]))
|
||||||
(Rsh(16|8)Ux16 <t> x y) -> (MOVDGE <t> (SRW <t> (MOV(H|B)Zreg x) y) (MOVDconst [0]) (CMPWUconst (MOVHZreg y) [64]))
|
(Rsh(16|8)Ux16 <t> x y) -> (LOCGR {s390x.GreaterOrEqual} <t> (SRW <t> (MOV(H|B)Zreg x) y) (MOVDconst [0]) (CMPWUconst (MOVHZreg y) [64]))
|
||||||
(Rsh(16|8)Ux8 <t> x y) -> (MOVDGE <t> (SRW <t> (MOV(H|B)Zreg x) y) (MOVDconst [0]) (CMPWUconst (MOVBZreg y) [64]))
|
(Rsh(16|8)Ux8 <t> x y) -> (LOCGR {s390x.GreaterOrEqual} <t> (SRW <t> (MOV(H|B)Zreg x) y) (MOVDconst [0]) (CMPWUconst (MOVBZreg y) [64]))
|
||||||
|
|
||||||
// Signed right shift needs to return 0/-1 if shift amount is >= width of shifted value.
|
// Signed right shift needs to return 0/-1 if shift amount is >= width of shifted value.
|
||||||
// We implement this by setting the shift value to 63 (all ones) if the shift value is more than 63.
|
// We implement this by setting the shift value to 63 (all ones) if the shift value is more than 63.
|
||||||
// result = arg >> (shift >= 64 ? 63 : shift)
|
// result = arg >> (shift >= 64 ? 63 : shift)
|
||||||
(Rsh(64|32)x64 x y) -> (SRA(D|W) x (MOVDGE <y.Type> y (MOVDconst <y.Type> [63]) (CMPUconst y [64])))
|
(Rsh(64|32)x64 x y) -> (SRA(D|W) x (LOCGR {s390x.GreaterOrEqual} <y.Type> y (MOVDconst <y.Type> [63]) (CMPUconst y [64])))
|
||||||
(Rsh(64|32)x32 x y) -> (SRA(D|W) x (MOVDGE <y.Type> y (MOVDconst <y.Type> [63]) (CMPWUconst y [64])))
|
(Rsh(64|32)x32 x y) -> (SRA(D|W) x (LOCGR {s390x.GreaterOrEqual} <y.Type> y (MOVDconst <y.Type> [63]) (CMPWUconst y [64])))
|
||||||
(Rsh(64|32)x16 x y) -> (SRA(D|W) x (MOVDGE <y.Type> y (MOVDconst <y.Type> [63]) (CMPWUconst (MOVHZreg y) [64])))
|
(Rsh(64|32)x16 x y) -> (SRA(D|W) x (LOCGR {s390x.GreaterOrEqual} <y.Type> y (MOVDconst <y.Type> [63]) (CMPWUconst (MOVHZreg y) [64])))
|
||||||
(Rsh(64|32)x8 x y) -> (SRA(D|W) x (MOVDGE <y.Type> y (MOVDconst <y.Type> [63]) (CMPWUconst (MOVBZreg y) [64])))
|
(Rsh(64|32)x8 x y) -> (SRA(D|W) x (LOCGR {s390x.GreaterOrEqual} <y.Type> y (MOVDconst <y.Type> [63]) (CMPWUconst (MOVBZreg y) [64])))
|
||||||
|
|
||||||
(Rsh(16|8)x64 x y) -> (SRAW (MOV(H|B)reg x) (MOVDGE <y.Type> y (MOVDconst <y.Type> [63]) (CMPUconst y [64])))
|
(Rsh(16|8)x64 x y) -> (SRAW (MOV(H|B)reg x) (LOCGR {s390x.GreaterOrEqual} <y.Type> y (MOVDconst <y.Type> [63]) (CMPUconst y [64])))
|
||||||
(Rsh(16|8)x32 x y) -> (SRAW (MOV(H|B)reg x) (MOVDGE <y.Type> y (MOVDconst <y.Type> [63]) (CMPWUconst y [64])))
|
(Rsh(16|8)x32 x y) -> (SRAW (MOV(H|B)reg x) (LOCGR {s390x.GreaterOrEqual} <y.Type> y (MOVDconst <y.Type> [63]) (CMPWUconst y [64])))
|
||||||
(Rsh(16|8)x16 x y) -> (SRAW (MOV(H|B)reg x) (MOVDGE <y.Type> y (MOVDconst <y.Type> [63]) (CMPWUconst (MOVHZreg y) [64])))
|
(Rsh(16|8)x16 x y) -> (SRAW (MOV(H|B)reg x) (LOCGR {s390x.GreaterOrEqual} <y.Type> y (MOVDconst <y.Type> [63]) (CMPWUconst (MOVHZreg y) [64])))
|
||||||
(Rsh(16|8)x8 x y) -> (SRAW (MOV(H|B)reg x) (MOVDGE <y.Type> y (MOVDconst <y.Type> [63]) (CMPWUconst (MOVBZreg y) [64])))
|
(Rsh(16|8)x8 x y) -> (SRAW (MOV(H|B)reg x) (LOCGR {s390x.GreaterOrEqual} <y.Type> y (MOVDconst <y.Type> [63]) (CMPWUconst (MOVBZreg y) [64])))
|
||||||
|
|
||||||
// Lowering rotates
|
// Lowering rotates
|
||||||
(RotateLeft8 <t> x (MOVDconst [c])) -> (Or8 (Lsh8x64 <t> x (MOVDconst [c&7])) (Rsh8Ux64 <t> x (MOVDconst [-c&7])))
|
(RotateLeft8 <t> x (MOVDconst [c])) -> (Or8 (Lsh8x64 <t> x (MOVDconst [c&7])) (Rsh8Ux64 <t> x (MOVDconst [-c&7])))
|
||||||
@ -253,55 +253,53 @@
|
|||||||
(RotateLeft64 x y) -> (RLLG x y)
|
(RotateLeft64 x y) -> (RLLG x y)
|
||||||
|
|
||||||
// Lowering comparisons
|
// Lowering comparisons
|
||||||
(Less64 x y) -> (MOVDLT (MOVDconst [0]) (MOVDconst [1]) (CMP x y))
|
(Less64 x y) -> (LOCGR {s390x.Less} (MOVDconst [0]) (MOVDconst [1]) (CMP x y))
|
||||||
(Less32 x y) -> (MOVDLT (MOVDconst [0]) (MOVDconst [1]) (CMPW x y))
|
(Less32 x y) -> (LOCGR {s390x.Less} (MOVDconst [0]) (MOVDconst [1]) (CMPW x y))
|
||||||
(Less(16|8) x y) -> (MOVDLT (MOVDconst [0]) (MOVDconst [1]) (CMPW (MOV(H|B)reg x) (MOV(H|B)reg y)))
|
(Less(16|8) x y) -> (LOCGR {s390x.Less} (MOVDconst [0]) (MOVDconst [1]) (CMPW (MOV(H|B)reg x) (MOV(H|B)reg y)))
|
||||||
(Less64U x y) -> (MOVDLT (MOVDconst [0]) (MOVDconst [1]) (CMPU x y))
|
(Less64U x y) -> (LOCGR {s390x.Less} (MOVDconst [0]) (MOVDconst [1]) (CMPU x y))
|
||||||
(Less32U x y) -> (MOVDLT (MOVDconst [0]) (MOVDconst [1]) (CMPWU x y))
|
(Less32U x y) -> (LOCGR {s390x.Less} (MOVDconst [0]) (MOVDconst [1]) (CMPWU x y))
|
||||||
(Less(16|8)U x y) -> (MOVDLT (MOVDconst [0]) (MOVDconst [1]) (CMPWU (MOV(H|B)Zreg x) (MOV(H|B)Zreg y)))
|
(Less(16|8)U x y) -> (LOCGR {s390x.Less} (MOVDconst [0]) (MOVDconst [1]) (CMPWU (MOV(H|B)Zreg x) (MOV(H|B)Zreg y)))
|
||||||
// Use SETG with reversed operands to dodge NaN case.
|
(Less64F x y) -> (LOCGR {s390x.Less} (MOVDconst [0]) (MOVDconst [1]) (FCMP x y))
|
||||||
(Less64F x y) -> (MOVDGTnoinv (MOVDconst [0]) (MOVDconst [1]) (FCMP y x))
|
(Less32F x y) -> (LOCGR {s390x.Less} (MOVDconst [0]) (MOVDconst [1]) (FCMPS x y))
|
||||||
(Less32F x y) -> (MOVDGTnoinv (MOVDconst [0]) (MOVDconst [1]) (FCMPS y x))
|
|
||||||
|
|
||||||
(Leq64 x y) -> (MOVDLE (MOVDconst [0]) (MOVDconst [1]) (CMP x y))
|
(Leq64 x y) -> (LOCGR {s390x.LessOrEqual} (MOVDconst [0]) (MOVDconst [1]) (CMP x y))
|
||||||
(Leq32 x y) -> (MOVDLE (MOVDconst [0]) (MOVDconst [1]) (CMPW x y))
|
(Leq32 x y) -> (LOCGR {s390x.LessOrEqual} (MOVDconst [0]) (MOVDconst [1]) (CMPW x y))
|
||||||
(Leq(16|8) x y) -> (MOVDLE (MOVDconst [0]) (MOVDconst [1]) (CMPW (MOV(H|B)reg x) (MOV(H|B)reg y)))
|
(Leq(16|8) x y) -> (LOCGR {s390x.LessOrEqual} (MOVDconst [0]) (MOVDconst [1]) (CMPW (MOV(H|B)reg x) (MOV(H|B)reg y)))
|
||||||
(Leq64U x y) -> (MOVDLE (MOVDconst [0]) (MOVDconst [1]) (CMPU x y))
|
(Leq64U x y) -> (LOCGR {s390x.LessOrEqual} (MOVDconst [0]) (MOVDconst [1]) (CMPU x y))
|
||||||
(Leq32U x y) -> (MOVDLE (MOVDconst [0]) (MOVDconst [1]) (CMPWU x y))
|
(Leq32U x y) -> (LOCGR {s390x.LessOrEqual} (MOVDconst [0]) (MOVDconst [1]) (CMPWU x y))
|
||||||
(Leq(16|8)U x y) -> (MOVDLE (MOVDconst [0]) (MOVDconst [1]) (CMPWU (MOV(H|B)Zreg x) (MOV(H|B)Zreg y)))
|
(Leq(16|8)U x y) -> (LOCGR {s390x.LessOrEqual} (MOVDconst [0]) (MOVDconst [1]) (CMPWU (MOV(H|B)Zreg x) (MOV(H|B)Zreg y)))
|
||||||
// Use SETGE with reversed operands to dodge NaN case.
|
(Leq64F x y) -> (LOCGR {s390x.LessOrEqual} (MOVDconst [0]) (MOVDconst [1]) (FCMP x y))
|
||||||
(Leq64F x y) -> (MOVDGEnoinv (MOVDconst [0]) (MOVDconst [1]) (FCMP y x))
|
(Leq32F x y) -> (LOCGR {s390x.LessOrEqual} (MOVDconst [0]) (MOVDconst [1]) (FCMPS x y))
|
||||||
(Leq32F x y) -> (MOVDGEnoinv (MOVDconst [0]) (MOVDconst [1]) (FCMPS y x))
|
|
||||||
|
|
||||||
(Greater64 x y) -> (MOVDGT (MOVDconst [0]) (MOVDconst [1]) (CMP x y))
|
(Greater64 x y) -> (LOCGR {s390x.Greater} (MOVDconst [0]) (MOVDconst [1]) (CMP x y))
|
||||||
(Greater32 x y) -> (MOVDGT (MOVDconst [0]) (MOVDconst [1]) (CMPW x y))
|
(Greater32 x y) -> (LOCGR {s390x.Greater} (MOVDconst [0]) (MOVDconst [1]) (CMPW x y))
|
||||||
(Greater(16|8) x y) -> (MOVDGT (MOVDconst [0]) (MOVDconst [1]) (CMPW (MOV(H|B)reg x) (MOV(H|B)reg y)))
|
(Greater(16|8) x y) -> (LOCGR {s390x.Greater} (MOVDconst [0]) (MOVDconst [1]) (CMPW (MOV(H|B)reg x) (MOV(H|B)reg y)))
|
||||||
(Greater64U x y) -> (MOVDGT (MOVDconst [0]) (MOVDconst [1]) (CMPU x y))
|
(Greater64U x y) -> (LOCGR {s390x.Greater} (MOVDconst [0]) (MOVDconst [1]) (CMPU x y))
|
||||||
(Greater32U x y) -> (MOVDGT (MOVDconst [0]) (MOVDconst [1]) (CMPWU x y))
|
(Greater32U x y) -> (LOCGR {s390x.Greater} (MOVDconst [0]) (MOVDconst [1]) (CMPWU x y))
|
||||||
(Greater(16|8)U x y) -> (MOVDGT (MOVDconst [0]) (MOVDconst [1]) (CMPWU (MOV(H|B)Zreg x) (MOV(H|B)Zreg y)))
|
(Greater(16|8)U x y) -> (LOCGR {s390x.Greater} (MOVDconst [0]) (MOVDconst [1]) (CMPWU (MOV(H|B)Zreg x) (MOV(H|B)Zreg y)))
|
||||||
(Greater64F x y) -> (MOVDGTnoinv (MOVDconst [0]) (MOVDconst [1]) (FCMP x y))
|
(Greater64F x y) -> (LOCGR {s390x.Greater} (MOVDconst [0]) (MOVDconst [1]) (FCMP x y))
|
||||||
(Greater32F x y) -> (MOVDGTnoinv (MOVDconst [0]) (MOVDconst [1]) (FCMPS x y))
|
(Greater32F x y) -> (LOCGR {s390x.Greater} (MOVDconst [0]) (MOVDconst [1]) (FCMPS x y))
|
||||||
|
|
||||||
(Geq64 x y) -> (MOVDGE (MOVDconst [0]) (MOVDconst [1]) (CMP x y))
|
(Geq64 x y) -> (LOCGR {s390x.GreaterOrEqual} (MOVDconst [0]) (MOVDconst [1]) (CMP x y))
|
||||||
(Geq32 x y) -> (MOVDGE (MOVDconst [0]) (MOVDconst [1]) (CMPW x y))
|
(Geq32 x y) -> (LOCGR {s390x.GreaterOrEqual} (MOVDconst [0]) (MOVDconst [1]) (CMPW x y))
|
||||||
(Geq(16|8) x y) -> (MOVDGE (MOVDconst [0]) (MOVDconst [1]) (CMPW (MOV(H|B)reg x) (MOV(H|B)reg y)))
|
(Geq(16|8) x y) -> (LOCGR {s390x.GreaterOrEqual} (MOVDconst [0]) (MOVDconst [1]) (CMPW (MOV(H|B)reg x) (MOV(H|B)reg y)))
|
||||||
(Geq64U x y) -> (MOVDGE (MOVDconst [0]) (MOVDconst [1]) (CMPU x y))
|
(Geq64U x y) -> (LOCGR {s390x.GreaterOrEqual} (MOVDconst [0]) (MOVDconst [1]) (CMPU x y))
|
||||||
(Geq32U x y) -> (MOVDGE (MOVDconst [0]) (MOVDconst [1]) (CMPWU x y))
|
(Geq32U x y) -> (LOCGR {s390x.GreaterOrEqual} (MOVDconst [0]) (MOVDconst [1]) (CMPWU x y))
|
||||||
(Geq(16|8)U x y) -> (MOVDGE (MOVDconst [0]) (MOVDconst [1]) (CMPWU (MOV(H|B)Zreg x) (MOV(H|B)Zreg y)))
|
(Geq(16|8)U x y) -> (LOCGR {s390x.GreaterOrEqual} (MOVDconst [0]) (MOVDconst [1]) (CMPWU (MOV(H|B)Zreg x) (MOV(H|B)Zreg y)))
|
||||||
(Geq64F x y) -> (MOVDGEnoinv (MOVDconst [0]) (MOVDconst [1]) (FCMP x y))
|
(Geq64F x y) -> (LOCGR {s390x.GreaterOrEqual} (MOVDconst [0]) (MOVDconst [1]) (FCMP x y))
|
||||||
(Geq32F x y) -> (MOVDGEnoinv (MOVDconst [0]) (MOVDconst [1]) (FCMPS x y))
|
(Geq32F x y) -> (LOCGR {s390x.GreaterOrEqual} (MOVDconst [0]) (MOVDconst [1]) (FCMPS x y))
|
||||||
|
|
||||||
(Eq(64|Ptr) x y) -> (MOVDEQ (MOVDconst [0]) (MOVDconst [1]) (CMP x y))
|
(Eq(64|Ptr) x y) -> (LOCGR {s390x.Equal} (MOVDconst [0]) (MOVDconst [1]) (CMP x y))
|
||||||
(Eq32 x y) -> (MOVDEQ (MOVDconst [0]) (MOVDconst [1]) (CMPW x y))
|
(Eq32 x y) -> (LOCGR {s390x.Equal} (MOVDconst [0]) (MOVDconst [1]) (CMPW x y))
|
||||||
(Eq(16|8|B) x y) -> (MOVDEQ (MOVDconst [0]) (MOVDconst [1]) (CMPW (MOV(H|B|B)reg x) (MOV(H|B|B)reg y)))
|
(Eq(16|8|B) x y) -> (LOCGR {s390x.Equal} (MOVDconst [0]) (MOVDconst [1]) (CMPW (MOV(H|B|B)reg x) (MOV(H|B|B)reg y)))
|
||||||
(Eq64F x y) -> (MOVDEQ (MOVDconst [0]) (MOVDconst [1]) (FCMP x y))
|
(Eq64F x y) -> (LOCGR {s390x.Equal} (MOVDconst [0]) (MOVDconst [1]) (FCMP x y))
|
||||||
(Eq32F x y) -> (MOVDEQ (MOVDconst [0]) (MOVDconst [1]) (FCMPS x y))
|
(Eq32F x y) -> (LOCGR {s390x.Equal} (MOVDconst [0]) (MOVDconst [1]) (FCMPS x y))
|
||||||
|
|
||||||
(Neq(64|Ptr) x y) -> (MOVDNE (MOVDconst [0]) (MOVDconst [1]) (CMP x y))
|
(Neq(64|Ptr) x y) -> (LOCGR {s390x.NotEqual} (MOVDconst [0]) (MOVDconst [1]) (CMP x y))
|
||||||
(Neq32 x y) -> (MOVDNE (MOVDconst [0]) (MOVDconst [1]) (CMPW x y))
|
(Neq32 x y) -> (LOCGR {s390x.NotEqual} (MOVDconst [0]) (MOVDconst [1]) (CMPW x y))
|
||||||
(Neq(16|8|B) x y) -> (MOVDNE (MOVDconst [0]) (MOVDconst [1]) (CMPW (MOV(H|B|B)reg x) (MOV(H|B|B)reg y)))
|
(Neq(16|8|B) x y) -> (LOCGR {s390x.NotEqual} (MOVDconst [0]) (MOVDconst [1]) (CMPW (MOV(H|B|B)reg x) (MOV(H|B|B)reg y)))
|
||||||
(Neq64F x y) -> (MOVDNE (MOVDconst [0]) (MOVDconst [1]) (FCMP x y))
|
(Neq64F x y) -> (LOCGR {s390x.NotEqual} (MOVDconst [0]) (MOVDconst [1]) (FCMP x y))
|
||||||
(Neq32F x y) -> (MOVDNE (MOVDconst [0]) (MOVDconst [1]) (FCMPS x y))
|
(Neq32F x y) -> (LOCGR {s390x.NotEqual} (MOVDconst [0]) (MOVDconst [1]) (FCMPS x y))
|
||||||
|
|
||||||
// Lowering loads
|
// Lowering loads
|
||||||
(Load <t> ptr mem) && (is64BitInt(t) || isPtr(t)) -> (MOVDload ptr mem)
|
(Load <t> ptr mem) && (is64BitInt(t) || isPtr(t)) -> (MOVDload ptr mem)
|
||||||
@ -405,9 +403,9 @@
|
|||||||
(InterCall [argwid] entry mem) -> (CALLinter [argwid] entry mem)
|
(InterCall [argwid] entry mem) -> (CALLinter [argwid] entry mem)
|
||||||
|
|
||||||
// Miscellaneous
|
// Miscellaneous
|
||||||
(IsNonNil p) -> (MOVDNE (MOVDconst [0]) (MOVDconst [1]) (CMPconst p [0]))
|
(IsNonNil p) -> (LOCGR {s390x.NotEqual} (MOVDconst [0]) (MOVDconst [1]) (CMPconst p [0]))
|
||||||
(IsInBounds idx len) -> (MOVDLT (MOVDconst [0]) (MOVDconst [1]) (CMPU idx len))
|
(IsInBounds idx len) -> (LOCGR {s390x.Less} (MOVDconst [0]) (MOVDconst [1]) (CMPU idx len))
|
||||||
(IsSliceInBounds idx len) -> (MOVDLE (MOVDconst [0]) (MOVDconst [1]) (CMPU idx len))
|
(IsSliceInBounds idx len) -> (LOCGR {s390x.LessOrEqual} (MOVDconst [0]) (MOVDconst [1]) (CMPU idx len))
|
||||||
(NilCheck ptr mem) -> (LoweredNilCheck ptr mem)
|
(NilCheck ptr mem) -> (LoweredNilCheck ptr mem)
|
||||||
(GetG mem) -> (LoweredGetG mem)
|
(GetG mem) -> (LoweredGetG mem)
|
||||||
(GetClosurePtr) -> (LoweredGetClosurePtr)
|
(GetClosurePtr) -> (LoweredGetClosurePtr)
|
||||||
@ -418,18 +416,7 @@
|
|||||||
(ITab (Load ptr mem)) -> (MOVDload ptr mem)
|
(ITab (Load ptr mem)) -> (MOVDload ptr mem)
|
||||||
|
|
||||||
// block rewrites
|
// block rewrites
|
||||||
(If (MOVDLT (MOVDconst [0]) (MOVDconst [1]) cmp) yes no) -> (LT cmp yes no)
|
(If cond yes no) -> (BRC {s390x.NotEqual} (CMPWconst [0] (MOVBZreg <typ.Bool> cond)) yes no)
|
||||||
(If (MOVDLE (MOVDconst [0]) (MOVDconst [1]) cmp) yes no) -> (LE cmp yes no)
|
|
||||||
(If (MOVDGT (MOVDconst [0]) (MOVDconst [1]) cmp) yes no) -> (GT cmp yes no)
|
|
||||||
(If (MOVDGE (MOVDconst [0]) (MOVDconst [1]) cmp) yes no) -> (GE cmp yes no)
|
|
||||||
(If (MOVDEQ (MOVDconst [0]) (MOVDconst [1]) cmp) yes no) -> (EQ cmp yes no)
|
|
||||||
(If (MOVDNE (MOVDconst [0]) (MOVDconst [1]) cmp) yes no) -> (NE cmp yes no)
|
|
||||||
|
|
||||||
// Special case for floating point - LF/LEF not generated.
|
|
||||||
(If (MOVDGTnoinv (MOVDconst [0]) (MOVDconst [1]) cmp) yes no) -> (GTF cmp yes no)
|
|
||||||
(If (MOVDGEnoinv (MOVDconst [0]) (MOVDconst [1]) cmp) yes no) -> (GEF cmp yes no)
|
|
||||||
|
|
||||||
(If cond yes no) -> (NE (CMPWconst [0] (MOVBZreg <typ.Bool> cond)) yes no)
|
|
||||||
|
|
||||||
// Write barrier.
|
// Write barrier.
|
||||||
(WB {fn} destptr srcptr mem) -> (LoweredWB {fn} destptr srcptr mem)
|
(WB {fn} destptr srcptr mem) -> (LoweredWB {fn} destptr srcptr mem)
|
||||||
@ -554,21 +541,21 @@
|
|||||||
|
|
||||||
// Remove zero extension of conditional move.
|
// Remove zero extension of conditional move.
|
||||||
// Note: only for MOVBZreg for now since it is added as part of 'if' statement lowering.
|
// Note: only for MOVBZreg for now since it is added as part of 'if' statement lowering.
|
||||||
(MOVBZreg x:(MOVD(LT|LE|GT|GE|EQ|NE|GTnoinv|GEnoinv) (MOVDconst [c]) (MOVDconst [d]) _))
|
(MOVBZreg x:(LOCGR (MOVDconst [c]) (MOVDconst [d]) _))
|
||||||
&& int64(uint8(c)) == c
|
&& int64(uint8(c)) == c
|
||||||
&& int64(uint8(d)) == d
|
&& int64(uint8(d)) == d
|
||||||
&& (!x.Type.IsSigned() || x.Type.Size() > 1)
|
&& (!x.Type.IsSigned() || x.Type.Size() > 1)
|
||||||
-> x
|
-> x
|
||||||
|
|
||||||
// Fold boolean tests into blocks.
|
// Fold boolean tests into blocks.
|
||||||
(NE (CMPWconst [0] (MOVDLT (MOVDconst [0]) (MOVDconst [1]) cmp)) yes no) -> (LT cmp yes no)
|
(BRC {c} (CMPWconst [0] (LOCGR {d} (MOVDconst [0]) (MOVDconst [x]) cmp)) yes no)
|
||||||
(NE (CMPWconst [0] (MOVDLE (MOVDconst [0]) (MOVDconst [1]) cmp)) yes no) -> (LE cmp yes no)
|
&& x != 0
|
||||||
(NE (CMPWconst [0] (MOVDGT (MOVDconst [0]) (MOVDconst [1]) cmp)) yes no) -> (GT cmp yes no)
|
&& c.(s390x.CCMask) == s390x.Equal
|
||||||
(NE (CMPWconst [0] (MOVDGE (MOVDconst [0]) (MOVDconst [1]) cmp)) yes no) -> (GE cmp yes no)
|
-> (BRC {d} cmp no yes)
|
||||||
(NE (CMPWconst [0] (MOVDEQ (MOVDconst [0]) (MOVDconst [1]) cmp)) yes no) -> (EQ cmp yes no)
|
(BRC {c} (CMPWconst [0] (LOCGR {d} (MOVDconst [0]) (MOVDconst [x]) cmp)) yes no)
|
||||||
(NE (CMPWconst [0] (MOVDNE (MOVDconst [0]) (MOVDconst [1]) cmp)) yes no) -> (NE cmp yes no)
|
&& x != 0
|
||||||
(NE (CMPWconst [0] (MOVDGTnoinv (MOVDconst [0]) (MOVDconst [1]) cmp)) yes no) -> (GTF cmp yes no)
|
&& c.(s390x.CCMask) == s390x.NotEqual
|
||||||
(NE (CMPWconst [0] (MOVDGEnoinv (MOVDconst [0]) (MOVDconst [1]) cmp)) yes no) -> (GEF cmp yes no)
|
-> (BRC {d} cmp yes no)
|
||||||
|
|
||||||
// Fold constants into instructions.
|
// Fold constants into instructions.
|
||||||
(ADD x (MOVDconst [c])) && is32Bit(c) -> (ADDconst [c] x)
|
(ADD x (MOVDconst [c])) && is32Bit(c) -> (ADDconst [c] x)
|
||||||
@ -669,12 +656,7 @@
|
|||||||
(MOVDaddridx [c] {s} x (ADDconst [d] y)) && is20Bit(c+d) && y.Op != OpSB -> (MOVDaddridx [c+d] {s} x y)
|
(MOVDaddridx [c] {s} x (ADDconst [d] y)) && is20Bit(c+d) && y.Op != OpSB -> (MOVDaddridx [c+d] {s} x y)
|
||||||
|
|
||||||
// reverse ordering of compare instruction
|
// reverse ordering of compare instruction
|
||||||
(MOVDLT x y (InvertFlags cmp)) -> (MOVDGT x y cmp)
|
(LOCGR {c} x y (InvertFlags cmp)) -> (LOCGR {c.(s390x.CCMask).ReverseComparison()} x y cmp)
|
||||||
(MOVDGT x y (InvertFlags cmp)) -> (MOVDLT x y cmp)
|
|
||||||
(MOVDLE x y (InvertFlags cmp)) -> (MOVDGE x y cmp)
|
|
||||||
(MOVDGE x y (InvertFlags cmp)) -> (MOVDLE x y cmp)
|
|
||||||
(MOVDEQ x y (InvertFlags cmp)) -> (MOVDEQ x y cmp)
|
|
||||||
(MOVDNE x y (InvertFlags cmp)) -> (MOVDNE x y cmp)
|
|
||||||
|
|
||||||
// replace load from same location as preceding store with copy
|
// replace load from same location as preceding store with copy
|
||||||
(MOVDload [off] {sym} ptr1 (MOVDstore [off] {sym} ptr2 x _)) && isSamePtr(ptr1, ptr2) -> x
|
(MOVDload [off] {sym} ptr1 (MOVDstore [off] {sym} ptr2 x _)) && isSamePtr(ptr1, ptr2) -> x
|
||||||
@ -948,7 +930,7 @@
|
|||||||
(MOVDaddridx [off1+off2] {mergeSym(sym1,sym2)} x y)
|
(MOVDaddridx [off1+off2] {mergeSym(sym1,sym2)} x y)
|
||||||
|
|
||||||
// Absorb InvertFlags into branches.
|
// Absorb InvertFlags into branches.
|
||||||
((LT|GT|LE|GE|EQ|NE) (InvertFlags cmp) yes no) -> ((GT|LT|GE|LE|EQ|NE) cmp yes no)
|
(BRC {c} (InvertFlags cmp) yes no) -> (BRC {c.(s390x.CCMask).ReverseComparison()} cmp yes no)
|
||||||
|
|
||||||
// Constant comparisons.
|
// Constant comparisons.
|
||||||
(CMPconst (MOVDconst [x]) [y]) && x==y -> (FlagEQ)
|
(CMPconst (MOVDconst [x]) [y]) && x==y -> (FlagEQ)
|
||||||
@ -994,54 +976,26 @@
|
|||||||
(CMP(W|W|WU|WU)const (MOV(W|WZ|W|WZ)reg x) [c]) -> (CMP(W|W|WU|WU)const x [c])
|
(CMP(W|W|WU|WU)const (MOV(W|WZ|W|WZ)reg x) [c]) -> (CMP(W|W|WU|WU)const x [c])
|
||||||
|
|
||||||
// Absorb flag constants into branches.
|
// Absorb flag constants into branches.
|
||||||
(EQ (FlagEQ) yes no) -> (First nil yes no)
|
(BRC {c} (FlagEQ) yes no) && c.(s390x.CCMask) & s390x.Equal != 0 -> (First nil yes no)
|
||||||
(EQ (FlagLT) yes no) -> (First nil no yes)
|
(BRC {c} (FlagLT) yes no) && c.(s390x.CCMask) & s390x.Less != 0 -> (First nil yes no)
|
||||||
(EQ (FlagGT) yes no) -> (First nil no yes)
|
(BRC {c} (FlagGT) yes no) && c.(s390x.CCMask) & s390x.Greater != 0 -> (First nil yes no)
|
||||||
|
(BRC {c} (FlagOV) yes no) && c.(s390x.CCMask) & s390x.Unordered != 0 -> (First nil yes no)
|
||||||
|
|
||||||
(NE (FlagEQ) yes no) -> (First nil no yes)
|
(BRC {c} (FlagEQ) yes no) && c.(s390x.CCMask) & s390x.Equal == 0 -> (First nil no yes)
|
||||||
(NE (FlagLT) yes no) -> (First nil yes no)
|
(BRC {c} (FlagLT) yes no) && c.(s390x.CCMask) & s390x.Less == 0 -> (First nil no yes)
|
||||||
(NE (FlagGT) yes no) -> (First nil yes no)
|
(BRC {c} (FlagGT) yes no) && c.(s390x.CCMask) & s390x.Greater == 0 -> (First nil no yes)
|
||||||
|
(BRC {c} (FlagOV) yes no) && c.(s390x.CCMask) & s390x.Unordered == 0 -> (First nil no yes)
|
||||||
(LT (FlagEQ) yes no) -> (First nil no yes)
|
|
||||||
(LT (FlagLT) yes no) -> (First nil yes no)
|
|
||||||
(LT (FlagGT) yes no) -> (First nil no yes)
|
|
||||||
|
|
||||||
(LE (FlagEQ) yes no) -> (First nil yes no)
|
|
||||||
(LE (FlagLT) yes no) -> (First nil yes no)
|
|
||||||
(LE (FlagGT) yes no) -> (First nil no yes)
|
|
||||||
|
|
||||||
(GT (FlagEQ) yes no) -> (First nil no yes)
|
|
||||||
(GT (FlagLT) yes no) -> (First nil no yes)
|
|
||||||
(GT (FlagGT) yes no) -> (First nil yes no)
|
|
||||||
|
|
||||||
(GE (FlagEQ) yes no) -> (First nil yes no)
|
|
||||||
(GE (FlagLT) yes no) -> (First nil no yes)
|
|
||||||
(GE (FlagGT) yes no) -> (First nil yes no)
|
|
||||||
|
|
||||||
// Absorb flag constants into SETxx ops.
|
// Absorb flag constants into SETxx ops.
|
||||||
(MOVDEQ _ x (FlagEQ)) -> x
|
(LOCGR {c} _ x (FlagEQ)) && c.(s390x.CCMask) & s390x.Equal != 0 -> x
|
||||||
(MOVDEQ y _ (FlagLT)) -> y
|
(LOCGR {c} _ x (FlagLT)) && c.(s390x.CCMask) & s390x.Less != 0 -> x
|
||||||
(MOVDEQ y _ (FlagGT)) -> y
|
(LOCGR {c} _ x (FlagGT)) && c.(s390x.CCMask) & s390x.Greater != 0 -> x
|
||||||
|
(LOCGR {c} _ x (FlagOV)) && c.(s390x.CCMask) & s390x.Unordered != 0 -> x
|
||||||
|
|
||||||
(MOVDNE y _ (FlagEQ)) -> y
|
(LOCGR {c} x _ (FlagEQ)) && c.(s390x.CCMask) & s390x.Equal == 0 -> x
|
||||||
(MOVDNE _ x (FlagLT)) -> x
|
(LOCGR {c} x _ (FlagLT)) && c.(s390x.CCMask) & s390x.Less == 0 -> x
|
||||||
(MOVDNE _ x (FlagGT)) -> x
|
(LOCGR {c} x _ (FlagGT)) && c.(s390x.CCMask) & s390x.Greater == 0 -> x
|
||||||
|
(LOCGR {c} x _ (FlagOV)) && c.(s390x.CCMask) & s390x.Unordered == 0 -> x
|
||||||
(MOVDLT y _ (FlagEQ)) -> y
|
|
||||||
(MOVDLT _ x (FlagLT)) -> x
|
|
||||||
(MOVDLT y _ (FlagGT)) -> y
|
|
||||||
|
|
||||||
(MOVDLE _ x (FlagEQ)) -> x
|
|
||||||
(MOVDLE _ x (FlagLT)) -> x
|
|
||||||
(MOVDLE y _ (FlagGT)) -> y
|
|
||||||
|
|
||||||
(MOVDGT y _ (FlagEQ)) -> y
|
|
||||||
(MOVDGT y _ (FlagLT)) -> y
|
|
||||||
(MOVDGT _ x (FlagGT)) -> x
|
|
||||||
|
|
||||||
(MOVDGE _ x (FlagEQ)) -> x
|
|
||||||
(MOVDGE y _ (FlagLT)) -> y
|
|
||||||
(MOVDGE _ x (FlagGT)) -> x
|
|
||||||
|
|
||||||
// Remove redundant *const ops
|
// Remove redundant *const ops
|
||||||
(ADDconst [0] x) -> x
|
(ADDconst [0] x) -> x
|
||||||
|
@ -354,18 +354,9 @@ func init() {
|
|||||||
|
|
||||||
{name: "FSQRT", argLength: 1, reg: fp11, asm: "FSQRT"}, // sqrt(arg0)
|
{name: "FSQRT", argLength: 1, reg: fp11, asm: "FSQRT"}, // sqrt(arg0)
|
||||||
|
|
||||||
{name: "MOVDEQ", argLength: 3, reg: gp2flags1, resultInArg0: true, asm: "MOVDEQ"}, // extract == condition from arg0
|
// Conditional register-register moves.
|
||||||
{name: "MOVDNE", argLength: 3, reg: gp2flags1, resultInArg0: true, asm: "MOVDNE"}, // extract != condition from arg0
|
// The aux for these values is an s390x.CCMask value representing the condition code mask.
|
||||||
{name: "MOVDLT", argLength: 3, reg: gp2flags1, resultInArg0: true, asm: "MOVDLT"}, // extract signed < condition from arg0
|
{name: "LOCGR", argLength: 3, reg: gp2flags1, resultInArg0: true, asm: "LOCGR", aux: "ArchSpecific"}, // load arg1 into arg0 if the condition code in arg2 matches a masked bit in aux.
|
||||||
{name: "MOVDLE", argLength: 3, reg: gp2flags1, resultInArg0: true, asm: "MOVDLE"}, // extract signed <= condition from arg0
|
|
||||||
{name: "MOVDGT", argLength: 3, reg: gp2flags1, resultInArg0: true, asm: "MOVDGT"}, // extract signed > condition from arg0
|
|
||||||
{name: "MOVDGE", argLength: 3, reg: gp2flags1, resultInArg0: true, asm: "MOVDGE"}, // extract signed >= condition from arg0
|
|
||||||
|
|
||||||
// Different rules for floating point conditions because
|
|
||||||
// any comparison involving a NaN is always false and thus
|
|
||||||
// the patterns for inverting conditions cannot be used.
|
|
||||||
{name: "MOVDGTnoinv", argLength: 3, reg: gp2flags1, resultInArg0: true, asm: "MOVDGT"}, // extract floating > condition from arg0
|
|
||||||
{name: "MOVDGEnoinv", argLength: 3, reg: gp2flags1, resultInArg0: true, asm: "MOVDGE"}, // extract floating >= condition from arg0
|
|
||||||
|
|
||||||
{name: "MOVBreg", argLength: 1, reg: gp11sp, asm: "MOVB", typ: "Int64"}, // sign extend arg0 from int8 to int64
|
{name: "MOVBreg", argLength: 1, reg: gp11sp, asm: "MOVB", typ: "Int64"}, // sign extend arg0 from int8 to int64
|
||||||
{name: "MOVBZreg", argLength: 1, reg: gp11sp, asm: "MOVBZ", typ: "UInt64"}, // zero extend arg0 from int8 to int64
|
{name: "MOVBZreg", argLength: 1, reg: gp11sp, asm: "MOVBZ", typ: "UInt64"}, // zero extend arg0 from int8 to int64
|
||||||
@ -717,14 +708,7 @@ func init() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var S390Xblocks = []blockData{
|
var S390Xblocks = []blockData{
|
||||||
{name: "EQ"},
|
{name: "BRC"}, // aux is condition code mask (s390x.CCMask)
|
||||||
{name: "NE"},
|
|
||||||
{name: "LT"},
|
|
||||||
{name: "LE"},
|
|
||||||
{name: "GT"},
|
|
||||||
{name: "GE"},
|
|
||||||
{name: "GTF"}, // FP comparison
|
|
||||||
{name: "GEF"}, // FP comparison
|
|
||||||
}
|
}
|
||||||
|
|
||||||
archs = append(archs, arch{
|
archs = append(archs, arch{
|
||||||
@ -738,5 +722,8 @@ func init() {
|
|||||||
fpregmask: fp,
|
fpregmask: fp,
|
||||||
framepointerreg: -1, // not used
|
framepointerreg: -1, // not used
|
||||||
linkreg: int8(num["R14"]),
|
linkreg: int8(num["R14"]),
|
||||||
|
imports: []string{
|
||||||
|
"cmd/internal/obj/s390x",
|
||||||
|
},
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -41,6 +41,7 @@ type arch struct {
|
|||||||
framepointerreg int8
|
framepointerreg int8
|
||||||
linkreg int8
|
linkreg int8
|
||||||
generic bool
|
generic bool
|
||||||
|
imports []string
|
||||||
}
|
}
|
||||||
|
|
||||||
type opData struct {
|
type opData struct {
|
||||||
|
@ -554,11 +554,13 @@ func fprint(w io.Writer, n Node) {
|
|||||||
fmt.Fprintf(w, "// Code generated from gen/%s%s.rules; DO NOT EDIT.\n", n.arch.name, n.suffix)
|
fmt.Fprintf(w, "// Code generated from gen/%s%s.rules; DO NOT EDIT.\n", n.arch.name, n.suffix)
|
||||||
fmt.Fprintf(w, "// generated with: cd gen; go run *.go\n")
|
fmt.Fprintf(w, "// generated with: cd gen; go run *.go\n")
|
||||||
fmt.Fprintf(w, "\npackage ssa\n")
|
fmt.Fprintf(w, "\npackage ssa\n")
|
||||||
for _, path := range []string{
|
for _, path := range append([]string{
|
||||||
"fmt", "math",
|
"fmt",
|
||||||
"cmd/internal/obj", "cmd/internal/objabi",
|
"math",
|
||||||
|
"cmd/internal/obj",
|
||||||
|
"cmd/internal/objabi",
|
||||||
"cmd/compile/internal/types",
|
"cmd/compile/internal/types",
|
||||||
} {
|
}, n.arch.imports...) {
|
||||||
fmt.Fprintf(w, "import %q\n", path)
|
fmt.Fprintf(w, "import %q\n", path)
|
||||||
}
|
}
|
||||||
for _, f := range n.list {
|
for _, f := range n.list {
|
||||||
@ -1162,7 +1164,7 @@ func parseValue(val string, arch arch, loc string) (op opData, oparch, typ, auxi
|
|||||||
}
|
}
|
||||||
if aux != "" {
|
if aux != "" {
|
||||||
switch op.aux {
|
switch op.aux {
|
||||||
case "String", "Sym", "SymOff", "SymValAndOff", "Typ", "TypSize", "CCop":
|
case "String", "Sym", "SymOff", "SymValAndOff", "Typ", "TypSize", "CCop", "ArchSpecific":
|
||||||
default:
|
default:
|
||||||
log.Fatalf("%s: op %s %s can't have aux", loc, op.name, op.aux)
|
log.Fatalf("%s: op %s %s can't have aux", loc, op.name, op.aux)
|
||||||
}
|
}
|
||||||
|
@ -37,7 +37,7 @@ func TestLoopConditionS390X(t *testing.T) {
|
|||||||
// MOVD $0, R2
|
// MOVD $0, R2
|
||||||
// MOVD $1, R3
|
// MOVD $1, R3
|
||||||
// CMP R0, R1
|
// CMP R0, R1
|
||||||
// MOVDLT R2, R3
|
// LOCGR $(8+2) R2, R3
|
||||||
// CMPW R2, $0
|
// CMPW R2, $0
|
||||||
// BNE done
|
// BNE done
|
||||||
// ADD $3, R4
|
// ADD $3, R4
|
||||||
@ -76,12 +76,7 @@ func TestLoopConditionS390X(t *testing.T) {
|
|||||||
CheckFunc(fun.f)
|
CheckFunc(fun.f)
|
||||||
|
|
||||||
checkOpcodeCounts(t, fun.f, map[Op]int{
|
checkOpcodeCounts(t, fun.f, map[Op]int{
|
||||||
OpS390XMOVDLT: 0,
|
OpS390XLOCGR: 0,
|
||||||
OpS390XMOVDGT: 0,
|
|
||||||
OpS390XMOVDLE: 0,
|
|
||||||
OpS390XMOVDGE: 0,
|
|
||||||
OpS390XMOVDEQ: 0,
|
|
||||||
OpS390XMOVDNE: 0,
|
|
||||||
OpS390XCMP: 1,
|
OpS390XCMP: 1,
|
||||||
OpS390XCMPWconst: 0,
|
OpS390XCMPWconst: 0,
|
||||||
})
|
})
|
||||||
|
@ -83,6 +83,7 @@ const (
|
|||||||
auxTyp // aux is a type
|
auxTyp // aux is a type
|
||||||
auxTypSize // aux is a type, auxInt is a size, must have Aux.(Type).Size() == AuxInt
|
auxTypSize // aux is a type, auxInt is a size, must have Aux.(Type).Size() == AuxInt
|
||||||
auxCCop // aux is a ssa.Op that represents a flags-to-bool conversion (e.g. LessThan)
|
auxCCop // aux is a ssa.Op that represents a flags-to-bool conversion (e.g. LessThan)
|
||||||
|
auxArchSpecific // aux type is specific to a particular backend (see the relevant op for the actual type)
|
||||||
)
|
)
|
||||||
|
|
||||||
// A SymEffect describes the effect that an SSA Value has on the variable
|
// A SymEffect describes the effect that an SSA Value has on the variable
|
||||||
|
@ -111,14 +111,7 @@ const (
|
|||||||
BlockPPC64FGT
|
BlockPPC64FGT
|
||||||
BlockPPC64FGE
|
BlockPPC64FGE
|
||||||
|
|
||||||
BlockS390XEQ
|
BlockS390XBRC
|
||||||
BlockS390XNE
|
|
||||||
BlockS390XLT
|
|
||||||
BlockS390XLE
|
|
||||||
BlockS390XGT
|
|
||||||
BlockS390XGE
|
|
||||||
BlockS390XGTF
|
|
||||||
BlockS390XGEF
|
|
||||||
|
|
||||||
BlockPlain
|
BlockPlain
|
||||||
BlockIf
|
BlockIf
|
||||||
@ -227,14 +220,7 @@ var blockString = [...]string{
|
|||||||
BlockPPC64FGT: "FGT",
|
BlockPPC64FGT: "FGT",
|
||||||
BlockPPC64FGE: "FGE",
|
BlockPPC64FGE: "FGE",
|
||||||
|
|
||||||
BlockS390XEQ: "EQ",
|
BlockS390XBRC: "BRC",
|
||||||
BlockS390XNE: "NE",
|
|
||||||
BlockS390XLT: "LT",
|
|
||||||
BlockS390XLE: "LE",
|
|
||||||
BlockS390XGT: "GT",
|
|
||||||
BlockS390XGE: "GE",
|
|
||||||
BlockS390XGTF: "GTF",
|
|
||||||
BlockS390XGEF: "GEF",
|
|
||||||
|
|
||||||
BlockPlain: "Plain",
|
BlockPlain: "Plain",
|
||||||
BlockIf: "If",
|
BlockIf: "If",
|
||||||
@ -1967,14 +1953,7 @@ const (
|
|||||||
OpS390XNOT
|
OpS390XNOT
|
||||||
OpS390XNOTW
|
OpS390XNOTW
|
||||||
OpS390XFSQRT
|
OpS390XFSQRT
|
||||||
OpS390XMOVDEQ
|
OpS390XLOCGR
|
||||||
OpS390XMOVDNE
|
|
||||||
OpS390XMOVDLT
|
|
||||||
OpS390XMOVDLE
|
|
||||||
OpS390XMOVDGT
|
|
||||||
OpS390XMOVDGE
|
|
||||||
OpS390XMOVDGTnoinv
|
|
||||||
OpS390XMOVDGEnoinv
|
|
||||||
OpS390XMOVBreg
|
OpS390XMOVBreg
|
||||||
OpS390XMOVBZreg
|
OpS390XMOVBZreg
|
||||||
OpS390XMOVHreg
|
OpS390XMOVHreg
|
||||||
@ -26453,115 +26432,11 @@ var opcodeTable = [...]opInfo{
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "MOVDEQ",
|
name: "LOCGR",
|
||||||
|
auxType: auxArchSpecific,
|
||||||
argLen: 3,
|
argLen: 3,
|
||||||
resultInArg0: true,
|
resultInArg0: true,
|
||||||
asm: s390x.AMOVDEQ,
|
asm: s390x.ALOCGR,
|
||||||
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: "MOVDNE",
|
|
||||||
argLen: 3,
|
|
||||||
resultInArg0: true,
|
|
||||||
asm: s390x.AMOVDNE,
|
|
||||||
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: "MOVDLT",
|
|
||||||
argLen: 3,
|
|
||||||
resultInArg0: true,
|
|
||||||
asm: s390x.AMOVDLT,
|
|
||||||
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: "MOVDLE",
|
|
||||||
argLen: 3,
|
|
||||||
resultInArg0: true,
|
|
||||||
asm: s390x.AMOVDLE,
|
|
||||||
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: "MOVDGT",
|
|
||||||
argLen: 3,
|
|
||||||
resultInArg0: true,
|
|
||||||
asm: s390x.AMOVDGT,
|
|
||||||
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: "MOVDGE",
|
|
||||||
argLen: 3,
|
|
||||||
resultInArg0: true,
|
|
||||||
asm: s390x.AMOVDGE,
|
|
||||||
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: "MOVDGTnoinv",
|
|
||||||
argLen: 3,
|
|
||||||
resultInArg0: true,
|
|
||||||
asm: s390x.AMOVDGT,
|
|
||||||
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: "MOVDGEnoinv",
|
|
||||||
argLen: 3,
|
|
||||||
resultInArg0: true,
|
|
||||||
asm: s390x.AMOVDGE,
|
|
||||||
reg: regInfo{
|
reg: regInfo{
|
||||||
inputs: []inputInfo{
|
inputs: []inputInfo{
|
||||||
{0, 23551}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14
|
{0, 23551}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -179,7 +179,7 @@ func (v *Value) auxString() string {
|
|||||||
return fmt.Sprintf(" [%g]", v.AuxFloat())
|
return fmt.Sprintf(" [%g]", v.AuxFloat())
|
||||||
case auxString:
|
case auxString:
|
||||||
return fmt.Sprintf(" {%q}", v.Aux)
|
return fmt.Sprintf(" {%q}", v.Aux)
|
||||||
case auxSym, auxTyp:
|
case auxSym, auxTyp, auxArchSpecific:
|
||||||
if v.Aux != nil {
|
if v.Aux != nil {
|
||||||
return fmt.Sprintf(" {%v}", v.Aux)
|
return fmt.Sprintf(" {%v}", v.Aux)
|
||||||
}
|
}
|
||||||
|
@ -2639,35 +2639,35 @@ func (c *ctxtz) addcallreloc(sym *obj.LSym, add int64) *obj.Reloc {
|
|||||||
return rel
|
return rel
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *ctxtz) branchMask(p *obj.Prog) uint32 {
|
func (c *ctxtz) branchMask(p *obj.Prog) CCMask {
|
||||||
switch p.As {
|
switch p.As {
|
||||||
case ABRC, ALOCR, ALOCGR,
|
case ABRC, ALOCR, ALOCGR,
|
||||||
ACRJ, ACGRJ, ACIJ, ACGIJ,
|
ACRJ, ACGRJ, ACIJ, ACGIJ,
|
||||||
ACLRJ, ACLGRJ, ACLIJ, ACLGIJ:
|
ACLRJ, ACLGRJ, ACLIJ, ACLGIJ:
|
||||||
return uint32(p.From.Offset)
|
return CCMask(p.From.Offset)
|
||||||
case ABEQ, ACMPBEQ, ACMPUBEQ, AMOVDEQ:
|
case ABEQ, ACMPBEQ, ACMPUBEQ, AMOVDEQ:
|
||||||
return 0x8
|
return Equal
|
||||||
case ABGE, ACMPBGE, ACMPUBGE, AMOVDGE:
|
case ABGE, ACMPBGE, ACMPUBGE, AMOVDGE:
|
||||||
return 0xA
|
return GreaterOrEqual
|
||||||
case ABGT, ACMPBGT, ACMPUBGT, AMOVDGT:
|
case ABGT, ACMPBGT, ACMPUBGT, AMOVDGT:
|
||||||
return 0x2
|
return Greater
|
||||||
case ABLE, ACMPBLE, ACMPUBLE, AMOVDLE:
|
case ABLE, ACMPBLE, ACMPUBLE, AMOVDLE:
|
||||||
return 0xC
|
return LessOrEqual
|
||||||
case ABLT, ACMPBLT, ACMPUBLT, AMOVDLT:
|
case ABLT, ACMPBLT, ACMPUBLT, AMOVDLT:
|
||||||
return 0x4
|
return Less
|
||||||
case ABNE, ACMPBNE, ACMPUBNE, AMOVDNE:
|
case ABNE, ACMPBNE, ACMPUBNE, AMOVDNE:
|
||||||
return 0x7
|
return NotEqual
|
||||||
case ABLEU: // LE or unordered
|
case ABLEU: // LE or unordered
|
||||||
return 0xD
|
return NotGreater
|
||||||
case ABLTU: // LT or unordered
|
case ABLTU: // LT or unordered
|
||||||
return 0x5
|
return LessOrUnordered
|
||||||
case ABVC:
|
case ABVC:
|
||||||
return 0x0 // needs extra instruction
|
return Never // needs extra instruction
|
||||||
case ABVS:
|
case ABVS:
|
||||||
return 0x1 // unordered
|
return Unordered
|
||||||
}
|
}
|
||||||
c.ctxt.Diag("unknown conditional branch %v", p.As)
|
c.ctxt.Diag("unknown conditional branch %v", p.As)
|
||||||
return 0xF
|
return Always
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *ctxtz) asmout(p *obj.Prog, asm *[]byte) {
|
func (c *ctxtz) asmout(p *obj.Prog, asm *[]byte) {
|
||||||
@ -3073,7 +3073,7 @@ func (c *ctxtz) asmout(p *obj.Prog, asm *[]byte) {
|
|||||||
if p.As == ABCL || p.As == ABL {
|
if p.As == ABCL || p.As == ABL {
|
||||||
zRR(op_BASR, uint32(REG_LR), uint32(r), asm)
|
zRR(op_BASR, uint32(REG_LR), uint32(r), asm)
|
||||||
} else {
|
} else {
|
||||||
zRR(op_BCR, 0xF, uint32(r), asm)
|
zRR(op_BCR, uint32(Always), uint32(r), asm)
|
||||||
}
|
}
|
||||||
|
|
||||||
case 16: // conditional branch
|
case 16: // conditional branch
|
||||||
@ -3081,7 +3081,7 @@ func (c *ctxtz) asmout(p *obj.Prog, asm *[]byte) {
|
|||||||
if p.Pcond != nil {
|
if p.Pcond != nil {
|
||||||
v = int32((p.Pcond.Pc - p.Pc) >> 1)
|
v = int32((p.Pcond.Pc - p.Pc) >> 1)
|
||||||
}
|
}
|
||||||
mask := c.branchMask(p)
|
mask := uint32(c.branchMask(p))
|
||||||
if p.To.Sym == nil && int32(int16(v)) == v {
|
if p.To.Sym == nil && int32(int16(v)) == v {
|
||||||
zRI(op_BRC, mask, uint32(v), asm)
|
zRI(op_BRC, mask, uint32(v), asm)
|
||||||
} else {
|
} else {
|
||||||
@ -3092,14 +3092,14 @@ func (c *ctxtz) asmout(p *obj.Prog, asm *[]byte) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
case 17: // move on condition
|
case 17: // move on condition
|
||||||
m3 := c.branchMask(p)
|
m3 := uint32(c.branchMask(p))
|
||||||
zRRF(op_LOCGR, m3, 0, uint32(p.To.Reg), uint32(p.From.Reg), asm)
|
zRRF(op_LOCGR, m3, 0, uint32(p.To.Reg), uint32(p.From.Reg), asm)
|
||||||
|
|
||||||
case 18: // br/bl reg
|
case 18: // br/bl reg
|
||||||
if p.As == ABL {
|
if p.As == ABL {
|
||||||
zRR(op_BASR, uint32(REG_LR), uint32(p.To.Reg), asm)
|
zRR(op_BASR, uint32(REG_LR), uint32(p.To.Reg), asm)
|
||||||
} else {
|
} else {
|
||||||
zRR(op_BCR, 0xF, uint32(p.To.Reg), asm)
|
zRR(op_BCR, uint32(Always), uint32(p.To.Reg), asm)
|
||||||
}
|
}
|
||||||
|
|
||||||
case 19: // mov $sym+n(SB) reg
|
case 19: // mov $sym+n(SB) reg
|
||||||
@ -3233,7 +3233,7 @@ func (c *ctxtz) asmout(p *obj.Prog, asm *[]byte) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
case 25: // load on condition (register)
|
case 25: // load on condition (register)
|
||||||
m3 := c.branchMask(p)
|
m3 := uint32(c.branchMask(p))
|
||||||
var opcode uint32
|
var opcode uint32
|
||||||
switch p.As {
|
switch p.As {
|
||||||
case ALOCR:
|
case ALOCR:
|
||||||
@ -3448,7 +3448,7 @@ func (c *ctxtz) asmout(p *obj.Prog, asm *[]byte) {
|
|||||||
zRRE(op_MLGR, uint32(p.To.Reg), uint32(p.From.Reg), asm)
|
zRRE(op_MLGR, uint32(p.To.Reg), uint32(p.From.Reg), asm)
|
||||||
|
|
||||||
case 66:
|
case 66:
|
||||||
zRR(op_BCR, 0, 0, asm)
|
zRR(op_BCR, uint32(Never), 0, asm)
|
||||||
|
|
||||||
case 67: // fmov $0 freg
|
case 67: // fmov $0 freg
|
||||||
var opcode uint32
|
var opcode uint32
|
||||||
@ -3634,7 +3634,7 @@ func (c *ctxtz) asmout(p *obj.Prog, asm *[]byte) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
case 80: // sync
|
case 80: // sync
|
||||||
zRR(op_BCR, 0xE, 0, asm)
|
zRR(op_BCR, uint32(NotEqual), 0, asm)
|
||||||
|
|
||||||
case 81: // float to fixed and fixed to float moves (no conversion)
|
case 81: // float to fixed and fixed to float moves (no conversion)
|
||||||
switch p.As {
|
switch p.As {
|
||||||
@ -3830,7 +3830,7 @@ func (c *ctxtz) asmout(p *obj.Prog, asm *[]byte) {
|
|||||||
if p.From.Type == obj.TYPE_CONST {
|
if p.From.Type == obj.TYPE_CONST {
|
||||||
r1, r2 = p.Reg, p.RestArgs[0].Reg
|
r1, r2 = p.Reg, p.RestArgs[0].Reg
|
||||||
}
|
}
|
||||||
m3 := c.branchMask(p)
|
m3 := uint32(c.branchMask(p))
|
||||||
|
|
||||||
var opcode uint32
|
var opcode uint32
|
||||||
switch p.As {
|
switch p.As {
|
||||||
@ -3859,7 +3859,7 @@ func (c *ctxtz) asmout(p *obj.Prog, asm *[]byte) {
|
|||||||
// the condition code.
|
// the condition code.
|
||||||
m3 ^= 0xe // invert 3-bit mask
|
m3 ^= 0xe // invert 3-bit mask
|
||||||
zRIE(_b, opcode, uint32(r1), uint32(r2), uint32(sizeRIE+sizeRIL)/2, 0, 0, m3, 0, asm)
|
zRIE(_b, opcode, uint32(r1), uint32(r2), uint32(sizeRIE+sizeRIL)/2, 0, 0, m3, 0, asm)
|
||||||
zRIL(_c, op_BRCL, 0xf, uint32(v-sizeRIE/2), asm)
|
zRIL(_c, op_BRCL, uint32(Always), uint32(v-sizeRIE/2), asm)
|
||||||
} else {
|
} else {
|
||||||
zRIE(_b, opcode, uint32(r1), uint32(r2), uint32(v), 0, 0, m3, 0, asm)
|
zRIE(_b, opcode, uint32(r1), uint32(r2), uint32(v), 0, 0, m3, 0, asm)
|
||||||
}
|
}
|
||||||
@ -3875,7 +3875,7 @@ func (c *ctxtz) asmout(p *obj.Prog, asm *[]byte) {
|
|||||||
if p.From.Type == obj.TYPE_CONST {
|
if p.From.Type == obj.TYPE_CONST {
|
||||||
r1 = p.Reg
|
r1 = p.Reg
|
||||||
}
|
}
|
||||||
m3 := c.branchMask(p)
|
m3 := uint32(c.branchMask(p))
|
||||||
|
|
||||||
var opcode uint32
|
var opcode uint32
|
||||||
switch p.As {
|
switch p.As {
|
||||||
@ -3899,7 +3899,7 @@ func (c *ctxtz) asmout(p *obj.Prog, asm *[]byte) {
|
|||||||
// the condition code.
|
// the condition code.
|
||||||
m3 ^= 0xe // invert 3-bit mask
|
m3 ^= 0xe // invert 3-bit mask
|
||||||
zRIE(_c, opcode, uint32(r1), m3, uint32(sizeRIE+sizeRIL)/2, 0, 0, 0, uint32(i2), asm)
|
zRIE(_c, opcode, uint32(r1), m3, uint32(sizeRIE+sizeRIL)/2, 0, 0, 0, uint32(i2), asm)
|
||||||
zRIL(_c, op_BRCL, 0xf, uint32(v-sizeRIE/2), asm)
|
zRIL(_c, op_BRCL, uint32(Always), uint32(v-sizeRIE/2), asm)
|
||||||
} else {
|
} else {
|
||||||
zRIE(_c, opcode, uint32(r1), m3, uint32(v), 0, 0, 0, uint32(i2), asm)
|
zRIE(_c, opcode, uint32(r1), m3, uint32(v), 0, 0, 0, uint32(i2), asm)
|
||||||
}
|
}
|
||||||
|
120
src/cmd/internal/obj/s390x/condition_code.go
Normal file
120
src/cmd/internal/obj/s390x/condition_code.go
Normal file
@ -0,0 +1,120 @@
|
|||||||
|
// Copyright 2019 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package s390x
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
)
|
||||||
|
|
||||||
|
// CCMask represents a 4-bit condition code mask. Bits that
|
||||||
|
// are not part of the mask should be 0.
|
||||||
|
//
|
||||||
|
// Condition code masks represent the 4 possible values of
|
||||||
|
// the 2-bit condition code as individual bits. Since IBM Z
|
||||||
|
// is a big-endian platform bits are numbered from left to
|
||||||
|
// right. The lowest value, 0, is represented by 8 (0b1000)
|
||||||
|
// and the highest value, 3, is represented by 1 (0b0001).
|
||||||
|
//
|
||||||
|
// Note that condition code values have different semantics
|
||||||
|
// depending on the instruction that set the condition code.
|
||||||
|
// The names given here assume that the condition code was
|
||||||
|
// set by an integer or floating point comparison. Other
|
||||||
|
// instructions may use these same codes to indicate
|
||||||
|
// different results such as a carry or overflow.
|
||||||
|
type CCMask uint8
|
||||||
|
|
||||||
|
const (
|
||||||
|
Never CCMask = 0 // no-op
|
||||||
|
|
||||||
|
// 1-bit masks
|
||||||
|
Equal CCMask = 1 << 3
|
||||||
|
Less CCMask = 1 << 2
|
||||||
|
Greater CCMask = 1 << 1
|
||||||
|
Unordered CCMask = 1 << 0
|
||||||
|
|
||||||
|
// 2-bit masks
|
||||||
|
EqualOrUnordered CCMask = Equal | Unordered // not less and not greater
|
||||||
|
LessOrEqual CCMask = Less | Equal // ordered and not greater
|
||||||
|
LessOrGreater CCMask = Less | Greater // ordered and not equal
|
||||||
|
LessOrUnordered CCMask = Less | Unordered // not greater and not equal
|
||||||
|
GreaterOrEqual CCMask = Greater | Equal // ordered and not less
|
||||||
|
GreaterOrUnordered CCMask = Greater | Unordered // not less and not equal
|
||||||
|
|
||||||
|
// 3-bit masks
|
||||||
|
NotEqual CCMask = Always ^ Equal
|
||||||
|
NotLess CCMask = Always ^ Less
|
||||||
|
NotGreater CCMask = Always ^ Greater
|
||||||
|
NotUnordered CCMask = Always ^ Unordered
|
||||||
|
|
||||||
|
// 4-bit mask
|
||||||
|
Always CCMask = Equal | Less | Greater | Unordered
|
||||||
|
)
|
||||||
|
|
||||||
|
// Inverse returns the complement of the condition code mask.
|
||||||
|
func (c CCMask) Inverse() CCMask {
|
||||||
|
return c ^ Always
|
||||||
|
}
|
||||||
|
|
||||||
|
// ReverseComparison swaps the bits at 0b0100 and 0b0010 in the mask,
|
||||||
|
// reversing the behavior of greater than and less than conditions.
|
||||||
|
func (c CCMask) ReverseComparison() CCMask {
|
||||||
|
r := c & EqualOrUnordered
|
||||||
|
if c&Less != 0 {
|
||||||
|
r |= Greater
|
||||||
|
}
|
||||||
|
if c&Greater != 0 {
|
||||||
|
r |= Less
|
||||||
|
}
|
||||||
|
return r
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c CCMask) String() string {
|
||||||
|
switch c {
|
||||||
|
// 0-bit mask
|
||||||
|
case Never:
|
||||||
|
return "Never"
|
||||||
|
|
||||||
|
// 1-bit masks
|
||||||
|
case Equal:
|
||||||
|
return "Equal"
|
||||||
|
case Less:
|
||||||
|
return "Less"
|
||||||
|
case Greater:
|
||||||
|
return "Greater"
|
||||||
|
case Unordered:
|
||||||
|
return "Unordered"
|
||||||
|
|
||||||
|
// 2-bit masks
|
||||||
|
case EqualOrUnordered:
|
||||||
|
return "EqualOrUnordered"
|
||||||
|
case LessOrEqual:
|
||||||
|
return "LessOrEqual"
|
||||||
|
case LessOrGreater:
|
||||||
|
return "LessOrGreater"
|
||||||
|
case LessOrUnordered:
|
||||||
|
return "LessOrUnordered"
|
||||||
|
case GreaterOrEqual:
|
||||||
|
return "GreaterOrEqual"
|
||||||
|
case GreaterOrUnordered:
|
||||||
|
return "GreaterOrUnordered"
|
||||||
|
|
||||||
|
// 3-bit masks
|
||||||
|
case NotEqual:
|
||||||
|
return "NotEqual"
|
||||||
|
case NotLess:
|
||||||
|
return "NotLess"
|
||||||
|
case NotGreater:
|
||||||
|
return "NotGreater"
|
||||||
|
case NotUnordered:
|
||||||
|
return "NotUnordered"
|
||||||
|
|
||||||
|
// 4-bit mask
|
||||||
|
case Always:
|
||||||
|
return "Always"
|
||||||
|
}
|
||||||
|
|
||||||
|
// invalid
|
||||||
|
return fmt.Sprintf("Invalid (%#x)", c)
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user