default:
default_:
- elprintf_sh2(sh2, EL_ANOMALY,
- "drc: illegal op %04x @ %08x", op, pc - 2);
+ if (!(op_flags[i] & OF_B_IN_DS))
+ elprintf_sh2(sh2, EL_ANOMALY,
+ "drc: illegal op %04x @ %08x", op, pc - 2);
tmp = rcache_get_reg(SHR_SP, RC_GR_RMW);
emith_sub_r_imm(tmp, 4*2);
// push PC
rcache_get_reg_arg(0, SHR_SP);
tmp = rcache_get_tmp_arg(1);
- emith_move_r_imm(tmp, pc - 2);
+ if (drcf.pending_branch_indirect) {
+ tmp2 = rcache_get_reg(SHR_PC, RC_GR_READ);
+ emith_move_r_r(tmp, tmp2);
+ }
+ else
+ emith_move_r_imm(tmp, pc - 2);
emit_memhandler_write(2);
// obtain new PC
- emit_memhandler_read_rr(SHR_PC, SHR_VBR, 4 * 4, 2);
+ v = (op_flags[i] & OF_B_IN_DS) ? 6 : 4;
+ emit_memhandler_read_rr(SHR_PC, SHR_VBR, v * 4, 2);
// indirect jump -> back to dispatcher
rcache_flush();
emith_jump(sh2_drc_dispatcher);
1 + cpuid, SH2_DRCBLK_DA_SHIFT, 0xfff);
}
-int sh2_execute(SH2 *sh2c, int cycles)
+int sh2_execute_drc(SH2 *sh2c, int cycles)
{
int ret_cycles;
- sh2c->cycles_timeslice = cycles;
-
// cycles are kept in SHR_SR unused bits (upper 20)
// bit11 contains T saved for delay slot
// others are usual SH2 flags
dbg(1, "warning: drc returned with cycles: %d", ret_cycles);
sh2c->sr &= 0x3f3;
- return sh2c->cycles_timeslice - ret_cycles;
+ return ret_cycles;
}
#if (DRC_DEBUG & 2)
is_slave ? 's' : 'm', op, pc);
break;
}
+
+ if (op_flags[i] & OF_DELAY_OP) {
+ switch (opd->op) {
+ case OP_BRANCH:
+ case OP_BRANCH_CT:
+ case OP_BRANCH_CF:
+ case OP_BRANCH_R:
+ case OP_BRANCH_RF:
+ elprintf(EL_ANOMALY, "%csh2 drc: branch in DS @ %08x",
+ is_slave ? 's' : 'm', pc);
+ opd->op = OP_UNHANDLED;
+ op_flags[i] |= OF_B_IN_DS;
+ next_is_delay = 0;
+ break;
+ }
+ }
}
i_end = i;
end_pc = pc;