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:
parent
9c2be4c22d
commit
7ab4b5586d
1
src/cmd/asm/internal/asm/testdata/arm64.s
vendored
1
src/cmd/asm/internal/asm/testdata/arm64.s
vendored
@ -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
|
||||
|
4
src/cmd/asm/internal/asm/testdata/arm64enc.s
vendored
4
src/cmd/asm/internal/asm/testdata/arm64enc.s
vendored
@ -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
|
||||
|
34
src/cmd/asm/internal/asm/testdata/arm64error.s
vendored
34
src/cmd/asm/internal/asm/testdata/arm64error.s
vendored
@ -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
|
||||
|
@ -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)®_EXT != 0 || (a.Index-obj.RBaseARM64)®_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 {
|
||||
|
Loading…
Reference in New Issue
Block a user