X-Git-Url: https://notaz.gp2x.de/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=deps%2Flightrec%2Flightrec.c;h=454007b11670817872b20d68322356784b3c9d3e;hb=878e6cda26bbf4af5090a01709db026d42c233b4;hp=f589ce85392ad386564b8e64fcfeb38517cbd5ff;hpb=2e6c828e00165e0a11ee44a144c7ec8ac24a4b60;p=pcsx_rearmed.git diff --git a/deps/lightrec/lightrec.c b/deps/lightrec/lightrec.c index f589ce85..454007b1 100644 --- a/deps/lightrec/lightrec.c +++ b/deps/lightrec/lightrec.c @@ -35,6 +35,8 @@ static bool lightrec_block_is_fully_tagged(const struct block *block); static void lightrec_mtc2(struct lightrec_state *state, u8 reg, u32 data); static u32 lightrec_mfc2(struct lightrec_state *state, u8 reg); +static void lightrec_reap_block(struct lightrec_state *state, void *data); + static void lightrec_default_sb(struct lightrec_state *state, u32 opcode, void *host, u32 addr, u32 data) { @@ -703,9 +705,15 @@ static struct block * lightrec_get_block(struct lightrec_state *state, u32 pc) if (ENABLE_THREADED_COMPILER) lightrec_recompiler_remove(state->rec, block); - lightrec_unregister_block(state->block_cache, block); remove_from_code_lut(state->block_cache, block); - lightrec_free_block(state, block); + + if (ENABLE_THREADED_COMPILER) { + lightrec_reaper_add(state->reaper, + lightrec_reap_block, block); + } else { + lightrec_unregister_block(state->block_cache, block); + lightrec_free_block(state, block); + } } block = NULL; @@ -869,6 +877,13 @@ static void * lightrec_emit_code(struct lightrec_state *state, if (has_code_buffer) { jit_get_code(&code_size); + +#ifdef __i386__ + /* Lightning's code size estimation routine is buggy on x86 and + * will return a value that's too small. */ + code_size *= 2; +#endif + code = lightrec_alloc_code(state, (size_t) code_size); if (!code) { @@ -896,6 +911,12 @@ static void * lightrec_emit_code(struct lightrec_state *state, } code = jit_emit(); + if (!code) { + if (has_code_buffer) + lightrec_free_code(state, code); + + return NULL; + } jit_get_code(&new_code_size); lightrec_register(MEM_FOR_CODE, new_code_size); @@ -925,14 +946,6 @@ static struct block * generate_wrapper(struct lightrec_state *state) jit_node_t *to_end[C_WRAPPERS_COUNT - 1]; u8 tmp = JIT_R1; -#ifdef __sh__ - /* On SH, GBR-relative loads target the r0 register. - * Use it as the temporary register to factorize the move to - * JIT_R1. */ - if (LIGHTREC_REG_STATE == _GBR) - tmp = _R0; -#endif - block = lightrec_malloc(state, MEM_FOR_IR, sizeof(*block)); if (!block) goto err_no_mem; @@ -1017,7 +1030,7 @@ static struct block * generate_wrapper(struct lightrec_state *state) block->function = lightrec_emit_code(state, block, _jit, &block->code_size); if (!block->function) - goto err_free_block; + goto err_free_jit; state->wrappers_eps[C_WRAPPERS_COUNT - 1] = block->function; @@ -1032,6 +1045,8 @@ static struct block * generate_wrapper(struct lightrec_state *state) jit_clear_state(); return block; +err_free_jit: + jit_destroy_state(); err_free_block: lightrec_free(state, MEM_FOR_IR, sizeof(*block), block); err_no_mem: @@ -1241,9 +1256,9 @@ static struct block * generate_dispatcher(struct lightrec_state *state) to_end = jit_blei(LIGHTREC_REG_CYCLE, 0); /* Convert next PC to KUNSEG and avoid mirrors */ - jit_andi(JIT_V1, JIT_V0, 0x10000000 | (RAM_SIZE - 1)); - jit_rshi_u(JIT_R1, JIT_V1, 28); + jit_andi(JIT_V1, JIT_V0, RAM_SIZE - 1); jit_andi(JIT_R2, JIT_V0, BIOS_SIZE - 1); + jit_andi(JIT_R1, JIT_V0, BIT(28)); jit_addi(JIT_R2, JIT_R2, RAM_SIZE); jit_movnr(JIT_V1, JIT_R2, JIT_R1); @@ -1315,7 +1330,7 @@ static struct block * generate_dispatcher(struct lightrec_state *state) block->function = lightrec_emit_code(state, block, _jit, &block->code_size); if (!block->function) - goto err_free_block; + goto err_free_jit; state->eob_wrapper_func = jit_address(addr2); if (OPT_DETECT_IMPOSSIBLE_BRANCHES) @@ -1335,6 +1350,8 @@ static struct block * generate_dispatcher(struct lightrec_state *state) jit_clear_state(); return block; +err_free_jit: + jit_destroy_state(); err_free_block: lightrec_free(state, MEM_FOR_IR, sizeof(*block), block); err_no_mem: @@ -1559,6 +1576,8 @@ static void lightrec_reap_opcode_list(struct lightrec_state *state, void *data) int lightrec_compile_block(struct lightrec_cstate *cstate, struct block *block) { + struct block *dead_blocks[ARRAY_SIZE(cstate->targets)]; + u32 was_dead[ARRAY_SIZE(cstate->targets) / 8]; struct lightrec_state *state = cstate->state; struct lightrec_branch_target *target; bool fully_tagged = false; @@ -1677,11 +1696,8 @@ int lightrec_compile_block(struct lightrec_cstate *cstate, /* Add compiled function to the LUT */ lut_write(state, lut_offset(block->pc), block->function); - if (ENABLE_THREADED_COMPILER) - lightrec_reaper_continue(state->reaper); - /* Detect old blocks that have been covered by the new one */ - for (i = 0; i < cstate->nb_targets; i++) { + for (i = 0; ENABLE_THREADED_COMPILER && i < cstate->nb_targets; i++) { target = &cstate->targets[i]; if (!target->offset) @@ -1689,12 +1705,6 @@ int lightrec_compile_block(struct lightrec_cstate *cstate, offset = block->pc + target->offset * sizeof(u32); - /* Pause the reaper while we search for the block until we set - * the BLOCK_IS_DEAD flag, otherwise the block may be removed - * under our feet. */ - if (ENABLE_THREADED_COMPILER) - lightrec_reaper_pause(state->reaper); - block2 = lightrec_find_block(state->block_cache, offset); if (block2) { /* No need to check if block2 is compilable - it must @@ -1703,17 +1713,26 @@ int lightrec_compile_block(struct lightrec_cstate *cstate, /* Set the "block dead" flag to prevent the dynarec from * recompiling this block */ old_flags = block_set_flags(block2, BLOCK_IS_DEAD); + + if (old_flags & BLOCK_IS_DEAD) + was_dead[i / 32] |= BIT(i % 32); + else + was_dead[i / 32] &= ~BIT(i % 32); } - if (ENABLE_THREADED_COMPILER) { - lightrec_reaper_continue(state->reaper); + dead_blocks[i] = block2; - /* If block2 was pending for compilation, cancel it. - * If it's being compiled right now, wait until it - * finishes. */ - if (block2) - lightrec_recompiler_remove(state->rec, block2); - } + /* If block2 was pending for compilation, cancel it. + * If it's being compiled right now, wait until it finishes. */ + if (block2) + lightrec_recompiler_remove(state->rec, block2); + } + + for (i = 0; i < cstate->nb_targets; i++) { + target = &cstate->targets[i]; + + if (!target->offset) + continue; /* We know from now on that block2 (if present) isn't going to * be compiled. We can override the LUT entry with our new @@ -1721,6 +1740,12 @@ int lightrec_compile_block(struct lightrec_cstate *cstate, offset = lut_offset(block->pc) + target->offset; lut_write(state, offset, jit_address(target->label)); + if (ENABLE_THREADED_COMPILER) { + block2 = dead_blocks[i]; + } else { + offset = block->pc + target->offset * sizeof(u32); + block2 = lightrec_find_block(state->block_cache, offset); + } if (block2) { pr_debug("Reap block 0x%08x as it's covered by block " "0x%08x\n", block2->pc, block->pc); @@ -1729,7 +1754,7 @@ int lightrec_compile_block(struct lightrec_cstate *cstate, if (!ENABLE_THREADED_COMPILER) { lightrec_unregister_block(state->block_cache, block2); lightrec_free_block(state, block2); - } else if (!(old_flags & BLOCK_IS_DEAD)) { + } else if (!(was_dead[i / 32] & BIT(i % 32))) { lightrec_reaper_add(state->reaper, lightrec_reap_block, block2); @@ -1737,6 +1762,9 @@ int lightrec_compile_block(struct lightrec_cstate *cstate, } } + if (ENABLE_THREADED_COMPILER) + lightrec_reaper_continue(state->reaper); + if (ENABLE_DISASSEMBLER) { pr_debug("Compiling block at PC: 0x%08x\n", block->pc); jit_disassemble(); @@ -1899,11 +1927,12 @@ void lightrec_free_cstate(struct lightrec_cstate *cstate) } struct lightrec_state * lightrec_init(char *argv0, - const struct lightrec_mem_map *map, + const struct lightrec_mem_map *maps, size_t nb, const struct lightrec_ops *ops) { - const struct lightrec_mem_map *codebuf_map = &map[PSX_MAP_CODE_BUFFER]; + const struct lightrec_mem_map *codebuf_map = &maps[PSX_MAP_CODE_BUFFER]; + const struct lightrec_mem_map *map; struct lightrec_state *state; uintptr_t addr; void *tlsf = NULL; @@ -1941,7 +1970,7 @@ struct lightrec_state * lightrec_init(char *argv0, else lut_size = CODE_LUT_SIZE * sizeof(void *); - init_jit(argv0); + init_jit_with_debug(argv0, stdout); state = calloc(1, sizeof(*state) + lut_size); if (!state) @@ -1973,7 +2002,7 @@ struct lightrec_state * lightrec_init(char *argv0, } state->nb_maps = nb; - state->maps = map; + state->maps = maps; memcpy(&state->ops, ops, sizeof(*ops)); @@ -1991,21 +2020,21 @@ struct lightrec_state * lightrec_init(char *argv0, state->c_wrappers[C_WRAPPER_MTC] = lightrec_mtc_cb; state->c_wrappers[C_WRAPPER_CP] = lightrec_cp_cb; - map = &state->maps[PSX_MAP_BIOS]; + map = &maps[PSX_MAP_BIOS]; state->offset_bios = (uintptr_t)map->address - map->pc; - map = &state->maps[PSX_MAP_SCRATCH_PAD]; + map = &maps[PSX_MAP_SCRATCH_PAD]; state->offset_scratch = (uintptr_t)map->address - map->pc; - map = &state->maps[PSX_MAP_HW_REGISTERS]; + map = &maps[PSX_MAP_HW_REGISTERS]; state->offset_io = (uintptr_t)map->address - map->pc; - map = &state->maps[PSX_MAP_KERNEL_USER_RAM]; + map = &maps[PSX_MAP_KERNEL_USER_RAM]; state->offset_ram = (uintptr_t)map->address - map->pc; - if (state->maps[PSX_MAP_MIRROR1].address == map->address + 0x200000 && - state->maps[PSX_MAP_MIRROR2].address == map->address + 0x400000 && - state->maps[PSX_MAP_MIRROR3].address == map->address + 0x600000) + if (maps[PSX_MAP_MIRROR1].address == map->address + 0x200000 && + maps[PSX_MAP_MIRROR2].address == map->address + 0x400000 && + maps[PSX_MAP_MIRROR3].address == map->address + 0x600000) state->mirrors_mapped = true; if (state->offset_bios == 0 && @@ -2150,5 +2179,19 @@ struct lightrec_registers * lightrec_get_registers(struct lightrec_state *state) void lightrec_set_cycles_per_opcode(struct lightrec_state *state, u32 cycles) { + if (state->cycles_per_op == cycles) + return; + state->cycles_per_op = cycles; + + if (ENABLE_THREADED_COMPILER) { + lightrec_recompiler_pause(state->rec); + lightrec_reaper_reap(state->reaper); + } + + lightrec_invalidate_all(state); + lightrec_free_all_blocks(state->block_cache); + + if (ENABLE_THREADED_COMPILER) + lightrec_recompiler_unpause(state->rec); }