cmd/asm,cmd/compile: support 5 operand RLWNM/RLWMI on ppc64

These instructions are actually 5 argument opcodes as specified
by the ISA.  Prior to this patch, the MB and ME arguments were
merged into a single bitmask operand to workaround the limitations
of the ppc64 assembler backend.

This limitation no longer exists. Thus, we can pass operands for
these opcodes without having to merge the MB and ME arguments in
the assembler frontend or compiler backend.

Likewise, support for 4 operand variants is unchanged.

Change-Id: Ib086774f3581edeaadfd2190d652aaaa8a90daeb
Reviewed-on: https://go-review.googlesource.com/c/go/+/298750
Reviewed-by: Lynn Boger <laboger@linux.vnet.ibm.com>
Reviewed-by: Carlos Eduardo Seo <carlos.seo@linaro.org>
Trust: Carlos Eduardo Seo <carlos.seo@linaro.org>
This commit is contained in:
Paul E. Murphy 2021-01-05 16:44:43 -06:00 committed by Lynn Boger
parent 18510ae88f
commit 48ddf70128
6 changed files with 58 additions and 47 deletions

View file

@ -799,19 +799,11 @@ func (p *Parser) asmInstruction(op obj.As, cond string, a []obj.Addr) {
p.errorf("can't handle %s instruction with 4 operands", op)
return
case 5:
if p.arch.Family == sys.PPC64 && arch.IsPPC64RLD(op) {
// Always reg, reg, con, con, reg. (con, con is a 'mask').
if p.arch.Family == sys.PPC64 {
prog.From = a[0]
// Second arg is always a register type on ppc64.
prog.Reg = p.getRegister(prog, op, &a[1])
mask1 := p.getConstant(prog, op, &a[2])
mask2 := p.getConstant(prog, op, &a[3])
var mask uint32
if mask1 < mask2 {
mask = (^uint32(0) >> uint(mask1)) & (^uint32(0) << uint(31-mask2))
} else {
mask = (^uint32(0) >> uint(mask2+1)) & (^uint32(0) << uint(31-(mask1-1)))
}
prog.SetFrom3Const(int64(mask))
prog.SetRestArgs([]obj.Addr{a[2], a[3]})
prog.To = a[4]
break
}

View file

@ -280,11 +280,17 @@ TEXT asmtest(SB),DUPOK|NOSPLIT,$0
ROTLW R3, R4, R5 // 5c85183e
EXTSWSLI $3, R4, R5 // 7c851ef4
RLWMI $7, R3, $65535, R6 // 50663c3e
RLWMI $7, R3, $16, $31, R6 // 50663c3e
RLWMICC $7, R3, $65535, R6 // 50663c3f
RLWMICC $7, R3, $16, $31, R6 // 50663c3f
RLWNM $3, R4, $7, R6 // 54861f7e
RLWNM $3, R4, $29, $31, R6 // 54861f7e
RLWNM R3, R4, $7, R6 // 5c861f7e
RLWNM R3, R4, $29, $31, R6 // 5c861f7e
RLWNMCC $3, R4, $7, R6 // 54861f7f
RLWNMCC $3, R4, $29, $31, R6 // 54861f7f
RLWNMCC R3, R4, $7, R6 // 5c861f7f
RLWNMCC R3, R4, $29, $31, R6 // 5c861f7f
RLDMI $0, R4, $7, R6 // 7886076c
RLDMICC $0, R4, $7, R6 // 7886076d
RLDIMI $0, R4, $7, R6 // 788601cc

View file

@ -653,21 +653,21 @@ func ssaGenValue(s *ssagen.State, v *ssa.Value) {
// Auxint holds encoded rotate + mask
case ssa.OpPPC64RLWINM, ssa.OpPPC64RLWMI:
rot, _, _, mask := ssa.DecodePPC64RotateMask(v.AuxInt)
rot, mb, me, _ := ssa.DecodePPC64RotateMask(v.AuxInt)
p := s.Prog(v.Op.Asm())
p.To = obj.Addr{Type: obj.TYPE_REG, Reg: v.Reg()}
p.Reg = v.Args[0].Reg()
p.From = obj.Addr{Type: obj.TYPE_CONST, Offset: int64(rot)}
p.SetFrom3Const(int64(mask))
p.SetRestArgs([]obj.Addr{{Type: obj.TYPE_CONST, Offset: mb}, {Type: obj.TYPE_CONST, Offset: me}})
// Auxint holds mask
case ssa.OpPPC64RLWNM:
_, _, _, mask := ssa.DecodePPC64RotateMask(v.AuxInt)
_, mb, me, _ := ssa.DecodePPC64RotateMask(v.AuxInt)
p := s.Prog(v.Op.Asm())
p.To = obj.Addr{Type: obj.TYPE_REG, Reg: v.Reg()}
p.Reg = v.Args[0].Reg()
p.From = obj.Addr{Type: obj.TYPE_REG, Reg: v.Args[1].Reg()}
p.SetFrom3Const(int64(mask))
p.SetRestArgs([]obj.Addr{{Type: obj.TYPE_CONST, Offset: mb}, {Type: obj.TYPE_CONST, Offset: me}})
case ssa.OpPPC64MADDLD:
r := v.Reg()

View file

@ -181,7 +181,9 @@ var optab = []Optab{
{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: ARLWMI, a1: C_REG, a2: C_REG, a3: C_LCON, a6: C_REG, type_: 63, size: 4},
{as: ARLWMI, a1: C_REG, a2: C_REG, a3: C_SCON, a4: C_SCON, a6: C_REG, type_: 103, 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},
@ -3861,6 +3863,17 @@ func (c *ctxt9) asmout(p *obj.Prog, o *Optab, out []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: /* RLWMI 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)
}
out[0] = o1

View file

@ -176,38 +176,38 @@ func f32(x uint32) uint32 {
func checkMaskedRotate32(a []uint32, r int) {
i := 0
// ppc64le: "RLWNM\t[$]16, R[0-9]+, [$]16711680, R[0-9]+"
// ppc64: "RLWNM\t[$]16, R[0-9]+, [$]16711680, R[0-9]+"
// ppc64le: "RLWNM\t[$]16, R[0-9]+, [$]8, [$]15, R[0-9]+"
// ppc64: "RLWNM\t[$]16, R[0-9]+, [$]8, [$]15, R[0-9]+"
a[i] = bits.RotateLeft32(a[i], 16) & 0xFF0000
i++
// ppc64le: "RLWNM\t[$]16, R[0-9]+, [$]16711680, R[0-9]+"
// ppc64: "RLWNM\t[$]16, R[0-9]+, [$]16711680, R[0-9]+"
// ppc64le: "RLWNM\t[$]16, R[0-9]+, [$]8, [$]15, R[0-9]+"
// ppc64: "RLWNM\t[$]16, R[0-9]+, [$]8, [$]15, R[0-9]+"
a[i] = bits.RotateLeft32(a[i]&0xFF, 16)
i++
// ppc64le: "RLWNM\t[$]4, R[0-9]+, [$]4080, R[0-9]+"
// ppc64: "RLWNM\t[$]4, R[0-9]+, [$]4080, R[0-9]+"
// ppc64le: "RLWNM\t[$]4, R[0-9]+, [$]20, [$]27, R[0-9]+"
// ppc64: "RLWNM\t[$]4, R[0-9]+, [$]20, [$]27, R[0-9]+"
a[i] = bits.RotateLeft32(a[i], 4) & 0xFF0
i++
// ppc64le: "RLWNM\t[$]16, R[0-9]+, [$]255, R[0-9]+"
// ppc64: "RLWNM\t[$]16, R[0-9]+, [$]255, R[0-9]+"
// ppc64le: "RLWNM\t[$]16, R[0-9]+, [$]24, [$]31, R[0-9]+"
// ppc64: "RLWNM\t[$]16, R[0-9]+, [$]24, [$]31, R[0-9]+"
a[i] = bits.RotateLeft32(a[i]&0xFF0000, 16)
i++
// ppc64le: "RLWNM\tR[0-9]+, R[0-9]+, [$]16711680, R[0-9]+"
// ppc64: "RLWNM\tR[0-9]+, R[0-9]+, [$]16711680, R[0-9]+"
// ppc64le: "RLWNM\tR[0-9]+, R[0-9]+, [$]8, [$]15, R[0-9]+"
// ppc64: "RLWNM\tR[0-9]+, R[0-9]+, [$]8, [$]15, R[0-9]+"
a[i] = bits.RotateLeft32(a[i], r) & 0xFF0000
i++
// ppc64le: "RLWNM\tR[0-9]+, R[0-9]+, [$]65280, R[0-9]+"
// ppc64: "RLWNM\tR[0-9]+, R[0-9]+, [$]65280, R[0-9]+"
// ppc64le: "RLWNM\tR[0-9]+, R[0-9]+, [$]16, [$]23, R[0-9]+"
// ppc64: "RLWNM\tR[0-9]+, R[0-9]+, [$]16, [$]23, R[0-9]+"
a[i] = bits.RotateLeft32(a[3], r) & 0xFF00
i++
// ppc64le: "RLWNM\tR[0-9]+, R[0-9]+, [$]4293922815, R[0-9]+"
// ppc64: "RLWNM\tR[0-9]+, R[0-9]+, [$]4293922815, R[0-9]+"
// ppc64le: "RLWNM\tR[0-9]+, R[0-9]+, [$]20, [$]11, R[0-9]+"
// ppc64: "RLWNM\tR[0-9]+, R[0-9]+, [$]20, [$]11, R[0-9]+"
a[i] = bits.RotateLeft32(a[3], r) & 0xFFF00FFF
i++
// ppc64le: "RLWNM\t[$]4, R[0-9]+, [$]4293922815, R[0-9]+"
// ppc64: "RLWNM\t[$]4, R[0-9]+, [$]4293922815, R[0-9]+"
// ppc64le: "RLWNM\t[$]4, R[0-9]+, [$]20, [$]11, R[0-9]+"
// ppc64: "RLWNM\t[$]4, R[0-9]+, [$]20, [$]11, R[0-9]+"
a[i] = bits.RotateLeft32(a[3], 4) & 0xFFF00FFF
i++
}

View file

@ -240,12 +240,12 @@ func checkWidenAfterShift(v int64, u uint64) (int64, uint64) {
func checkShiftAndMask32(v []uint32) {
i := 0
// ppc64le: "RLWNM\t[$]24, R[0-9]+, [$]1044480, R[0-9]+"
// ppc64: "RLWNM\t[$]24, R[0-9]+, [$]1044480, R[0-9]+"
// ppc64le: "RLWNM\t[$]24, R[0-9]+, [$]12, [$]19, R[0-9]+"
// ppc64: "RLWNM\t[$]24, R[0-9]+, [$]12, [$]19, R[0-9]+"
v[i] = (v[i] & 0xFF00000) >> 8
i++
// ppc64le: "RLWNM\t[$]26, R[0-9]+, [$]1020, R[0-9]+"
// ppc64: "RLWNM\t[$]26, R[0-9]+, [$]1020, R[0-9]+"
// ppc64le: "RLWNM\t[$]26, R[0-9]+, [$]22, [$]29, R[0-9]+"
// ppc64: "RLWNM\t[$]26, R[0-9]+, [$]22, [$]29, R[0-9]+"
v[i] = (v[i] & 0xFF00) >> 6
i++
// ppc64le: "MOVW\tR0"
@ -256,12 +256,12 @@ func checkShiftAndMask32(v []uint32) {
// ppc64: "MOVW\tR0"
v[i] = (v[i] & 0xF000000) >> 28
i++
// ppc64le: "RLWNM\t[$]26, R[0-9]+, [$]255, R[0-9]+"
// ppc64: "RLWNM\t[$]26, R[0-9]+, [$]255, R[0-9]+"
// ppc64le: "RLWNM\t[$]26, R[0-9]+, [$]24, [$]31, R[0-9]+"
// ppc64: "RLWNM\t[$]26, R[0-9]+, [$]24, [$]31, R[0-9]+"
v[i] = (v[i] >> 6) & 0xFF
i++
// ppc64le: "RLWNM\t[$]26, R[0-9]+, [$]1044480, R[0-9]+"
// ppc64: "RLWNM\t[$]26, R[0-9]+, [$]1044480, R[0-9]+"
// ppc64le: "RLWNM\t[$]26, R[0-9]+, [$]12, [$]19, R[0-9]+"
// ppc64: "RLWNM\t[$]26, R[0-9]+, [$]12, [$]19, R[0-9]+"
v[i] = (v[i] >> 6) & 0xFF000
i++
// ppc64le: "MOVW\tR0"
@ -275,16 +275,16 @@ func checkShiftAndMask32(v []uint32) {
}
func checkMergedShifts32(a [256]uint32, b [256]uint64, u uint32, v uint32) {
//ppc64le: -"CLRLSLDI", "RLWNM\t[$]10, R[0-9]+, [$]1020, R[0-9]+"
//ppc64: -"CLRLSLDI", "RLWNM\t[$]10, R[0-9]+, [$]1020, R[0-9]+"
//ppc64le: -"CLRLSLDI", "RLWNM\t[$]10, R[0-9]+, [$]22, [$]29, R[0-9]+"
//ppc64: -"CLRLSLDI", "RLWNM\t[$]10, R[0-9]+, [$]22, [$]29, R[0-9]+"
a[0] = a[uint8(v>>24)]
//ppc64le: -"CLRLSLDI", "RLWNM\t[$]11, R[0-9]+, [$]2040, R[0-9]+"
//ppc64: -"CLRLSLDI", "RLWNM\t[$]11, R[0-9]+, [$]2040, R[0-9]+"
//ppc64le: -"CLRLSLDI", "RLWNM\t[$]11, R[0-9]+, [$]21, [$]28, R[0-9]+"
//ppc64: -"CLRLSLDI", "RLWNM\t[$]11, R[0-9]+, [$]21, [$]28, R[0-9]+"
b[0] = b[uint8(v>>24)]
//ppc64le: -"CLRLSLDI", "RLWNM\t[$]15, R[0-9]+, [$]2040, R[0-9]+"
//ppc64: -"CLRLSLDI", "RLWNM\t[$]15, R[0-9]+, [$]2040, R[0-9]+"
//ppc64le: -"CLRLSLDI", "RLWNM\t[$]15, R[0-9]+, [$]21, [$]28, R[0-9]+"
//ppc64: -"CLRLSLDI", "RLWNM\t[$]15, R[0-9]+, [$]21, [$]28, R[0-9]+"
b[1] = b[(v>>20)&0xFF]
//ppc64le: -"SLD", "RLWNM\t[$]10, R[0-9]+, [$]1016, R[0-9]+"
//ppc64: -"SLD", "RLWNM\t[$]10, R[0-9]+, [$]1016, R[0-9]+"
//ppc64le: -"SLD", "RLWNM\t[$]10, R[0-9]+, [$]22, [$]28, R[0-9]+"
//ppc64: -"SLD", "RLWNM\t[$]10, R[0-9]+, [$]22, [$]28, R[0-9]+"
b[2] = b[v>>25]
}