From 32eb2c8cd20a21a24d8f1e78ebabc1b20d657531 Mon Sep 17 00:00:00 2001 From: Floogle <18466542+skyfloogle@users.noreply.github.com> Date: Tue, 9 Jan 2024 19:50:49 +0100 Subject: [PATCH] allow late timer interrupts --- include/v810_cpu.h | 2 +- source/common/v810_cpu.c | 24 ++++++++++++++---------- source/common/v810_mem.c | 2 +- 3 files changed, 16 insertions(+), 12 deletions(-) diff --git a/include/v810_cpu.h b/include/v810_cpu.h index 56d883b..84371c4 100644 --- a/include/v810_cpu.h +++ b/include/v810_cpu.h @@ -120,7 +120,7 @@ void v810_exit(); void v810_reset(); // Generate Interupt #n -void v810_int(WORD iNum, WORD PC); +bool v810_int(WORD iNum, WORD PC); // Generate Exception #n void v810_exp(WORD iNum, WORD eCode); diff --git a/source/common/v810_cpu.c b/source/common/v810_cpu.c index c16fcf3..5ac38c1 100644 --- a/source/common/v810_cpu.c +++ b/source/common/v810_cpu.c @@ -206,14 +206,17 @@ int serviceInt(unsigned int cycles, WORD PC) { if (tHReg.tCount <= 0) { tHReg.tCount += tHReg.tTHW; //reset counter tHReg.TCR |= 0x02; //Zero Status - if (tHReg.TCR & 0x08) { - v810_int(1, PC); - return 1; - } } tHReg.TLB = (tHReg.tCount&0xFF); tHReg.THB = ((tHReg.tCount>>8)&0xFF); } + if ((tHReg.TCR & 0x02) && (tHReg.TCR & 0x08)) { + // zero & interrupt enabled + return v810_int(1, PC); + } + } else { + // don't get too overzealous if we turn it off and on again + lasttime = cycles; } return 0; @@ -332,12 +335,12 @@ int serviceDisplayInt(unsigned int cycles, WORD PC) { } // Generate Interupt #n -void v810_int(WORD iNum, WORD PC) { - if (iNum > 0x0F) return; // Invalid Interupt number... - if((v810_state->S_REG[PSW] & PSW_NP)) return; - if((v810_state->S_REG[PSW] & PSW_EP)) return; // Exception pending? - if((v810_state->S_REG[PSW] & PSW_ID)) return; // Interupt disabled - if(iNum < ((v810_state->S_REG[PSW] & PSW_IA)>>16)) return; // Interupt to low on the chain +bool v810_int(WORD iNum, WORD PC) { + if (iNum > 0x0F) return false; // Invalid Interupt number... + if((v810_state->S_REG[PSW] & PSW_NP)) return false; + if((v810_state->S_REG[PSW] & PSW_EP)) return false; // Exception pending? + if((v810_state->S_REG[PSW] & PSW_ID)) return false; // Interupt disabled + if(iNum < ((v810_state->S_REG[PSW] & PSW_IA)>>16)) return false; // Interupt to low on the chain dprintf(1, "[INT]: iNum=0x%lx\n", iNum); @@ -354,6 +357,7 @@ void v810_int(WORD iNum, WORD PC) { if((iNum+=1) > 0x0F) (iNum = 0x0F); v810_state->S_REG[PSW] = v810_state->S_REG[PSW] | (iNum << 16); //Set the Interupt + return true; } // Generate exception #n diff --git a/source/common/v810_mem.c b/source/common/v810_mem.c index 498d62c..9c8d7f4 100644 --- a/source/common/v810_mem.c +++ b/source/common/v810_mem.c @@ -515,7 +515,7 @@ void hcreg_wbyte(WORD addr, BYTE data) { } tHReg.TCR = (((data|0xE4)&0xFD)|(tHReg.TCR&0x02)); - if ((data & 0x04) && (!(tHReg.TCR & 0x01))) { //cannot clear ZStat if timer is enabled... + if ((data & 0x05) == 0x04 || !(data & 0x08)) { tHReg.TCR &= 0xFD; // Clear the ZStat Flag... } break;