From dcd018b5c54cd23b36ef732473f0d99fbb57f6fc Mon Sep 17 00:00:00 2001 From: "Paul E. Murphy" Date: Tue, 19 Sep 2023 17:01:28 -0500 Subject: [PATCH] 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 LUCI-TryBot-Result: Go LUCI Reviewed-by: Michael Pratt Reviewed-by: Lynn Boger Run-TryBot: Paul Murphy TryBot-Result: Gopher Robot --- src/cmd/asm/internal/asm/testdata/ppc64.s | 8 ++++ src/cmd/internal/obj/ppc64/asm9.go | 9 +++++ src/cmd/internal/obj/ppc64/obj9.go | 47 ++++++++++++++++++++++- test/codegen/constants.go | 20 +++++++--- 4 files changed, 76 insertions(+), 8 deletions(-) diff --git a/src/cmd/asm/internal/asm/testdata/ppc64.s b/src/cmd/asm/internal/asm/testdata/ppc64.s index a8b9e33db3..6f5182e1f9 100644 --- a/src/cmd/asm/internal/asm/testdata/ppc64.s +++ b/src/cmd/asm/internal/asm/testdata/ppc64.s @@ -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 diff --git a/src/cmd/internal/obj/ppc64/asm9.go b/src/cmd/internal/obj/ppc64/asm9.go index 65b8c583d9..ef683f69aa 100644 --- a/src/cmd/internal/obj/ppc64/asm9.go +++ b/src/cmd/internal/obj/ppc64/asm9.go @@ -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) diff --git a/src/cmd/internal/obj/ppc64/obj9.go b/src/cmd/internal/obj/ppc64/obj9.go index df0c36cde0..ab397892c2 100644 --- a/src/cmd/internal/obj/ppc64/obj9.go +++ b/src/cmd/internal/obj/ppc64/obj9.go @@ -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 diff --git a/test/codegen/constants.go b/test/codegen/constants.go index 756aeda5f7..3ce17d0ad3 100644 --- a/test/codegen/constants.go +++ b/test/codegen/constants.go @@ -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 } -- 2.44.0