From 878e6cda26bbf4af5090a01709db026d42c233b4 Mon Sep 17 00:00:00 2001 From: Paul Cercueil Date: Fri, 17 May 2024 19:33:45 +0200 Subject: [PATCH] git subrepo pull --force deps/lightrec subrepo: subdir: "deps/lightrec" merged: "8d3db1a4e7" upstream: origin: "https://github.com/pcercuei/lightrec.git" branch: "master" commit: "8d3db1a4e7" git-subrepo: version: "0.4.6" origin: "https://github.com/ingydotnet/git-subrepo.git" commit: "110b9eb" --- deps/lightrec/.gitrepo | 4 +- deps/lightrec/CMakeLists.txt | 104 ++++++++++++++-------------- deps/lightrec/blockcache.c | 7 +- deps/lightrec/blockcache.h | 2 + deps/lightrec/constprop.c | 6 +- deps/lightrec/emitter.c | 108 ++++++++++++++---------------- deps/lightrec/lightning-wrapper.h | 8 --- deps/lightrec/lightrec.c | 68 +++++++++++++------ deps/lightrec/optimizer.c | 10 +-- deps/lightrec/recompiler.c | 27 ++++++-- deps/lightrec/recompiler.h | 3 + deps/lightrec/regcache.h | 9 +-- 12 files changed, 197 insertions(+), 159 deletions(-) diff --git a/deps/lightrec/.gitrepo b/deps/lightrec/.gitrepo index 1f5764a3..73ce0b72 100644 --- a/deps/lightrec/.gitrepo +++ b/deps/lightrec/.gitrepo @@ -6,7 +6,7 @@ [subrepo] remote = https://github.com/pcercuei/lightrec.git branch = master - commit = d88760e40c1d2a5698c7b6f6a53cce31fda799f0 - parent = 963f41620dce6ddb2527b7e3dced09564031f783 + commit = 8d3db1a4e76c7b81301013f18650011b7e5eabf3 + parent = fcd42d7decc2ed71801e4cbe575c4d2726b2743e method = merge cmdver = 0.4.6 diff --git a/deps/lightrec/CMakeLists.txt b/deps/lightrec/CMakeLists.txt index 9ca058ec..c3eb6f8f 100644 --- a/deps/lightrec/CMakeLists.txt +++ b/deps/lightrec/CMakeLists.txt @@ -1,31 +1,5 @@ cmake_minimum_required(VERSION 3.5) -project(lightrec LANGUAGES C VERSION 0.8) - -set(BUILD_SHARED_LIBS ON CACHE BOOL "Build shared libraries") -if (NOT BUILD_SHARED_LIBS) - add_definitions(-DLIGHTREC_STATIC) -endif (NOT BUILD_SHARED_LIBS) - -if (NOT LOG_LEVEL) - set(LOG_LEVEL Info CACHE STRING "Log level" FORCE) - set_property(CACHE LOG_LEVEL PROPERTY STRINGS NoLog Error Warning Info Debug) -endif() - -if (NOT CMAKE_BUILD_TYPE) - set(CMAKE_BUILD_TYPE RelWithDebInfo CACHE STRING - "Choose the type of build, options are: None(CMAKE_CXX_FLAGS or CMAKE_C_FLAGS used) Debug Release RelWithDebInfo MinSizeRel." - FORCE) - set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS None Debug Release RelWithDebInfo MinSizeRel) -endif() - -string(TOUPPER ${LOG_LEVEL} LIGHTREC_LOG_LEVEL) -add_definitions(-DLOG_LEVEL=${LIGHTREC_LOG_LEVEL}_L) - -if (CMAKE_COMPILER_IS_GNUCC) - add_compile_options(-fvisibility=hidden) -endif() - -set(HAS_DEFAULT_ELM ${CMAKE_COMPILER_IS_GNUCC}) +project(lightrec LANGUAGES C VERSION 0.9) list(APPEND LIGHTREC_SOURCES blockcache.c @@ -52,11 +26,47 @@ list(APPEND LIGHTREC_HEADERS regcache.h ) +add_library(lightrec ${LIGHTREC_SOURCES} ${LIGHTREC_HEADERS}) +set_target_properties(lightrec PROPERTIES + VERSION ${PROJECT_VERSION} + SOVERSION ${PROJECT_VERSION_MAJOR} + PUBLIC_HEADER lightrec.h + C_STANDARD 11 + C_STANDARD_REQUIRED ON + C_EXTENSIONS OFF +) + +set(BUILD_SHARED_LIBS ON CACHE BOOL "Build shared libraries") +if (NOT BUILD_SHARED_LIBS) + target_compile_definitions(lightrec PRIVATE LIGHTREC_STATIC) +endif (NOT BUILD_SHARED_LIBS) + +if (NOT LOG_LEVEL) + set(LOG_LEVEL Info CACHE STRING "Log level" FORCE) + set_property(CACHE LOG_LEVEL PROPERTY STRINGS NoLog Error Warning Info Debug) +endif() + +if (NOT CMAKE_BUILD_TYPE) + set(CMAKE_BUILD_TYPE RelWithDebInfo CACHE STRING + "Choose the type of build, options are: None(CMAKE_CXX_FLAGS or CMAKE_C_FLAGS used) Debug Release RelWithDebInfo MinSizeRel." + FORCE) + set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS None Debug Release RelWithDebInfo MinSizeRel) +endif() + +string(TOUPPER ${LOG_LEVEL} LIGHTREC_LOG_LEVEL) +target_compile_definitions(lightrec PRIVATE LOG_LEVEL=${LIGHTREC_LOG_LEVEL}_L) + +if (CMAKE_COMPILER_IS_GNUCC) + target_compile_options(lightrec PRIVATE -fvisibility=hidden) +endif() + +set(HAS_DEFAULT_ELM ${CMAKE_COMPILER_IS_GNUCC}) + option(ENABLE_FIRST_PASS "Run the interpreter as first-pass optimization" ON) option(ENABLE_THREADED_COMPILER "Enable threaded compiler" ON) if (ENABLE_THREADED_COMPILER) - list(APPEND LIGHTREC_SOURCES recompiler.c reaper.c) + target_sources(lightrec PRIVATE recompiler.c reaper.c) if (NOT ENABLE_FIRST_PASS) message(SEND_ERROR "Threaded compiler requires first-pass optimization") @@ -75,54 +85,46 @@ option(OPT_FLAG_MULT_DIV "(optimization) Flag MULT/DIV that only use one of HI/L option(OPT_EARLY_UNLOAD "(optimization) Unload registers early" ON) option(OPT_PRELOAD_PC "(optimization) Preload PC value into register" ON) -include_directories(${CMAKE_CURRENT_BINARY_DIR}) - -add_library(${PROJECT_NAME} ${LIGHTREC_SOURCES} ${LIGHTREC_HEADERS}) -set_target_properties(${PROJECT_NAME} PROPERTIES - VERSION ${PROJECT_VERSION} - SOVERSION ${PROJECT_VERSION_MAJOR} - PUBLIC_HEADER lightrec.h - C_STANDARD 11 - C_STANDARD_REQUIRED ON - C_EXTENSIONS OFF -) +target_include_directories(lightrec PRIVATE ${CMAKE_CURRENT_BINARY_DIR}) if (CMAKE_C_COMPILER_ID MATCHES "GNU|Clang") - target_compile_options(${PROJECT_NAME} PRIVATE -Wall) + target_compile_options(lightrec PRIVATE -Wall) endif() if (CMAKE_C_COMPILER_ID STREQUAL "Clang") - target_compile_options(${PROJECT_NAME} PRIVATE -Wno-initializer-overrides) + target_compile_options(lightrec PRIVATE -Wno-initializer-overrides) endif() if (ENABLE_THREADED_COMPILER) - find_library(PTHREAD_LIBRARIES pthread REQUIRED) - find_path(PTHREAD_INCLUDE_DIR pthread.h REQUIRED) + include(FindThreads) + + if (NOT CMAKE_USE_PTHREADS_INIT) + message(SEND_ERROR "Could not find compatible threads library") + endif() - include_directories(${PTHREAD_INCLUDE_DIR}) - target_link_libraries(${PROJECT_NAME} PRIVATE ${PTHREAD_LIBRARIES}) + target_link_libraries(lightrec PUBLIC Threads::Threads) endif (ENABLE_THREADED_COMPILER) option(ENABLE_CODE_BUFFER "Enable external code buffer" ON) if (ENABLE_CODE_BUFFER) - target_sources(${PROJECT_NAME} PRIVATE tlsf/tlsf.c) - target_include_directories(${PROJECT_NAME} PRIVATE tlsf) + target_sources(lightrec PRIVATE tlsf/tlsf.c) + target_include_directories(lightrec PRIVATE tlsf) endif (ENABLE_CODE_BUFFER) find_library(LIBLIGHTNING lightning REQUIRED) find_path(LIBLIGHTNING_INCLUDE_DIR lightning.h REQUIRED) -include_directories(${LIBLIGHTNING_INCLUDE_DIR}) -target_link_libraries(${PROJECT_NAME} PRIVATE ${LIBLIGHTNING}) +target_include_directories(lightrec PUBLIC ${LIBLIGHTNING_INCLUDE_DIR}) +target_link_libraries(lightrec PUBLIC ${LIBLIGHTNING}) if (LOG_LEVEL STREQUAL Debug) set(ENABLE_DISASSEMBLER ON) - target_sources(${PROJECT_NAME} PRIVATE disassembler.c) + target_sources(lightrec PRIVATE disassembler.c) endif() configure_file(lightrec-config.h.cmakein lightrec-config.h @ONLY) include(GNUInstallDirs) -install(TARGETS ${PROJECT_NAME} +install(TARGETS lightrec ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} diff --git a/deps/lightrec/blockcache.c b/deps/lightrec/blockcache.c index d72d64e0..ecfe80e8 100644 --- a/deps/lightrec/blockcache.c +++ b/deps/lightrec/blockcache.c @@ -159,9 +159,14 @@ void lightrec_remove_outdated_blocks(struct blockcache *cache, lightrec_free_blocks(cache, except, false); } -void lightrec_free_block_cache(struct blockcache *cache) +void lightrec_free_all_blocks(struct blockcache *cache) { lightrec_free_blocks(cache, NULL, true); +} + +void lightrec_free_block_cache(struct blockcache *cache) +{ + lightrec_free_all_blocks(cache); lightrec_free(cache->state, MEM_FOR_LIGHTREC, sizeof(*cache), cache); } diff --git a/deps/lightrec/blockcache.h b/deps/lightrec/blockcache.h index 2e55ff65..3859fb8e 100644 --- a/deps/lightrec/blockcache.h +++ b/deps/lightrec/blockcache.h @@ -21,6 +21,8 @@ void lightrec_unregister_block(struct blockcache *cache, struct block *block); struct blockcache * lightrec_blockcache_init(struct lightrec_state *state); void lightrec_free_block_cache(struct blockcache *cache); +void lightrec_free_all_blocks(struct blockcache *cache); + u32 lightrec_calculate_block_hash(const struct block *block); _Bool lightrec_block_is_outdated(struct lightrec_state *state, struct block *block); diff --git a/deps/lightrec/constprop.c b/deps/lightrec/constprop.c index 19403a69..b21339aa 100644 --- a/deps/lightrec/constprop.c +++ b/deps/lightrec/constprop.c @@ -335,8 +335,9 @@ void lightrec_consts_propagate(const struct block *block, case OP_SPECIAL_SRA: v[c.r.rd].value = (s32)v[c.r.rt].value >> c.r.imm; + v[c.r.rd].sign = (s32)(v[c.r.rt].sign + | (~v[c.r.rt].known & 0x80000000)) >> c.r.imm; v[c.r.rd].known = (s32)v[c.r.rt].known >> c.r.imm; - v[c.r.rd].sign = (s32)v[c.r.rt].sign >> c.r.imm; break; case OP_SPECIAL_SLLV: @@ -370,8 +371,9 @@ void lightrec_consts_propagate(const struct block *block, if ((v[c.r.rs].known & 0x1f) == 0x1f) { imm = v[c.r.rs].value & 0x1f; v[c.r.rd].value = (s32)v[c.r.rt].value >> imm; + v[c.r.rd].sign = (s32)(v[c.r.rt].sign + | (~v[c.r.rt].known & 0x80000000)) >> imm; v[c.r.rd].known = (s32)v[c.r.rt].known >> imm; - v[c.r.rd].sign = (s32)v[c.r.rt].sign >> imm; } else { v[c.r.rd].known = 0; v[c.r.rd].sign = 0; diff --git a/deps/lightrec/emitter.c b/deps/lightrec/emitter.c index 3875e58e..e1a176c3 100644 --- a/deps/lightrec/emitter.c +++ b/deps/lightrec/emitter.c @@ -1258,12 +1258,36 @@ static u32 rec_io_mask(const struct lightrec_state *state) return 0x1f800000 | GENMASK(31 - clz32(length - 1), 0); } +static void rec_add_offset(struct lightrec_cstate *cstate, + jit_state_t *_jit, u8 reg_out, u8 reg_in, + uintptr_t offset) +{ + struct regcache *reg_cache = cstate->reg_cache; + u8 reg_imm; + + reg_imm = lightrec_alloc_reg_temp_with_value(reg_cache, _jit, offset); + jit_addr(reg_out, reg_in, reg_imm); + + lightrec_free_reg(reg_cache, reg_imm); +} + +static void rec_and_mask(struct lightrec_cstate *cstate, + jit_state_t *_jit, u8 reg_out, u8 reg_in, u32 mask) +{ + struct regcache *reg_cache = cstate->reg_cache; + u8 reg_imm; + + reg_imm = lightrec_alloc_reg_temp_with_value(reg_cache, _jit, mask); + jit_andr(reg_out, reg_in, reg_imm); + + lightrec_free_reg(reg_cache, reg_imm); +} + static void rec_store_memory(struct lightrec_cstate *cstate, const struct block *block, u16 offset, jit_code_t code, - jit_code_t swap_code, - uintptr_t addr_offset, u32 addr_mask, - bool invalidate) + jit_code_t swap_code, uintptr_t addr_offset, + u32 addr_mask, bool invalidate) { const struct lightrec_state *state = cstate->state; struct regcache *reg_cache = cstate->reg_cache; @@ -1282,7 +1306,6 @@ static void rec_store_memory(struct lightrec_cstate *cstate, bool need_tmp = !no_mask || add_imm || invalidate; bool swc2 = c.i.op == OP_SWC2; u8 in_reg = swc2 ? REG_TEMP : c.i.rt; - s8 reg_imm; rs = lightrec_alloc_reg_in(reg_cache, _jit, c.i.rs, 0); if (need_tmp) @@ -1300,23 +1323,14 @@ static void rec_store_memory(struct lightrec_cstate *cstate, } if (!no_mask) { - reg_imm = lightrec_alloc_reg_temp_with_value(reg_cache, _jit, - addr_mask); - - jit_andr(tmp, addr_reg, reg_imm); + rec_and_mask(cstate, _jit, tmp, addr_reg, addr_mask); addr_reg = tmp; - - lightrec_free_reg(reg_cache, reg_imm); } if (addr_offset) { - reg_imm = lightrec_alloc_reg_temp_with_value(reg_cache, _jit, - addr_offset); tmp2 = lightrec_alloc_reg_temp(reg_cache, _jit); - jit_addr(tmp2, addr_reg, reg_imm); + rec_add_offset(cstate, _jit, tmp2, addr_reg, addr_offset); addr_reg2 = tmp2; - - lightrec_free_reg(reg_cache, reg_imm); } else { addr_reg2 = addr_reg; } @@ -1419,39 +1433,32 @@ static void rec_store_direct_no_invalidate(struct lightrec_cstate *cstate, jit_code_t swap_code) { const struct lightrec_state *state = cstate->state; + u32 ram_size = state->mirrors_mapped ? RAM_SIZE * 4 : RAM_SIZE; struct regcache *reg_cache = cstate->reg_cache; union code c = block->opcode_list[offset].c; jit_state_t *_jit = block->_jit; jit_node_t *to_not_ram, *to_end; bool swc2 = c.i.op == OP_SWC2; - u8 tmp, tmp2 = 0, rs, rt, in_reg = swc2 ? REG_TEMP : c.i.rt; - u32 addr_mask; - s32 reg_imm; + u8 addr_reg, tmp, tmp2 = 0, rs, rt, in_reg = swc2 ? REG_TEMP : c.i.rt; s16 imm; jit_note(__FILE__, __LINE__); rs = lightrec_alloc_reg_in(reg_cache, _jit, c.i.rs, 0); tmp = lightrec_alloc_reg_temp(reg_cache, _jit); - if (state->mirrors_mapped) - addr_mask = 0x1f800000 | (4 * RAM_SIZE - 1); - else - addr_mask = 0x1f800000 | (RAM_SIZE - 1); - - reg_imm = lightrec_alloc_reg_temp_with_value(reg_cache, _jit, addr_mask); - /* Convert to KUNSEG and avoid RAM mirrors */ if ((c.i.op == OP_META_SWU || !state->mirrors_mapped) && c.i.imm) { imm = 0; jit_addi(tmp, rs, (s16)c.i.imm); - jit_andr(tmp, tmp, reg_imm); + addr_reg = tmp; } else { imm = (s16)c.i.imm; - jit_andr(tmp, rs, reg_imm); + addr_reg = rs; } + rec_and_mask(cstate, _jit, tmp, addr_reg, 0x1f800000 | (ram_size - 1)); + lightrec_free_reg(reg_cache, rs); - lightrec_free_reg(reg_cache, reg_imm); if (state->offset_ram != state->offset_scratch) { tmp2 = lightrec_alloc_reg_temp(reg_cache, _jit); @@ -1508,11 +1515,10 @@ static void rec_store_direct(struct lightrec_cstate *cstate, const struct block jit_state_t *_jit = block->_jit; jit_node_t *to_not_ram, *to_end; bool swc2 = c.i.op == OP_SWC2; - u8 tmp, tmp2, tmp3, masked_reg, rs, rt; + u8 addr_reg, tmp, tmp2, tmp3, rs, rt, reg_imm; u8 in_reg = swc2 ? REG_TEMP : c.i.rt; - u32 addr_mask = 0x1f800000 | (ram_size - 1); + u32 mask; bool different_offsets = state->offset_ram != state->offset_scratch; - s32 reg_imm; jit_note(__FILE__, __LINE__); @@ -1520,34 +1526,33 @@ static void rec_store_direct(struct lightrec_cstate *cstate, const struct block tmp2 = lightrec_alloc_reg_temp(reg_cache, _jit); tmp3 = lightrec_alloc_reg_in(reg_cache, _jit, 0, 0); - reg_imm = lightrec_alloc_reg_temp_with_value(reg_cache, _jit, addr_mask); - /* Convert to KUNSEG and avoid RAM mirrors */ if (c.i.imm) { jit_addi(tmp2, rs, (s16)c.i.imm); - jit_andr(tmp2, tmp2, reg_imm); + addr_reg = tmp2; } else { - jit_andr(tmp2, rs, reg_imm); + addr_reg = rs; } + rec_and_mask(cstate, _jit, tmp2, addr_reg, 0x1f800000 | (ram_size - 1)); + lightrec_free_reg(reg_cache, rs); - lightrec_free_reg(reg_cache, reg_imm); tmp = lightrec_alloc_reg_temp(reg_cache, _jit); + mask = c.i.op == OP_SW ? RAM_SIZE - 1 : (RAM_SIZE - 1) & ~3; + reg_imm = lightrec_alloc_reg_temp_with_value(reg_cache, _jit, mask); + if (different_offsets) { to_not_ram = jit_bgti(tmp2, ram_size); - masked_reg = tmp2; + addr_reg = tmp2; } else { jit_lti_u(tmp, tmp2, ram_size); jit_movnr(tmp, tmp2, tmp); - masked_reg = tmp; + addr_reg = tmp; } /* Compute the offset to the code LUT */ - if (c.i.op == OP_SW) - jit_andi(tmp, masked_reg, RAM_SIZE - 1); - else - jit_andi(tmp, masked_reg, (RAM_SIZE - 1) & ~3); + jit_andr(tmp, addr_reg, reg_imm); if (!lut_is_32bit(state)) jit_lshi(tmp, tmp, 1); @@ -1589,6 +1594,7 @@ static void rec_store_direct(struct lightrec_cstate *cstate, const struct block lightrec_free_reg(reg_cache, tmp); lightrec_free_reg(reg_cache, tmp3); + lightrec_free_reg(reg_cache, reg_imm); rt = lightrec_alloc_reg_in(reg_cache, _jit, in_reg, 0); @@ -1710,6 +1716,7 @@ static void rec_load_memory(struct lightrec_cstate *cstate, jit_code_t code, jit_code_t swap_code, bool is_unsigned, uintptr_t addr_offset, u32 addr_mask) { + struct lightrec_state *state = cstate->state; struct regcache *reg_cache = cstate->reg_cache; struct opcode *op = &block->opcode_list[offset]; bool load_delay = op_flag_load_delay(op->flags) && !cstate->no_load_delay; @@ -1717,7 +1724,6 @@ static void rec_load_memory(struct lightrec_cstate *cstate, u8 rs, rt, out_reg, addr_reg, flags = REG_EXT; bool no_mask = op_flag_no_mask(op->flags); union code c = op->c; - s8 reg_imm; s16 imm; if (load_delay || c.i.op == OP_LWC2) @@ -1734,7 +1740,7 @@ static void rec_load_memory(struct lightrec_cstate *cstate, rt = lightrec_alloc_reg_out(reg_cache, _jit, out_reg, flags); if ((op->i.op == OP_META_LWU && c.i.imm) - || (!cstate->state->mirrors_mapped && c.i.imm && !no_mask)) { + || (!state->mirrors_mapped && c.i.imm && !no_mask)) { jit_addi(rt, rs, (s16)c.i.imm); addr_reg = rt; imm = 0; @@ -1747,23 +1753,13 @@ static void rec_load_memory(struct lightrec_cstate *cstate, imm = LIGHTNING_UNALIGNED_32BIT; if (!no_mask) { - reg_imm = lightrec_alloc_reg_temp_with_value(reg_cache, _jit, - addr_mask); - - jit_andr(rt, addr_reg, reg_imm); + rec_and_mask(cstate, _jit, rt, addr_reg, addr_mask); addr_reg = rt; - - lightrec_free_reg(reg_cache, reg_imm); } if (addr_offset) { - reg_imm = lightrec_alloc_reg_temp_with_value(reg_cache, _jit, - addr_offset); - - jit_addr(rt, addr_reg, reg_imm); + rec_add_offset(cstate, _jit, rt, addr_reg, addr_offset); addr_reg = rt; - - lightrec_free_reg(reg_cache, reg_imm); } jit_new_node_www(code, rt, addr_reg, imm); diff --git a/deps/lightrec/lightning-wrapper.h b/deps/lightrec/lightning-wrapper.h index 4cb97d3a..88e93e06 100644 --- a/deps/lightrec/lightning-wrapper.h +++ b/deps/lightrec/lightning-wrapper.h @@ -21,14 +21,6 @@ #define jit_b() jit_beqr(0, 0) -#if defined(__sh__) -#define jit_add_state(u,v) \ - do { \ - jit_new_node_ww(jit_code_movr,_R0,LIGHTREC_REG_STATE); \ - jit_new_node_www(jit_code_addr,u,v,_R0); \ - } while (0) -#else #define jit_add_state(u,v) jit_addr(u,v,LIGHTREC_REG_STATE) -#endif #endif /* __LIGHTNING_WRAPPER_H__ */ diff --git a/deps/lightrec/lightrec.c b/deps/lightrec/lightrec.c index 1cfc4274..454007b1 100644 --- a/deps/lightrec/lightrec.c +++ b/deps/lightrec/lightrec.c @@ -877,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) { @@ -904,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); @@ -933,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; @@ -1025,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; @@ -1040,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: @@ -1249,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); @@ -1323,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) @@ -1343,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: @@ -1918,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; @@ -1992,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)); @@ -2010,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 && @@ -2169,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); } diff --git a/deps/lightrec/optimizer.c b/deps/lightrec/optimizer.c index 199ca40b..cb9ba5b8 100644 --- a/deps/lightrec/optimizer.c +++ b/deps/lightrec/optimizer.c @@ -642,7 +642,7 @@ lightrec_remove_useless_lui(struct block *block, unsigned int offset, return; } - if (op->i.imm != 0 || op->i.rt == 0 || offset == block->nb_ops - 1) + if (op->i.imm != 0 || op->i.rt == 0 || is_delay_slot(list, offset)) return; reader = find_next_reader(list, offset + 1, op->i.rt); @@ -1002,10 +1002,10 @@ static int lightrec_transform_ops(struct lightrec_state *state, struct block *bl break; case OP_LUI: - if (i == 0 || !has_delay_slot(list[i - 1].c)) + if (!is_delay_slot(list, i)) lightrec_modify_lui(block, i); lightrec_remove_useless_lui(block, i, v); - if (i == 0 || !has_delay_slot(list[i - 1].c)) + if (!is_delay_slot(list, i)) lightrec_lui_to_movi(block, i); break; @@ -2099,7 +2099,7 @@ static int lightrec_flag_mults_divs(struct lightrec_state *state, struct block * list->flags &= ~(LIGHTREC_NO_LO | LIGHTREC_NO_HI); } - if (reg_lo > 0 && reg_lo != REG_LO) { + if (0/* Broken */ && reg_lo > 0 && reg_lo != REG_LO) { pr_debug("Found register %s to hold LO (rs = %u, rt = %u)\n", lightrec_reg_name(reg_lo), list->r.rs, list->r.rt); @@ -2109,7 +2109,7 @@ static int lightrec_flag_mults_divs(struct lightrec_state *state, struct block * list->r.rd = 0; } - if (reg_hi > 0 && reg_hi != REG_HI) { + if (0/* Broken */ && reg_hi > 0 && reg_hi != REG_HI) { pr_debug("Found register %s to hold HI (rs = %u, rt = %u)\n", lightrec_reg_name(reg_hi), list->r.rs, list->r.rt); diff --git a/deps/lightrec/recompiler.c b/deps/lightrec/recompiler.c index a6d2f322..1ccef7a0 100644 --- a/deps/lightrec/recompiler.c +++ b/deps/lightrec/recompiler.c @@ -38,7 +38,7 @@ struct recompiler { pthread_cond_t cond; pthread_cond_t cond2; pthread_mutex_t mutex; - bool stop, must_flush; + bool stop, pause, must_flush; struct slist_elm slist; pthread_mutex_t alloc_mutex; @@ -49,7 +49,7 @@ struct recompiler { static unsigned int get_processors_count(void) { - unsigned int nb = 1; + int nb = 1; #if defined(PTW32_VERSION) nb = pthread_num_processors_np(); @@ -59,7 +59,7 @@ static unsigned int get_processors_count(void) nb = sysctlbyname("hw.ncpu", &count, &size, NULL, 0) ? 1 : count; #elif defined(_SC_NPROCESSORS_ONLN) - nb = sysconf(_SC_NPROCESSORS_ONLN); + nb = (int)sysconf(_SC_NPROCESSORS_ONLN); #endif return nb < 1 ? 1 : nb; @@ -131,7 +131,8 @@ static void lightrec_compile_list(struct recompiler *rec, struct block *block; int ret; - while (!!(block_rec = lightrec_get_best_elm(&rec->slist))) { + while (!rec->pause && + !!(block_rec = lightrec_get_best_elm(&rec->slist))) { block_rec->compiling = true; block = block_rec->block; @@ -187,7 +188,7 @@ static void * lightrec_recompiler_thd(void *d) if (rec->stop) goto out_unlock; - } while (slist_empty(&rec->slist)); + } while (rec->pause || slist_empty(&rec->slist)); lightrec_compile_list(rec, thd); } @@ -228,6 +229,7 @@ struct recompiler *lightrec_recompiler_init(struct lightrec_state *state) rec->state = state; rec->stop = false; + rec->pause = false; rec->must_flush = false; rec->nb_recs = nb_recs; slist_init(&rec->slist); @@ -486,3 +488,18 @@ void lightrec_code_alloc_unlock(struct lightrec_state *state) { pthread_mutex_unlock(&state->rec->alloc_mutex); } + +void lightrec_recompiler_pause(struct recompiler *rec) +{ + rec->pause = true; + + pthread_mutex_lock(&rec->mutex); + pthread_cond_broadcast(&rec->cond); + lightrec_cancel_list(rec); + pthread_mutex_unlock(&rec->mutex); +} + +void lightrec_recompiler_unpause(struct recompiler *rec) +{ + rec->pause = false; +} diff --git a/deps/lightrec/recompiler.h b/deps/lightrec/recompiler.h index b9fc5798..febc0ec6 100644 --- a/deps/lightrec/recompiler.h +++ b/deps/lightrec/recompiler.h @@ -18,6 +18,9 @@ void lightrec_recompiler_remove(struct recompiler *rec, struct block *block); void * lightrec_recompiler_run_first_pass(struct lightrec_state *state, struct block *block, u32 *pc); +void lightrec_recompiler_pause(struct recompiler *rec); +void lightrec_recompiler_unpause(struct recompiler *rec); + void lightrec_code_alloc_lock(struct lightrec_state *state); void lightrec_code_alloc_unlock(struct lightrec_state *state); diff --git a/deps/lightrec/regcache.h b/deps/lightrec/regcache.h index b919ce08..4b7cb89c 100644 --- a/deps/lightrec/regcache.h +++ b/deps/lightrec/regcache.h @@ -8,13 +8,8 @@ #include "lightning-wrapper.h" -#if defined(__sh__) -# define NUM_REGS JIT_V_NUM -# define LIGHTREC_REG_STATE _GBR -#else -# define NUM_REGS (JIT_V_NUM - 1) -# define LIGHTREC_REG_STATE (JIT_V(JIT_V_NUM - 1)) -#endif +#define NUM_REGS (JIT_V_NUM - 1) +#define LIGHTREC_REG_STATE (JIT_V(JIT_V_NUM - 1)) #if defined(__powerpc__) # define NUM_TEMPS JIT_R_NUM -- 2.39.5