Update lightrec 20220910 (#686)
[pcsx_rearmed.git] / deps / lightning / lib / jit_fallback.c
1 #if PROTO
2 #define fallback_save(r0)               _fallback_save(_jit, r0)
3 static void _fallback_save(jit_state_t*, jit_int32_t);
4 #define fallback_load(r0)               _fallback_load(_jit, r0)
5 static void _fallback_load(jit_state_t*, jit_int32_t);
6 #define fallback_save_regs(r0)          _fallback_save_regs(_jit, r0)
7 static void _fallback_save_regs(jit_state_t*, jit_int32_t);
8 #define fallback_load_regs(r0)          _fallback_load_regs(_jit, r0)
9 static void _fallback_load_regs(jit_state_t*, jit_int32_t);
10 #define fallback_calli(i0, i1)          _fallback_calli(_jit, i0, i1)
11 static void _fallback_calli(jit_state_t*, jit_word_t, jit_word_t);
12 #define fallback_casx(r0,r1,r2,r3,im)   _fallback_casx(_jit,r0,r1,r2,r3,im)
13 static void _fallback_casx(jit_state_t *, jit_int32_t, jit_int32_t,
14                            jit_int32_t, jit_int32_t, jit_word_t);
15 #endif
16
17 #if CODE
18 static void
19 _fallback_save(jit_state_t *_jit, jit_int32_t r0)
20 {
21     jit_int32_t         offset, regno, spec;
22     for (offset = 0; offset < JIT_R_NUM; offset++) {
23         spec =  _rvs[offset].spec;
24         regno = jit_regno(spec);
25         if (regno == r0) {
26             if (!(spec & jit_class_sav))
27                 stxi(_jitc->function->regoff[offset], rn(JIT_FP), regno);
28             break;
29         }
30     }
31 }
32
33 static void
34 _fallback_load(jit_state_t *_jit, jit_int32_t r0)
35 {
36     jit_int32_t         offset, regno, spec;
37     for (offset = 0; offset < JIT_R_NUM; offset++) {
38         spec =  _rvs[offset].spec;
39         regno = jit_regno(spec);
40         if (regno == r0) {
41             if (!(spec & jit_class_sav))
42                 ldxi(regno, rn(JIT_FP), _jitc->function->regoff[offset]);
43             break;
44         }
45     }
46 }
47
48 static void
49 _fallback_save_regs(jit_state_t *_jit, jit_int32_t r0)
50 {
51     jit_int32_t         offset, regno, spec;
52     for (offset = 0; offset < JIT_R_NUM; offset++) {
53         regno = JIT_R(offset);
54         spec =  _rvs[regno].spec;
55         if ((spec & jit_class_gpr) && regno == r0)
56             continue;
57         if (!(spec & jit_class_sav)) {
58             if (!_jitc->function->regoff[regno]) {
59                 _jitc->function->regoff[regno] =
60                     jit_allocai(sizeof(jit_word_t));
61                 _jitc->again = 1;
62             }
63             jit_regset_setbit(&_jitc->regsav, regno);
64             emit_stxi(_jitc->function->regoff[regno], JIT_FP, regno);
65         }
66     }
67     /* If knew for certain float registers are not used by
68      * pthread_mutex_lock and pthread_mutex_unlock, could skip this */
69     for (offset = 0; offset < JIT_F_NUM; offset++) {
70         regno = JIT_F(offset);
71         spec =  _rvs[regno].spec;
72         if (!(spec & jit_class_sav)) {
73             if (!_jitc->function->regoff[regno]) {
74                 _jitc->function->regoff[regno] =
75                     jit_allocai(sizeof(jit_word_t));
76                 _jitc->again = 1;
77             }
78             jit_regset_setbit(&_jitc->regsav, regno);
79             emit_stxi_d(_jitc->function->regoff[regno], JIT_FP, regno);
80         }
81     }
82 }
83
84 static void
85 _fallback_load_regs(jit_state_t *_jit, jit_int32_t r0)
86 {
87     jit_int32_t         offset, regno, spec;
88     for (offset = 0; offset < JIT_R_NUM; offset++) {
89         regno = JIT_R(offset);
90         spec =  _rvs[regno].spec;
91         if ((spec & jit_class_gpr) && regno == r0)
92             continue;
93         if (!(spec & jit_class_sav)) {
94             jit_regset_clrbit(&_jitc->regsav, regno);
95             emit_ldxi(regno, JIT_FP, _jitc->function->regoff[regno]);
96         }
97     }
98     /* If knew for certain float registers are not used by
99      * pthread_mutex_lock and pthread_mutex_unlock, could skip this */
100     for (offset = 0; offset < JIT_F_NUM; offset++) {
101         regno = JIT_F(offset);
102         spec =  _rvs[regno].spec;
103         if (!(spec & jit_class_sav)) {
104             jit_regset_clrbit(&_jitc->regsav, regno);
105             emit_ldxi_d(regno, JIT_FP, _jitc->function->regoff[regno]);
106         }
107     }
108 }
109
110 static void
111 _fallback_calli(jit_state_t *_jit, jit_word_t i0, jit_word_t i1)
112 {
113 #  if defined(__mips__)
114     movi(rn(_A0), i1);
115 #  elif defined(__arm__)
116     movi(rn(_R0), i1);
117 #  elif defined(__sparc__)
118     movi(rn(_O0), i1);
119 #  elif defined(__ia64__)
120     /* avoid confusion with pushargi patching */
121     if (i1 >= -2097152 && i1 <= 2097151)
122         MOVI(_jitc->rout, i1);
123     else
124         MOVL(_jitc->rout, i1);
125 #  elif defined(__hppa__)
126     movi(_R26_REGNO, i1);
127 #  elif defined(__s390__) || defined(__s390x__)
128     movi(rn(_R2), i1);
129 #  elif defined(__alpha__)
130     movi(rn(_A0), i1);
131 #  elif defined(__riscv__)
132     movi(rn(JIT_RA0), i1);
133 #  endif
134     calli(i0);
135 }
136
137 static void
138 _fallback_casx(jit_state_t *_jit, jit_int32_t r0, jit_int32_t r1,
139                jit_int32_t r2, jit_int32_t r3, jit_word_t i0)
140 {
141     jit_int32_t         r1_reg, iscasi;
142     jit_word_t          jump, done;
143     /* XXX only attempts to fallback cas for lightning jit code */
144     static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
145     if ((iscasi = r1 == _NOREG)) {
146         r1_reg = jit_get_reg(jit_class_gpr);
147         r1 = rn(r1_reg);
148         movi(r1, i0);
149     }
150     fallback_save_regs(r0);
151     fallback_calli((jit_word_t)pthread_mutex_lock, (jit_word_t)&mutex);
152     fallback_load(r1);
153     ldr(r0, r1);
154     fallback_load(r2);
155     eqr(r0, r0, r2);
156     fallback_save(r0);
157     jump = bnei(_jit->pc.w, r0, 1);
158     fallback_load(r3);
159 #  if __WORDSIZE == 32
160     str_i(r1, r3);
161 #  else
162     str_l(r1, r3);
163 #  endif
164     /* done: */
165     done = _jit->pc.w;
166     fallback_calli((jit_word_t)pthread_mutex_unlock, (jit_word_t)&mutex);
167     fallback_load(r0);
168 #  if defined(__arm__)
169     patch_at(arm_patch_jump, jump, done);
170 #  else
171     patch_at(jump, done);
172 #  endif
173     fallback_load_regs(r0);
174     if (iscasi)
175         jit_unget_reg(r1_reg);
176 }
177 #endif