1
0
mirror of https://github.com/golang/go synced 2024-11-26 20:21:25 -07:00

cmd/internal/obj/arm64: add CONSTRAINED UNPREDICTABLE behavior check for some load/store

According to ARM64 manual, it is "constrained unpredictable behavior"
if the src and dst registers of some load/store instructions are same.
In order to completely prevent such unpredictable behavior, adding the
check for load/store instructions that are supported by the assembler
in the assembler.

Add test cases.

Update #25823

Change-Id: I64c14ad99ee543d778e7ec8ae6516a532293dbb3
Reviewed-on: https://go-review.googlesource.com/120660
Run-TryBot: Cherry Zhang <cherryyz@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Cherry Zhang <cherryyz@google.com>
This commit is contained in:
fanzha02 2018-06-15 10:20:00 +00:00 committed by Cherry Zhang
parent 9c2be4c22d
commit 7ab4b5586d
4 changed files with 95 additions and 12 deletions

View File

@ -654,6 +654,7 @@ again:
CALL foo(SB)
// LDP/STP
LDP (R0), (R0, R1) // 000440a9
LDP (R0), (R1, R2) // 010840a9
LDP 8(R0), (R1, R2) // 018840a9
LDP -8(R0), (R1, R2) // 01887fa9

View File

@ -188,8 +188,8 @@ TEXT asmtest(SB),DUPOK|NOSPLIT,$-8
MOVBU (R18)(R14<<0), R23 // 577a6e38
MOVBU (R2)(R8.SXTX), R19 // 53e86838
MOVBU (R27)(R23), R14 // MOVBU (R27)(R23*1), R14 // 6e6b7738
MOVHU.P 107(R13), R13 // adb54678
MOVHU.W 192(R2), R2 // 420c4c78
MOVHU.P 107(R14), R13 // cdb54678
MOVHU.W 192(R3), R2 // 620c4c78
MOVHU 6844(R4), R18 // 92787579
MOVHU (R5)(R25.SXTW), R15 // afc87978
//TODO MOVBW.P 77(R18), R11 // 4bd6c438

View File

