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 <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>
This commit is contained in:
Paul E. Murphy 2023-07-07 11:46:45 -05:00 committed by Paul Murphy
parent 7286800338
commit 5f872db5fc
2 changed files with 40 additions and 49 deletions

View 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

View 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))