mirror of https://github.com/golang/go.git
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:
parent
7286800338
commit
5f872db5fc
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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))
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue