From: fanzha02 Date: Fri, 15 Jun 2018 10:20:00 +0000 (+0000) Subject: cmd/internal/obj/arm64: add CONSTRAINED UNPREDICTABLE behavior check for some load... X-Git-Tag: go1.12beta1~1144 X-Git-Url: http://www.git.cypherpunks.su/?a=commitdiff_plain;h=7ab4b5586d37513bfa48f769773007ff8e9b732d;p=gostls13.git 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 TryBot-Result: Gobot Gobot Reviewed-by: Cherry Zhang --- diff --git a/src/cmd/asm/internal/asm/testdata/arm64.s b/src/cmd/asm/internal/asm/testdata/arm64.s index 361b7a45c0..9e2e2b1dc5 100644 --- a/src/cmd/asm/internal/asm/testdata/arm64.s +++ b/src/cmd/asm/internal/asm/testdata/arm64.s @@ -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 diff --git a/src/cmd/asm/internal/asm/testdata/arm64enc.s b/src/cmd/asm/internal/asm/testdata/arm64enc.s index ee4673c1ae..432ab74493 100644 --- a/src/cmd/asm/internal/asm/testdata/arm64enc.s +++ b/src/cmd/asm/internal/asm/testdata/arm64enc.s @@ -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 diff --git a/src/cmd/asm/internal/asm/testdata/arm64error.s b/src/cmd/asm/internal/asm/testdata/arm64error.s index b2ec0cc425..bbdce479c5 100644 --- a/src/cmd/asm/internal/asm/testdata/arm64error.s +++ b/src/cmd/asm/internal/asm/testdata/arm64error.s @@ -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 diff --git a/src/cmd/internal/obj/arm64/asm7.go b/src/cmd/internal/obj/arm64/asm7.go index 7507976257..09ffc5dccf 100644 --- a/src/cmd/internal/obj/arm64/asm7.go +++ b/src/cmd/internal/obj/arm64/asm7.go @@ -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 {