git subrepo pull --force deps/lightrec
authorPaul Cercueil <paul@crapouillou.net>
Fri, 4 Aug 2023 21:30:38 +0000 (23:30 +0200)
committerPaul Cercueil <paul@crapouillou.net>
Fri, 4 Aug 2023 21:32:27 +0000 (23:32 +0200)
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
deps/lightrec/emitter.c
deps/lightrec/lightrec-private.h
deps/lightrec/lightrec.c
deps/lightrec/lightrec.h
deps/lightrec/regcache.c
deps/lightrec/regcache.h

index b617407..6d4845d 100644 (file)
@@ -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
index 1b4082b..02510f0 100644 (file)
@@ -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) {
index 12e953a..1f8e10b 100644 (file)
@@ -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__ */
index d5b1de9..45c3149 100644 (file)
@@ -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,
index bd878c8..0798b58 100644 (file)
@@ -75,6 +75,7 @@ enum psx_map {
        PSX_MAP_MIRROR2,
        PSX_MAP_MIRROR3,
        PSX_MAP_CODE_BUFFER,
+       PSX_MAP_PPORT_MIRROR,
 
        PSX_MAP_UNKNOWN,
 };
index 2a7ffe9..d9926d3 100644 (file)
@@ -11,7 +11,7 @@
 #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,
@@ -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)
index 55f1cfd..abf7053 100644 (file)
@@ -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);