X-Git-Url: https://notaz.gp2x.de/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=deps%2Flightrec%2Flightrec.c;h=3b3fd09037bd033fef73bdd996a48962ff978485;hb=0b8caa417c2bef660d6a0c70cbab71f1e997023b;hp=d172a30adb26ba5f08357e3a03fb920bea755578;hpb=02487de7ff9fcbb6d7d692a6b3ae6e6539708abc;p=pcsx_rearmed.git diff --git a/deps/lightrec/lightrec.c b/deps/lightrec/lightrec.c index d172a30a..3b3fd090 100644 --- a/deps/lightrec/lightrec.c +++ b/deps/lightrec/lightrec.c @@ -27,9 +27,6 @@ #include #include #include -#if ENABLE_TINYMM -#include -#endif #define GENMASK(h, l) \ (((uintptr_t)-1 << (l)) & ((uintptr_t)-1 >> (__WORDSIZE - 1 - (h)))) @@ -328,7 +325,8 @@ static void lightrec_rw_helper(struct lightrec_state *state, case OP_LW: if (op.i.rt) state->regs.gpr[op.i.rt] = ret; - default: /* fall-through */ + fallthrough; + default: break; } } @@ -372,6 +370,16 @@ static u32 clamp_s32(s32 val, s32 min, s32 max) return val < min ? min : val > max ? max : val; } +static u16 load_u16(u32 *ptr) +{ + return ((struct u16x2 *) ptr)->l; +} + +static void store_u16(u32 *ptr, u16 value) +{ + ((struct u16x2 *) ptr)->l = value; +} + static u32 lightrec_mfc2(struct lightrec_state *state, u8 reg) { s16 gteir1, gteir2, gteir3; @@ -384,25 +392,26 @@ static u32 lightrec_mfc2(struct lightrec_state *state, u8 reg) case 9: case 10: case 11: - return (s32)(s16) state->regs.cp2d[reg]; + return (s32)(s16) load_u16(&state->regs.cp2d[reg]); case 7: case 16: case 17: case 18: case 19: - return (u16) state->regs.cp2d[reg]; + return load_u16(&state->regs.cp2d[reg]); case 28: case 29: - gteir1 = (s16) state->regs.cp2d[9]; - gteir2 = (s16) state->regs.cp2d[10]; - gteir3 = (s16) state->regs.cp2d[11]; + gteir1 = (s16) load_u16(&state->regs.cp2d[9]); + gteir2 = (s16) load_u16(&state->regs.cp2d[10]); + gteir3 = (s16) load_u16(&state->regs.cp2d[11]); return clamp_s32(gteir1 >> 7, 0, 0x1f) << 0 | clamp_s32(gteir2 >> 7, 0, 0x1f) << 5 | clamp_s32(gteir3 >> 7, 0, 0x1f) << 10; case 15: reg = 14; - default: /* fall-through */ + fallthrough; + default: return state->regs.cp2d[reg]; } } @@ -503,7 +512,8 @@ static void lightrec_mtc2(struct lightrec_state *state, u8 reg, u32 data) return; case 30: state->regs.cp2d[31] = count_leading_bits((s32) data); - default: /* fall-through */ + fallthrough; + default: state->regs.cp2d[reg] = data; break; } @@ -519,15 +529,15 @@ static void lightrec_ctc2(struct lightrec_state *state, u8 reg, u32 data) case 27: case 29: case 30: - data = (s32)(s16) data; + store_u16(&state->regs.cp2c[reg], data); break; case 31: data = (data & 0x7ffff000) | !!(data & 0x7f87e000) << 31; - default: /* fall-through */ + fallthrough; + default: + state->regs.cp2c[reg] = data; break; } - - state->regs.cp2c[reg] = data; } void lightrec_mtc(struct lightrec_state *state, union code op, u32 data) @@ -623,9 +633,10 @@ static void * get_next_block_func(struct lightrec_state *state, u32 pc) struct block *block; bool should_recompile; void *func; + int err; for (;;) { - func = lut_read(state, pc); + func = lut_read(state, lut_offset(pc)); if (func && func != state->get_next_block) break; @@ -647,10 +658,15 @@ static void * get_next_block_func(struct lightrec_state *state, u32 pc) lightrec_unregister(MEM_FOR_CODE, block->code_size); - if (ENABLE_THREADED_COMPILER) + if (ENABLE_THREADED_COMPILER) { lightrec_recompiler_add(state->rec, block); - else - lightrec_compile_block(state->cstate, block); + } else { + err = lightrec_compile_block(state->cstate, block); + if (err) { + state->exit_flags = LIGHTREC_EXIT_NOMEM; + return NULL; + } + } } if (ENABLE_THREADED_COMPILER && likely(!should_recompile)) @@ -672,7 +688,11 @@ static void * get_next_block_func(struct lightrec_state *state, u32 pc) pc = lightrec_emulate_block(state, block, pc); /* Then compile it using the profiled data */ - lightrec_compile_block(state->cstate, block); + err = lightrec_compile_block(state->cstate, block); + if (err) { + state->exit_flags = LIGHTREC_EXIT_NOMEM; + return NULL; + } } else { lightrec_recompiler_add(state->rec, block); } @@ -696,7 +716,49 @@ static s32 c_function_wrapper(struct lightrec_state *state, s32 cycles_delta, return state->target_cycle - state->current_cycle; } +static void * lightrec_alloc_code(struct lightrec_state *state, size_t size) +{ + void *code; + + if (ENABLE_THREADED_COMPILER) + lightrec_code_alloc_lock(state); + + code = tlsf_malloc(state->tlsf, size); + + if (ENABLE_THREADED_COMPILER) + lightrec_code_alloc_unlock(state); + + return code; +} + +static void lightrec_realloc_code(struct lightrec_state *state, + void *ptr, size_t size) +{ + /* NOTE: 'size' MUST be smaller than the size specified during + * the allocation. */ + + if (ENABLE_THREADED_COMPILER) + lightrec_code_alloc_lock(state); + + tlsf_realloc(state->tlsf, ptr, size); + + if (ENABLE_THREADED_COMPILER) + lightrec_code_alloc_unlock(state); +} + +static void lightrec_free_code(struct lightrec_state *state, void *ptr) +{ + if (ENABLE_THREADED_COMPILER) + lightrec_code_alloc_lock(state); + + tlsf_free(state->tlsf, ptr); + + if (ENABLE_THREADED_COMPILER) + lightrec_code_alloc_unlock(state); +} + static void * lightrec_emit_code(struct lightrec_state *state, + const struct block *block, jit_state_t *_jit, unsigned int *size) { bool has_code_buffer = ENABLE_CODE_BUFFER && state->tlsf; @@ -710,9 +772,28 @@ static void * lightrec_emit_code(struct lightrec_state *state, if (has_code_buffer) { jit_get_code(&code_size); - code = tlsf_malloc(state->tlsf, (size_t) code_size); - if (!code) - return NULL; + code = lightrec_alloc_code(state, (size_t) code_size); + + if (!code) { + if (ENABLE_THREADED_COMPILER) { + /* If we're using the threaded compiler, return + * an allocation error here. The threaded + * compiler will then empty its job queue and + * request a code flush using the reaper. */ + return NULL; + } + + /* Remove outdated blocks, and try again */ + lightrec_remove_outdated_blocks(state->block_cache, block); + + pr_debug("Re-try to alloc %zu bytes...\n", code_size); + + code = lightrec_alloc_code(state, code_size); + if (!code) { + pr_err("Could not alloc even after removing old blocks!\n"); + return NULL; + } + } jit_set_code(code, code_size); } @@ -723,7 +804,7 @@ static void * lightrec_emit_code(struct lightrec_state *state, lightrec_register(MEM_FOR_CODE, new_code_size); if (has_code_buffer) { - tlsf_realloc(state->tlsf, code, new_code_size); + lightrec_realloc_code(state, code, (size_t) new_code_size); pr_debug("Creating code block at address 0x%" PRIxPTR ", " "code size: %" PRIuPTR " new: %" PRIuPTR "\n", @@ -819,7 +900,7 @@ static struct block * generate_wrapper(struct lightrec_state *state) block->flags = 0; block->nb_ops = 0; - block->function = lightrec_emit_code(state, _jit, + block->function = lightrec_emit_code(state, block, _jit, &block->code_size); if (!block->function) goto err_free_block; @@ -1002,7 +1083,7 @@ static struct block * generate_dispatcher(struct lightrec_state *state) block->flags = 0; block->nb_ops = 0; - block->function = lightrec_emit_code(state, _jit, + block->function = lightrec_emit_code(state, block, _jit, &block->code_size); if (!block->function) goto err_free_block; @@ -1124,6 +1205,7 @@ static struct block * lightrec_precompile_block(struct lightrec_state *state, block->next = NULL; block->flags = 0; block->code_size = 0; + block->precompile_date = state->current_cycle; #if ENABLE_THREADED_COMPILER block->op_list_freed = (atomic_flag)ATOMIC_FLAG_INIT; #endif @@ -1189,7 +1271,8 @@ static bool lightrec_block_is_fully_tagged(const struct block *block) case OP_SWC2: if (!LIGHTREC_FLAGS_GET_IO_MODE(op->flags)) return false; - default: /* fall-through */ + fallthrough; + default: continue; } } @@ -1215,7 +1298,7 @@ static void lightrec_free_function(struct lightrec_state *state, void *fn) { if (ENABLE_CODE_BUFFER && state->tlsf) { pr_debug("Freeing code block at 0x%" PRIxPTR "\n", (uintptr_t) fn); - tlsf_free(state->tlsf, fn); + lightrec_free_code(state, fn); } } @@ -1235,7 +1318,7 @@ int lightrec_compile_block(struct lightrec_cstate *cstate, jit_state_t *_jit, *oldjit; jit_node_t *start_of_block; bool skip_next = false; - void *old_fn; + void *old_fn, *new_fn; unsigned int i, j; u32 offset; @@ -1326,12 +1409,16 @@ int lightrec_compile_block(struct lightrec_cstate *cstate, jit_ret(); jit_epilog(); - block->function = lightrec_emit_code(state, _jit, - &block->code_size); - if (!block->function) { - pr_err("Unable to compile block!\n"); + new_fn = lightrec_emit_code(state, block, _jit, &block->code_size); + if (!new_fn) { + if (!ENABLE_THREADED_COMPILER) + pr_err("Unable to compile block!\n"); + block->_jit = oldjit; + _jit_destroy_state(_jit); + return -ENOMEM; } + block->function = new_fn; block->flags &= ~BLOCK_SHOULD_RECOMPILE; /* Add compiled function to the LUT */ @@ -1504,8 +1591,10 @@ void lightrec_free_block(struct lightrec_state *state, struct block *block) lightrec_free_opcode_list(state, block); if (block->_jit) _jit_destroy_state(block->_jit); - lightrec_free_function(state, block->function); - lightrec_unregister(MEM_FOR_CODE, block->code_size); + if (block->function) { + lightrec_free_function(state, block->function); + lightrec_unregister(MEM_FOR_CODE, block->code_size); + } lightrec_free(state, MEM_FOR_IR, sizeof(*block), block); } @@ -1539,7 +1628,7 @@ struct lightrec_state * lightrec_init(char *argv0, size_t nb, const struct lightrec_ops *ops) { - const struct lightrec_mem_map *codebuf_map; + const struct lightrec_mem_map *codebuf_map = &map[PSX_MAP_CODE_BUFFER]; struct lightrec_state *state; uintptr_t addr; void *tlsf = NULL; @@ -1552,9 +1641,8 @@ struct lightrec_state * lightrec_init(char *argv0, return NULL; } - if (ENABLE_CODE_BUFFER && nb > PSX_MAP_CODE_BUFFER) { - codebuf_map = &map[PSX_MAP_CODE_BUFFER]; - + if (ENABLE_CODE_BUFFER && nb > PSX_MAP_CODE_BUFFER + && codebuf_map->address) { tlsf = tlsf_create_with_pool(codebuf_map->address, codebuf_map->length); if (!tlsf) { @@ -1584,15 +1672,9 @@ struct lightrec_state * lightrec_init(char *argv0, state->tlsf = tlsf; state->with_32bit_lut = with_32bit_lut; -#if ENABLE_TINYMM - state->tinymm = tinymm_init(malloc, free, 4096); - if (!state->tinymm) - goto err_free_state; -#endif - state->block_cache = lightrec_blockcache_init(state); if (!state->block_cache) - goto err_free_tinymm; + goto err_free_state; if (ENABLE_THREADED_COMPILER) { state->rec = lightrec_recompiler_init(state); @@ -1668,11 +1750,7 @@ err_free_recompiler: lightrec_free_cstate(state->cstate); err_free_block_cache: lightrec_free_block_cache(state->block_cache); -err_free_tinymm: -#if ENABLE_TINYMM - tinymm_shutdown(state->tinymm); err_free_state: -#endif lightrec_unregister(MEM_FOR_LIGHTREC, sizeof(*state) + lut_elm_size(state) * CODE_LUT_SIZE); free(state); @@ -1703,9 +1781,6 @@ void lightrec_destroy(struct lightrec_state *state) if (ENABLE_CODE_BUFFER && state->tlsf) tlsf_destroy(state->tlsf); -#if ENABLE_TINYMM - tinymm_shutdown(state->tinymm); -#endif lightrec_unregister(MEM_FOR_LIGHTREC, sizeof(*state) + lut_elm_size(state) * CODE_LUT_SIZE); free(state); @@ -1714,17 +1789,23 @@ void lightrec_destroy(struct lightrec_state *state) void lightrec_invalidate(struct lightrec_state *state, u32 addr, u32 len) { u32 kaddr = kunseg(addr & ~0x3); - const struct lightrec_mem_map *map = lightrec_get_map(state, NULL, kaddr); - - if (map) { - if (map != &state->maps[PSX_MAP_KERNEL_USER_RAM]) - return; + enum psx_map idx = lightrec_get_map_idx(state, kaddr); + switch (idx) { + case PSX_MAP_MIRROR1: + case PSX_MAP_MIRROR2: + case PSX_MAP_MIRROR3: /* Handle mirrors */ - kaddr &= (state->maps[PSX_MAP_KERNEL_USER_RAM].length - 1); - - lightrec_invalidate_map(state, map, kaddr, len); + kaddr &= RAM_SIZE - 1; + fallthrough; + case PSX_MAP_KERNEL_USER_RAM: + break; + default: + return; } + + memset(lut_address(state, lut_offset(kaddr)), 0, + ((len + 3) / 4) * lut_elm_size(state)); } void lightrec_invalidate_all(struct lightrec_state *state)