[subrepo]
remote = https://github.com/pcercuei/lightrec.git
branch = master
- commit = 68a5d16b6b5ce155aebf7f4708483eaeb4992997
- parent = bbda82f029ab0a9bbc91cb411d2cb56745d45510
+ commit = 15216f3a2e7207432245682e80d97dc361f28fde
+ parent = 266ec37b97da56dbf277426d3f4b5ef833a08e55
method = merge
cmdver = 0.4.3
} else {
lightrec_jump_to_eob(state, _jit);
}
+
+ lightrec_regcache_reset(reg_cache);
}
void lightrec_emit_jump_to_interpreter(struct lightrec_cstate *state,
* PC (which might have an offset) in JIT_V0. */
lightrec_load_imm(reg_cache, _jit, JIT_V0, block->pc,
block->pc + (offset << 2));
+ if (lightrec_store_next_pc()) {
+ jit_stxi_i(offsetof(struct lightrec_state, next_pc),
+ LIGHTREC_REG_STATE, JIT_V0);
+ }
+
jit_movi(JIT_V1, (uintptr_t)block);
jit_subi(LIGHTREC_REG_CYCLE, LIGHTREC_REG_CYCLE, state->cycles);
lightrec_load_imm(reg_cache, _jit, JIT_V0, block->pc,
block->pc + (offset << 2));
+ if (lightrec_store_next_pc()) {
+ jit_stxi_i(offsetof(struct lightrec_state, next_pc),
+ LIGHTREC_REG_STATE, JIT_V0);
+ }
+
jit_subi(LIGHTREC_REG_CYCLE, LIGHTREC_REG_CYCLE, state->cycles);
lightrec_jump_to_eob(state, _jit);
if (add_imm) {
jit_addi(tmp, addr_reg, (s16)c.i.imm);
+ lightrec_free_reg(reg_cache, rs);
addr_reg = tmp;
imm = 0;
} else if (simm) {
struct lightrec_state {
struct lightrec_registers regs;
u32 temp_reg;
+ u32 curr_pc;
u32 next_pc;
uintptr_t wrapper_regs[NUM_TEMPS];
u8 in_delay_slot_n;
return op_flag_no_ds(list[i].flags) ? &list[i - 1] : &list[i + 1];
}
+static inline _Bool lightrec_store_next_pc(void)
+{
+ return NUM_REGS + NUM_TEMPS <= 4;
+}
+
#endif /* __LIGHTREC_PRIVATE_H__ */
u16 offset = (u16)arg;
block = lightrec_find_block_from_lut(state->block_cache,
- arg >> 16, state->next_pc);
+ arg >> 16, state->curr_pc);
if (unlikely(!block)) {
pr_err("rw_generic: No block found in LUT for PC 0x%x offset 0x%x\n",
- state->next_pc, offset);
+ state->curr_pc, offset);
lightrec_set_exit_flags(state, LIGHTREC_EXIT_SEGFAULT);
return;
}
} while (state->exit_flags == LIGHTREC_EXIT_NORMAL
&& state->current_cycle < state->target_cycle);
- state->next_pc = pc;
+ state->curr_pc = pc;
return func;
}
jit_subr(LIGHTREC_REG_CYCLE, JIT_R2, JIT_R1);
}
+static void sync_next_pc(jit_state_t *_jit)
+{
+ if (lightrec_store_next_pc()) {
+ jit_ldxi_i(JIT_V0, LIGHTREC_REG_STATE,
+ offsetof(struct lightrec_state, next_pc));
+ }
+}
+
static struct block * generate_dispatcher(struct lightrec_state *state)
{
struct block *block;
* in JIT_V0 and the address of the block in JIT_V1. */
addr4 = jit_indirect();
+ sync_next_pc(_jit);
update_cycle_counter_before_c(_jit);
jit_prepare();
* in question; and if it does, handle it accordingly. */
addr5 = jit_indirect();
+ sync_next_pc(_jit);
update_cycle_counter_before_c(_jit);
jit_prepare();
jit_retval(JIT_V0);
update_cycle_counter_after_c(_jit);
-
- if (OPT_DETECT_IMPOSSIBLE_BRANCHES)
- jit_patch(jmp2);
}
+ /* The block will jump here, with the number of cycles remaining in
+ * LIGHTREC_REG_CYCLE */
+ addr2 = jit_indirect();
+
+ sync_next_pc(_jit);
+
+ if (OPT_HANDLE_LOAD_DELAYS && OPT_DETECT_IMPOSSIBLE_BRANCHES)
+ jit_patch(jmp2);
+
if (OPT_REPLACE_MEMSET
&& (OPT_DETECT_IMPOSSIBLE_BRANCHES || OPT_HANDLE_LOAD_DELAYS)) {
jit_patch(jmp);
}
- /* The block will jump here, with the number of cycles remaining in
- * LIGHTREC_REG_CYCLE */
- addr2 = jit_indirect();
-
- /* Store back the next_pc to the lightrec_state structure */
- offset = offsetof(struct lightrec_state, next_pc);
+ /* Store back the next PC to the lightrec_state structure */
+ offset = offsetof(struct lightrec_state, curr_pc);
jit_stxi_i(offset, LIGHTREC_REG_STATE, JIT_V0);
/* Jump to end if state->target_cycle < state->current_cycle */
/* Reset JIT_V0 to the next PC */
jit_ldxi_ui(JIT_V0, LIGHTREC_REG_STATE,
- offsetof(struct lightrec_state, next_pc));
+ offsetof(struct lightrec_state, curr_pc));
/* If we get non-NULL, loop */
jit_patch_at(jit_bnei(JIT_V1, 0), loop);
block->_jit = _jit;
lightrec_regcache_reset(cstate->reg_cache);
- lightrec_preload_pc(cstate->reg_cache);
+ lightrec_preload_pc(cstate->reg_cache, _jit);
cstate->cycles = 0;
cstate->nb_local_branches = 0;
target_cycle = UINT_MAX;
state->target_cycle = target_cycle;
- state->next_pc = pc;
+ state->curr_pc = pc;
block_trace = get_next_block_func(state, pc);
if (block_trace) {
cycles_delta = state->target_cycle - state->current_cycle;
- cycles_delta = (*func)(state, state->next_pc,
+ cycles_delta = (*func)(state, state->curr_pc,
block_trace, cycles_delta);
state->current_cycle = state->target_cycle - cycles_delta;
if (LOG_LEVEL >= INFO_L)
lightrec_print_info(state);
- return state->next_pc;
+ return state->curr_pc;
}
u32 lightrec_run_interpreter(struct lightrec_state *state, u32 pc,
PSX_MAP_MIRROR2,
PSX_MAP_MIRROR3,
PSX_MAP_CODE_BUFFER,
+ PSX_MAP_PPORT_MIRROR,
PSX_MAP_UNKNOWN,
};
#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,
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(offsetof(struct lightrec_state, 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 = offsetof(struct lightrec_state, 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)
lightrec_discard_nreg(nreg);
}
- lightrec_clean_reg(cache, _jit, JIT_V0);
+ if (lightrec_store_next_pc()) {
+ jit_stxi_i(offsetof(struct lightrec_state, 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)
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)
void lightrec_set_reg_out_flags(struct regcache *cache, u8 jit_reg, u8 flags);
void lightrec_regcache_reset(struct regcache *cache);
-void lightrec_preload_pc(struct regcache *cache);
+void lightrec_preload_pc(struct regcache *cache, jit_state_t *_jit);
void lightrec_free_reg(struct regcache *cache, u8 jit_reg);
void lightrec_free_regs(struct regcache *cache);