mirror of
https://github.com/simple64/simple64.git
synced 2026-09-04 11:24:32 +02:00
333 lines
9.7 KiB
C
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
|