mirror of
https://github.com/RaySollium99/picodrive.git
synced 2025-09-06 07:38:05 -04:00
32x: watchdog for Star Wars, SCI IRQs for X-men (also needs idle loop hacks)
git-svn-id: file:///home/notaz/opt/svn/PicoDrive@799 be3aeb3a-fb24-0410-a615-afba39da0efa
This commit is contained in:
parent
236990cf77
commit
1d7a28a723
8 changed files with 167 additions and 54 deletions
|
@ -44,7 +44,9 @@ typedef struct
|
|||
UINT32 delay;
|
||||
UINT32 test_irq;
|
||||
|
||||
int pending_irq;
|
||||
int pending_irl;
|
||||
int pending_int_irq; // internal irq
|
||||
int pending_int_vector;
|
||||
void (*irq_callback)(int id, int level);
|
||||
int is_slave;
|
||||
|
||||
|
@ -58,5 +60,6 @@ void sh2_init(SH2 *sh2, int is_slave);
|
|||
void sh2_reset(SH2 *sh2);
|
||||
int sh2_execute(SH2 *sh2_, int cycles);
|
||||
void sh2_irl_irq(SH2 *sh2, int level);
|
||||
void sh2_internal_irq(SH2 *sh2, int level, int vector);
|
||||
|
||||
#endif /* __SH2_H__ */
|
||||
|
|
|
@ -57,6 +57,25 @@ void sh2_reset(SH2 *sh2)
|
|||
sh2->sr = I;
|
||||
}
|
||||
|
||||
static void sh2_do_irq(SH2 *sh2, int level, int vector)
|
||||
{
|
||||
sh2->irq_callback(sh2->is_slave, level);
|
||||
|
||||
sh2->r[15] -= 4;
|
||||
WL(sh2->r[15], sh2->sr); /* push SR onto stack */
|
||||
sh2->r[15] -= 4;
|
||||
WL(sh2->r[15], sh2->pc); /* push PC onto stack */
|
||||
|
||||
/* set I flags in SR */
|
||||
sh2->sr = (sh2->sr & ~I) | (level << 4);
|
||||
|
||||
/* fetch PC */
|
||||
sh2->pc = RL(sh2->vbr + vector * 4);
|
||||
|
||||
/* 13 cycles at best */
|
||||
sh2_icount -= 13;
|
||||
}
|
||||
|
||||
/* Execute cycles - returns number of cycles actually run */
|
||||
int sh2_execute(SH2 *sh2_, int cycles)
|
||||
{
|
||||
|
@ -105,8 +124,10 @@ int sh2_execute(SH2 *sh2_, int cycles)
|
|||
|
||||
if (sh2->test_irq && !sh2->delay)
|
||||
{
|
||||
if (sh2->pending_irq)
|
||||
sh2_irl_irq(sh2, sh2->pending_irq);
|
||||
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--;
|
||||
|
@ -124,29 +145,21 @@ void sh2_init(SH2 *sh2, int is_slave)
|
|||
|
||||
void sh2_irl_irq(SH2 *sh2, int level)
|
||||
{
|
||||
int vector;
|
||||
|
||||
sh2->pending_irq = level;
|
||||
|
||||
sh2->pending_irl = level;
|
||||
if (level <= ((sh2->sr >> 4) & 0x0f))
|
||||
/* masked */
|
||||
return;
|
||||
|
||||
sh2->irq_callback(sh2->is_slave, level);
|
||||
vector = 64 + level/2;
|
||||
|
||||
sh2->r[15] -= 4;
|
||||
WL(sh2->r[15], sh2->sr); /* push SR onto stack */
|
||||
sh2->r[15] -= 4;
|
||||
WL(sh2->r[15], sh2->pc); /* push PC onto stack */
|
||||
|
||||
/* set I flags in SR */
|
||||
sh2->sr = (sh2->sr & ~I) | (level << 4);
|
||||
|
||||
/* fetch PC */
|
||||
sh2->pc = RL(sh2->vbr + vector * 4);
|
||||
|
||||
/* 13 cycles at best */
|
||||
sh2_icount -= 13;
|
||||
sh2_do_irq(sh2, level, 64 + level/2);
|
||||
}
|
||||
|
||||
void sh2_internal_irq(SH2 *sh2, int level, int vector)
|
||||
{
|
||||
sh2->pending_int_irq = level;
|
||||
sh2->pending_int_vector = vector;
|
||||
if (level <= ((sh2->sr >> 4) & 0x0f))
|
||||
return;
|
||||
|
||||
sh2_do_irq(sh2, level, vector);
|
||||
sh2->pending_int_irq = 0; // auto-clear
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue