}
end_op:
- if (delayed_op == 1) {
+ if (delayed_op == 1)
emit_move_r_r(SHR_PC, SHR_PPC);
- break;
- }
+
if (test_irq && delayed_op != 2) {
emith_pass_arg(1, sh2);
emith_call(sh2_test_irq);
break;
}
+ if (delayed_op == 1)
+ break;
#if (DRC_DEBUG & 2)
host_dasm(tcache_dsm_ptr, (char *)tcache_ptr - (char *)tcache_dsm_ptr);
{
while (((signed int)sh2->sr >> 12) > 0)
{
- block_desc *bd = HASH_FUNC(sh2->pc_hashtab, sh2->pc);
void *block = NULL;
+ block_desc *bd;
+
+ // FIXME: must avoid doing it so often..
+ sh2_test_irq(sh2);
+
+ bd = HASH_FUNC(sh2->pc_hashtab, sh2->pc);
if (bd != NULL) {
if (bd->addr == sh2->pc)
static void __attribute__((regparm(1))) sh2_test_irq(SH2 *sh2)
{
- if (sh2->pending_irl > sh2->pending_int_irq)
- sh2_irl_irq(sh2, sh2->pending_irl);
- else
- sh2_internal_irq(sh2, sh2->pending_int_irq, sh2->pending_int_vector);
+ if (sh2->pending_level > ((sh2->sr >> 4) & 0x0f))
+ {
+ if (sh2->pending_irl > sh2->pending_int_irq)
+ sh2_do_irq(sh2, sh2->pending_irl, 64 + sh2->pending_irl/2);
+ else {
+ sh2_do_irq(sh2, sh2->pending_int_irq, sh2->pending_int_vector);
+ sh2->pending_int_irq = 0; // auto-clear
+ sh2->pending_level = sh2->pending_irl;
+ }
+ }
}
int sh2_drc_init(SH2 *sh2)
{
UINT32 opcode;
+ if (sh2->test_irq && !sh2->delay && sh2->pending_level > ((sh2->sr >> 4) & 0x0f))
+ {
+ if (sh2->pending_irl > sh2->pending_int_irq)
+ sh2_do_irq(sh2, sh2->pending_irl, 64 + sh2->pending_irl/2);
+ else {
+ sh2_do_irq(sh2, sh2->pending_int_irq, sh2->pending_int_vector);
+ sh2->pending_int_irq = 0; // auto-clear
+ sh2->pending_level = sh2->pending_irl;
+ }
+ sh2->test_irq = 0;
+ }
+
if (sh2->delay)
{
sh2->ppc = sh2->delay;
default: op1111(opcode); break;
}
- if (sh2->test_irq && !sh2->delay)
- {
- if (sh2->pending_irl > sh2->pending_int_irq)
- sh2_irl_irq(sh2, sh2->pending_irl);
- else
- sh2_internal_irq(sh2, sh2->pending_int_irq, sh2->pending_int_vector);
- sh2->test_irq = 0;
- }
sh2->icount--;
}
while (sh2->icount > 0 || sh2->delay); /* can't interrupt before delay */
sh2->pending_int_irq = 0;
}
-static void sh2_do_irq(SH2 *sh2, int level, int vector)
+void sh2_do_irq(SH2 *sh2, int level, int vector)
{
sh2->irq_callback(sh2->is_slave, level);
void sh2_irl_irq(SH2 *sh2, int level)
{
sh2->pending_irl = level;
- if (level <= ((sh2->sr >> 4) & 0x0f))
- return;
+ if (level > sh2->pending_int_irq)
+ sh2->pending_level = level;
+ else
+ sh2->pending_level = sh2->pending_int_irq;
- sh2_do_irq(sh2, level, 64 + level/2);
+ sh2->test_irq = 1;
}
void sh2_internal_irq(SH2 *sh2, int level, int vector)
{
+ // FIXME: multiple internal irqs not handled..
+ // assuming internal irqs never clear until accepted
sh2->pending_int_irq = level;
sh2->pending_int_vector = vector;
- if (level <= ((sh2->sr >> 4) & 0x0f))
- return;
+ if (level > sh2->pending_level)
+ sh2->pending_level = level;
- sh2_do_irq(sh2, level, vector);
- sh2->pending_int_irq = 0; // auto-clear
+ sh2->test_irq = 1;
}
void **pc_hashtab; // 70\r
\r
// common\r
+ int pending_level; // MAX(pending_irl, pending_int_irq)\r
int pending_irl;\r
int pending_int_irq; // internal irq\r
int pending_int_vector;\r
void sh2_reset(SH2 *sh2);\r
void sh2_irl_irq(SH2 *sh2, int level);\r
void sh2_internal_irq(SH2 *sh2, int level, int vector);\r
+void sh2_do_irq(SH2 *sh2, int level, int vector);\r
\r
void sh2_execute(SH2 *sh2, int cycles);\r
\r
#define sh2_reg(c, x) (c) ? ssh2.r[x] : msh2.r[x]\r
#define sh2_gbr(c) (c) ? ssh2.gbr : msh2.gbr\r
#define sh2_vbr(c) (c) ? ssh2.vbr : msh2.vbr\r
-#define sh2_sr(c) (c) ? ssh2.sr : msh2.sr\r
+#define sh2_sr(c) (((c) ? ssh2.sr : msh2.sr) & 0xfff)\r
\r
#define sh2_set_gbr(c, v) \\r
{ if (c) ssh2.gbr = v; else msh2.gbr = v; }\r