From f5ee77cadf78d389ce40f00988ee9bde1d567dc7 Mon Sep 17 00:00:00 2001 From: Paul Cercueil Date: Wed, 13 Sep 2023 00:20:43 +0200 Subject: [PATCH] git subrepo pull --force deps/lightrec subrepo: subdir: "deps/lightrec" merged: "b53e0e808d" upstream: origin: "https://github.com/pcercuei/lightrec.git" branch: "master" commit: "b53e0e808d" git-subrepo: version: "0.4.6" origin: "https://github.com/ingydotnet/git-subrepo.git" commit: "110b9eb" --- deps/lightrec/.gitrepo | 4 ++-- deps/lightrec/blockcache.c | 4 ++-- deps/lightrec/emitter.c | 41 +++++++++++++++++++------------- deps/lightrec/interpreter.c | 22 +++++++++++------ deps/lightrec/lightrec-private.h | 5 ++++ deps/lightrec/lightrec.c | 26 ++++++++++---------- deps/lightrec/optimizer.c | 18 ++++++++++++++ deps/lightrec/recompiler.c | 8 +++---- 8 files changed, 84 insertions(+), 44 deletions(-) diff --git a/deps/lightrec/.gitrepo b/deps/lightrec/.gitrepo index ddebd0bf..6696c606 100644 --- a/deps/lightrec/.gitrepo +++ b/deps/lightrec/.gitrepo @@ -6,7 +6,7 @@ [subrepo] remote = https://github.com/pcercuei/lightrec.git branch = master - commit = 3eee0e1e7e5ada68f2da11b7951def4366caae38 - parent = c9f33835ba76a0578cfd388353e04c6391869e0a + commit = b53e0e808d1425d93d3430f526b9f739b1a9c42e + parent = fb865ffe3d7e066905271b7b9e678d63dc7b780e method = merge cmdver = 0.4.6 diff --git a/deps/lightrec/blockcache.c b/deps/lightrec/blockcache.c index bb58cdb1..d72d64e0 100644 --- a/deps/lightrec/blockcache.c +++ b/deps/lightrec/blockcache.c @@ -101,7 +101,7 @@ void lightrec_unregister_block(struct blockcache *cache, struct block *block) } } - pr_err("Block at PC 0x%x is not in cache\n", block->pc); + pr_err("Block at "PC_FMT" is not in cache\n", block->pc); } static bool lightrec_block_is_old(const struct lightrec_state *state, @@ -142,7 +142,7 @@ static void lightrec_free_blocks(struct blockcache *cache, if (ENABLE_THREADED_COMPILER) lightrec_recompiler_remove(state->rec, block); - pr_debug("Freeing outdated block at PC 0x%08x\n", block->pc); + pr_debug("Freeing outdated block at "PC_FMT"\n", block->pc); remove_from_code_lut(cache, block); lightrec_unregister_block(cache, block); lightrec_free_block(state, block); diff --git a/deps/lightrec/emitter.c b/deps/lightrec/emitter.c index 275ed2ac..6f482cc4 100644 --- a/deps/lightrec/emitter.c +++ b/deps/lightrec/emitter.c @@ -1240,7 +1240,7 @@ static void rec_io(struct lightrec_cstate *state, } } -static u32 rec_ram_mask(struct lightrec_state *state) +static u32 rec_ram_mask(const struct lightrec_state *state) { return (RAM_SIZE << (state->mirrors_mapped * 2)) - 1; } @@ -1264,7 +1264,7 @@ static void rec_store_memory(struct lightrec_cstate *cstate, struct opcode *op = &block->opcode_list[offset]; jit_state_t *_jit = block->_jit; union code c = op->c; - u8 rs, rt, tmp, tmp2, tmp3, addr_reg, addr_reg2; + u8 rs, rt, tmp = 0, tmp2 = 0, tmp3, addr_reg, addr_reg2; s16 imm = (s16)c.i.imm; s32 simm = (s32)imm << (1 - lut_is_32bit(state)); s32 lut_offt = offsetof(struct lightrec_state, code_lut); @@ -1369,7 +1369,7 @@ static void rec_store_ram(struct lightrec_cstate *cstate, u16 offset, jit_code_t code, jit_code_t swap_code, bool invalidate) { - struct lightrec_state *state = cstate->state; + const struct lightrec_state *state = cstate->state; _jit_note(block->_jit, __FILE__, __LINE__); @@ -1405,7 +1405,7 @@ static void rec_store_direct_no_invalidate(struct lightrec_cstate *cstate, u16 offset, jit_code_t code, jit_code_t swap_code) { - struct lightrec_state *state = cstate->state; + const struct lightrec_state *state = cstate->state; struct regcache *reg_cache = cstate->reg_cache; union code c = block->opcode_list[offset].c; jit_state_t *_jit = block->_jit; @@ -1482,7 +1482,7 @@ static void rec_store_direct_no_invalidate(struct lightrec_cstate *cstate, static void rec_store_direct(struct lightrec_cstate *cstate, const struct block *block, u16 offset, jit_code_t code, jit_code_t swap_code) { - struct lightrec_state *state = cstate->state; + 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; @@ -1492,6 +1492,7 @@ static void rec_store_direct(struct lightrec_cstate *cstate, const struct block u8 tmp, tmp2, tmp3, masked_reg, rs, rt; u8 in_reg = swc2 ? REG_TEMP : c.i.rt; u32 addr_mask = 0x1f800000 | (ram_size - 1); + bool different_offsets = state->offset_ram != state->offset_scratch; s32 reg_imm; jit_note(__FILE__, __LINE__); @@ -1514,7 +1515,7 @@ static void rec_store_direct(struct lightrec_cstate *cstate, const struct block lightrec_free_reg(reg_cache, reg_imm); tmp = lightrec_alloc_reg_temp(reg_cache, _jit); - if (state->offset_ram != state->offset_scratch) { + if (different_offsets) { to_not_ram = jit_bgti(tmp2, ram_size); masked_reg = tmp2; } else { @@ -1539,7 +1540,7 @@ static void rec_store_direct(struct lightrec_cstate *cstate, const struct block else jit_stxi(offsetof(struct lightrec_state, code_lut), tmp, tmp3); - if (state->offset_ram != state->offset_scratch) { + if (different_offsets) { jit_movi(tmp, state->offset_ram); to_end = jit_b(); @@ -1549,7 +1550,7 @@ static void rec_store_direct(struct lightrec_cstate *cstate, const struct block if (state->offset_ram || state->offset_scratch) jit_movi(tmp, state->offset_scratch); - if (state->offset_ram != state->offset_scratch) + if (different_offsets) jit_patch(to_end); if (state->offset_ram || state->offset_scratch) @@ -1784,13 +1785,14 @@ static void rec_load_direct(struct lightrec_cstate *cstate, jit_code_t code, jit_code_t swap_code, bool is_unsigned) { - struct lightrec_state *state = cstate->state; + const 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; jit_state_t *_jit = block->_jit; jit_node_t *to_not_ram, *to_not_bios, *to_end, *to_end2; u8 tmp, rs, rt, out_reg, addr_reg, flags = REG_EXT; + bool different_offsets = state->offset_bios != state->offset_scratch; union code c = op->c; s32 addr_mask; u32 reg_imm; @@ -1872,7 +1874,7 @@ static void rec_load_direct(struct lightrec_cstate *cstate, jit_patch(to_not_ram); - if (state->offset_bios != state->offset_scratch) + if (different_offsets) to_not_bios = jit_bmci(addr_reg, BIT(22)); /* Convert to KUNSEG */ @@ -1880,7 +1882,7 @@ static void rec_load_direct(struct lightrec_cstate *cstate, jit_movi(tmp, state->offset_bios); - if (state->offset_bios != state->offset_scratch) { + if (different_offsets) { to_end2 = jit_b(); jit_patch(to_not_bios); @@ -2730,12 +2732,19 @@ static void rec_meta_MULT2(struct lightrec_cstate *state, hi = lightrec_alloc_reg_out(reg_cache, _jit, reg_hi, hiflags); - if (c.r.op >= 32) + if (c.r.op >= 32) { jit_lshi(hi, rs, c.r.op - 32); - else if (is_signed) - jit_rshi(hi, rs, 32 - c.r.op); - else - jit_rshi_u(hi, rs, 32 - c.r.op); + } else if (is_signed) { + if (c.r.op) + jit_rshi(hi, rs, 32 - c.r.op); + else + jit_rshi(hi, rs, 31); + } else { + if (c.r.op) + jit_rshi_u(hi, rs, 32 - c.r.op); + else + jit_movi(hi, 0); + } lightrec_free_reg(reg_cache, hi); } diff --git a/deps/lightrec/interpreter.c b/deps/lightrec/interpreter.c index 2112b553..247fdb65 100644 --- a/deps/lightrec/interpreter.c +++ b/deps/lightrec/interpreter.c @@ -155,7 +155,7 @@ static u32 int_delay_slot(struct interpreter *inter, u32 pc, bool branch) bool run_first_op = false, dummy_ld = false, save_rs = false, load_in_ds, branch_in_ds = false, branch_at_addr = false, branch_taken; - u32 old_rs, new_rt, new_rs = 0; + u32 new_rt, old_rs = 0, new_rs = 0; u32 next_pc, ds_next_pc; u32 cause, epc; @@ -997,12 +997,20 @@ static u32 int_META_MULT2(struct interpreter *inter) } if (!op_flag_no_hi(inter->op->flags)) { - if (c.r.op >= 32) + if (c.r.op >= 32) { reg_cache[reg_hi] = rs << (c.r.op - 32); - else if (c.i.op == OP_META_MULT2) - reg_cache[reg_hi] = (s32) rs >> (32 - c.r.op); - else - reg_cache[reg_hi] = rs >> (32 - c.r.op); + } + else if (c.i.op == OP_META_MULT2) { + if (c.r.op) + reg_cache[reg_hi] = (s32) rs >> (32 - c.r.op); + else + reg_cache[reg_hi] = (s32) rs >> 31; + } else { + if (c.r.op) + reg_cache[reg_hi] = rs >> (32 - c.r.op); + else + reg_cache[reg_hi] = 0; + } } return jump_next(inter); @@ -1205,7 +1213,7 @@ u32 lightrec_emulate_block(struct lightrec_state *state, struct block *block, u3 if (offset < block->nb_ops) return lightrec_emulate_block_list(state, block, offset); - pr_err("PC 0x%x is outside block at PC 0x%x\n", pc, block->pc); + pr_err(PC_FMT" is outside block at "PC_FMT"\n", pc, block->pc); lightrec_set_exit_flags(state, LIGHTREC_EXIT_SEGFAULT); diff --git a/deps/lightrec/lightrec-private.h b/deps/lightrec/lightrec-private.h index 456d7af2..0df9f938 100644 --- a/deps/lightrec/lightrec-private.h +++ b/deps/lightrec/lightrec-private.h @@ -20,6 +20,11 @@ #include #endif +#include +#include + +#define PC_FMT "PC 0x%08"PRIx32 + #define ARRAY_SIZE(x) (sizeof(x) ? sizeof(x) / sizeof((x)[0]) : 0) #define GENMASK(h, l) \ diff --git a/deps/lightrec/lightrec.c b/deps/lightrec/lightrec.c index 79db4477..5cf45983 100644 --- a/deps/lightrec/lightrec.c +++ b/deps/lightrec/lightrec.c @@ -94,9 +94,9 @@ static void __segfault_cb(struct lightrec_state *state, u32 addr, { lightrec_set_exit_flags(state, LIGHTREC_EXIT_SEGFAULT); pr_err("Segmentation fault in recompiled code: invalid " - "load/store at address 0x%08x\n", addr); + "load/store at address "PC_FMT"\n", addr); if (block) - pr_err("Was executing block PC 0x%08x\n", block->pc); + pr_err("Was executing block "PC_FMT"\n", block->pc); } static void lightrec_swl(struct lightrec_state *state, @@ -290,7 +290,7 @@ u32 lightrec_rw(struct lightrec_state *state, union code op, u32 base, old_flags = block_set_flags(block, BLOCK_SHOULD_RECOMPILE); if (!(old_flags & BLOCK_SHOULD_RECOMPILE)) { - pr_debug("Opcode of block at PC 0x%08x has been tagged" + pr_debug("Opcode of block at "PC_FMT" has been tagged" " - flag for recompilation\n", block->pc); lut_write(state, lut_offset(block->pc), NULL); @@ -378,7 +378,7 @@ static void lightrec_rw_generic_cb(struct lightrec_state *state, u32 arg) block = lightrec_find_block_from_lut(state->block_cache, 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", + pr_err("rw_generic: No block found in LUT for "PC_FMT" offset 0x%"PRIx16"\n", state->curr_pc, offset); lightrec_set_exit_flags(state, LIGHTREC_EXIT_SEGFAULT); return; @@ -665,7 +665,7 @@ static struct block * lightrec_get_block(struct lightrec_state *state, u32 pc) u8 old_flags; if (block && lightrec_block_is_outdated(state, block)) { - pr_debug("Block at PC 0x%08x is outdated!\n", block->pc); + pr_debug("Block at "PC_FMT" is outdated!\n", block->pc); old_flags = block_set_flags(block, BLOCK_IS_DEAD); if (!(old_flags & BLOCK_IS_DEAD)) { @@ -685,7 +685,7 @@ static struct block * lightrec_get_block(struct lightrec_state *state, u32 pc) if (!block) { block = lightrec_precompile_block(state, pc); if (!block) { - pr_err("Unable to recompile block at PC 0x%x\n", pc); + pr_err("Unable to recompile block at "PC_FMT"\n", pc); lightrec_set_exit_flags(state, LIGHTREC_EXIT_SEGFAULT); return NULL; } @@ -724,7 +724,7 @@ static void * get_next_block_func(struct lightrec_state *state, u32 pc) !block_has_flag(block, BLOCK_IS_DEAD); if (unlikely(should_recompile)) { - pr_debug("Block at PC 0x%08x should recompile\n", pc); + pr_debug("Block at "PC_FMT" should recompile\n", pc); if (ENABLE_THREADED_COMPILER) { lightrec_recompiler_add(state->rec, block); @@ -1018,12 +1018,12 @@ static u32 lightrec_memset(struct lightrec_state *state) u32 length = state->regs.gpr[5] * 4; if (!map) { - pr_err("Unable to find memory map for memset target address " - "0x%x\n", kunseg_pc); + pr_err("Unable to find memory map for memset target address "PC_FMT"\n", + kunseg_pc); return 0; } - pr_debug("Calling host memset, PC 0x%x (host address 0x%" PRIxPTR ") for %u bytes\n", + pr_debug("Calling host memset, "PC_FMT" (host address 0x%"PRIxPTR") for %u bytes\n", kunseg_pc, (uintptr_t)host, length); memset(host, 0, length); @@ -1046,7 +1046,7 @@ static u32 lightrec_check_load_delay(struct lightrec_state *state, u32 pc, u8 re } else { block = lightrec_get_block(state, pc); if (unlikely(!block)) { - pr_err("Unable to get block at PC 0x%08x\n", pc); + pr_err("Unable to get block at "PC_FMT"\n", pc); lightrec_set_exit_flags(state, LIGHTREC_EXIT_SEGFAULT); pc = 0; } else { @@ -1497,7 +1497,7 @@ static void lightrec_reap_block(struct lightrec_state *state, void *data) { struct block *block = data; - pr_debug("Reap dead block at PC 0x%08x\n", block->pc); + pr_debug("Reap dead block at "PC_FMT"\n", block->pc); lightrec_unregister_block(state->block_cache, block); lightrec_free_block(state, block); } @@ -1717,7 +1717,7 @@ int lightrec_compile_block(struct lightrec_cstate *cstate, old_flags = block_set_flags(block, BLOCK_NO_OPCODE_LIST); if (fully_tagged && !(old_flags & BLOCK_NO_OPCODE_LIST)) { - pr_debug("Block PC 0x%08x is fully tagged" + pr_debug("Block "PC_FMT" is fully tagged" " - free opcode list\n", block->pc); if (ENABLE_THREADED_COMPILER) { diff --git a/deps/lightrec/optimizer.c b/deps/lightrec/optimizer.c index 38d77d8e..c01e024b 100644 --- a/deps/lightrec/optimizer.c +++ b/deps/lightrec/optimizer.c @@ -867,6 +867,12 @@ static void lightrec_reset_syncs(struct block *block) } } +static void maybe_remove_load_delay(struct opcode *op) +{ + if (op_flag_load_delay(op->flags) && opcode_is_load(op->c)) + op->flags &= ~LIGHTREC_LOAD_DELAY; +} + static int lightrec_transform_ops(struct lightrec_state *state, struct block *block) { struct opcode *op, *list = block->opcode_list; @@ -907,6 +913,9 @@ static int lightrec_transform_ops(struct lightrec_state *state, struct block *bl (v[op->i.rs].value ^ v[op->i.rt].value)) { pr_debug("Found never-taken BEQ\n"); + if (!op_flag_no_ds(op->flags)) + maybe_remove_load_delay(&list[i + 1]); + local = op_flag_local_branch(op->flags); op->opcode = 0; op->flags = 0; @@ -931,6 +940,9 @@ static int lightrec_transform_ops(struct lightrec_state *state, struct block *bl v[op->i.rs].value == v[op->i.rt].value) { pr_debug("Found never-taken BNE\n"); + if (!op_flag_no_ds(op->flags)) + maybe_remove_load_delay(&list[i + 1]); + local = op_flag_local_branch(op->flags); op->opcode = 0; op->flags = 0; @@ -959,6 +971,9 @@ static int lightrec_transform_ops(struct lightrec_state *state, struct block *bl v[op->i.rs].value & BIT(31)) { pr_debug("Found never-taken BGTZ\n"); + if (!op_flag_no_ds(op->flags)) + maybe_remove_load_delay(&list[i + 1]); + local = op_flag_local_branch(op->flags); op->opcode = 0; op->flags = 0; @@ -1017,6 +1032,9 @@ static int lightrec_transform_ops(struct lightrec_state *state, struct block *bl } else { pr_debug("Found never-taken BLTZ/BGEZ\n"); + if (!op_flag_no_ds(op->flags)) + maybe_remove_load_delay(&list[i + 1]); + local = op_flag_local_branch(op->flags); op->opcode = 0; op->flags = 0; diff --git a/deps/lightrec/recompiler.c b/deps/lightrec/recompiler.c index 08a9235a..c764f119 100644 --- a/deps/lightrec/recompiler.c +++ b/deps/lightrec/recompiler.c @@ -159,7 +159,7 @@ static void lightrec_compile_list(struct recompiler *rec, } if (ret) { - pr_err("Unable to compile block at PC 0x%x: %d\n", + pr_err("Unable to compile block at "PC_FMT": %d\n", block->pc, ret); } } @@ -361,7 +361,7 @@ int lightrec_recompiler_add(struct recompiler *rec, struct block *block) goto out_unlock; } - pr_debug("Adding block PC 0x%x to recompiler\n", block->pc); + pr_debug("Adding block "PC_FMT" to recompiler\n", block->pc); block_rec->block = block; block_rec->compiling = false; @@ -438,7 +438,7 @@ void * lightrec_recompiler_run_first_pass(struct lightrec_state *state, old_flags = block_set_flags(block, BLOCK_NO_OPCODE_LIST); if (!(old_flags & BLOCK_NO_OPCODE_LIST)) { - pr_debug("Block PC 0x%08x is fully tagged" + pr_debug("Block "PC_FMT" is fully tagged" " - free opcode list\n", block->pc); /* The block was already compiled but the opcode list @@ -466,7 +466,7 @@ void * lightrec_recompiler_run_first_pass(struct lightrec_state *state, old_flags = block_set_flags(block, BLOCK_NO_OPCODE_LIST); if (!(old_flags & BLOCK_NO_OPCODE_LIST)) { - pr_debug("Block PC 0x%08x is fully tagged" + pr_debug("Block "PC_FMT" is fully tagged" " - free opcode list\n", block->pc); lightrec_free_opcode_list(state, block->opcode_list); -- 2.39.2