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