From 0e720fb13f7933930608b62854ea8f4a9d97c934 Mon Sep 17 00:00:00 2001 From: Paul Cercueil Date: Fri, 4 Aug 2023 23:30:38 +0200 Subject: [PATCH] git subrepo pull --force deps/lightrec subrepo: subdir: "deps/lightrec" merged: "15216f3a2e" upstream: origin: "https://github.com/pcercuei/lightrec.git" branch: "master" commit: "15216f3a2e" git-subrepo: version: "0.4.3" origin: "https://github.com/ingydotnet/git-subrepo.git" commit: "2f68596" --- deps/lightrec/.gitrepo | 4 +-- deps/lightrec/emitter.c | 13 +++++++++ deps/lightrec/lightrec-private.h | 6 ++++ deps/lightrec/lightrec.c | 46 +++++++++++++++++++----------- deps/lightrec/lightrec.h | 1 + deps/lightrec/regcache.c | 49 +++++++++++++++++++++++++------- deps/lightrec/regcache.h | 2 +- 7 files changed, 90 insertions(+), 31 deletions(-) diff --git a/deps/lightrec/.gitrepo b/deps/lightrec/.gitrepo index b6174072..6d4845d0 100644 --- a/deps/lightrec/.gitrepo +++ b/deps/lightrec/.gitrepo @@ -6,7 +6,7 @@ [subrepo] remote = https://github.com/pcercuei/lightrec.git branch = master - commit = 68a5d16b6b5ce155aebf7f4708483eaeb4992997 - parent = bbda82f029ab0a9bbc91cb411d2cb56745d45510 + commit = 15216f3a2e7207432245682e80d97dc361f28fde + parent = 266ec37b97da56dbf277426d3f4b5ef833a08e55 method = merge cmdver = 0.4.3 diff --git a/deps/lightrec/emitter.c b/deps/lightrec/emitter.c index 1b4082b7..02510f0e 100644 --- a/deps/lightrec/emitter.c +++ b/deps/lightrec/emitter.c @@ -124,6 +124,8 @@ static void lightrec_emit_end_of_block(struct lightrec_cstate *state, } else { lightrec_jump_to_eob(state, _jit); } + + lightrec_regcache_reset(reg_cache); } void lightrec_emit_jump_to_interpreter(struct lightrec_cstate *state, @@ -138,6 +140,11 @@ 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); @@ -154,6 +161,11 @@ static void lightrec_emit_eob(struct lightrec_cstate *state, 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); @@ -1214,6 +1226,7 @@ static void rec_store_memory(struct lightrec_cstate *cstate, 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) { diff --git a/deps/lightrec/lightrec-private.h b/deps/lightrec/lightrec-private.h index 12e953a2..1f8e10b5 100644 --- a/deps/lightrec/lightrec-private.h +++ b/deps/lightrec/lightrec-private.h @@ -156,6 +156,7 @@ struct lightrec_cstate { 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; @@ -360,4 +361,9 @@ get_delay_slot(const struct opcode *list, u16 i) 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__ */ diff --git a/deps/lightrec/lightrec.c b/deps/lightrec/lightrec.c index d5b1de96..45c3149d 100644 --- a/deps/lightrec/lightrec.c +++ b/deps/lightrec/lightrec.c @@ -376,10 +376,10 @@ static void lightrec_rw_generic_cb(struct lightrec_state *state, u32 arg) 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; } @@ -776,7 +776,7 @@ static void * get_next_block_func(struct lightrec_state *state, u32 pc) } while (state->exit_flags == LIGHTREC_EXIT_NORMAL && state->current_cycle < state->target_cycle); - state->next_pc = pc; + state->curr_pc = pc; return func; } @@ -1077,6 +1077,14 @@ static void update_cycle_counter_after_c(jit_state_t *_jit) 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; @@ -1140,6 +1148,7 @@ static struct block * generate_dispatcher(struct lightrec_state *state) * 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(); @@ -1167,6 +1176,7 @@ static struct block * generate_dispatcher(struct lightrec_state *state) * in question; and if it does, handle it accordingly. */ addr5 = jit_indirect(); + sync_next_pc(_jit); update_cycle_counter_before_c(_jit); jit_prepare(); @@ -1178,22 +1188,24 @@ static struct block * generate_dispatcher(struct lightrec_state *state) 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 */ @@ -1254,7 +1266,7 @@ static struct block * generate_dispatcher(struct lightrec_state *state) /* 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); @@ -1543,7 +1555,7 @@ int lightrec_compile_block(struct lightrec_cstate *cstate, 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; @@ -1763,13 +1775,13 @@ u32 lightrec_execute(struct lightrec_state *state, u32 pc, u32 target_cycle) 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; @@ -1781,7 +1793,7 @@ u32 lightrec_execute(struct lightrec_state *state, u32 pc, u32 target_cycle) 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, diff --git a/deps/lightrec/lightrec.h b/deps/lightrec/lightrec.h index bd878c86..0798b581 100644 --- a/deps/lightrec/lightrec.h +++ b/deps/lightrec/lightrec.h @@ -75,6 +75,7 @@ enum psx_map { PSX_MAP_MIRROR2, PSX_MAP_MIRROR3, PSX_MAP_CODE_BUFFER, + PSX_MAP_PPORT_MIRROR, PSX_MAP_UNKNOWN, }; diff --git a/deps/lightrec/regcache.c b/deps/lightrec/regcache.c index 2a7ffe92..d9926d38 100644 --- a/deps/lightrec/regcache.c +++ b/deps/lightrec/regcache.c @@ -11,7 +11,7 @@ #include #include -#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, @@ -422,20 +422,31 @@ void lightrec_load_next_pc_imm(struct regcache *cache, 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) @@ -444,6 +455,15 @@ 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) @@ -481,10 +501,15 @@ void lightrec_load_next_pc(struct regcache *cache, jit_state_t *_jit, u8 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) @@ -632,7 +657,7 @@ void lightrec_regcache_reset(struct regcache *cache) 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; @@ -641,6 +666,8 @@ void lightrec_preload_pc(struct regcache *cache) 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) diff --git a/deps/lightrec/regcache.h b/deps/lightrec/regcache.h index 55f1cfd9..abf70532 100644 --- a/deps/lightrec/regcache.h +++ b/deps/lightrec/regcache.h @@ -63,7 +63,7 @@ u8 lightrec_get_reg_in_flags(struct regcache *cache, u8 jit_reg); 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); -- 2.39.5