32x, drc, fix saving SH2 SR in dma

This commit is contained in:
kub 2021-05-11 22:05:57 +02:00
parent 78c2237ab8
commit ca1b77e601
3 changed files with 9 additions and 4 deletions

View file

@ -70,12 +70,13 @@ extern void REGPARM(1) (*sh2_drc_restore_sr)(SH2 *sh2);
#else #else
#define DRC_DECLARE_SR register long _sh2_sr asm(DRC_SR_REG) #define DRC_DECLARE_SR register long _sh2_sr asm(DRC_SR_REG)
#endif #endif
// NB: save/load SR register only when DRC is executing and not in DMA access
#define DRC_SAVE_SR(sh2) \ #define DRC_SAVE_SR(sh2) \
if (likely(sh2->state & SH2_IN_DRC)) \ if (likely((sh2->state & (SH2_IN_DRC|SH2_STATE_SLEEP)) == SH2_IN_DRC)) \
sh2->sr = (s32)_sh2_sr sh2->sr = (s32)_sh2_sr
// sh2_drc_save_sr(sh2) // sh2_drc_save_sr(sh2)
#define DRC_RESTORE_SR(sh2) \ #define DRC_RESTORE_SR(sh2) \
if (likely(sh2->state & SH2_IN_DRC)) \ if (likely((sh2->state & (SH2_IN_DRC|SH2_STATE_SLEEP)) == SH2_IN_DRC)) \
_sh2_sr = (s32)sh2->sr _sh2_sr = (s32)sh2->sr
// sh2_drc_restore_sr(sh2) // sh2_drc_restore_sr(sh2)
#else #else

View file

@ -50,8 +50,8 @@ typedef struct SH2_
#define SH2_STATE_CPOLL (1 << 2) // polling comm regs #define SH2_STATE_CPOLL (1 << 2) // polling comm regs
#define SH2_STATE_VPOLL (1 << 3) // polling VDP #define SH2_STATE_VPOLL (1 << 3) // polling VDP
#define SH2_STATE_RPOLL (1 << 4) // polling address in SDRAM #define SH2_STATE_RPOLL (1 << 4) // polling address in SDRAM
#define SH2_TIMER_RUN (1 << 7) // SOC WDT timer is running #define SH2_TIMER_RUN (1 << 6) // SOC WDT timer is running
#define SH2_IN_DRC (1 << 8) // DRC in use #define SH2_IN_DRC (1 << 7) // DRC in use
unsigned int state; unsigned int state;
uint32_t poll_addr; uint32_t poll_addr;
int poll_cycles; int poll_cycles;

View file

@ -480,10 +480,12 @@ void REGPARM(3) sh2_peripheral_write32(u32 a, u32 d, SH2 *sh2)
if (!(dmac->dmaor & DMA_DME)) if (!(dmac->dmaor & DMA_DME))
return; return;
DRC_SAVE_SR(sh2);
if ((dmac->chan[0].chcr & (DMA_TE|DMA_DE)) == DMA_DE) if ((dmac->chan[0].chcr & (DMA_TE|DMA_DE)) == DMA_DE)
dmac_trigger(sh2, &dmac->chan[0]); dmac_trigger(sh2, &dmac->chan[0]);
if ((dmac->chan[1].chcr & (DMA_TE|DMA_DE)) == DMA_DE) if ((dmac->chan[1].chcr & (DMA_TE|DMA_DE)) == DMA_DE)
dmac_trigger(sh2, &dmac->chan[1]); dmac_trigger(sh2, &dmac->chan[1]);
DRC_RESTORE_SR(sh2);
break; break;
} }
@ -538,7 +540,9 @@ static void dreq1_do(SH2 *sh2, struct dma_chan *chan)
if ((chan->dar & ~0xf) != 0x20004030) if ((chan->dar & ~0xf) != 0x20004030)
elprintf(EL_32XP|EL_ANOMALY, "dreq1: bad dar?: %08x\n", chan->dar); elprintf(EL_32XP|EL_ANOMALY, "dreq1: bad dar?: %08x\n", chan->dar);
sh2->state |= SH2_STATE_SLEEP;
dmac_transfer_one(sh2, chan); dmac_transfer_one(sh2, chan);
sh2->state &= ~SH2_STATE_SLEEP;
if (chan->tcr == 0) if (chan->tcr == 0)
dmac_transfer_complete(sh2, chan); dmac_transfer_complete(sh2, chan);
} }