cdrom: add a timing hack
[pcsx_rearmed.git] / deps / lightrec / emitter.c
index cf32f7a..3f7da58 100644 (file)
@@ -87,21 +87,16 @@ static void lightrec_emit_end_of_block(struct lightrec_cstate *state,
        lightrec_jump_to_eob(state, _jit);
 }
 
-void lightrec_emit_eob(struct lightrec_cstate *state, const struct block *block,
-                      u16 offset, bool after_op)
+void lightrec_emit_eob(struct lightrec_cstate *state,
+                      const struct block *block, u16 offset)
 {
        struct regcache *reg_cache = state->reg_cache;
        jit_state_t *_jit = block->_jit;
-       union code c = block->opcode_list[offset].c;
-       u32 cycles = state->cycles;
-
-       if (after_op)
-               cycles += lightrec_cycles_of_opcode(c);
 
        lightrec_clean_regs(reg_cache, _jit);
 
        jit_movi(JIT_V0, block->pc + (offset << 2));
-       jit_subi(LIGHTREC_REG_CYCLE, LIGHTREC_REG_CYCLE, cycles);
+       jit_subi(LIGHTREC_REG_CYCLE, LIGHTREC_REG_CYCLE, state->cycles);
 
        lightrec_jump_to_eob(state, _jit);
 }
@@ -250,7 +245,7 @@ static void rec_b(struct lightrec_cstate *state, const struct block *block, u16
 
        if (op_flag_local_branch(op->flags)) {
                /* Recompile the delay slot */
-               if (next && next->opcode && !op_flag_no_ds(op->flags))
+               if (!op_flag_no_ds(op->flags) && next->opcode)
                        lightrec_rec_opcode(state, block, offset + 1);
 
                if (link) {
@@ -679,10 +674,8 @@ static void rec_special_or_nor(struct lightrec_cstate *state,
        if (!nor)
                flags_rd = REG_ZEXT & flags_rs & flags_rt;
 
-       /* E(rd) = (E(rs) & E(rt)) | (E(rt) & !Z(rt)) | (E(rs) & !Z(rs)) */
-       if ((REG_EXT & flags_rs & flags_rt) ||
-           ((flags_rt & (REG_EXT | REG_ZEXT)) == REG_EXT) ||
-           ((flags_rs & (REG_EXT | REG_ZEXT)) == REG_EXT))
+       /* E(rd) = E(rs) & E(rt) */
+       if (REG_EXT & flags_rs & flags_rt)
                flags_rd |= REG_EXT;
 
        lightrec_set_reg_out_flags(reg_cache, rd, flags_rd);
@@ -1129,6 +1122,13 @@ static u32 rec_ram_mask(struct lightrec_state *state)
        return (RAM_SIZE << (state->mirrors_mapped * 2)) - 1;
 }
 
+static u32 rec_io_mask(const struct lightrec_state *state)
+{
+       u32 length = state->maps[PSX_MAP_HW_REGISTERS].length;
+
+       return GENMASK(31 - clz32(length - 1), 0);
+}
+
 static void rec_store_memory(struct lightrec_cstate *cstate,
                             const struct block *block,
                             u16 offset, jit_code_t code,
@@ -1260,7 +1260,7 @@ static void rec_store_io(struct lightrec_cstate *cstate,
 
        return rec_store_memory(cstate, block, offset, code, swap_code,
                                cstate->state->offset_io,
-                               0x1fffffff, false);
+                               rec_io_mask(cstate->state), false);
 }
 
 static void rec_store_direct_no_invalidate(struct lightrec_cstate *cstate,
@@ -1584,7 +1584,7 @@ static void rec_load_io(struct lightrec_cstate *cstate,
        _jit_note(block->_jit, __FILE__, __LINE__);
 
        rec_load_memory(cstate, block, offset, code, swap_code, is_unsigned,
-                       cstate->state->offset_io, 0x1fffffff);
+                       cstate->state->offset_io, rec_io_mask(cstate->state));
 }
 
 static void rec_load_direct(struct lightrec_cstate *cstate,
@@ -1819,6 +1819,18 @@ static void rec_special_BREAK(struct lightrec_cstate *state,
        rec_break_syscall(state, block, offset, LIGHTREC_EXIT_BREAK);
 }
 
+static void rec_mfc(struct lightrec_cstate *state, const struct block *block, u16 offset)
+{
+       struct regcache *reg_cache = state->reg_cache;
+       union code c = block->opcode_list[offset].c;
+       jit_state_t *_jit = block->_jit;
+
+       jit_note(__FILE__, __LINE__);
+       lightrec_clean_reg_if_loaded(reg_cache, _jit, c.i.rt, true);
+
+       call_to_c_wrapper(state, block, c.opcode, C_WRAPPER_MFC);
+}
+
 static void rec_mtc(struct lightrec_cstate *state, const struct block *block, u16 offset)
 {
        struct regcache *reg_cache = state->reg_cache;
@@ -1956,8 +1968,10 @@ rec_mtc0(struct lightrec_cstate *state, const struct block *block, u16 offset)
        lightrec_free_reg(reg_cache, rt);
 
        if (!op_flag_no_ds(block->opcode_list[offset].flags) &&
-           (c.r.rd == 12 || c.r.rd == 13))
-               lightrec_emit_eob(state, block, offset + 1, true);
+           (c.r.rd == 12 || c.r.rd == 13)) {
+               state->cycles += lightrec_cycles_of_opcode(c);
+               lightrec_emit_eob(state, block, offset + 1);
+       }
 }
 
 static void rec_cp0_MFC0(struct lightrec_cstate *state,
@@ -2021,6 +2035,12 @@ static void rec_cp2_basic_MFC2(struct lightrec_cstate *state,
 
        _jit_name(block->_jit, __func__);
 
+       if (state->state->ops.cop2_notify) {
+               /* We must call cop2_notify, handle that in C. */
+               rec_mfc(state, block, offset);
+               return;
+       }
+
        flags = (zext_regs & BIT(reg)) ? REG_ZEXT : REG_EXT;
        rt = lightrec_alloc_reg_out(reg_cache, _jit, c.r.rt, flags);
 
@@ -2089,6 +2109,12 @@ static void rec_cp2_basic_CFC2(struct lightrec_cstate *state,
 
        _jit_name(block->_jit, __func__);
 
+       if (state->state->ops.cop2_notify) {
+               /* We must call cop2_notify, handle that in C. */
+               rec_mfc(state, block, offset);
+               return;
+       }
+
        switch (c.r.rd) {
        case 4:
        case 12:
@@ -2120,6 +2146,12 @@ static void rec_cp2_basic_MTC2(struct lightrec_cstate *state,
 
        _jit_name(block->_jit, __func__);
 
+       if (state->state->ops.cop2_notify) {
+               /* We must call cop2_notify, handle that in C. */
+               rec_mtc(state, block, offset);
+               return;
+       }
+
        if (c.r.rd == 31)
                return;
 
@@ -2204,6 +2236,12 @@ static void rec_cp2_basic_CTC2(struct lightrec_cstate *state,
 
        _jit_name(block->_jit, __func__);
 
+       if (state->state->ops.cop2_notify) {
+               /* We must call cop2_notify, handle that in C. */
+               rec_mtc(state, block, offset);
+               return;
+       }
+
        rt = lightrec_alloc_reg_in(reg_cache, _jit, c.r.rt, 0);
 
        switch (c.r.rd) {