@ -8,7 +8,19 @@ TEXT errors(SB),$0
ADDSW R7->32, R14, R13 // ERROR "shift amount out of range 0 to 31"
ADD R1.UXTB<<5, R2, R3 // ERROR "shift amount out of range 0 to 4"
ADDS R1.UXTX<<7, R2, R3 // ERROR "shift amount out of range 0 to 4"
AND $0x22220000, R2, RSP // ERROR "illegal combination"
ANDS $0x22220000, R2, RSP // ERROR "illegal combination"
ADD R1, R2, R3, R4 // ERROR "illegal combination"
BICW R7@>33, R5, R16 // ERROR "shift amount out of range 0 to 31"
CINC CS, R2, R3, R4 // ERROR "illegal combination"
CSEL LT, R1, R2 // ERROR "illegal combination"
LDP.P 8(R2), (R2, R3) // ERROR "constrained unpredictable behavior"
LDP.W 8(R3), (R2, R3) // ERROR "constrained unpredictable behavior"
LDP (R1), (R2, R2) // ERROR "constrained unpredictable behavior"
LDP (R0), (F0, F1) // ERROR "invalid register pair"
LDP (R0), (R3, ZR) // ERROR "invalid register pair"
LDXPW (RSP), (R2, R2) // ERROR "constrained unpredictable behavior"
LDAXPW (R5), (R2, R2) // ERROR "constrained unpredictable behavior"
MOVD.P 300(R2), R3 // ERROR "offset out of range [-255,254]"
MOVD.P R3, 344(R2) // ERROR "offset out of range [-255,254]"
MOVD (R3)(R7.SXTX<<2), R8 // ERROR "invalid index shift amount"
@ -16,6 +28,17 @@ TEXT errors(SB),$0
MOVWU (R5)(R4<<1), R10 // ERROR "invalid index shift amount"
MOVB (R5)(R4.SXTW<<5), R10 // ERROR "invalid index shift amount"
MOVH R5, (R6)(R2<<3) // ERROR "invalid index shift amount"
MADD R1, R2, R3 // ERROR "illegal combination"
MOVD.P R1, 8(R1) // ERROR "constrained unpredictable behavior"
MOVD.W 16(R2), R2 // ERROR "constrained unpredictable behavior"
STP (F2, F3), (R0) // ERROR "invalid register pair"
STP.W (R1, R2), 8(R1) // ERROR "constrained unpredictable behavior"
STP.P (R1, R2), 8(R2) // ERROR "constrained unpredictable behavior"
STLXP (R6, R11), (RSP), R6 // ERROR "constrained unpredictable behavior"
STXP (R6, R11), (R2), R2 // ERROR "constrained unpredictable behavior"
STLXR R3, (RSP), R3 // ERROR "constrained unpredictable behavior"
STXR R3, (R4), R4 // ERROR "constrained unpredictable behavior"
STLXRB R2, (R5), R5 // ERROR "constrained unpredictable behavior"
VLD1 (R8)(R13), [V2.B16] // ERROR "illegal combination"
VLD1 8(R9), [V2.B16] // ERROR "illegal combination"
VST1 [V1.B16], (R8)(R13) // ERROR "illegal combination"
@ -83,15 +106,8 @@ TEXT errors(SB),$0
VST1.P [V1.B16], (R8)(R9<<1) // ERROR "invalid extended register"
VREV64 V1.H4, V2.H8 // ERROR "invalid arrangement"
VREV64 V1.D1, V2.D1 // ERROR "invalid arrangement"
ADD R1, R2, R3, R4 // ERROR "illegal combination"
MADD R1, R2, R3 // ERROR "illegal combination"
CINC CS, R2, R3, R4 // ERROR "illegal combination"
CSEL LT, R1, R2 // ERROR "illegal combination"
AND $0x22220000, R2, RSP // ERROR "illegal combination"
ANDS $0x22220000, R2, RSP // ERROR "illegal combination"
LDP (R0), (F0, F1) // ERROR "invalid register pair"
LDP (R0), (R3, ZR) // ERROR "invalid register pair"
STP (F2, F3), (R0) // ERROR "invalid register pair"
FLDPD (R0), (R1, R2) // ERROR "invalid register pair"
FLDPD (R1), (F2, F2) // ERROR "constrained unpredictable behavior"
FLDPS (R2), (F3, F3) // ERROR "constrained unpredictable behavior"
FSTPD (R1, R2), (R0) // ERROR "invalid register pair"
RET

View File

