From fdf33147c33ab1cb27c4bd06b377f744411030c3 Mon Sep 17 00:00:00 2001 From: Paul Cercueil Date: Wed, 12 Oct 2022 10:50:32 +0100 Subject: [PATCH] git subrepo pull --force deps/lightrec subrepo: subdir: "deps/lightrec" merged: "75374fa374" upstream: origin: "https://github.com/pcercuei/lightrec.git" branch: "master" commit: "75374fa374" git-subrepo: version: "0.4.3" origin: "https://github.com/ingydotnet/git-subrepo.git" commit: "2f68596" --- deps/lightrec/.gitrepo | 4 +- deps/lightrec/emitter.c | 36 ++++++++++++++++++ deps/lightrec/lightrec-private.h | 1 + deps/lightrec/lightrec.c | 64 ++++++++++++++++++++++---------- deps/lightrec/lightrec.h | 1 + deps/lightrec/optimizer.c | 18 +++++++++ 6 files changed, 103 insertions(+), 21 deletions(-) diff --git a/deps/lightrec/.gitrepo b/deps/lightrec/.gitrepo index a5daddd7..3db9689b 100644 --- a/deps/lightrec/.gitrepo +++ b/deps/lightrec/.gitrepo @@ -6,7 +6,7 @@ [subrepo] remote = https://github.com/pcercuei/lightrec.git branch = master - commit = 962ba057937b7fcb809f16682b4e24d27f08cdb1 - parent = 5b2da975316f1d88d02a14f8f2c876b2213ff1f3 + commit = 75374fa374a367c85f5cac6c1b9fc2c583298d42 + parent = 22a3b99d24fada1c7a5e7ab4458c132a0c387d50 method = merge cmdver = 0.4.3 diff --git a/deps/lightrec/emitter.c b/deps/lightrec/emitter.c index 523daf77..270fd48a 100644 --- a/deps/lightrec/emitter.c +++ b/deps/lightrec/emitter.c @@ -1817,6 +1817,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; @@ -2019,6 +2031,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); @@ -2087,6 +2105,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: @@ -2118,6 +2142,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; @@ -2202,6 +2232,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) { diff --git a/deps/lightrec/lightrec-private.h b/deps/lightrec/lightrec-private.h index 1b120db1..6b6f7217 100644 --- a/deps/lightrec/lightrec-private.h +++ b/deps/lightrec/lightrec-private.h @@ -123,6 +123,7 @@ struct lightrec_branch_target { enum c_wrappers { C_WRAPPER_RW, C_WRAPPER_RW_GENERIC, + C_WRAPPER_MFC, C_WRAPPER_MTC, C_WRAPPER_CP, C_WRAPPERS_COUNT, diff --git a/deps/lightrec/lightrec.c b/deps/lightrec/lightrec.c index fa08a800..43636b2a 100644 --- a/deps/lightrec/lightrec.c +++ b/deps/lightrec/lightrec.c @@ -432,22 +432,37 @@ u32 lightrec_mfc(struct lightrec_state *state, union code op) if (op.i.op == OP_CP0) return state->regs.cp0[op.r.rd]; else if (op.r.rs == OP_CP2_BASIC_MFC2) - return lightrec_mfc2(state, op.r.rd); + val = lightrec_mfc2(state, op.r.rd); + else { + val = state->regs.cp2c[op.r.rd]; + + switch (op.r.rd) { + case 4: + case 12: + case 20: + case 26: + case 27: + case 29: + case 30: + val = (u32)(s16)val; + fallthrough; + default: + break; + } + } - val = state->regs.cp2c[op.r.rd]; + if (state->ops.cop2_notify) + (*state->ops.cop2_notify)(state, op.opcode, val); - switch (op.r.rd) { - case 4: - case 12: - case 20: - case 26: - case 27: - case 29: - case 30: - return (u32)(s16)val; - default: - return val; - } + return val; +} + +static void lightrec_mfc_cb(struct lightrec_state *state, union code op) +{ + u32 rt = lightrec_mfc(state, op); + + if (op.r.rt) + state->regs.gpr[op.r.rt] = rt; } static void lightrec_mtc0(struct lightrec_state *state, u8 reg, u32 data) @@ -566,12 +581,17 @@ static void lightrec_ctc2(struct lightrec_state *state, u8 reg, u32 data) void lightrec_mtc(struct lightrec_state *state, union code op, u32 data) { - if (op.i.op == OP_CP0) + if (op.i.op == OP_CP0) { lightrec_mtc0(state, op.r.rd, data); - else if (op.r.rs == OP_CP2_BASIC_CTC2) - lightrec_ctc2(state, op.r.rd, data); - else - lightrec_mtc2(state, op.r.rd, data); + } else { + if (op.r.rs == OP_CP2_BASIC_CTC2) + lightrec_ctc2(state, op.r.rd, data); + else + lightrec_mtc2(state, op.r.rd, data); + + if (state->ops.cop2_notify) + (*state->ops.cop2_notify)(state, op.opcode, data); + } } static void lightrec_mtc_cb(struct lightrec_state *state, u32 arg) @@ -1703,6 +1723,11 @@ struct lightrec_state * lightrec_init(char *argv0, return NULL; } + if (ops->cop2_notify) + pr_debug("Optional cop2_notify callback in lightrec_ops\n"); + else + pr_debug("No optional cop2_notify callback in lightrec_ops\n"); + if (ENABLE_CODE_BUFFER && nb > PSX_MAP_CODE_BUFFER && codebuf_map->address) { tlsf = tlsf_create_with_pool(codebuf_map->address, @@ -1767,6 +1792,7 @@ struct lightrec_state * lightrec_init(char *argv0, state->c_wrappers[C_WRAPPER_RW] = lightrec_rw_cb; state->c_wrappers[C_WRAPPER_RW_GENERIC] = lightrec_rw_generic_cb; + state->c_wrappers[C_WRAPPER_MFC] = lightrec_mfc_cb; state->c_wrappers[C_WRAPPER_MTC] = lightrec_mtc_cb; state->c_wrappers[C_WRAPPER_CP] = lightrec_cp_cb; diff --git a/deps/lightrec/lightrec.h b/deps/lightrec/lightrec.h index 9613da36..310036ce 100644 --- a/deps/lightrec/lightrec.h +++ b/deps/lightrec/lightrec.h @@ -85,6 +85,7 @@ struct lightrec_mem_map { }; struct lightrec_ops { + void (*cop2_notify)(struct lightrec_state *state, u32 op, u32 data); void (*cop2_op)(struct lightrec_state *state, u32 op); void (*enable_ram)(struct lightrec_state *state, _Bool enable); _Bool (*hw_direct)(u32 kaddr, _Bool is_write, u8 size); diff --git a/deps/lightrec/optimizer.c b/deps/lightrec/optimizer.c index 01907225..3e94cff3 100644 --- a/deps/lightrec/optimizer.c +++ b/deps/lightrec/optimizer.c @@ -181,6 +181,8 @@ static u64 opcode_write_mask(union code op) case OP_LBU: case OP_LHU: case OP_LWR: + case OP_META_EXTC: + case OP_META_EXTS: return BIT(op.i.rt); case OP_JAL: return BIT(31); @@ -763,6 +765,22 @@ static u32 lightrec_propagate_consts(const struct opcode *op, known &= ~BIT(c.r.rd); } break; + case OP_META_EXTC: + if (known & BIT(c.i.rs)) { + known |= BIT(c.i.rt); + v[c.i.rt] = (s32)(s8)v[c.i.rs]; + } else { + known &= ~BIT(c.i.rt); + } + break; + case OP_META_EXTS: + if (known & BIT(c.i.rs)) { + known |= BIT(c.i.rt); + v[c.i.rt] = (s32)(s16)v[c.i.rs]; + } else { + known &= ~BIT(c.i.rt); + } + break; default: break; } -- 2.39.2