Files
2024-01-14 08:20:53 -07:00

333 lines
9.7 KiB
C

#if PROTO
#define fallback_save(r0) _fallback_save(_jit, r0)
static void _fallback_save(jit_state_t*, jit_int32_t);
#define fallback_load(r0) _fallback_load(_jit, r0)
static void _fallback_load(jit_state_t*, jit_int32_t);
#define fallback_save_regs(r0) _fallback_save_regs(_jit, r0)
static void _fallback_save_regs(jit_state_t*, jit_int32_t);
#define fallback_load_regs(r0) _fallback_load_regs(_jit, r0)
static void _fallback_load_regs(jit_state_t*, jit_int32_t);
#define fallback_calli(i0, i1) _fallback_calli(_jit, i0, i1)
static void _fallback_calli(jit_state_t*, jit_word_t, jit_word_t);
#define fallback_casx(r0,r1,r2,r3,im) _fallback_casx(_jit,r0,r1,r2,r3,im)
static void _fallback_casx(jit_state_t *, jit_int32_t, jit_int32_t,
jit_int32_t, jit_int32_t, jit_word_t);
#define fallback_clo(r0,r1) _fallback_clo(_jit,r0,r1)
static void _fallback_clo(jit_state_t*, jit_int32_t, jit_int32_t);
#define fallback_clz(r0,r1) _fallback_clz(_jit,r0,r1)
static void _fallback_clz(jit_state_t*, jit_int32_t, jit_int32_t);
#define fallback_cto(r0,r1) _fallback_cto(_jit,r0,r1)
static void _fallback_cto(jit_state_t*, jit_int32_t, jit_int32_t);
#define fallback_ctz(r0,r1) _fallback_ctz(_jit,r0,r1)
static void _fallback_ctz(jit_state_t*, jit_int32_t, jit_int32_t);
# if defined(__ia64__)
# define fallback_patch_jmpi(inst,lbl) \
do { \
sync(); \
patch_at(jit_code_jmpi, inst, lbl); \
} while (0)
# else
# define fallback_patch_jmpi(inst,lbl) fallback_patch_at(inst,lbl)
# endif
# if defined(__arm__)
# define fallback_patch_at(inst,lbl) patch_at(arm_patch_jump,inst,lbl)
# elif defined(__ia64__)
# define fallback_patch_at(inst,lbl) \
do { \
sync(); \
patch_at(jit_code_bnei, inst, lbl); \
} while (0);
# else
# define fallback_patch_at(inst,lbl) patch_at(inst,lbl)
# endif
# if defined(__mips__)
# define fallback_jmpi(i0) jmpi(i0,NULL,1)
# elif defined(__arm__)
# define fallback_jmpi(i0) jmpi_p(i0,1)
# elif defined(__s390__) || defined(__s390x__)
# define fallback_jmpi(i0) jmpi(i0,1)
# else
# define fallback_jmpi(i0) jmpi(i0)
# endif
# if defined(__mips__)
# define fallback_bnei(i0,r0,i1) bnei(i0,r0,i1,NULL)
# elif defined(__s390__) || defined(__s390x__)
# define fallback_bnei(i0,r0,i1) bnei_p(i0,r0,i1)
# else
# define fallback_bnei(i0,r0,i1) bnei(i0,r0,i1)
# endif
# if defined(__s390__) || defined(__s390x__)
# define fallback_bmsr(i0,r0,r1) bmsr_p(i0,r0,r1)
# else
# define fallback_bmsr(i0,r0,r1) bmsr(i0,r0,r1)
# endif
#endif
#if CODE
static void
_fallback_save(jit_state_t *_jit, jit_int32_t r0)
{
jit_int32_t offset, regno, spec;
for (offset = 0; offset < JIT_R_NUM; offset++) {
spec = _rvs[offset].spec;
regno = jit_regno(spec);
if (regno == r0) {
if (!(spec & jit_class_sav))
stxi(_jitc->function->regoff[JIT_R(offset)], rn(JIT_FP), regno);
break;
}
}
}
static void
_fallback_load(jit_state_t *_jit, jit_int32_t r0)
{
jit_int32_t offset, regno, spec;
for (offset = 0; offset < JIT_R_NUM; offset++) {
spec = _rvs[offset].spec;
regno = jit_regno(spec);
if (regno == r0) {
if (!(spec & jit_class_sav))
ldxi(regno, rn(JIT_FP), _jitc->function->regoff[JIT_R(offset)]);
break;
}
}
}
static void
_fallback_save_regs(jit_state_t *_jit, jit_int32_t r0)
{
jit_int32_t regno, spec;
for (regno = 0; regno < _jitc->reglen; regno++) {
spec = _rvs[regno].spec;
if ((jit_regset_tstbit(&_jitc->regarg, regno) ||
jit_regset_tstbit(&_jitc->reglive, regno)) &&
!(spec & jit_class_sav)) {
if (!_jitc->function->regoff[regno]) {
_jitc->function->regoff[regno] =
jit_allocai(spec & jit_class_gpr ?
sizeof(jit_word_t) : sizeof(jit_float64_t));
_jitc->again = 1;
}
if ((spec & jit_class_gpr) && rn(regno) == r0)
continue;
jit_regset_setbit(&_jitc->regsav, regno);
if (spec & jit_class_gpr)
emit_stxi(_jitc->function->regoff[regno], JIT_FP, regno);
else
emit_stxi_d(_jitc->function->regoff[regno], JIT_FP, regno);
}
}
}
static void
_fallback_load_regs(jit_state_t *_jit, jit_int32_t r0)
{
jit_int32_t regno, spec;
for (regno = 0; regno < _jitc->reglen; regno++) {
spec = _rvs[regno].spec;
if ((jit_regset_tstbit(&_jitc->regarg, regno) ||
jit_regset_tstbit(&_jitc->reglive, regno)) &&
!(spec & jit_class_sav)) {
if ((spec & jit_class_gpr) && rn(regno) == r0)
continue;
jit_regset_setbit(&_jitc->regsav, regno);
if (spec & jit_class_gpr)
emit_ldxi(regno, JIT_FP, _jitc->function->regoff[regno]);
else
emit_ldxi_d(regno, JIT_FP, _jitc->function->regoff[regno]);
}
}
}
static void
_fallback_calli(jit_state_t *_jit, jit_word_t i0, jit_word_t i1)
{
# if defined(__arm__)
movi(rn(_R0), i1);
# elif defined(__hppa__)
movi(_R26_REGNO, i1);
# endif
# if defined(__arm__)
calli(i0, jit_exchange_p());
# elif defined(__mips__)
calli(i0, NULL, 0);
# elif defined(__powerpc__) && _CALL_SYSV
calli(i0, 0);
# elif defined(__s390__) || defined(__s390x__)
calli(i0, 0);
# else
calli(i0);
# endif
}
static void
_fallback_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 jump, done;
/* XXX only attempts to fallback cas for lightning jit code */
static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
if ((iscasi = r1 == _NOREG)) {
r1_reg = jit_get_reg(jit_class_gpr|jit_class_sav);
r1 = rn(r1_reg);
movi(r1, i0);
}
fallback_save_regs(r0);
fallback_calli((jit_word_t)pthread_mutex_lock, (jit_word_t)&mutex);
fallback_load(r1);
ldr(r0, r1);
fallback_load(r2);
eqr(r0, r0, r2);
fallback_save(r0);
jump = fallback_bnei(_jit->pc.w, r0, 1);
fallback_load(r3);
# if __WORDSIZE == 32
str_i(r1, r3);
# else
str_l(r1, r3);
# endif
/* done: */
done = _jit->pc.w;
fallback_calli((jit_word_t)pthread_mutex_unlock, (jit_word_t)&mutex);
fallback_load(r0);
fallback_patch_at(jump, done);
fallback_load_regs(r0);
if (iscasi)
jit_unget_reg(r1_reg);
}
static void
_fallback_clo(jit_state_t *_jit, jit_int32_t r0, jit_int32_t r1)
{
jit_word_t clz, done;
comr(r0, r1);
clz = fallback_bnei(_jit->pc.w, r0, 0);
movi(r0, __WORDSIZE);
done = fallback_jmpi(_jit->pc.w);
fallback_patch_at(clz, _jit->pc.w);
fallback_clz(r0, r0);
fallback_patch_jmpi(done, _jit->pc.w);
}
static void
_fallback_clz(jit_state_t *_jit, jit_int32_t r0, jit_int32_t r1)
{
jit_int32_t r1_reg, r2, r2_reg;
jit_word_t clz, l32, l16, l8, l4, l2, l1;
l32 = fallback_bnei(_jit->pc.w, r1, 0);
movi(r0, __WORDSIZE);
clz = fallback_jmpi(_jit->pc.w);
fallback_patch_at(l32, _jit->pc.w);
r2_reg = jit_get_reg(jit_class_gpr);
r2 = rn(r2_reg);
r1_reg = jit_get_reg(jit_class_gpr);
movr(rn(r1_reg), r1);
r1 = rn(r1_reg);
movi(r0, 0);
# if __WORDSIZE == 64
movi(r2, 0xffffffff00000000UL);
l32 = fallback_bmsr(_jit->pc.w, r1, r2);
lshi(r1, r1, 32);
addi(r0, r0, 32);
fallback_patch_at(l32, _jit->pc.w);
lshi(r2, r2, 16);
# else
movi(r2, 0xffff0000UL);
# endif
l16 = fallback_bmsr(_jit->pc.w, r1, r2);
lshi(r1, r1, 16);
addi(r0, r0, 16);
fallback_patch_at(l16, _jit->pc.w);
lshi(r2, r2, 8);
l8 = fallback_bmsr(_jit->pc.w, r1, r2);
lshi(r1, r1, 8);
addi(r0, r0, 8);
fallback_patch_at(l8, _jit->pc.w);
lshi(r2, r2, 4);
l4 = fallback_bmsr(_jit->pc.w, r1, r2);
lshi(r1, r1, 4);
addi(r0, r0, 4);
fallback_patch_at(l4, _jit->pc.w);
lshi(r2, r2, 2);
l2 = fallback_bmsr(_jit->pc.w, r1, r2);
lshi(r1, r1, 2);
addi(r0, r0, 2);
fallback_patch_at(l2, _jit->pc.w);
lshi(r2, r2, 1);
l1 = fallback_bmsr(_jit->pc.w, r1, r2);
addi(r0, r0, 1);
fallback_patch_at(l1, _jit->pc.w);
fallback_patch_jmpi(clz, _jit->pc.w);
jit_unget_reg(r2_reg);
jit_unget_reg(r1_reg);
}
static void
_fallback_cto(jit_state_t *_jit, jit_int32_t r0, jit_int32_t r1)
{
jit_word_t ctz, done;
comr(r0, r1);
ctz = fallback_bnei(_jit->pc.w, r0, 0);
movi(r0, __WORDSIZE);
done = fallback_jmpi(_jit->pc.w);
fallback_patch_at(ctz, _jit->pc.w);
fallback_ctz(r0, r0);
fallback_patch_jmpi(done, _jit->pc.w);
}
static void
_fallback_ctz(jit_state_t *_jit, jit_int32_t r0, jit_int32_t r1)
{
jit_int32_t r1_reg, r2, r2_reg;
jit_word_t ctz, l32, l16, l8, l4, l2, l1;
l32 = fallback_bnei(_jit->pc.w, r1, 0);
movi(r0, __WORDSIZE);
ctz = fallback_jmpi(_jit->pc.w);
fallback_patch_at(l32, _jit->pc.w);
r2_reg = jit_get_reg(jit_class_gpr);
r2 = rn(r2_reg);
r1_reg = jit_get_reg(jit_class_gpr);
movr(rn(r1_reg), r1);
r1 = rn(r1_reg);
movi(r0, 0);
# if __WORDSIZE == 64
movi(r2, 0xffffffffUL);
l32 = fallback_bmsr(_jit->pc.w, r1, r2);
rshi_u(r1, r1, 32);
addi(r0, r0, 32);
fallback_patch_at(l32, _jit->pc.w);
rshi(r2, r2, 16);
# else
movi(r2, 0xffffUL);
# endif
l16 = fallback_bmsr(_jit->pc.w, r1, r2);
rshi_u(r1, r1, 16);
addi(r0, r0, 16);
fallback_patch_at(l16, _jit->pc.w);
rshi(r2, r2, 8);
l8 = fallback_bmsr(_jit->pc.w, r1, r2);
rshi_u(r1, r1, 8);
addi(r0, r0, 8);
fallback_patch_at(l8, _jit->pc.w);
rshi(r2, r2, 4);
l4 = fallback_bmsr(_jit->pc.w, r1, r2);
rshi_u(r1, r1, 4);
addi(r0, r0, 4);
fallback_patch_at(l4, _jit->pc.w);
rshi(r2, r2, 2);
l2 = fallback_bmsr(_jit->pc.w, r1, r2);
rshi_u(r1, r1, 2);
addi(r0, r0, 2);
fallback_patch_at(l2, _jit->pc.w);
rshi(r2, r2, 1);
l1 = fallback_bmsr(_jit->pc.w, r1, r2);
addi(r0, r0, 1);
fallback_patch_at(l1, _jit->pc.w);
fallback_patch_jmpi(ctz, _jit->pc.w);
jit_unget_reg(r2_reg);
jit_unget_reg(r1_reg);
}
#endif