Update lightrec 20220910 (#686)
[pcsx_rearmed.git] / deps / lightning / lib / jit_arm-cpu.c
index 14ba36b..91bb17c 100644 (file)
@@ -36,6 +36,7 @@
 #  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);
@@ -179,7 +180,23 @@ extern unsigned    __aeabi_uidivmod(unsigned, unsigned);
 #  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
@@ -399,6 +416,12 @@ static void _tcit(jit_state_t*,unsigned int,int);
 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))
@@ -718,6 +741,9 @@ static void _torl(jit_state_t*,int,int,int) maybe_unused;
 #  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))
@@ -771,6 +797,9 @@ static void _torl(jit_state_t*,int,int,int) maybe_unused;
 #  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)
@@ -847,6 +876,11 @@ static jit_word_t _movi_p(jit_state_t*,jit_int32_t,jit_word_t);
 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)
@@ -1508,6 +1542,22 @@ _torl(jit_state_t *_jit, int o, int rn, int im)
     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)
 {
@@ -1610,6 +1660,55 @@ _movzr(jit_state_t *_jit, jit_int32_t r0, jit_int32_t r1, jit_int32_t r2)
     _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)
 {