[subrepo]
remote = https://github.com/pcercuei/lightrec.git
branch = master
- commit = 8d3db1a4e76c7b81301013f18650011b7e5eabf3
- parent = fcd42d7decc2ed71801e4cbe575c4d2726b2743e
+ commit = bd0b82792284f22566bbfc78d8882e1e91b10516
+ parent = 1229a4ea3dea3e1e47c46cd7afed38860fd91a57
method = merge
cmdver = 0.4.6
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);
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);
}
}
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);
}
}
}
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));
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;
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),
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);
}
}
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);
}
}
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);
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);
/* 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);
* 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);
}
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
/* 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);
}
}
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);
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);
}
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);
}
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;
}
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);
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)
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)
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);
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; */
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);
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
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 {
#include <inttypes.h>
#include <stdint.h>
-#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)
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;
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);
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)
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();
/* 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));
}
}
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]));
}
}
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");
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);
}
{
if (lightrec_store_next_pc()) {
jit_ldxi_ui(JIT_V0, LIGHTREC_REG_STATE,
- offsetof(struct lightrec_state, next_pc));
+ lightrec_offset(next_pc));
}
}
{
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;
/* 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);
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);
}
/* 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);
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;
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);
}
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) {
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();
}
}
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) {
/* 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;
}
* 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;
}
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);
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;
}
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;
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);
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;
}
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);
{
/* 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);