1
0
mirror of https://github.com/golang/go synced 2024-11-19 22:04:44 -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:
fanzha02 2017-06-13 11:07:34 +00:00 committed by Cherry Zhang
parent 5f29a7a705
commit 556fb16bbd
2 changed files with 43 additions and 15 deletions

View File

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

View File

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