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"
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"
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
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
}
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 {
}
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 {
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 {
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
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 {
} 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)
/* 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 {