#include <stdbool.h>
#include <stddef.h>
-#define REG_PC (offsetof(struct lightrec_state, next_pc) / sizeof(u32))
+#define REG_PC (offsetof(struct lightrec_state, curr_pc) / sizeof(u32))
enum reg_priority {
REG_IS_TEMP,
nreg->value = value;
}
+u8 lightrec_alloc_reg_temp_with_value(struct regcache *cache,
+ jit_state_t *_jit, intptr_t value)
+{
+ s8 reg;
+
+ reg = lightrec_get_reg_with_value(cache, value);
+ if (reg < 0) {
+ reg = lightrec_alloc_reg_temp(cache, _jit);
+ jit_movi((u8)reg, value);
+ lightrec_temp_set_value(cache, (u8)reg, value);
+ }
+
+ return (u8)reg;
+}
+
u8 lightrec_alloc_reg_out(struct regcache *cache, jit_state_t *_jit,
u16 reg, u8 flags)
{
lightrec_unload_nreg(cache, _jit, nreg, jit_reg);
if (nreg->prio < REG_IS_LOADED && reg != 0) {
- s16 offset = offsetof(struct lightrec_state, regs.gpr)
- + (reg << 2);
+ s16 offset = lightrec_offset(regs.gpr) + (reg << 2);
nreg->zero_extended = flags & REG_ZEXT;
nreg->extended = !nreg->zero_extended;
return jit_reg;
}
+void lightrec_remap_reg(struct regcache *cache, jit_state_t *_jit,
+ u8 jit_reg, u16 reg_out, bool discard)
+{
+ struct native_register *nreg;
+
+ lightrec_discard_reg_if_loaded(cache, reg_out);
+
+ nreg = lightning_reg_to_lightrec(cache, jit_reg);
+ clean_reg(_jit, nreg, jit_reg, !discard);
+
+ nreg->output = true;
+ nreg->emulated_register = reg_out;
+ nreg->extend = nreg->extended;
+ nreg->zero_extend = nreg->zero_extended;
+}
+
static bool reg_pc_is_mapped(struct regcache *cache)
{
struct native_register *nreg = lightning_reg_to_lightrec(cache, JIT_V0);
jit_state_t *_jit, u32 pc, u32 imm)
{
struct native_register *nreg = lightning_reg_to_lightrec(cache, JIT_V0);
+ u8 reg = JIT_V0;
+
+ if (lightrec_store_next_pc())
+ reg = lightrec_alloc_reg_temp(cache, _jit);
if (reg_pc_is_mapped(cache)) {
/* JIT_V0 contains next PC - so we can overwrite it */
- lightrec_load_imm(cache, _jit, JIT_V0, pc, imm);
+ lightrec_load_imm(cache, _jit, reg, pc, imm);
} else {
/* JIT_V0 contains something else - invalidate it */
- lightrec_unload_reg(cache, _jit, JIT_V0);
+ if (reg == JIT_V0)
+ lightrec_unload_reg(cache, _jit, JIT_V0);
- jit_movi(JIT_V0, imm);
+ jit_movi(reg, imm);
}
- nreg->prio = REG_IS_LOADED;
- nreg->emulated_register = -1;
- nreg->locked = true;
+ if (lightrec_store_next_pc()) {
+ jit_stxi_i(lightrec_offset(next_pc), LIGHTREC_REG_STATE, reg);
+ lightrec_free_reg(cache, reg);
+ } else {
+ nreg->prio = REG_IS_LOADED;
+ nreg->emulated_register = -1;
+ nreg->locked = true;
+ }
}
void lightrec_load_next_pc(struct regcache *cache, jit_state_t *_jit, u8 reg)
u16 offset;
u8 jit_reg;
+ if (lightrec_store_next_pc()) {
+ jit_reg = lightrec_alloc_reg_in(cache, _jit, reg, 0);
+ offset = lightrec_offset(next_pc);
+ jit_stxi_i(offset, LIGHTREC_REG_STATE, jit_reg);
+ lightrec_free_reg(cache, jit_reg);
+
+ return;
+ }
+
/* Invalidate JIT_V0 if it is not mapped to 'reg' */
nreg_v0 = lightning_reg_to_lightrec(cache, JIT_V0);
if (nreg_v0->prio >= REG_IS_LOADED && nreg_v0->emulated_register != reg)
if (!nreg) {
/* Not mapped - load the value from the register cache */
- offset = offsetof(struct lightrec_state, regs.gpr) + (reg << 2);
+ offset = lightrec_offset(regs.gpr) + (reg << 2);
jit_ldxi_ui(JIT_V0, LIGHTREC_REG_STATE, offset);
nreg_v0->prio = REG_IS_LOADED;
lightrec_discard_nreg(nreg);
}
- lightrec_clean_reg(cache, _jit, JIT_V0);
+ if (lightrec_store_next_pc()) {
+ jit_stxi_i(lightrec_offset(next_pc),
+ LIGHTREC_REG_STATE, JIT_V0);
+ } else {
+ lightrec_clean_reg(cache, _jit, JIT_V0);
- nreg_v0->zero_extended = true;
- nreg_v0->locked = true;
+ nreg_v0->zero_extended = true;
+ nreg_v0->locked = true;
+ }
}
static void free_reg(struct native_register *nreg)
{
/* If we get a dirty register, store back the old value */
if (nreg->prio == REG_IS_DIRTY) {
- s16 offset = offsetof(struct lightrec_state, regs.gpr)
+ s16 offset = lightrec_offset(regs.gpr)
+ (nreg->emulated_register << 2);
jit_stxi_i(offset, LIGHTREC_REG_STATE, jit_reg);
memset(&cache->lightrec_regs, 0, sizeof(cache->lightrec_regs));
}
-void lightrec_preload_pc(struct regcache *cache)
+void lightrec_preload_pc(struct regcache *cache, jit_state_t *_jit)
{
struct native_register *nreg;
nreg->emulated_register = REG_PC;
nreg->prio = REG_IS_LOADED;
nreg->zero_extended = true;
+
+ jit_live(JIT_V0);
}
struct regcache * lightrec_regcache_init(struct lightrec_state *state)