]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/internal/obj/ppc64: improve RLWNM encoding
authorPaul E. Murphy <murp@ibm.com>
Fri, 7 Jul 2023 16:46:45 +0000 (11:46 -0500)
committerPaul Murphy <murp@ibm.com>
Fri, 15 Sep 2023 15:33:33 +0000 (15:33 +0000)
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 <heschi@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Bryan Mills <bcmills@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
Reviewed-by: Lynn Boger <laboger@linux.vnet.ibm.com>
Run-TryBot: Paul Murphy <murp@ibm.com>

src/cmd/asm/internal/asm/testdata/ppc64.s
src/cmd/internal/obj/ppc64/asm9.go

index a0f1276aa1f43853c431ef55362e5672d2c7ff0e..2bf04971edbf1d76ef731417109e24cd382a9a45 100644 (file)
@@ -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
index 660a27b5cfee5daf48e5f0b36557a108eb7043ff..c1207b01f98528dbe78c9f70b82eba79410d8010 100644 (file)
@@ -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<<uint(31-i)) != 0 {
-                       m[0] = byte(i)
+                       m[0] = uint32(i)
                        for {
-                               m[1] = byte(i)
+                               m[1] = uint32(i)
                                i++
                                if i >= 32 || v&(1<<uint(31-i)) == 0 {
                                        break
@@ -2520,10 +2517,12 @@ func getmask(m []byte, v uint32) bool {
        return false
 }
 
-func (c *ctxt9) maskgen(p *obj.Prog, m []byte, v uint32) {
-       if !getmask(m, v) {
+func (c *ctxt9) maskgen(p *obj.Prog, v uint32) (mb, me uint32) {
+       var m [2]uint32
+       if !getmask(&m, v) {
                c.ctxt.Diag("cannot generate mask #%x\n%v", v, p)
        }
+       return m[0], m[1]
 }
 
 /*
@@ -3499,31 +3498,30 @@ func asmout(c *ctxt9, p *obj.Prog, o *Optab, out *[5]uint32) {
                v := c.regoff(&p.To)
                o1 = AOP_IRR(c.opirr(p.As), uint32(r), uint32(p.Reg), uint32(v))
 
-       case 62: /* rlwmi $sh,s,$mask,a */
+       case 62: /* clrlslwi $sh,s,$mask,a */
                v := c.regoff(&p.From)
-               switch p.As {
-               case ACLRLSLWI:
-                       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)
-                       }
-
-                       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))