X-Git-Url: https://notaz.gp2x.de/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=deps%2Flightrec%2Finterpreter.c;h=ea8098cd4217fc70b981ce4beb9901b3091fe334;hb=9259d7486618d69721fee743c3e4d0b5c83805fe;hp=922f0810e18f91438644429c8b4e66fc9a9e754c;hpb=47e92264b0bcdd851e8b0973cd5036cc6ca8e4ba;p=pcsx_rearmed.git diff --git a/deps/lightrec/interpreter.c b/deps/lightrec/interpreter.c index 922f0810..ea8098cd 100644 --- a/deps/lightrec/interpreter.c +++ b/deps/lightrec/interpreter.c @@ -63,7 +63,7 @@ static inline u32 jump_skip(struct interpreter *inter) inter->op = next_op(inter); inter->offset++; - if (inter->op->flags & LIGHTREC_SYNC) { + if (op_flag_sync(inter->op->flags)) { inter->state->current_cycle += inter->cycles; inter->cycles = 0; } @@ -101,8 +101,8 @@ static void update_cycles_before_branch(struct interpreter *inter) if (!inter->delay_slot) { cycles = lightrec_cycles_of_opcode(inter->op->c); - if (has_delay_slot(inter->op->c) && - !(inter->op->flags & LIGHTREC_NO_DS)) + if (!op_flag_no_ds(inter->op->flags) && + has_delay_slot(inter->op->c)) cycles += lightrec_cycles_of_opcode(next_op(inter)->c); inter->cycles += cycles; @@ -329,7 +329,7 @@ static u32 int_jump(struct interpreter *inter, bool link) if (link) state->regs.gpr[31] = old_pc + 8; - if (inter->op->flags & LIGHTREC_NO_DS) + if (op_flag_no_ds(inter->op->flags)) return pc; return int_delay_slot(inter, pc, true); @@ -348,14 +348,18 @@ static u32 int_JAL(struct interpreter *inter) static u32 int_jumpr(struct interpreter *inter, u8 link_reg) { struct lightrec_state *state = inter->state; - u32 old_pc, next_pc = state->regs.gpr[inter->op->r.rs]; + u32 old_pc = int_get_branch_pc(inter); + u32 next_pc = state->regs.gpr[inter->op->r.rs]; - if (link_reg) { - old_pc = int_get_branch_pc(inter); - state->regs.gpr[link_reg] = old_pc + 8; + if (op_flag_emulate_branch(inter->op->flags) && inter->offset) { + inter->cycles -= lightrec_cycles_of_opcode(inter->op->c); + return old_pc; } - if (inter->op->flags & LIGHTREC_NO_DS) + if (link_reg) + state->regs.gpr[link_reg] = old_pc + 8; + + if (op_flag_no_ds(inter->op->flags)) return next_pc; return int_delay_slot(inter, next_pc, true); @@ -373,8 +377,7 @@ static u32 int_special_JALR(struct interpreter *inter) static u32 int_do_branch(struct interpreter *inter, u32 old_pc, u32 next_pc) { - if (!inter->delay_slot && - (inter->op->flags & LIGHTREC_LOCAL_BRANCH) && + if (!inter->delay_slot && op_flag_local_branch(inter->op->flags) && (s16)inter->op->c.i.imm >= 0) { next_pc = old_pc + ((1 + (s16)inter->op->c.i.imm) << 2); next_pc = lightrec_emulate_block(inter->state, inter->block, next_pc); @@ -388,9 +391,14 @@ static u32 int_branch(struct interpreter *inter, u32 pc, { u32 next_pc = pc + 4 + ((s16)code.i.imm << 2); + if (op_flag_emulate_branch(inter->op->flags) && inter->offset) { + inter->cycles -= lightrec_cycles_of_opcode(inter->op->c); + return pc; + } + update_cycles_before_branch(inter); - if (inter->op->flags & LIGHTREC_NO_DS) { + if (op_flag_no_ds(inter->op->flags)) { if (branch) return int_do_branch(inter, pc, next_pc); else @@ -403,7 +411,7 @@ static u32 int_branch(struct interpreter *inter, u32 pc, if (branch) return int_do_branch(inter, pc, next_pc); - if (inter->op->flags & LIGHTREC_EMULATE_BRANCH) + if (op_flag_emulate_branch(inter->op->flags)) return pc + 8; else return jump_after_branch(inter); @@ -492,12 +500,12 @@ static u32 int_ctc(struct interpreter *inter) struct lightrec_state *state = inter->state; const struct opcode *op = inter->op; - lightrec_mtc(state, op->c, state->regs.gpr[op->r.rt]); + lightrec_mtc(state, op->c, op->r.rd, state->regs.gpr[op->r.rt]); /* If we have a MTC0 or CTC0 to CP0 register 12 (Status) or 13 (Cause), * return early so that the emulator will be able to check software * interrupt status. */ - if (!(inter->op->flags & LIGHTREC_NO_DS) && + if (!op_flag_no_ds(inter->op->flags) && op->i.op == OP_CP0 && (op->r.rd == 12 || op->r.rd == 13)) return int_get_ds_pc(inter, 1); else @@ -618,7 +626,7 @@ static u32 int_store(struct interpreter *inter) { u32 next_pc; - if (likely(!(inter->op->flags & LIGHTREC_SMC))) + if (likely(!op_flag_smc(inter->op->flags))) return int_io(inter, false); lightrec_rw(inter->state, inter->op->c, @@ -765,9 +773,9 @@ static u32 int_special_MULT(struct interpreter *inter) u8 reg_hi = get_mult_div_hi(inter->op->c); u64 res = (s64)rs * (s64)rt; - if (!(inter->op->flags & LIGHTREC_NO_HI)) + if (!op_flag_no_hi(inter->op->flags)) reg_cache[reg_hi] = res >> 32; - if (!(inter->op->flags & LIGHTREC_NO_LO)) + if (!op_flag_no_lo(inter->op->flags)) reg_cache[reg_lo] = res; return jump_next(inter); @@ -782,9 +790,9 @@ static u32 int_special_MULTU(struct interpreter *inter) u8 reg_hi = get_mult_div_hi(inter->op->c); u64 res = (u64)rs * (u64)rt; - if (!(inter->op->flags & LIGHTREC_NO_HI)) + if (!op_flag_no_hi(inter->op->flags)) reg_cache[reg_hi] = res >> 32; - if (!(inter->op->flags & LIGHTREC_NO_LO)) + if (!op_flag_no_lo(inter->op->flags)) reg_cache[reg_lo] = res; return jump_next(inter); @@ -807,9 +815,9 @@ static u32 int_special_DIV(struct interpreter *inter) hi = rs % rt; } - if (!(inter->op->flags & LIGHTREC_NO_HI)) + if (!op_flag_no_hi(inter->op->flags)) reg_cache[reg_hi] = hi; - if (!(inter->op->flags & LIGHTREC_NO_LO)) + if (!op_flag_no_lo(inter->op->flags)) reg_cache[reg_lo] = lo; return jump_next(inter); @@ -832,9 +840,9 @@ static u32 int_special_DIVU(struct interpreter *inter) hi = rs % rt; } - if (!(inter->op->flags & LIGHTREC_NO_HI)) + if (!op_flag_no_hi(inter->op->flags)) reg_cache[reg_hi] = hi; - if (!(inter->op->flags & LIGHTREC_NO_LO)) + if (!op_flag_no_lo(inter->op->flags)) reg_cache[reg_lo] = lo; return jump_next(inter); @@ -977,6 +985,33 @@ static u32 int_META_EXTS(struct interpreter *inter) return jump_next(inter); } +static u32 int_META_MULT2(struct interpreter *inter) +{ + u32 *reg_cache = inter->state->regs.gpr; + union code c = inter->op->c; + u32 rs = reg_cache[c.r.rs]; + u8 reg_lo = get_mult_div_lo(c); + u8 reg_hi = get_mult_div_hi(c); + + if (!op_flag_no_lo(inter->op->flags)) { + if (c.r.op < 32) + reg_cache[reg_lo] = rs << c.r.op; + else + reg_cache[reg_lo] = 0; + } + + if (!op_flag_no_hi(inter->op->flags)) { + if (c.r.op >= 32) + reg_cache[reg_hi] = rs << (c.r.op - 32); + else if (c.i.op == OP_META_MULT2) + reg_cache[reg_hi] = (s32) rs >> (32 - c.r.op); + else + reg_cache[reg_hi] = rs >> (32 - c.r.op); + } + + return jump_next(inter); +} + static const lightrec_int_func_t int_standard[64] = { SET_DEFAULT_ELM(int_standard, int_unimplemented), [OP_SPECIAL] = int_SPECIAL, @@ -1015,6 +1050,8 @@ static const lightrec_int_func_t int_standard[64] = { [OP_META_MOV] = int_META_MOV, [OP_META_EXTC] = int_META_EXTC, [OP_META_EXTS] = int_META_EXTS, + [OP_META_MULT2] = int_META_MULT2, + [OP_META_MULTU2] = int_META_MULT2, }; static const lightrec_int_func_t int_special[64] = { @@ -1147,5 +1184,7 @@ u32 lightrec_emulate_block(struct lightrec_state *state, struct block *block, u3 pr_err("PC 0x%x is outside block at PC 0x%x\n", pc, block->pc); + lightrec_set_exit_flags(state, LIGHTREC_EXIT_SEGFAULT); + return 0; }