@ -1085,6 +1085,23 @@ func (c *ctxt7) regoff(a *obj.Addr) uint32 {
return uint32(c.instoffset)
}
func isSTLXRop(op obj.As) bool {
switch op {
case ASTLXR, ASTLXRW, ASTLXRB, ASTLXRH,
ASTXR, ASTXRW, ASTXRB, ASTXRH:
return true
}
return false
}
func isSTXPop(op obj.As) bool {
switch op {
case ASTXP, ASTLXP, ASTXPW, ASTLXPW:
return true
}
return false
}
func isRegShiftOrExt(a *obj.Addr) bool {
return (a.Index-obj.RBaseARM64)&REG_EXT != 0 || (a.Index-obj.RBaseARM64)&REG_LSL != 0
}
@ -2502,6 +2519,17 @@ func SYSARG4(op1 int, Cn int, Cm int, op2 int) int {
return SYSARG5(0, op1, Cn, Cm, op2)
}
// checkUnpredictable checks if the sourse and transfer registers are the same register.
// ARM64 manual says it is "constrained unpredictable" if the src and dst registers of STP/LDP are same.
func (c *ctxt7) checkUnpredictable(p *obj.Prog, isload bool, wback bool, rn int16, rt1 int16, rt2 int16) {
if wback && rn != REGSP && (rn == rt1 || rn == rt2) {
c.ctxt.Diag("constrained unpredictable behavior: %v", p)
}
if isload && rt1 == rt2 {
c.ctxt.Diag("constrained unpredictable behavior: %v", p)
}
}
/* checkindex checks if index >= 0 && index <= maxindex */
func (c *ctxt7) checkindex(p *obj.Prog, index, maxindex int) {
if index < 0 || index > maxindex {
@ -2940,6 +2968,10 @@ func (c *ctxt7) asmout(p *obj.Prog, o *Optab, out []uint32) {
}
case 22: /* movT (R)O!,R; movT O(R)!, R -> ldrT */
if p.As != AFMOVS && p.As != AFMOVD && p.From.Reg != REGSP && p.From.Reg == p.To.Reg {
c.ctxt.Diag("constrained unpredictable behavior: %v", p)
}
v := int32(p.From.Offset)
if v < -256 || v > 255 {
@ -2954,6 +2986,10 @@ func (c *ctxt7) asmout(p *obj.Prog, o *Optab, out []uint32) {
o1 |= ((uint32(v) & 0x1FF) << 12) | (uint32(p.From.Reg&31) << 5) | uint32(p.To.Reg&31)
case 23: /* movT R,(R)O!; movT O(R)!, R -> strT */
if p.As != AFMOVS && p.As != AFMOVD && p.To.Reg != REGSP && p.From.Reg == p.To.Reg {
c.ctxt.Diag("constrained unpredictable behavior: %v", p)
}
v := int32(p.To.Offset)
if v < -256 || v > 255 {
@ -3551,6 +3587,9 @@ func (c *ctxt7) asmout(p *obj.Prog, o *Optab, out []uint32) {
o1 |= 0x1F << 16
o1 |= uint32(p.From.Reg&31) << 5
if p.As == ALDXP || p.As == ALDXPW || p.As == ALDAXP || p.As == ALDAXPW {
if int(p.To.Reg) == int(p.To.Offset) {
c.ctxt.Diag("constrained unpredictable behavior: %v", p)
}
o1 |= uint32(p.To.Offset&31) << 10
} else {
o1 |= 0x1F << 10
@ -3558,6 +3597,19 @@ func (c *ctxt7) asmout(p *obj.Prog, o *Optab, out []uint32) {
o1 |= uint32(p.To.Reg & 31)
case 59: /* stxr/stlxr/stxp/stlxp */
s := p.RegTo2
n := p.To.Reg
t := p.From.Reg
if isSTLXRop(p.As) {
if s == t || (s == n && n != REGSP) {
c.ctxt.Diag("constrained unpredictable behavior: %v", p)
}
} else if isSTXPop(p.As) {
t2 := int16(p.From.Offset)
if (s == t || s == t2) || (s == n && n != REGSP) {
c.ctxt.Diag("constrained unpredictable behavior: %v", p)
}
}
o1 = c.opstore(p, p.As)
if p.RegTo2 != obj.REG_NONE {
@ -3565,7 +3617,7 @@ func (c *ctxt7) asmout(p *obj.Prog, o *Optab, out []uint32) {
} else {
o1 |= 0x1F << 16
}
if p.As == ASTXP || p.As == ASTXPW || p.As == ASTLXP || p.As == ASTLXPW {
if isSTXPop(p.As) {
o1 |= uint32(p.From.Offset&31) << 10
}
o1 |= uint32(p.To.Reg&31)<<5 | uint32(p.From.Reg&31)
@ -6177,6 +6229,20 @@ func (c *ctxt7) opextr(p *obj.Prog, a obj.As, v int32, rn int, rm int, rt int) u
/* genrate instruction encoding for LDP/LDPW/LDPSW/STP/STPW */
func (c *ctxt7) opldpstp(p *obj.Prog, o *Optab, vo int32, rbase, rl, rh, ldp uint32) uint32 {
wback := false
if o.scond == C_XPOST || o.scond == C_XPRE {
wback = true
}
switch p.As {
case ALDP, ALDPW, ALDPSW:
c.checkUnpredictable(p, true, wback, p.From.Reg, p.To.Reg, int16(p.To.Offset))
case ASTP, ASTPW:
if wback == true {
c.checkUnpredictable(p, false, true, p.To.Reg, p.From.Reg, int16(p.From.Offset))
}
case AFLDPD, AFLDPS:
c.checkUnpredictable(p, true, false, p.From.Reg, p.To.Reg, int16(p.To.Offset))
}
var ret uint32
// check offset
switch p.As {