add a thp-based huge page alloc fallback
[pcsx_rearmed.git] / deps / lightrec / emitter.c
index b7ace19..6f482cc 100644 (file)
@@ -28,13 +28,6 @@ static void rec_cp2_do_mfc2(struct lightrec_cstate *state,
                            const struct block *block, u16 offset,
                            u8 reg, u8 out_reg);
 
-static void unknown_opcode(struct lightrec_cstate *state, const struct block *block, u16 offset)
-{
-       pr_warn("Unknown opcode: 0x%08x at PC 0x%08x\n",
-               block->opcode_list[offset].c.opcode,
-               block->pc + (offset << 2));
-}
-
 static void
 lightrec_jump_to_fn(jit_state_t *_jit, void (*fn)(void))
 {
@@ -1247,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;
 }
@@ -1271,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);
@@ -1376,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__);
 
@@ -1412,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;
@@ -1489,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;
@@ -1499,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__);
@@ -1521,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 {
@@ -1546,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();
@@ -1556,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)
@@ -1791,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;
@@ -1879,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 */
@@ -1887,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);
@@ -2009,9 +2004,9 @@ static void rec_LW(struct lightrec_cstate *state, const struct block *block, u16
        rec_load(state, block, offset, code, jit_code_bswapr_ui, false);
 }
 
-static void rec_break_syscall(struct lightrec_cstate *state,
-                             const struct block *block, u16 offset,
-                             u32 exit_code)
+static void rec_exit_early(struct lightrec_cstate *state,
+                          const struct block *block, u16 offset,
+                          u32 exit_code, u32 pc)
 {
        struct regcache *reg_cache = state->reg_cache;
        jit_state_t *_jit = block->_jit;
@@ -2036,24 +2031,25 @@ static void rec_break_syscall(struct lightrec_cstate *state,
 
        lightrec_free_reg(reg_cache, tmp);
 
-       /* TODO: the return address should be "pc - 4" if we're a delay slot */
-       lightrec_emit_end_of_block(state, block, offset, -1,
-                                  get_ds_pc(block, offset, 0),
-                                  31, 0, true);
+       lightrec_emit_end_of_block(state, block, offset, -1, pc, 31, 0, true);
 }
 
 static void rec_special_SYSCALL(struct lightrec_cstate *state,
                                const struct block *block, u16 offset)
 {
        _jit_name(block->_jit, __func__);
-       rec_break_syscall(state, block, offset, LIGHTREC_EXIT_SYSCALL);
+
+       /* TODO: the return address should be "pc - 4" if we're a delay slot */
+       rec_exit_early(state, block, offset, LIGHTREC_EXIT_SYSCALL,
+                      get_ds_pc(block, offset, 0));
 }
 
 static void rec_special_BREAK(struct lightrec_cstate *state,
                              const struct block *block, u16 offset)
 {
        _jit_name(block->_jit, __func__);
-       rec_break_syscall(state, block, offset, LIGHTREC_EXIT_BREAK);
+       rec_exit_early(state, block, offset, LIGHTREC_EXIT_BREAK,
+                      get_ds_pc(block, offset, 0));
 }
 
 static void rec_mfc(struct lightrec_cstate *state, const struct block *block, u16 offset)
@@ -2736,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);
                }
@@ -2777,6 +2780,13 @@ static void rec_meta_COM(struct lightrec_cstate *state,
        lightrec_free_reg(reg_cache, rd);
 }
 
+static void unknown_opcode(struct lightrec_cstate *state,
+                          const struct block *block, u16 offset)
+{
+       rec_exit_early(state, block, offset, LIGHTREC_EXIT_UNKNOWN_OP,
+                      block->pc + (offset << 2));
+}
+
 static const lightrec_rec_func_t rec_standard[64] = {
        SET_DEFAULT_ELM(rec_standard, unknown_opcode),
        [OP_SPECIAL]            = rec_SPECIAL,