git subrepo pull --force deps/lightrec
authorPaul Cercueil <paul@crapouillou.net>
Tue, 12 Sep 2023 22:20:43 +0000 (00:20 +0200)
committernotaz <notasas@gmail.com>
Tue, 12 Sep 2023 22:50:28 +0000 (01:50 +0300)
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
deps/lightrec/blockcache.c
deps/lightrec/emitter.c
deps/lightrec/interpreter.c
deps/lightrec/lightrec-private.h
deps/lightrec/lightrec.c
deps/lightrec/optimizer.c
deps/lightrec/recompiler.c

index ddebd0b..6696c60 100644 (file)
@@ -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
index bb58cdb..d72d64e 100644 (file)
@@ -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);
index 275ed2a..6f482cc 100644 (file)
@@ -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);
                }
index 2112b55..247fdb6 100644 (file)
@@ -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);
 
index 456d7af..0df9f93 100644 (file)
 #include <immintrin.h>
 #endif
 
+#include <inttypes.h>
+#include <stdint.h>
+
+#define PC_FMT "PC 0x%08"PRIx32
+
 #define ARRAY_SIZE(x) (sizeof(x) ? sizeof(x) / sizeof((x)[0]) : 0)
 
 #define GENMASK(h, l) \
index 79db447..5cf4598 100644 (file)
@@ -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) {
index 38d77d8..c01e024 100644 (file)
@@ -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;
index 08a9235..c764f11 100644 (file)
@@ -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);