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))
{
}
}
-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;
}
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);
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__);
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;
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;
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__);
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 {
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();
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)
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;
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 */
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);
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;
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)
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);
}
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,