mirror of
https://github.com/golang/go.git
synced 2025-05-05 23:53:05 +00:00
cmd/internal/obj/ppc64: generate MOVD mask constants in register
Add a new form of RLDC which maps directly to the ISA definition of rldc: RLDC Rs, $sh, $mb, Ra. This is used to generate mask constants described below. Using MOVD $-1, Rx; RLDC Rx, $sh, $mb, Rx, any mask constant can be generated. A mask is a contiguous series of 1 bits, which may wrap. Change-Id: Ifcaae1114080ad58b5fdaa3e5fc9019e2051f282 Reviewed-on: https://go-review.googlesource.com/c/go/+/531120 Reviewed-by: Matthew Dempsky <mdempsky@google.com> LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com> Reviewed-by: Michael Pratt <mpratt@google.com> Reviewed-by: Lynn Boger <laboger@linux.vnet.ibm.com> Run-TryBot: Paul Murphy <murp@ibm.com> TryBot-Result: Gopher Robot <gobot@golang.org>
This commit is contained in:
parent
26d07d80ca
commit
dcd018b5c5
8
src/cmd/asm/internal/asm/testdata/ppc64.s
vendored
8
src/cmd/asm/internal/asm/testdata/ppc64.s
vendored
@ -42,6 +42,10 @@ TEXT asmtest(SB),DUPOK|NOSPLIT,$0
|
||||
MOVD $2199090364416, R5 // 60058001
|
||||
// Hex constant 0xFFFFFE0004000000
|
||||
MOVD $-2198956146688, R5 // 38a08001
|
||||
// TODO: On GOPPC64={power8,power9}, this is preprocessed into MOVD $-1, R5; RLDC R5, $33, $63, R5.
|
||||
// This only captures the MOVD. Should the RLDC be appended to the encoding by the test?
|
||||
// Hex constant 0xFFFFFFFE00000001
|
||||
MOVD $-8589934591, R5 // 38a0ffff or 0602000038a00001
|
||||
|
||||
MOVD 8(R3), R4 // e8830008
|
||||
MOVD (R3)(R4), R5 // 7ca4182a
|
||||
@ -426,6 +430,10 @@ TEXT asmtest(SB),DUPOK|NOSPLIT,$0
|
||||
RLDIMI $0, R4, $7, R6 // 788601cc
|
||||
RLDIMICC $0, R4, $7, R6 // 788601cd
|
||||
RLDC $0, R4, $15, R6 // 78860728
|
||||
RLDC R3, $32, $12, R4 // 7864030a
|
||||
RLDC R3, $8, $32, R4 // 78644028
|
||||
RLDCCC R3, $32, $12, R4 // 7864030b
|
||||
RLDCCC R3, $8, $32, R4 // 78644029
|
||||
RLDCCC $0, R4, $15, R6 // 78860729
|
||||
RLDCL $0, R4, $7, R6 // 78860770
|
||||
RLDCLCC $0, R4, $15, R6 // 78860721
|
||||
|
@ -194,6 +194,7 @@ var optabBase = []Optab{
|
||||
{as: ACLRLSLWI, a1: C_SCON, a2: C_REG, a3: C_LCON, a6: C_REG, type_: 62, size: 4},
|
||||
{as: ARLDMI, a1: C_SCON, a2: C_REG, a3: C_LCON, a6: C_REG, type_: 30, size: 4},
|
||||
{as: ARLDC, a1: C_SCON, a2: C_REG, a3: C_LCON, a6: C_REG, type_: 29, size: 4},
|
||||
{as: ARLDC, a1: C_REG, a3: C_U8CON, a4: C_U8CON, a6: C_REG, type_: 9, size: 4},
|
||||
{as: ARLDCL, a1: C_SCON, a2: C_REG, a3: C_LCON, a6: C_REG, type_: 29, size: 4},
|
||||
{as: ARLDCL, a1: C_REG, a2: C_REG, a3: C_LCON, a6: C_REG, type_: 14, size: 4},
|
||||
{as: ARLDICL, a1: C_REG, a2: C_REG, a3: C_LCON, a6: C_REG, type_: 14, size: 4},
|
||||
@ -2723,6 +2724,14 @@ func asmout(c *ctxt9, p *obj.Prog, o *Optab, out *[5]uint32) {
|
||||
// Sign extend MOVB operations. This is ignored for other cases (o.size == 4).
|
||||
o2 = LOP_RRR(OP_EXTSB, uint32(p.To.Reg), uint32(p.To.Reg), 0)
|
||||
|
||||
case 9: /* RLDC Ra, $sh, $mb, Rb */
|
||||
sh := uint32(p.RestArgs[0].Addr.Offset) & 0x3F
|
||||
mb := uint32(p.RestArgs[1].Addr.Offset) & 0x3F
|
||||
o1 = AOP_RRR(c.opirr(p.As), uint32(p.From.Reg), uint32(p.To.Reg), (uint32(sh) & 0x1F))
|
||||
o1 |= (sh & 0x20) >> 4 // sh[5] is placed in bit 1.
|
||||
o1 |= (mb & 0x1F) << 6 // mb[0:4] is placed in bits 6-10.
|
||||
o1 |= (mb & 0x20) // mb[5] is placed in bit 5
|
||||
|
||||
case 10: /* sub Ra,[Rb],Rd => subf Rd,Ra,Rb */
|
||||
r := int(p.Reg)
|
||||
|
||||
|
@ -39,6 +39,39 @@ import (
|
||||
"math/bits"
|
||||
)
|
||||
|
||||
// Test if this value can encoded as a mask for
|
||||
// li -1, rx; rlic rx,rx,sh,mb.
|
||||
// Masks can also extend from the msb and wrap to
|
||||
// the lsb too. That is, the valid masks are 32 bit strings
|
||||
// of the form: 0..01..10..0 or 1..10..01..1 or 1...1
|
||||
func isPPC64DoublewordRotateMask(v64 int64) bool {
|
||||
// Isolate rightmost 1 (if none 0) and add.
|
||||
v := uint64(v64)
|
||||
vp := (v & -v) + v
|
||||
// Likewise, for the wrapping case.
|
||||
vn := ^v
|
||||
vpn := (vn & -vn) + vn
|
||||
return (v&vp == 0 || vn&vpn == 0) && v != 0
|
||||
}
|
||||
|
||||
// Encode a doubleword rotate mask into mb (mask begin) and
|
||||
// me (mask end, inclusive). Note, POWER ISA labels bits in
|
||||
// big endian order.
|
||||
func encodePPC64RLDCMask(mask int64) (mb, me int) {
|
||||
// Determine boundaries and then decode them
|
||||
mb = bits.LeadingZeros64(uint64(mask))
|
||||
me = 64 - bits.TrailingZeros64(uint64(mask))
|
||||
mbn := bits.LeadingZeros64(^uint64(mask))
|
||||
men := 64 - bits.TrailingZeros64(^uint64(mask))
|
||||
// Check for a wrapping mask (e.g bits at 0 and 63)
|
||||
if mb == 0 && me == 64 {
|
||||
// swap the inverted values
|
||||
mb, me = men, mbn
|
||||
}
|
||||
// Note, me is inclusive.
|
||||
return mb, me - 1
|
||||
}
|
||||
|
||||
func progedit(ctxt *obj.Link, p *obj.Prog, newprog obj.ProgAlloc) {
|
||||
p.From.Class = 0
|
||||
p.To.Class = 0
|
||||
@ -97,11 +130,21 @@ func progedit(ctxt *obj.Link, p *obj.Prog, newprog obj.ProgAlloc) {
|
||||
// Rewrite this value into MOVD $const>>shift, Rto; SLD $shift, Rto
|
||||
q := obj.Appendp(p, c.newprog)
|
||||
q.As = ASLD
|
||||
q.From.Type = obj.TYPE_CONST
|
||||
q.From.Offset = int64(shift)
|
||||
q.From.SetConst(int64(shift))
|
||||
q.To = p.To
|
||||
p.From.Offset >>= shift
|
||||
p = q
|
||||
// Is this constant a mask value? If so, generate MOVD $-1, Rto; RLDIC Rto, ^me, mb, Rto
|
||||
} else if isPPC64DoublewordRotateMask(val) {
|
||||
mb, me := encodePPC64RLDCMask(val)
|
||||
q := obj.Appendp(p, c.newprog)
|
||||
q.As = ARLDC
|
||||
q.AddRestSourceConst((^int64(me)) & 0x3F)
|
||||
q.AddRestSourceConst(int64(mb))
|
||||
q.From = p.To
|
||||
q.To = p.To
|
||||
p.From.Offset = -1
|
||||
p = q
|
||||
} else {
|
||||
// Load the constant from memory.
|
||||
p.From.Type = obj.TYPE_MEM
|
||||
|
@ -6,6 +6,7 @@
|
||||
|
||||
package codegen
|
||||
|
||||
// A uint16 or sint16 constant shifted left.
|
||||
func shifted16BitConstants(out [64]uint64) {
|
||||
// ppc64x: "MOVD\t[$]8193,", "SLD\t[$]27,"
|
||||
out[0] = 0x0000010008000000
|
||||
@ -15,11 +16,18 @@ func shifted16BitConstants(out [64]uint64) {
|
||||
out[2] = 0xFFFF000000000000
|
||||
// ppc64x: "MOVD\t[$]65535", "SLD\t[$]44,"
|
||||
out[3] = 0x0FFFF00000000000
|
||||
|
||||
// ppc64x: "MOVD\t[$]i64.fffff00000000001[(]SB[)]"
|
||||
out[4] = 0xFFFFF00000000001
|
||||
// ppc64x: "MOVD\t[$]i64.fffff80000000001[(]SB[)]"
|
||||
out[5] = 0xFFFFF80000000001
|
||||
// ppc64x: "MOVD\t[$]i64.0ffff80000000000[(]SB[)]"
|
||||
out[6] = 0x0FFFF80000000000
|
||||
}
|
||||
|
||||
// A contiguous set of 1 bits, potentially wrapping.
|
||||
func contiguousMaskConstants(out [64]uint64) {
|
||||
// ppc64x: "MOVD\t[$]-1", "RLDC\tR[0-9]+, [$]44, [$]63,"
|
||||
out[0] = 0xFFFFF00000000001
|
||||
// ppc64x: "MOVD\t[$]-1", "RLDC\tR[0-9]+, [$]43, [$]63,"
|
||||
out[1] = 0xFFFFF80000000001
|
||||
// ppc64x: "MOVD\t[$]-1", "RLDC\tR[0-9]+, [$]43, [$]4,"
|
||||
out[2] = 0x0FFFF80000000000
|
||||
// ppc64x/power8: "MOVD\t[$]-1", "RLDC\tR[0-9]+, [$]33, [$]63,"
|
||||
// ppc64x/power9: "MOVD\t[$]-1", "RLDC\tR[0-9]+, [$]33, [$]63,"
|
||||
// ppc64x/power10: "MOVD\t[$]-8589934591,"
|
||||
out[3] = 0xFFFFFFFE00000001
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user