git subrepo pull --force deps/lightrec
authorPaul Cercueil <paul@crapouillou.net>
Fri, 17 May 2024 17:33:45 +0000 (19:33 +0200)
committerPaul Cercueil <paul@crapouillou.net>
Fri, 17 May 2024 17:33:50 +0000 (19:33 +0200)
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"

12 files changed:
deps/lightrec/.gitrepo
deps/lightrec/CMakeLists.txt
deps/lightrec/blockcache.c
deps/lightrec/blockcache.h
deps/lightrec/constprop.c
deps/lightrec/emitter.c
deps/lightrec/lightning-wrapper.h
deps/lightrec/lightrec.c
deps/lightrec/optimizer.c
deps/lightrec/recompiler.c
deps/lightrec/recompiler.h
deps/lightrec/regcache.h

index 1f5764a..73ce0b7 100644 (file)
@@ -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
index 9ca058e..c3eb6f8 100644 (file)
@@ -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}
index d72d64e..ecfe80e 100644 (file)
@@ -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);
 }
 
index 2e55ff6..3859fb8 100644 (file)
@@ -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);
 
index 19403a6..b21339a 100644 (file)
@@ -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;
index 3875e58..e1a176c 100644 (file)
@@ -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);
index 4cb97d3..88e93e0 100644 (file)
 
 #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__ */
index 1cfc427..454007b 100644 (file)
@@ -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);
 }
index 199ca40..cb9ba5b 100644 (file)
@@ -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);
 
index a6d2f32..1ccef7a 100644 (file)
@@ -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;
+}
index b9fc579..febc0ec 100644 (file)
@@ -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);
 
index b919ce0..4b7cb89 100644 (file)
@@ -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