mirror of
https://github.com/golang/go
synced 2024-11-19 21:54:40 -07:00
cmd/internal/obj/arm64: fix assemble msr/mrs bug
The arguments <pstatefield> is a struct that includes two elements, element reg is special register, elememt enc is pstate field values. The current code compares two different type values and get a incorrect result. The fix follows pstate field to create a systemreg struct, each system register has a vaule to use in instruction. Uncomment the msr/mrs cases. Fixes #21464 Change-Id: I1bb1587ec8548f3e4bd8d5be4d7127bd10d53186 Reviewed-on: https://go-review.googlesource.com/56030 Reviewed-by: Cherry Zhang <cherryyz@google.com> Run-TryBot: Cherry Zhang <cherryyz@google.com> TryBot-Result: Gobot Gobot <gobot@golang.org>
This commit is contained in:
parent
5f29a7a705
commit
556fb16bbd
10
src/cmd/asm/internal/asm/testdata/arm64enc.s
vendored
10
src/cmd/asm/internal/asm/testdata/arm64enc.s
vendored
@ -246,11 +246,11 @@ TEXT asmtest(SB),DUPOK|NOSPLIT,$-8
|
|||||||
MOVKW $(3905<<16), R21 // MOVKW $255918080, R21 // 35e8a172
|
MOVKW $(3905<<16), R21 // MOVKW $255918080, R21 // 35e8a172
|
||||||
MOVK $(3905<<32), R21 // MOVK $16771847290880, R21 // 35e8c1f2
|
MOVK $(3905<<32), R21 // MOVK $16771847290880, R21 // 35e8c1f2
|
||||||
MOVD $0, R5 // 050080d2
|
MOVD $0, R5 // 050080d2
|
||||||
// MRS $4567, R16 // f03a32d5
|
MSR $1, SPSel // bf4100d5
|
||||||
// MRS $32345, R6 // 26cb3fd5
|
MSR $9, DAIFSet // df4903d5
|
||||||
// MSR R25, $3452 // 99af11d5
|
MSR $6, DAIFClr // ff4603d5
|
||||||
// MSR R25, $16896 // 194018d5
|
MRS ELR_EL1, R8 // 284038d5
|
||||||
// MSR $6, DAIFClr // ff4603d5
|
MSR R16, ELR_EL1 // 304018d5
|
||||||
MSUBW R1, R1, R12, R5 // 8585011b
|
MSUBW R1, R1, R12, R5 // 8585011b
|
||||||
MSUB R19, R16, R26, R2 // 42c3139b
|
MSUB R19, R16, R26, R2 // 42c3139b
|
||||||
MULW R26, R5, R22 // b67c1a1b
|
MULW R26, R5, R22 // b67c1a1b
|
||||||
|
@ -607,14 +607,22 @@ var optab = []Optab{
|
|||||||
* valid pstate field values, and value to use in instruction
|
* valid pstate field values, and value to use in instruction
|
||||||
*/
|
*/
|
||||||
var pstatefield = []struct {
|
var pstatefield = []struct {
|
||||||
a uint32
|
reg int16
|
||||||
b uint32
|
enc uint32
|
||||||
}{
|
}{
|
||||||
{REG_SPSel, 0<<16 | 4<<12 | 5<<5},
|
{REG_SPSel, 0<<16 | 4<<12 | 5<<5},
|
||||||
{REG_DAIFSet, 3<<16 | 4<<12 | 6<<5},
|
{REG_DAIFSet, 3<<16 | 4<<12 | 6<<5},
|
||||||
{REG_DAIFClr, 3<<16 | 4<<12 | 7<<5},
|
{REG_DAIFClr, 3<<16 | 4<<12 | 7<<5},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// the System register values, and value to use in instruction
|
||||||
|
var systemreg = []struct {
|
||||||
|
reg int16
|
||||||
|
enc uint32
|
||||||
|
}{
|
||||||
|
{REG_ELR_EL1, 8<<16 | 4<<12 | 1<<5},
|
||||||
|
}
|
||||||
|
|
||||||
func span7(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) {
|
func span7(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) {
|
||||||
p := cursym.Func.Text
|
p := cursym.Func.Text
|
||||||
if p == nil || p.Link == nil { // handle external functions and ELF section symbols
|
if p == nil || p.Link == nil { // handle external functions and ELF section symbols
|
||||||
@ -2745,21 +2753,41 @@ func (c *ctxt7) asmout(p *obj.Prog, o *Optab, out []uint32) {
|
|||||||
case 35: /* mov SPR,R -> mrs */
|
case 35: /* mov SPR,R -> mrs */
|
||||||
o1 = c.oprrr(p, AMRS)
|
o1 = c.oprrr(p, AMRS)
|
||||||
|
|
||||||
v := int32(p.From.Offset)
|
v := uint32(0)
|
||||||
|
for i := 0; i < len(systemreg); i++ {
|
||||||
|
if systemreg[i].reg == p.From.Reg {
|
||||||
|
v = systemreg[i].enc
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if v == 0 {
|
||||||
|
c.ctxt.Diag("illegal system register:\n%v", p)
|
||||||
|
}
|
||||||
if (o1 & uint32(v&^(3<<19))) != 0 {
|
if (o1 & uint32(v&^(3<<19))) != 0 {
|
||||||
c.ctxt.Diag("MRS register value overlap\n%v", p)
|
c.ctxt.Diag("MRS register value overlap\n%v", p)
|
||||||
}
|
}
|
||||||
o1 |= uint32(v)
|
|
||||||
|
o1 |= v
|
||||||
o1 |= uint32(p.To.Reg & 31)
|
o1 |= uint32(p.To.Reg & 31)
|
||||||
|
|
||||||
case 36: /* mov R,SPR */
|
case 36: /* mov R,SPR */
|
||||||
o1 = c.oprrr(p, AMSR)
|
o1 = c.oprrr(p, AMSR)
|
||||||
|
|
||||||
v := int32(p.To.Offset)
|
v := uint32(0)
|
||||||
|
for i := 0; i < len(systemreg); i++ {
|
||||||
|
if systemreg[i].reg == p.To.Reg {
|
||||||
|
v = systemreg[i].enc
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if v == 0 {
|
||||||
|
c.ctxt.Diag("illegal system register:\n%v", p)
|
||||||
|
}
|
||||||
if (o1 & uint32(v&^(3<<19))) != 0 {
|
if (o1 & uint32(v&^(3<<19))) != 0 {
|
||||||
c.ctxt.Diag("MSR register value overlap\n%v", p)
|
c.ctxt.Diag("MSR register value overlap\n%v", p)
|
||||||
}
|
}
|
||||||
o1 |= uint32(v)
|
|
||||||
|
o1 |= v
|
||||||
o1 |= uint32(p.From.Reg & 31)
|
o1 |= uint32(p.From.Reg & 31)
|
||||||
|
|
||||||
case 37: /* mov $con,PSTATEfield -> MSR [immediate] */
|
case 37: /* mov $con,PSTATEfield -> MSR [immediate] */
|
||||||
@ -2768,10 +2796,10 @@ func (c *ctxt7) asmout(p *obj.Prog, o *Optab, out []uint32) {
|
|||||||
}
|
}
|
||||||
o1 = c.opirr(p, AMSR)
|
o1 = c.opirr(p, AMSR)
|
||||||
o1 |= uint32((p.From.Offset & 0xF) << 8) /* Crm */
|
o1 |= uint32((p.From.Offset & 0xF) << 8) /* Crm */
|
||||||
v := int32(0)
|
v := uint32(0)
|
||||||
for i := 0; i < len(pstatefield); i++ {
|
for i := 0; i < len(pstatefield); i++ {
|
||||||
if int64(pstatefield[i].a) == p.To.Offset {
|
if pstatefield[i].reg == p.To.Reg {
|
||||||
v = int32(pstatefield[i].b)
|
v = pstatefield[i].enc
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2779,7 +2807,7 @@ func (c *ctxt7) asmout(p *obj.Prog, o *Optab, out []uint32) {
|
|||||||
if v == 0 {
|
if v == 0 {
|
||||||
c.ctxt.Diag("illegal PSTATE field for immediate move\n%v", p)
|
c.ctxt.Diag("illegal PSTATE field for immediate move\n%v", p)
|
||||||
}
|
}
|
||||||
o1 |= uint32(v)
|
o1 |= v
|
||||||
|
|
||||||
case 38: /* clrex [$imm] */
|
case 38: /* clrex [$imm] */
|
||||||
o1 = c.opimm(p, p.As)
|
o1 = c.opimm(p, p.As)
|
||||||
|
Loading…
Reference in New Issue
Block a user