From 5f872db5fc8a05c0b74bea1560595b34c268610a Mon Sep 17 00:00:00 2001 From: "Paul E. Murphy" Date: Fri, 7 Jul 2023 11:46:45 -0500 Subject: [PATCH] cmd/internal/obj/ppc64: improve RLWNM encoding If the rotate argument is the constant 0, rlwnm may be generated instead of rlwinm. In all reasonable cases, this is OK as R0 should hold 0. However, this could be problematic in some cases when writing PPC64 assembly. This consolidates the RLWNM and RLWMI optab entries. Invalid RLWMI usage is still rejected, however the error will be be slightly different. The invalid usage will be caught in oprrr instead of oplook. Change-Id: I9958bd24660fea5f8fc9e3e50d51daa7349e3206 Reviewed-on: https://go-review.googlesource.com/c/go/+/527275 Reviewed-by: Heschi Kreinick LUCI-TryBot-Result: Go LUCI Reviewed-by: Bryan Mills TryBot-Result: Gopher Robot Reviewed-by: Lynn Boger Run-TryBot: Paul Murphy --- src/cmd/asm/internal/asm/testdata/ppc64.s | 4 ++ src/cmd/internal/obj/ppc64/asm9.go | 85 ++++++++++------------- 2 files changed, 40 insertions(+), 49 deletions(-) diff --git a/src/cmd/asm/internal/asm/testdata/ppc64.s b/src/cmd/asm/internal/asm/testdata/ppc64.s index a0f1276aa1..2bf04971ed 100644 --- a/src/cmd/asm/internal/asm/testdata/ppc64.s +++ b/src/cmd/asm/internal/asm/testdata/ppc64.s @@ -398,7 +398,11 @@ TEXT asmtest(SB),DUPOK|NOSPLIT,$0 RLWMICC $7, R3, $65535, R6 // 50663c3f RLWMICC $7, R3, $16, $31, R6 // 50663c3f RLWNM $3, R4, $7, R6 // 54861f7e + RLWNM $0, R4, $7, R6 // 5486077e + RLWNM R0, R4, $7, R6 // 5c86077e RLWNM $3, R4, $29, $31, R6 // 54861f7e + RLWNM $0, R4, $29, $31, R6 // 5486077e + RLWNM R0, R4, $29, $31, R6 // 5c86077e RLWNM R3, R4, $7, R6 // 5c861f7e RLWNM R3, R4, $29, $31, R6 // 5c861f7e RLWNMCC $3, R4, $7, R6 // 54861f7f diff --git a/src/cmd/internal/obj/ppc64/asm9.go b/src/cmd/internal/obj/ppc64/asm9.go index 660a27b5cf..c1207b01f9 100644 --- a/src/cmd/internal/obj/ppc64/asm9.go +++ b/src/cmd/internal/obj/ppc64/asm9.go @@ -183,12 +183,10 @@ var optab = []Optab{ {as: ASRAD, a1: C_REG, a2: C_REG, a6: C_REG, type_: 6, size: 4}, {as: ASRAD, a1: C_SCON, a2: C_REG, a6: C_REG, type_: 56, size: 4}, {as: ASRAD, a1: C_SCON, a6: C_REG, type_: 56, size: 4}, - {as: ARLWMI, a1: C_SCON, a2: C_REG, a3: C_LCON, a6: C_REG, type_: 62, size: 4}, - {as: ARLWMI, a1: C_SCON, a2: C_REG, a3: C_SCON, a4: C_SCON, a6: C_REG, type_: 102, size: 4}, - {as: ARLWNM, a1: C_SCON, a2: C_REG, a3: C_LCON, a6: C_REG, type_: 62, size: 4}, - {as: ARLWNM, a1: C_SCON, a2: C_REG, a3: C_SCON, a4: C_SCON, a6: C_REG, type_: 102, size: 4}, + {as: ARLWNM, a1: C_SCON, a2: C_REG, a3: C_LCON, a6: C_REG, type_: 63, size: 4}, + {as: ARLWNM, a1: C_SCON, a2: C_REG, a3: C_SCON, a4: C_SCON, a6: C_REG, type_: 63, size: 4}, {as: ARLWNM, a1: C_REG, a2: C_REG, a3: C_LCON, a6: C_REG, type_: 63, size: 4}, - {as: ARLWNM, a1: C_REG, a2: C_REG, a3: C_SCON, a4: C_SCON, a6: C_REG, type_: 103, size: 4}, + {as: ARLWNM, a1: C_REG, a2: C_REG, a3: C_SCON, a4: C_SCON, a6: C_REG, type_: 63, size: 4}, {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}, @@ -1995,11 +1993,10 @@ func buildop(ctxt *obj.Link) { opset(APTESYNC, r0) opset(ATLBSYNC, r0) - case ARLWMI: - opset(ARLWMICC, r0) - case ARLWNM: opset(ARLWNMCC, r0) + opset(ARLWMI, r0) + opset(ARLWMICC, r0) case ARLDMI: opset(ARLDMICC, r0) @@ -2483,14 +2480,14 @@ func (c *ctxt9) symbolAccess(s *obj.LSym, d int64, reg int16, op uint32, reuse b /* * 32-bit masks */ -func getmask(m []byte, v uint32) bool { +func getmask(m *[2]uint32, v uint32) bool { m[1] = 0 - m[0] = m[1] + m[0] = 0 if v != ^uint32(0) && v&(1<<31) != 0 && v&1 != 0 { /* MB > ME */ if getmask(m, ^v) { - i := int(m[0]) + i := m[0] m[0] = m[1] + 1 - m[1] = byte(i - 1) + m[1] = i - 1 return true } @@ -2499,9 +2496,9 @@ func getmask(m []byte, v uint32) bool { for i := 0; i < 32; i++ { if v&(1<= 32 || v&(1< rlwinm ra,rs,n,b-n,31-n - // It maps onto rlwinm which is directly generated here. - if n > v || v >= 32 { - c.ctxt.Diag("Invalid n or b for CLRLSLWI: %x %x\n%v", v, n, p) - } - - o1 = OP_RLW(OP_RLWINM, uint32(p.To.Reg), uint32(p.Reg), uint32(n), uint32(v-n), uint32(31-n)) - default: - var mask [2]uint8 - c.maskgen(p, mask[:], uint32(c.regoff(p.GetFrom3()))) - o1 = AOP_RRR(c.opirr(p.As), uint32(p.Reg), uint32(p.To.Reg), uint32(v)) - o1 |= (uint32(mask[0])&31)<<6 | (uint32(mask[1])&31)<<1 + n := c.regoff(p.GetFrom3()) + // This is an extended mnemonic described in the ISA C.8.2 + // clrlslwi ra,rs,b,n -> rlwinm ra,rs,n,b-n,31-n + // It maps onto rlwinm which is directly generated here. + if n > v || v >= 32 { + c.ctxt.Diag("Invalid n or b for CLRLSLWI: %x %x\n%v", v, n, p) } - case 63: /* rlwmi b,s,$mask,a */ - var mask [2]uint8 - c.maskgen(p, mask[:], uint32(c.regoff(p.GetFrom3()))) - o1 = AOP_RRR(c.oprrr(p.As), uint32(p.Reg), uint32(p.To.Reg), uint32(p.From.Reg)) - o1 |= (uint32(mask[0])&31)<<6 | (uint32(mask[1])&31)<<1 + o1 = OP_RLW(OP_RLWINM, uint32(p.To.Reg), uint32(p.Reg), uint32(n), uint32(v-n), uint32(31-n)) + + case 63: /* rlwimi/rlwnm/rlwinm [$sh,b],s,[$mask or mb,me],a*/ + var mb, me uint32 + if len(p.RestArgs) == 1 { // Mask needs decomposed into mb and me. + mb, me = c.maskgen(p, uint32(p.RestArgs[0].Addr.Offset)) + } else { // Otherwise, mask is already passed as mb and me in RestArgs. + mb, me = uint32(p.RestArgs[0].Addr.Offset), uint32(p.RestArgs[1].Addr.Offset) + } + if p.From.Type == obj.TYPE_CONST { + o1 = OP_RLW(c.opirr(p.As), uint32(p.To.Reg), uint32(p.Reg), uint32(p.From.Offset), mb, me) + } else { + o1 = OP_RLW(c.oprrr(p.As), uint32(p.To.Reg), uint32(p.Reg), uint32(p.From.Reg), mb, me) + } case 64: /* mtfsf fr[, $m] {,fpcsr} */ var v int32 @@ -3924,17 +3922,6 @@ func asmout(c *ctxt9, p *obj.Prog, o *Optab, out *[5]uint32) { case 101: o1 = AOP_XX2(c.oprrr(p.As), uint32(p.To.Reg), uint32(0), uint32(p.From.Reg)) - case 102: /* RLWMI $sh,rs,$mb,$me,rt (M-form opcode)*/ - mb := uint32(c.regoff(&p.RestArgs[0].Addr)) - me := uint32(c.regoff(&p.RestArgs[1].Addr)) - sh := uint32(c.regoff(&p.From)) - o1 = OP_RLW(c.opirr(p.As), uint32(p.To.Reg), uint32(p.Reg), sh, mb, me) - - case 103: /* RLWNM rb,rs,$mb,$me,rt (M-form opcode)*/ - mb := uint32(c.regoff(&p.RestArgs[0].Addr)) - me := uint32(c.regoff(&p.RestArgs[1].Addr)) - o1 = OP_RLW(c.oprrr(p.As), uint32(p.To.Reg), uint32(p.Reg), uint32(p.From.Reg), mb, me) - case 104: /* VSX mtvsr* instructions, XX1-form RA,RB,XT */ o1 = AOP_XX1(c.oprrr(p.As), uint32(p.To.Reg), uint32(p.From.Reg), uint32(p.Reg)) -- 2.50.0