From 8afce295870dc97704b0e9e1efe1801b6b56090d Mon Sep 17 00:00:00 2001 From: Paul Cercueil Date: Tue, 11 Jun 2024 10:34:16 +0200 Subject: [PATCH] git subrepo pull --force deps/lightrec subrepo: subdir: "deps/lightrec" merged: "bd0b827922" upstream: origin: "https://github.com/pcercuei/lightrec.git" branch: "master" commit: "bd0b827922" git-subrepo: version: "0.4.6" origin: "https://github.com/ingydotnet/git-subrepo.git" commit: "110b9eb" --- deps/lightrec/.gitrepo | 4 +- deps/lightrec/constprop.c | 2 +- deps/lightrec/disassembler.c | 16 +-- deps/lightrec/emitter.c | 101 +++++--------- deps/lightrec/lightrec-private.h | 8 +- deps/lightrec/lightrec.c | 230 ++++++++++++++----------------- deps/lightrec/optimizer.c | 8 +- deps/lightrec/regcache.c | 14 +- 8 files changed, 164 insertions(+), 219 deletions(-) diff --git a/deps/lightrec/.gitrepo b/deps/lightrec/.gitrepo index 73ce0b72..9e04deb8 100644 --- a/deps/lightrec/.gitrepo +++ b/deps/lightrec/.gitrepo @@ -6,7 +6,7 @@ [subrepo] remote = https://github.com/pcercuei/lightrec.git branch = master - commit = 8d3db1a4e76c7b81301013f18650011b7e5eabf3 - parent = fcd42d7decc2ed71801e4cbe575c4d2726b2743e + commit = bd0b82792284f22566bbfc78d8882e1e91b10516 + parent = 1229a4ea3dea3e1e47c46cd7afed38860fd91a57 method = merge cmdver = 0.4.6 diff --git a/deps/lightrec/constprop.c b/deps/lightrec/constprop.c index b21339aa..97670bcf 100644 --- a/deps/lightrec/constprop.c +++ b/deps/lightrec/constprop.c @@ -736,7 +736,7 @@ lightrec_get_constprop_map(const struct lightrec_state *state, if ((min & 0xe0000000) != (max & 0xe0000000)) return PSX_MAP_UNKNOWN; - pr_debug("Min: 0x%08x max: 0x%08x Known: 0x%08x Sign: 0x%08x\n", + pr_debug("Min: "X32_FMT" max: "X32_FMT" Known: "X32_FMT" Sign: "X32_FMT"\n", min, max, v[reg].known, v[reg].sign); min = kunseg(min); diff --git a/deps/lightrec/disassembler.c b/deps/lightrec/disassembler.c index 5111d173..f0aef604 100644 --- a/deps/lightrec/disassembler.c +++ b/deps/lightrec/disassembler.c @@ -333,7 +333,7 @@ static int print_op_special(union code c, char *buf, size_t len, lightrec_reg_name(c.r.rs), lightrec_reg_name(c.r.rt)); default: - return snprintf(buf, len, "unknown (0x%08x)", c.opcode); + return snprintf(buf, len, "unknown ("X32_FMT")", c.opcode); } } @@ -362,7 +362,7 @@ static int print_op_cp(union code c, char *buf, size_t len, unsigned int cp) case OP_CP0_RFE: return snprintf(buf, len, "rfe "); default: - return snprintf(buf, len, "unknown (0x%08x)", c.opcode); + return snprintf(buf, len, "unknown ("X32_FMT")", c.opcode); } } } @@ -380,7 +380,7 @@ static int print_op(union code c, u32 pc, char *buf, size_t len, case OP_REGIMM: *flags_ptr = opcode_branch_flags; *nb_flags = ARRAY_SIZE(opcode_branch_flags); - return snprintf(buf, len, "%s%s,0x%x", + return snprintf(buf, len, "%s%s,0x%"PRIx32, regimm_opcodes[c.i.rt], lightrec_reg_name(c.i.rs), pc + 4 + ((s16)c.i.imm << 2)); @@ -388,14 +388,14 @@ static int print_op(union code c, u32 pc, char *buf, size_t len, case OP_JAL: *flags_ptr = opcode_branch_flags; *nb_flags = ARRAY_SIZE(opcode_branch_flags); - return snprintf(buf, len, "%s0x%x", + return snprintf(buf, len, "%s0x%"PRIx32, std_opcodes[c.i.op], (pc & 0xf0000000) | (c.j.imm << 2)); case OP_BEQ: if (c.i.rs == c.i.rt) { *flags_ptr = opcode_branch_flags; *nb_flags = ARRAY_SIZE(opcode_branch_flags); - return snprintf(buf, len, "b 0x%x", + return snprintf(buf, len, "b 0x%"PRIx32, pc + 4 + ((s16)c.i.imm << 2)); } fallthrough; @@ -404,7 +404,7 @@ static int print_op(union code c, u32 pc, char *buf, size_t len, case OP_BGTZ: *flags_ptr = opcode_branch_flags; *nb_flags = ARRAY_SIZE(opcode_branch_flags); - return snprintf(buf, len, "%s%s,%s,0x%x", + return snprintf(buf, len, "%s%s,%s,0x%"PRIx32, std_opcodes[c.i.op], lightrec_reg_name(c.i.rs), lightrec_reg_name(c.i.rt), @@ -482,7 +482,7 @@ static int print_op(union code c, u32 pc, char *buf, size_t len, lightrec_reg_name(get_mult_div_lo(c)), lightrec_reg_name(c.r.rs), c.r.op); default: - return snprintf(buf, len, "unknown (0x%08x)", c.opcode); + return snprintf(buf, len, "unknown ("X32_FMT")", c.opcode); } } @@ -518,7 +518,7 @@ void lightrec_print_disassembly(const struct block *block, const u32 *code_ptr) print_flags(buf3, sizeof(buf3), op, flags_ptr, nb_flags, is_io); - printf("0x%08x (0x%x)\t%s%*c%s%*c%s\n", pc, i << 2, + printf(X32_FMT" (0x%x)\t%s%*c%s%*c%s\n", pc, i << 2, buf, 30 - (int)count, ' ', buf2, 30 - (int)count2, ' ', buf3); } } diff --git a/deps/lightrec/emitter.c b/deps/lightrec/emitter.c index e1a176c3..8612119f 100644 --- a/deps/lightrec/emitter.c +++ b/deps/lightrec/emitter.c @@ -136,8 +136,7 @@ void lightrec_emit_jump_to_interpreter(struct lightrec_cstate *state, lightrec_load_imm(reg_cache, _jit, JIT_V0, block->pc, block->pc + (offset << 2)); if (lightrec_store_next_pc()) { - jit_stxi_i(offsetof(struct lightrec_state, next_pc), - LIGHTREC_REG_STATE, JIT_V0); + jit_stxi_i(lightrec_offset(next_pc), LIGHTREC_REG_STATE, JIT_V0); } jit_movi(JIT_V1, (uintptr_t)block); @@ -157,8 +156,7 @@ static void lightrec_emit_eob(struct lightrec_cstate *state, lightrec_load_imm(reg_cache, _jit, JIT_V0, block->pc, block->pc + (offset << 2)); if (lightrec_store_next_pc()) { - jit_stxi_i(offsetof(struct lightrec_state, next_pc), - LIGHTREC_REG_STATE, JIT_V0); + jit_stxi_i(lightrec_offset(next_pc), LIGHTREC_REG_STATE, JIT_V0); } jit_subi(LIGHTREC_REG_CYCLE, LIGHTREC_REG_CYCLE, state->cycles); @@ -1175,15 +1173,16 @@ static void call_to_c_wrapper(struct lightrec_cstate *state, /* Make sure JIT_R1 is not mapped; it will be used in the C wrapper. */ tmp2 = lightrec_alloc_reg(reg_cache, _jit, JIT_R1); + jit_movi(tmp2, (unsigned int)wrapper << (1 + __WORDSIZE / 32)); + tmp = lightrec_get_reg_with_value(reg_cache, - (intptr_t) state->state->wrappers_eps[wrapper]); + (intptr_t) state->state->c_wrapper); if (tmp < 0) { tmp = lightrec_alloc_reg_temp(reg_cache, _jit); - jit_ldxi(tmp, LIGHTREC_REG_STATE, - offsetof(struct lightrec_state, wrappers_eps[wrapper])); + jit_ldxi(tmp, LIGHTREC_REG_STATE, lightrec_offset(c_wrapper)); lightrec_temp_set_value(reg_cache, tmp, - (intptr_t) state->state->wrappers_eps[wrapper]); + (intptr_t) state->state->c_wrapper); } lightrec_free_reg(reg_cache, tmp2); @@ -1232,8 +1231,8 @@ static void rec_io(struct lightrec_cstate *state, * wrapper that it should write the REG_TEMP register instead of * the actual output register of the opcode. */ zero = lightrec_alloc_reg_in(reg_cache, _jit, 0, 0); - jit_stxi_c(offsetof(struct lightrec_state, in_delay_slot_n), - LIGHTREC_REG_STATE, zero); + jit_stxi_c(lightrec_offset(in_delay_slot_n), + LIGHTREC_REG_STATE, zero); lightrec_free_reg(reg_cache, zero); } @@ -1297,7 +1296,7 @@ static void rec_store_memory(struct lightrec_cstate *cstate, 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); + s32 lut_offt = lightrec_offset(code_lut); bool no_mask = op_flag_no_mask(op->flags); bool add_imm = c.i.imm && (c.i.op == OP_META_SWU @@ -1560,19 +1559,18 @@ static void rec_store_direct(struct lightrec_cstate *cstate, const struct block /* Write NULL to the code LUT to invalidate any block that's there */ if (lut_is_32bit(state)) - jit_stxi_i(offsetof(struct lightrec_state, code_lut), tmp, tmp3); + jit_stxi_i(lightrec_offset(code_lut), tmp, tmp3); else - jit_stxi(offsetof(struct lightrec_state, code_lut), tmp, tmp3); + jit_stxi(lightrec_offset(code_lut), tmp, tmp3); if (c.i.op == OP_META_SWU) { /* With a SWU opcode, we might have touched the following 32-bit * word, so invalidate it as well */ if (lut_is_32bit(state)) { - jit_stxi_i(offsetof(struct lightrec_state, code_lut) + 4, - tmp, tmp3); + jit_stxi_i(lightrec_offset(code_lut) + 4, tmp, tmp3); } else { - jit_stxi(offsetof(struct lightrec_state, code_lut) - + sizeof(uintptr_t), tmp, tmp3); + jit_stxi(lightrec_offset(code_lut) + sizeof(uintptr_t), + tmp, tmp3); } } @@ -2058,17 +2056,13 @@ static void rec_exit_early(struct lightrec_cstate *state, tmp = lightrec_alloc_reg_temp(reg_cache, _jit); jit_movi(tmp, exit_code); - jit_stxi_i(offsetof(struct lightrec_state, exit_flags), - LIGHTREC_REG_STATE, tmp); + jit_stxi_i(lightrec_offset(exit_flags), LIGHTREC_REG_STATE, tmp); - jit_ldxi_i(tmp, LIGHTREC_REG_STATE, - offsetof(struct lightrec_state, target_cycle)); + jit_ldxi_i(tmp, LIGHTREC_REG_STATE, lightrec_offset(target_cycle)); jit_subr(tmp, tmp, LIGHTREC_REG_CYCLE); jit_movi(LIGHTREC_REG_CYCLE, 0); - jit_stxi_i(offsetof(struct lightrec_state, target_cycle), - LIGHTREC_REG_STATE, tmp); - jit_stxi_i(offsetof(struct lightrec_state, current_cycle), - LIGHTREC_REG_STATE, tmp); + jit_stxi_i(lightrec_offset(target_cycle), LIGHTREC_REG_STATE, tmp); + jit_stxi_i(lightrec_offset(current_cycle), LIGHTREC_REG_STATE, tmp); lightrec_free_reg(reg_cache, tmp); @@ -2140,8 +2134,7 @@ rec_mfc0(struct lightrec_cstate *state, const struct block *block, u16 offset) rt = lightrec_alloc_reg_out(reg_cache, _jit, c.i.rt, REG_EXT); - jit_ldxi_i(rt, LIGHTREC_REG_STATE, - offsetof(struct lightrec_state, regs.cp0[c.r.rd])); + jit_ldxi_i(rt, LIGHTREC_REG_STATE, lightrec_offset(regs.cp0[c.r.rd])); lightrec_free_reg(reg_cache, rt); } @@ -2192,15 +2185,12 @@ rec_mtc0(struct lightrec_cstate *state, const struct block *block, u16 offset) rt = lightrec_alloc_reg_in(reg_cache, _jit, c.i.rt, 0); - if (c.r.rd != 13) { - jit_stxi_i(offsetof(struct lightrec_state, regs.cp0[c.r.rd]), - LIGHTREC_REG_STATE, rt); - } + if (c.r.rd != 13) + jit_stxi_i(lightrec_offset(regs.cp0[c.r.rd]), LIGHTREC_REG_STATE, rt); if (c.r.rd == 12 || c.r.rd == 13) { tmp = lightrec_alloc_reg_temp(reg_cache, _jit); - jit_ldxi_i(tmp, LIGHTREC_REG_STATE, - offsetof(struct lightrec_state, regs.cp0[13])); + jit_ldxi_i(tmp, LIGHTREC_REG_STATE, lightrec_offset(regs.cp0[13])); tmp2 = lightrec_alloc_reg_temp(reg_cache, _jit); } @@ -2213,10 +2203,8 @@ rec_mtc0(struct lightrec_cstate *state, const struct block *block, u16 offset) jit_ori(tmp, tmp, 0x0300); jit_xori(tmp, tmp, 0x0300); jit_orr(tmp, tmp, tmp2); - jit_ldxi_i(tmp2, LIGHTREC_REG_STATE, - offsetof(struct lightrec_state, regs.cp0[12])); - jit_stxi_i(offsetof(struct lightrec_state, regs.cp0[13]), - LIGHTREC_REG_STATE, tmp); + jit_ldxi_i(tmp2, LIGHTREC_REG_STATE, lightrec_offset(regs.cp0[12])); + jit_stxi_i(lightrec_offset(regs.cp0[13]), LIGHTREC_REG_STATE, tmp); status = tmp2; } @@ -2244,14 +2232,11 @@ rec_mtc0(struct lightrec_cstate *state, const struct block *block, u16 offset) if (c.r.rd == 12 || c.r.rd == 13) { to_end = jit_beqi(tmp, 0); - jit_ldxi_i(tmp2, LIGHTREC_REG_STATE, - offsetof(struct lightrec_state, target_cycle)); + jit_ldxi_i(tmp2, LIGHTREC_REG_STATE, lightrec_offset(target_cycle)); jit_subr(tmp2, tmp2, LIGHTREC_REG_CYCLE); jit_movi(LIGHTREC_REG_CYCLE, 0); - jit_stxi_i(offsetof(struct lightrec_state, target_cycle), - LIGHTREC_REG_STATE, tmp2); - jit_stxi_i(offsetof(struct lightrec_state, current_cycle), - LIGHTREC_REG_STATE, tmp2); + jit_stxi_i(lightrec_offset(target_cycle), LIGHTREC_REG_STATE, tmp2); + jit_stxi_i(lightrec_offset(current_cycle), LIGHTREC_REG_STATE, tmp2); jit_patch(to_end); @@ -2294,7 +2279,7 @@ static void rec_cp0_CTC0(struct lightrec_cstate *state, static unsigned int cp2d_i_offset(u8 reg) { - return offsetof(struct lightrec_state, regs.cp2d[reg]); + return lightrec_offset(regs.cp2d[reg]); } static unsigned int cp2d_s_offset(u8 reg) @@ -2304,7 +2289,7 @@ static unsigned int cp2d_s_offset(u8 reg) static unsigned int cp2c_i_offset(u8 reg) { - return offsetof(struct lightrec_state, regs.cp2c[reg]); + return lightrec_offset(regs.cp2c[reg]); } static unsigned int cp2c_s_offset(u8 reg) @@ -2586,8 +2571,7 @@ static void rec_cp0_RFE(struct lightrec_cstate *state, jit_note(__FILE__, __LINE__); status = lightrec_alloc_reg_temp(reg_cache, _jit); - jit_ldxi_i(status, LIGHTREC_REG_STATE, - offsetof(struct lightrec_state, regs.cp0[12])); + jit_ldxi_i(status, LIGHTREC_REG_STATE, lightrec_offset(regs.cp0[12])); tmp = lightrec_alloc_reg_temp(reg_cache, _jit); @@ -2597,10 +2581,8 @@ static void rec_cp0_RFE(struct lightrec_cstate *state, jit_andi(status, status, ~0xful); jit_orr(status, status, tmp); - jit_ldxi_i(tmp, LIGHTREC_REG_STATE, - offsetof(struct lightrec_state, regs.cp0[13])); - jit_stxi_i(offsetof(struct lightrec_state, regs.cp0[12]), - LIGHTREC_REG_STATE, status); + jit_ldxi_i(tmp, LIGHTREC_REG_STATE, lightrec_offset(regs.cp0[13])); + jit_stxi_i(lightrec_offset(regs.cp0[12]), LIGHTREC_REG_STATE, status); /* Exit dynarec in case there's a software interrupt. * exit_flags = !!(status & cause & 0x0300) & status; */ @@ -2608,8 +2590,7 @@ static void rec_cp0_RFE(struct lightrec_cstate *state, jit_andi(tmp, tmp, 0x0300); jit_nei(tmp, tmp, 0); jit_andr(tmp, tmp, status); - jit_stxi_i(offsetof(struct lightrec_state, exit_flags), - LIGHTREC_REG_STATE, tmp); + jit_stxi_i(lightrec_offset(exit_flags), LIGHTREC_REG_STATE, tmp); lightrec_free_reg(reg_cache, status); lightrec_free_reg(reg_cache, tmp); @@ -2662,16 +2643,7 @@ static void rec_meta_MOV(struct lightrec_cstate *state, unload_rd = OPT_EARLY_UNLOAD && LIGHTREC_FLAGS_GET_RD(op->flags) == LIGHTREC_REG_UNLOAD; - if (c.m.rs && !lightrec_reg_is_loaded(reg_cache, c.m.rs)) { - /* The source register is not yet loaded - we can load its value - * from the register cache directly into the target register. */ - rd = lightrec_alloc_reg_out(reg_cache, _jit, c.m.rd, REG_EXT); - - jit_ldxi_i(rd, LIGHTREC_REG_STATE, - offsetof(struct lightrec_state, regs.gpr) + (c.m.rs << 2)); - - lightrec_free_reg(reg_cache, rd); - } else if (unload_rd) { + if (unload_rd) { /* If the destination register will be unloaded right after the * MOV meta-opcode, we don't actually need to write any host * register - we can just store the source register directly to @@ -2681,8 +2653,7 @@ static void rec_meta_MOV(struct lightrec_cstate *state, rs = lightrec_alloc_reg_in(reg_cache, _jit, c.m.rs, 0); - jit_stxi_i(offsetof(struct lightrec_state, regs.gpr) - + (c.m.rd << 2), LIGHTREC_REG_STATE, rs); + jit_stxi_i(lightrec_offset(regs.gpr) + (c.m.rd << 2), LIGHTREC_REG_STATE, rs); lightrec_free_reg(reg_cache, rs); } else { diff --git a/deps/lightrec/lightrec-private.h b/deps/lightrec/lightrec-private.h index 0df9f938..920008c2 100644 --- a/deps/lightrec/lightrec-private.h +++ b/deps/lightrec/lightrec-private.h @@ -23,7 +23,8 @@ #include #include -#define PC_FMT "PC 0x%08"PRIx32 +#define X32_FMT "0x%08"PRIx32 +#define PC_FMT "PC "X32_FMT #define ARRAY_SIZE(x) (sizeof(x) ? sizeof(x) / sizeof((x)[0]) : 0) @@ -176,9 +177,9 @@ struct lightrec_state { u32 exit_flags; u32 old_cycle_counter; u32 cycles_per_op; + void *c_wrapper; struct block *dispatcher, *c_wrapper_block; void *c_wrappers[C_WRAPPERS_COUNT]; - void *wrappers_eps[C_WRAPPERS_COUNT]; struct blockcache *block_cache; struct recompiler *rec; struct lightrec_cstate *cstate; @@ -201,6 +202,9 @@ struct lightrec_state { void *code_lut[]; }; +#define lightrec_offset(ptr) \ + offsetof(struct lightrec_state, ptr) + u32 lightrec_rw(struct lightrec_state *state, union code op, u32 addr, u32 data, u32 *flags, struct block *block, u16 offset); diff --git a/deps/lightrec/lightrec.c b/deps/lightrec/lightrec.c index 454007b1..ec26bff7 100644 --- a/deps/lightrec/lightrec.c +++ b/deps/lightrec/lightrec.c @@ -942,9 +942,6 @@ static struct block * generate_wrapper(struct lightrec_state *state) struct block *block; jit_state_t *_jit; unsigned int i; - jit_node_t *addr[C_WRAPPERS_COUNT - 1]; - jit_node_t *to_end[C_WRAPPERS_COUNT - 1]; - u8 tmp = JIT_R1; block = lightrec_malloc(state, MEM_FOR_IR, sizeof(*block)); if (!block) @@ -961,20 +958,9 @@ static struct block * generate_wrapper(struct lightrec_state *state) jit_prolog(); jit_tramp(256); - /* Add entry points */ - for (i = C_WRAPPERS_COUNT - 1; i > 0; i--) { - jit_ldxi(tmp, LIGHTREC_REG_STATE, - offsetof(struct lightrec_state, c_wrappers[i])); - to_end[i - 1] = jit_b(); - addr[i - 1] = jit_indirect(); - } - - jit_ldxi(tmp, LIGHTREC_REG_STATE, - offsetof(struct lightrec_state, c_wrappers[0])); - - for (i = 0; i < C_WRAPPERS_COUNT - 1; i++) - jit_patch(to_end[i]); - jit_movr(JIT_R1, tmp); + /* Load pointer to C wrapper */ + jit_addr(JIT_R1, JIT_R1, LIGHTREC_REG_STATE); + jit_ldxi(JIT_R1, JIT_R1, lightrec_offset(c_wrappers)); jit_epilog(); jit_prolog(); @@ -982,7 +968,7 @@ static struct block * generate_wrapper(struct lightrec_state *state) /* Save all temporaries on stack */ for (i = 0; i < NUM_TEMPS; i++) { if (i + FIRST_TEMP != 1) { - jit_stxi(offsetof(struct lightrec_state, wrapper_regs[i]), + jit_stxi(lightrec_offset(wrapper_regs[i]), LIGHTREC_REG_STATE, JIT_R(i + FIRST_TEMP)); } } @@ -993,29 +979,25 @@ static struct block * generate_wrapper(struct lightrec_state *state) jit_pushargr(LIGHTREC_REG_STATE); jit_pushargr(JIT_R2); - jit_ldxi_ui(JIT_R2, LIGHTREC_REG_STATE, - offsetof(struct lightrec_state, target_cycle)); + jit_ldxi_ui(JIT_R2, LIGHTREC_REG_STATE, lightrec_offset(target_cycle)); /* state->current_cycle = state->target_cycle - delta; */ jit_subr(LIGHTREC_REG_CYCLE, JIT_R2, LIGHTREC_REG_CYCLE); - jit_stxi_i(offsetof(struct lightrec_state, current_cycle), - LIGHTREC_REG_STATE, LIGHTREC_REG_CYCLE); + jit_stxi_i(lightrec_offset(current_cycle), LIGHTREC_REG_STATE, LIGHTREC_REG_CYCLE); /* Call the wrapper function */ jit_finishr(JIT_R1); /* delta = state->target_cycle - state->current_cycle */; - jit_ldxi_ui(LIGHTREC_REG_CYCLE, LIGHTREC_REG_STATE, - offsetof(struct lightrec_state, current_cycle)); - jit_ldxi_ui(JIT_R1, LIGHTREC_REG_STATE, - offsetof(struct lightrec_state, target_cycle)); + jit_ldxi_ui(LIGHTREC_REG_CYCLE, LIGHTREC_REG_STATE, lightrec_offset(current_cycle)); + jit_ldxi_ui(JIT_R1, LIGHTREC_REG_STATE, lightrec_offset(target_cycle)); jit_subr(LIGHTREC_REG_CYCLE, JIT_R1, LIGHTREC_REG_CYCLE); /* Restore temporaries from stack */ for (i = 0; i < NUM_TEMPS; i++) { if (i + FIRST_TEMP != 1) { jit_ldxi(JIT_R(i + FIRST_TEMP), LIGHTREC_REG_STATE, - offsetof(struct lightrec_state, wrapper_regs[i])); + lightrec_offset(wrapper_regs[i])); } } @@ -1032,10 +1014,7 @@ static struct block * generate_wrapper(struct lightrec_state *state) if (!block->function) goto err_free_jit; - state->wrappers_eps[C_WRAPPERS_COUNT - 1] = block->function; - - for (i = 0; i < C_WRAPPERS_COUNT - 1; i++) - state->wrappers_eps[i] = jit_address(addr[i]); + state->c_wrapper = block->function; if (ENABLE_DISASSEMBLER) { pr_debug("Wrapper block:\n"); @@ -1104,20 +1083,16 @@ static u32 lightrec_check_load_delay(struct lightrec_state *state, u32 pc, u8 re static void update_cycle_counter_before_c(jit_state_t *_jit) { /* update state->current_cycle */ - jit_ldxi_i(JIT_R2, LIGHTREC_REG_STATE, - offsetof(struct lightrec_state, target_cycle)); + jit_ldxi_i(JIT_R2, LIGHTREC_REG_STATE, lightrec_offset(target_cycle)); jit_subr(JIT_R1, JIT_R2, LIGHTREC_REG_CYCLE); - jit_stxi_i(offsetof(struct lightrec_state, current_cycle), - LIGHTREC_REG_STATE, JIT_R1); + jit_stxi_i(lightrec_offset(current_cycle), LIGHTREC_REG_STATE, JIT_R1); } static void update_cycle_counter_after_c(jit_state_t *_jit) { /* Recalc the delta */ - jit_ldxi_i(JIT_R1, LIGHTREC_REG_STATE, - offsetof(struct lightrec_state, current_cycle)); - jit_ldxi_i(JIT_R2, LIGHTREC_REG_STATE, - offsetof(struct lightrec_state, target_cycle)); + jit_ldxi_i(JIT_R1, LIGHTREC_REG_STATE, lightrec_offset(current_cycle)); + jit_ldxi_i(JIT_R2, LIGHTREC_REG_STATE, lightrec_offset(target_cycle)); jit_subr(LIGHTREC_REG_CYCLE, JIT_R2, JIT_R1); } @@ -1125,7 +1100,7 @@ static void sync_next_pc(jit_state_t *_jit) { if (lightrec_store_next_pc()) { jit_ldxi_ui(JIT_V0, LIGHTREC_REG_STATE, - offsetof(struct lightrec_state, next_pc)); + lightrec_offset(next_pc)); } } @@ -1133,7 +1108,8 @@ static struct block * generate_dispatcher(struct lightrec_state *state) { struct block *block; jit_state_t *_jit; - jit_node_t *to_end, *loop, *addr, *addr2, *addr3, *addr4, *addr5, *jmp, *jmp2; + jit_node_t *to_end, *loop, *loop2, + *addr, *addr2, *addr3, *addr4, *addr5; unsigned int i; u32 offset; @@ -1165,92 +1141,13 @@ static struct block * generate_dispatcher(struct lightrec_state *state) /* Call the block's code */ jit_jmpr(JIT_V1); - if (OPT_REPLACE_MEMSET) { - /* Blocks will jump here when they need to call - * lightrec_memset() */ - addr3 = jit_indirect(); - - jit_movr(JIT_V1, LIGHTREC_REG_CYCLE); - - jit_prepare(); - jit_pushargr(LIGHTREC_REG_STATE); - - jit_finishi(lightrec_memset); - jit_retval(LIGHTREC_REG_CYCLE); - - jit_ldxi_ui(JIT_V0, LIGHTREC_REG_STATE, - offsetof(struct lightrec_state, regs.gpr[31])); - jit_subr(LIGHTREC_REG_CYCLE, JIT_V1, LIGHTREC_REG_CYCLE); - - if (OPT_DETECT_IMPOSSIBLE_BRANCHES || OPT_HANDLE_LOAD_DELAYS) - jmp = jit_b(); - } - - if (OPT_DETECT_IMPOSSIBLE_BRANCHES) { - /* Blocks will jump here when they reach a branch that should - * be executed with the interpreter, passing the branch's PC - * in JIT_V0 and the address of the block in JIT_V1. */ - addr4 = jit_indirect(); - - sync_next_pc(_jit); - update_cycle_counter_before_c(_jit); - - jit_prepare(); - jit_pushargr(LIGHTREC_REG_STATE); - jit_pushargr(JIT_V1); - jit_pushargr(JIT_V0); - jit_finishi(lightrec_emulate_block); - - jit_retval(JIT_V0); - - update_cycle_counter_after_c(_jit); - - if (OPT_HANDLE_LOAD_DELAYS) - jmp2 = jit_b(); - - } - - if (OPT_HANDLE_LOAD_DELAYS) { - /* Blocks will jump here when they reach a branch with a load - * opcode in its delay slot. The delay slot has already been - * executed; the load value is in (state->temp_reg), and the - * register number is in JIT_V1. - * Jump to a C function which will evaluate the branch target's - * first opcode, to make sure that it does not read the register - * in question; and if it does, handle it accordingly. */ - addr5 = jit_indirect(); - - sync_next_pc(_jit); - update_cycle_counter_before_c(_jit); - - jit_prepare(); - jit_pushargr(LIGHTREC_REG_STATE); - jit_pushargr(JIT_V0); - jit_pushargr(JIT_V1); - jit_finishi(lightrec_check_load_delay); - - jit_retval(JIT_V0); - - update_cycle_counter_after_c(_jit); - } - /* The block will jump here, with the number of cycles remaining in * LIGHTREC_REG_CYCLE */ addr2 = jit_indirect(); sync_next_pc(_jit); - if (OPT_HANDLE_LOAD_DELAYS && OPT_DETECT_IMPOSSIBLE_BRANCHES) - jit_patch(jmp2); - - if (OPT_REPLACE_MEMSET - && (OPT_DETECT_IMPOSSIBLE_BRANCHES || OPT_HANDLE_LOAD_DELAYS)) { - jit_patch(jmp); - } - - /* Store back the next PC to the lightrec_state structure */ - offset = offsetof(struct lightrec_state, curr_pc); - jit_stxi_i(offset, LIGHTREC_REG_STATE, JIT_V0); + loop2 = jit_label(); /* Jump to end if state->target_cycle < state->current_cycle */ to_end = jit_blei(LIGHTREC_REG_CYCLE, 0); @@ -1267,12 +1164,15 @@ static struct block * generate_dispatcher(struct lightrec_state *state) jit_lshi(JIT_V1, JIT_V1, 1); jit_add_state(JIT_V1, JIT_V1); - offset = offsetof(struct lightrec_state, code_lut); + offset = lightrec_offset(code_lut); if (lut_is_32bit(state)) jit_ldxi_ui(JIT_V1, JIT_V1, offset); else jit_ldxi(JIT_V1, JIT_V1, offset); + /* Store back the current PC to the lightrec_state structure */ + jit_stxi_i(lightrec_offset(curr_pc), LIGHTREC_REG_STATE, JIT_V0); + /* If we get non-NULL, loop */ jit_patch_at(jit_bnei(JIT_V1, 0), loop); @@ -1309,8 +1209,7 @@ static struct block * generate_dispatcher(struct lightrec_state *state) } /* Reset JIT_V0 to the next PC */ - jit_ldxi_ui(JIT_V0, LIGHTREC_REG_STATE, - offsetof(struct lightrec_state, curr_pc)); + jit_ldxi_ui(JIT_V0, LIGHTREC_REG_STATE, lightrec_offset(curr_pc)); /* If we get non-NULL, loop */ jit_patch_at(jit_bnei(JIT_V1, 0), loop); @@ -1319,7 +1218,80 @@ static struct block * generate_dispatcher(struct lightrec_state *state) jit_note(__FILE__, __LINE__); jit_patch(to_end); + /* Store back the current PC to the lightrec_state structure */ + jit_stxi_i(lightrec_offset(curr_pc), LIGHTREC_REG_STATE, JIT_V0); + jit_retr(LIGHTREC_REG_CYCLE); + + if (OPT_REPLACE_MEMSET) { + /* Blocks will jump here when they need to call + * lightrec_memset() */ + addr3 = jit_indirect(); + + jit_movr(JIT_V1, LIGHTREC_REG_CYCLE); + + jit_prepare(); + jit_pushargr(LIGHTREC_REG_STATE); + + jit_finishi(lightrec_memset); + jit_retval(LIGHTREC_REG_CYCLE); + + jit_ldxi_ui(JIT_V0, LIGHTREC_REG_STATE, lightrec_offset(regs.gpr[31])); + + jit_subr(LIGHTREC_REG_CYCLE, JIT_V1, LIGHTREC_REG_CYCLE); + + jit_patch_at(jit_b(), loop2); + } + + if (OPT_DETECT_IMPOSSIBLE_BRANCHES) { + /* Blocks will jump here when they reach a branch that should + * be executed with the interpreter, passing the branch's PC + * in JIT_V0 and the address of the block in JIT_V1. */ + addr4 = jit_indirect(); + + sync_next_pc(_jit); + update_cycle_counter_before_c(_jit); + + jit_prepare(); + jit_pushargr(LIGHTREC_REG_STATE); + jit_pushargr(JIT_V1); + jit_pushargr(JIT_V0); + jit_finishi(lightrec_emulate_block); + + jit_retval(JIT_V0); + + update_cycle_counter_after_c(_jit); + + jit_patch_at(jit_b(), loop2); + + } + + if (OPT_HANDLE_LOAD_DELAYS) { + /* Blocks will jump here when they reach a branch with a load + * opcode in its delay slot. The delay slot has already been + * executed; the load value is in (state->temp_reg), and the + * register number is in JIT_V1. + * Jump to a C function which will evaluate the branch target's + * first opcode, to make sure that it does not read the register + * in question; and if it does, handle it accordingly. */ + addr5 = jit_indirect(); + + sync_next_pc(_jit); + update_cycle_counter_before_c(_jit); + + jit_prepare(); + jit_pushargr(LIGHTREC_REG_STATE); + jit_pushargr(JIT_V0); + jit_pushargr(JIT_V1); + jit_finishi(lightrec_check_load_delay); + + jit_retval(JIT_V0); + + update_cycle_counter_after_c(_jit); + + jit_patch_at(jit_b(), loop2); + } + jit_epilog(); block->_jit = _jit; @@ -1472,7 +1444,7 @@ static struct block * lightrec_precompile_block(struct lightrec_state *state, lightrec_register(MEM_FOR_MIPS_CODE, length); if (ENABLE_DISASSEMBLER) { - pr_debug("Disassembled block at PC: 0x%08x\n", block->pc); + pr_debug("Disassembled block at "PC_FMT"\n", block->pc); lightrec_print_disassembly(block, code); } @@ -1747,8 +1719,8 @@ int lightrec_compile_block(struct lightrec_cstate *cstate, block2 = lightrec_find_block(state->block_cache, offset); } if (block2) { - pr_debug("Reap block 0x%08x as it's covered by block " - "0x%08x\n", block2->pc, block->pc); + pr_debug("Reap block "X32_FMT" as it's covered by block " + X32_FMT"\n", block2->pc, block->pc); /* Finally, reap the block. */ if (!ENABLE_THREADED_COMPILER) { @@ -1766,7 +1738,7 @@ int lightrec_compile_block(struct lightrec_cstate *cstate, lightrec_reaper_continue(state->reaper); if (ENABLE_DISASSEMBLER) { - pr_debug("Compiling block at PC: 0x%08x\n", block->pc); + pr_debug("Compiling block at "PC_FMT"\n", block->pc); jit_disassemble(); } @@ -1789,7 +1761,7 @@ int lightrec_compile_block(struct lightrec_cstate *cstate, } if (oldjit) { - pr_debug("Block 0x%08x recompiled, reaping old jit context.\n", + pr_debug("Block "X32_FMT" recompiled, reaping old jit context.\n", block->pc); if (ENABLE_THREADED_COMPILER) { diff --git a/deps/lightrec/optimizer.c b/deps/lightrec/optimizer.c index cb9ba5b8..0a3655b9 100644 --- a/deps/lightrec/optimizer.c +++ b/deps/lightrec/optimizer.c @@ -909,8 +909,8 @@ static int lightrec_transform_ops(struct lightrec_state *state, struct block *bl /* Transform all opcodes detected as useless to real NOPs * (0x0: SLL r0, r0, #0) */ if (op->opcode != 0 && is_nop(op->c)) { - pr_debug("Converting useless opcode 0x%08x to NOP\n", - op->opcode); + pr_debug("Converting useless opcode "X32_FMT" to NOP\n", + op->opcode); op->opcode = 0x0; } @@ -1740,7 +1740,7 @@ static int lightrec_flag_io(struct lightrec_state *state, struct block *block) * registers as address will never hit a code page. */ if (list->i.rs >= 28 && list->i.rs <= 29 && !state->maps[PSX_MAP_KERNEL_USER_RAM].ops) { - pr_debug("Flaging opcode 0x%08x as not requiring invalidation\n", + pr_debug("Flaging opcode "X32_FMT" as not requiring invalidation\n", list->opcode); list->flags |= LIGHTREC_NO_INVALIDATE; } @@ -2245,7 +2245,7 @@ static int lightrec_replace_memset(struct lightrec_state *state, struct block *b if (i == ARRAY_SIZE(memset_code) - 1) { /* success! */ - pr_debug("Block at PC 0x%x is a memset\n", block->pc); + pr_debug("Block at "PC_FMT" is a memset\n", block->pc); block_set_flags(block, BLOCK_IS_MEMSET | BLOCK_NEVER_COMPILE); diff --git a/deps/lightrec/regcache.c b/deps/lightrec/regcache.c index 45d77c6c..41d37789 100644 --- a/deps/lightrec/regcache.c +++ b/deps/lightrec/regcache.c @@ -373,8 +373,7 @@ u8 lightrec_alloc_reg_in(struct regcache *cache, jit_state_t *_jit, lightrec_unload_nreg(cache, _jit, nreg, jit_reg); if (nreg->prio < REG_IS_LOADED && reg != 0) { - s16 offset = offsetof(struct lightrec_state, regs.gpr) - + (reg << 2); + s16 offset = lightrec_offset(regs.gpr) + (reg << 2); nreg->zero_extended = flags & REG_ZEXT; nreg->extended = !nreg->zero_extended; @@ -470,8 +469,7 @@ void lightrec_load_next_pc_imm(struct regcache *cache, } if (lightrec_store_next_pc()) { - jit_stxi_i(offsetof(struct lightrec_state, next_pc), - LIGHTREC_REG_STATE, reg); + jit_stxi_i(lightrec_offset(next_pc), LIGHTREC_REG_STATE, reg); lightrec_free_reg(cache, reg); } else { nreg->prio = REG_IS_LOADED; @@ -488,7 +486,7 @@ void lightrec_load_next_pc(struct regcache *cache, jit_state_t *_jit, u8 reg) if (lightrec_store_next_pc()) { jit_reg = lightrec_alloc_reg_in(cache, _jit, reg, 0); - offset = offsetof(struct lightrec_state, next_pc); + offset = lightrec_offset(next_pc); jit_stxi_i(offset, LIGHTREC_REG_STATE, jit_reg); lightrec_free_reg(cache, jit_reg); @@ -504,7 +502,7 @@ void lightrec_load_next_pc(struct regcache *cache, jit_state_t *_jit, u8 reg) if (!nreg) { /* Not mapped - load the value from the register cache */ - offset = offsetof(struct lightrec_state, regs.gpr) + (reg << 2); + offset = lightrec_offset(regs.gpr) + (reg << 2); jit_ldxi_ui(JIT_V0, LIGHTREC_REG_STATE, offset); nreg_v0->prio = REG_IS_LOADED; @@ -533,7 +531,7 @@ void lightrec_load_next_pc(struct regcache *cache, jit_state_t *_jit, u8 reg) } if (lightrec_store_next_pc()) { - jit_stxi_i(offsetof(struct lightrec_state, next_pc), + jit_stxi_i(lightrec_offset(next_pc), LIGHTREC_REG_STATE, JIT_V0); } else { lightrec_clean_reg(cache, _jit, JIT_V0); @@ -574,7 +572,7 @@ static void clean_reg(jit_state_t *_jit, { /* If we get a dirty register, store back the old value */ if (nreg->prio == REG_IS_DIRTY) { - s16 offset = offsetof(struct lightrec_state, regs.gpr) + s16 offset = lightrec_offset(regs.gpr) + (nreg->emulated_register << 2); jit_stxi_i(offset, LIGHTREC_REG_STATE, jit_reg); -- 2.39.2