# define jit_armv5_p() (jit_cpu.version >= 5)
# define jit_armv5e_p() (jit_cpu.version > 5 || (jit_cpu.version == 5 && jit_cpu.extend))
# define jit_armv6_p() (jit_cpu.version >= 6)
+# define jit_armv7_p() (jit_cpu.version >= 7)
# define jit_armv7r_p() 0
# define stack_framesize 48
extern int __aeabi_idivmod(int, int);
# define ARM_XTR8 0x00000400 /* ?xt? rotate 8 bits */
# define ARM_XTR16 0x00000800 /* ?xt? rotate 16 bits */
# define ARM_XTR24 0x00000c00 /* ?xt? rotate 24 bits */
+# define ARM_LDREX 0x01900090
+# define THUMB2_LDREX 0xe8500000
+# define ARM_STREX 0x01800090
+# define THUMB2_STREX 0xe8400000
/* << ARMv6* */
+/* >> ARMv7 */
+# define ARM_DMB 0xf57ff050
+# define THUMB2_DMB 0xf3bf8f50
+# define DMB_SY 0xf
+# define DMB_ST 0xe
+# define DMB_ISH 0xb
+# define DMB_ISHST 0xa
+# define DMB_NSH 0x7
+# define DMB_NSHT 0x6
+# define DMB_OSH 0x3
+# define DMB_OSHST 0x2
+/* << ARMv7 */
# define ARM_SHIFT 0x01a00000
# define ARM_R 0x00000010 /* register shift */
# define ARM_LSL 0x00000000
static void _tpp(jit_state_t*,int,int);
# define torl(o,rn,im) _torl(_jit,o,rn,im)
static void _torl(jit_state_t*,int,int,int) maybe_unused;
+# define DMB(im) dmb(im)
+# define T2_DMB(im) tdmb(im)
+# define dmb(im) _dmb(_jit, im)
+static void _dmb(jit_state_t *_jit, int im);
+# define tdmb(im) _tdmb(_jit, im)
+static void _tdmb(jit_state_t *_jit, int im);
# define CC_MOV(cc,rd,rm) corrr(cc,ARM_MOV,0,rd,rm)
# define MOV(rd,rm) CC_MOV(ARM_CC_AL,rd,rm)
# define T1_MOV(rd,rm) is(THUMB_MOV|((_u4(rd)&8)<<4)|(_u4(rm)<<3)|(rd&7))
# define CC_LDRDIN(cc,rt,rn,im) corri8(cc,ARM_LDRDI,rn,rt,im)
# define LDRDIN(rt,rn,im) CC_LDRDIN(ARM_CC_AL,rt,rn,im)
# define T2_LDRDIN(rt,rt2,rn,im) torrri8(THUMB2_LDRDI,rn,rt,rt2,im)
+# define CC_LDREX(cc,rt,rn) corrrr(cc,ARM_LDREX,rn,rt,0xf,0xf)
+# define LDREX(rt,rn) CC_LDREX(ARM_CC_AL,rt,rn)
+# define T2_LDREX(rt,rn,im) torrri8(THUMB2_LDREX,rn,rt,0xf,im)
# define CC_STRB(cc,rt,rn,rm) corrr(cc,ARM_STRB|ARM_P,rn,rt,rm)
# define STRB(rt,rn,rm) CC_STRB(ARM_CC_AL,rt,rn,rm)
# define T1_STRB(rt,rn,rm) is(THUMB_STRB|(_u3(rm)<<6)|(_u3(rn)<<3)|_u3(rt))
# define CC_STRDIN(cc,rt,rn,im) corri8(cc,ARM_STRDI,rn,rt,im)
# define STRDIN(rt,rn,im) CC_STRDIN(ARM_CC_AL,rt,rn,im)
# define T2_STRDIN(rt,rt2,rn,im) torrri8(THUMB2_STRDI,rn,rt,rt2,im)
+# define CC_STREX(cc,rd,rt,rn) corrrr(cc,ARM_STREX,rn,rd,0xf,rt)
+# define STREX(rd,rt,rn) CC_STREX(ARM_CC_AL,rd,rt,rn)
+# define T2_STREX(rd,rt,rn,im) torrri8(THUMB2_STREX,rn,rt,rd,im)
# define CC_LDMIA(cc,rn,im) corl(cc,ARM_M|ARM_M_L|ARM_M_I,rn,im)
# define LDMIA(rn,im) CC_LDMIA(ARM_CC_AL,rn,im)
# define CC_LDM(cc,rn,im) CC_LDMIA(cc,rn,im)
static void _movnr(jit_state_t*,jit_int32_t,jit_int32_t,jit_int32_t);
# define movzr(r0,r1,r2) _movzr(_jit,r0,r1,r2)
static void _movzr(jit_state_t*,jit_int32_t,jit_int32_t,jit_int32_t);
+# define casx(r0, r1, r2, r3, i0) _casx(_jit, r0, r1, r2, r3, i0)
+static void _casx(jit_state_t *_jit,jit_int32_t,jit_int32_t,
+ jit_int32_t,jit_int32_t,jit_word_t);
+#define casr(r0, r1, r2, r3) casx(r0, r1, r2, r3, 0)
+#define casi(r0, i0, r1, r2) casx(r0, _NOREG, r1, r2, i0)
# define comr(r0,r1) _comr(_jit,r0,r1)
static void _comr(jit_state_t*,jit_int32_t,jit_int32_t);
# define negr(r0,r1) _negr(_jit,r0,r1)
iss(thumb.s[0], thumb.s[1]);
}
+static void
+_dmb(jit_state_t *_jit, int im)
+{
+ assert(!(im & 0xfffffff0));
+ ii(ARM_DMB|im);
+}
+
+static void
+_tdmb(jit_state_t *_jit, int im)
+{
+ jit_thumb_t thumb;
+ assert(!(im & 0xfffffff0));
+ thumb.i = THUMB2_DMB | im;
+ iss(thumb.s[0], thumb.s[1]);
+}
+
static void
_nop(jit_state_t *_jit, jit_int32_t i0)
{
_movznr(_jit, ARM_CC_EQ, r0, r1, r2);
}
+static void
+_casx(jit_state_t *_jit, jit_int32_t r0, jit_int32_t r1,
+ jit_int32_t r2, jit_int32_t r3, jit_word_t i0)
+{
+ jit_int32_t r1_reg, iscasi;
+ jit_word_t retry, done, jump0, jump1;
+ if (!jit_armv7_p())
+ fallback_casx(r0, r1, r2, r3, i0);
+ else {
+ if ((iscasi = (r1 == _NOREG))) {
+ r1_reg = jit_get_reg(jit_class_gpr);
+ r1 = rn(r1_reg);
+ movi(r1, i0);
+ }
+ if (jit_thumb_p()) {
+ T2_DMB(DMB_ISH);
+ /* retry: */
+ retry = _jit->pc.w;
+ T2_LDREX(r0, r1, 0);
+ jump0 = bner(_jit->pc.w, r0, r2); /* bne done r0 r2 */
+ T2_STREX(r0, r3, r1, 0);
+ jump1 = bnei(_jit->pc.w, r0, 0); /* bnei retry r0 0 */
+ /* done: */
+ done = _jit->pc.w;
+ /* r0 = 0 if memory updated, 1 otherwise */
+ xori(r0, r0, 1);
+ T2_DMB(DMB_ISH);
+ }
+ else {
+ DMB(DMB_ISH);
+ /* retry: */
+ retry = _jit->pc.w;
+ LDREX(r0, r1);
+ jump0 = bner(_jit->pc.w, r0, r2); /* bne done r0 r2 */
+ STREX(r0, r3, r1);
+ jump1 = bnei(_jit->pc.w, r0, 0); /* bnei retry r0 0 */
+ /* done: */
+ done = _jit->pc.w;
+ /* r0 = 0 if memory updated, 1 otherwise */
+ xori(r0, r0, 1);
+ DMB(DMB_ISH);
+ }
+ patch_at(arm_patch_jump, jump0, done);
+ patch_at(arm_patch_jump, jump1, retry);
+ if (iscasi)
+ jit_unget_reg(r1_reg);
+ }
+}
+
static void
_comr(jit_state_t *_jit, jit_int32_t r0, jit_int32_t r1)
{