Commit b10b2f8d authored by Lynn Boger's avatar Lynn Boger Committed by David Chase

cmd/internal: add shift opcodes with shift operands on ppc64x

Some original shift opcodes for ppc64x expected an operand to be
a mask instead of a shift count, preventing some valid shift counts
from being written.

This adds new opcodes for shifts where needed, using mnemonics that
match the ppc64 asm and allowing the assembler to accept the full set
of valid shift counts.

Fixes #15016

Change-Id: Id573489f852038d06def279c13fd0523736878a7
Reviewed-on: https://go-review.googlesource.com/31853
Run-TryBot: Lynn Boger <laboger@linux.vnet.ibm.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: 's avatarCarlos Eduardo Seo <cseo@linux.vnet.ibm.com>
Reviewed-by: 's avatarDavid Chase <drchase@google.com>
parent 5db7c6d3
...@@ -594,6 +594,15 @@ label1: ...@@ -594,6 +594,15 @@ label1:
// } // }
RLWMI R1, R2, 4, 5, R3 // RLWMI R1, R2, $201326592, R3 RLWMI R1, R2, 4, 5, R3 // RLWMI R1, R2, $201326592, R3
// opcodes added with constant shift counts, not masks
RLDICR $3, R2, $24, R4
RLDICL $1, R2, $61, R6
RLDIMI $7, R2, $52, R7
// //
// load/store multiple // load/store multiple
// //
......
...@@ -594,12 +594,18 @@ const ( ...@@ -594,12 +594,18 @@ const (
ARFID ARFID
ARLDMI ARLDMI
ARLDMICC ARLDMICC
ARLDIMI
ARLDIMICC
ARLDC ARLDC
ARLDCCC ARLDCCC
ARLDCR ARLDCR
ARLDCRCC ARLDCRCC
ARLDICR
ARLDICRCC
ARLDCL ARLDCL
ARLDCLCC ARLDCLCC
ARLDICL
ARLDICLCC
ASLBIA ASLBIA
ASLBIE ASLBIE
ASLBMFEE ASLBMFEE
......
...@@ -286,12 +286,18 @@ var Anames = []string{ ...@@ -286,12 +286,18 @@ var Anames = []string{
"RFID", "RFID",
"RLDMI", "RLDMI",
"RLDMICC", "RLDMICC",
"RLDIMI",
"RLDIMICC",
"RLDC", "RLDC",
"RLDCCC", "RLDCCC",
"RLDCR", "RLDCR",
"RLDCRCC", "RLDCRCC",
"RLDICR",
"RLDICRCC",
"RLDCL", "RLDCL",
"RLDCLCC", "RLDCLCC",
"RLDICL",
"RLDICLCC",
"SLBIA", "SLBIA",
"SLBIE", "SLBIE",
"SLBMFEE", "SLBMFEE",
......
...@@ -139,6 +139,8 @@ var optab = []Optab{ ...@@ -139,6 +139,8 @@ var optab = []Optab{
{ARLDC, C_SCON, C_REG, C_LCON, C_REG, 29, 4, 0}, {ARLDC, C_SCON, C_REG, C_LCON, C_REG, 29, 4, 0},
{ARLDCL, C_SCON, C_REG, C_LCON, C_REG, 29, 4, 0}, {ARLDCL, C_SCON, C_REG, C_LCON, C_REG, 29, 4, 0},
{ARLDCL, C_REG, C_REG, C_LCON, C_REG, 14, 4, 0}, {ARLDCL, C_REG, C_REG, C_LCON, C_REG, 14, 4, 0},
{ARLDICL, C_REG, C_REG, C_LCON, C_REG, 14, 4, 0},
{ARLDICL, C_SCON, C_REG, C_LCON, C_REG, 14, 4, 0},
{ARLDCL, C_REG, C_NONE, C_LCON, C_REG, 14, 4, 0}, {ARLDCL, C_REG, C_NONE, C_LCON, C_REG, 14, 4, 0},
{AFADD, C_FREG, C_NONE, C_NONE, C_FREG, 2, 4, 0}, {AFADD, C_FREG, C_NONE, C_NONE, C_FREG, 2, 4, 0},
{AFADD, C_FREG, C_FREG, C_NONE, C_FREG, 2, 4, 0}, {AFADD, C_FREG, C_FREG, C_NONE, C_FREG, 2, 4, 0},
...@@ -1484,6 +1486,8 @@ func buildop(ctxt *obj.Link) { ...@@ -1484,6 +1486,8 @@ func buildop(ctxt *obj.Link) {
case ARLDMI: case ARLDMI:
opset(ARLDMICC, r0) opset(ARLDMICC, r0)
opset(ARLDIMI, r0)
opset(ARLDIMICC, r0)
case ARLDC: case ARLDC:
opset(ARLDCCC, r0) opset(ARLDCCC, r0)
...@@ -1493,6 +1497,11 @@ func buildop(ctxt *obj.Link) { ...@@ -1493,6 +1497,11 @@ func buildop(ctxt *obj.Link) {
opset(ARLDCLCC, r0) opset(ARLDCLCC, r0)
opset(ARLDCRCC, r0) opset(ARLDCRCC, r0)
case ARLDICL:
opset(ARLDICLCC, r0)
opset(ARLDICR, r0)
opset(ARLDICRCC, r0)
case AFMOVD: case AFMOVD:
opset(AFMOVDCC, r0) opset(AFMOVDCC, r0)
opset(AFMOVDU, r0) opset(AFMOVDU, r0)
...@@ -2107,22 +2116,34 @@ func asmout(ctxt *obj.Link, p *obj.Prog, o *Optab, out []uint32) { ...@@ -2107,22 +2116,34 @@ func asmout(ctxt *obj.Link, p *obj.Prog, o *Optab, out []uint32) {
r = int(p.To.Reg) r = int(p.To.Reg)
} }
d := vregoff(ctxt, p.From3) d := vregoff(ctxt, p.From3)
var mask [2]uint8
maskgen64(ctxt, p, mask[:], uint64(d))
var a int var a int
switch p.As { switch p.As {
// These opcodes expect a mask operand that has to be converted into the
// appropriate operand. The way these were defined, not all valid masks are possible.
// Left here for compatibility in case they were used or generated.
case ARLDCL, ARLDCLCC: case ARLDCL, ARLDCLCC:
var mask [2]uint8
maskgen64(ctxt, p, mask[:], uint64(d))
a = int(mask[0]) /* MB */ a = int(mask[0]) /* MB */
if mask[1] != 63 { if mask[1] != 63 {
ctxt.Diag("invalid mask for rotate: %x (end != bit 63)\n%v", uint64(d), p) ctxt.Diag("invalid mask for rotate: %x (end != bit 63)\n%v", uint64(d), p)
} }
case ARLDCR, ARLDCRCC: case ARLDCR, ARLDCRCC:
var mask [2]uint8
maskgen64(ctxt, p, mask[:], uint64(d))
a = int(mask[1]) /* ME */ a = int(mask[1]) /* ME */
if mask[0] != 0 { if mask[0] != 0 {
ctxt.Diag("invalid mask for rotate: %x (start != 0)\n%v", uint64(d), p) ctxt.Diag("invalid mask for rotate: %x (start != 0)\n%v", uint64(d), p)
} }
// These opcodes use a shift count like the ppc64 asm, no mask conversion done
case ARLDICR, ARLDICRCC, ARLDICL, ARLDICLCC:
a = int(d)
default: default:
ctxt.Diag("unexpected op in rldc case\n%v", p) ctxt.Diag("unexpected op in rldc case\n%v", p)
a = 0 a = 0
...@@ -2403,18 +2424,32 @@ func asmout(ctxt *obj.Link, p *obj.Prog, o *Optab, out []uint32) { ...@@ -2403,18 +2424,32 @@ func asmout(ctxt *obj.Link, p *obj.Prog, o *Optab, out []uint32) {
v := regoff(ctxt, &p.From) v := regoff(ctxt, &p.From)
d := vregoff(ctxt, p.From3) d := vregoff(ctxt, p.From3)
var mask [2]uint8
maskgen64(ctxt, p, mask[:], uint64(d)) // Original opcodes had mask operands which had to be converted to a shift count as expected by
if int32(mask[1]) != (63 - v) { // the ppc64 asm.
ctxt.Diag("invalid mask for shift: %x (shift %d)\n%v", uint64(d), v, p) switch p.As {
} case ARLDMI, ARLDMICC:
o1 = AOP_RRR(opirr(ctxt, p.As), uint32(p.Reg), uint32(p.To.Reg), (uint32(v) & 0x1F)) var mask [2]uint8
o1 |= (uint32(mask[0]) & 31) << 6 maskgen64(ctxt, p, mask[:], uint64(d))
if v&0x20 != 0 { if int32(mask[1]) != (63 - v) {
o1 |= 1 << 1 ctxt.Diag("invalid mask for shift: %x (shift %d)\n%v", uint64(d), v, p)
} }
if mask[0]&0x20 != 0 { o1 = AOP_RRR(opirr(ctxt, p.As), uint32(p.Reg), uint32(p.To.Reg), (uint32(v) & 0x1F))
o1 |= 1 << 5 /* mb[5] is top bit */ o1 |= (uint32(mask[0]) & 31) << 6
if v&0x20 != 0 {
o1 |= 1 << 1
}
if mask[0]&0x20 != 0 {
o1 |= 1 << 5 /* mb[5] is top bit */
}
// Opcodes with shift count operands.
case ARLDIMI, ARLDIMICC:
o1 = AOP_RRR(opirr(ctxt, p.As), uint32(p.Reg), uint32(p.To.Reg), (uint32(v) & 0x1F))
o1 |= (uint32(d) & 31) << 6
if v&0x20 != 0 {
o1 |= 1 << 1
}
} }
case 31: /* dword */ case 31: /* dword */
...@@ -3340,6 +3375,15 @@ func oprrr(ctxt *obj.Link, a obj.As) uint32 { ...@@ -3340,6 +3375,15 @@ func oprrr(ctxt *obj.Link, a obj.As) uint32 {
case ARLDCR: case ARLDCR:
return OPVCC(30, 9, 0, 0) return OPVCC(30, 9, 0, 0)
case ARLDICL:
return OPVCC(30, 0, 0, 0)
case ARLDICLCC:
return OPVCC(30, 0, 0, 1)
case ARLDICR:
return OPVCC(30, 0, 0, 0) | 2<<1 // rldicr
case ARLDICRCC:
return OPVCC(30, 0, 0, 1) | 2<<1 // rldicr.
case ASYSCALL: case ASYSCALL:
return OPVCC(17, 1, 0, 0) return OPVCC(17, 1, 0, 0)
...@@ -3771,7 +3815,10 @@ func opirr(ctxt *obj.Link, a obj.As) uint32 { ...@@ -3771,7 +3815,10 @@ func opirr(ctxt *obj.Link, a obj.As) uint32 {
return OPVCC(30, 0, 0, 0) | 3<<2 /* rldimi */ return OPVCC(30, 0, 0, 0) | 3<<2 /* rldimi */
case ARLDMICC: case ARLDMICC:
return OPVCC(30, 0, 0, 1) | 3<<2 return OPVCC(30, 0, 0, 1) | 3<<2
case ARLDIMI:
return OPVCC(30, 0, 0, 0) | 3<<2 /* rldimi */
case ARLDIMICC:
return OPVCC(30, 0, 0, 1) | 3<<2
case ARLWNM: case ARLWNM:
return OPVCC(21, 0, 0, 0) /* rlwinm */ return OPVCC(21, 0, 0, 0) /* rlwinm */
case ARLWNMCC: case ARLWNMCC:
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment