mirror of
https://github.com/RaySollium99/picodrive.git
synced 2025-09-05 15:27:46 -04:00
z80, fix sms interrupt handling in cz80
This commit is contained in:
parent
4b3e9d92e3
commit
80bf9bcce9
5 changed files with 104 additions and 94 deletions
|
@ -199,7 +199,6 @@ void Cz80_Init(cz80_struc *CPU)
|
|||
CPU->pzR16[3] = pzAF;
|
||||
|
||||
zIX = zIY = 0xffff;
|
||||
zF = ZF;
|
||||
|
||||
CPU->Interrupt_Callback = Cz80_Interrupt_Callback;
|
||||
}
|
||||
|
@ -245,7 +244,6 @@ INT32 Cz80_Exec(cz80_struc *CPU, INT32 cycles)
|
|||
UINT32 adr = 0;
|
||||
UINT32 res;
|
||||
UINT32 val;
|
||||
int afterEI = 0;
|
||||
union16 *data;
|
||||
|
||||
PC = CPU->PC;
|
||||
|
@ -255,33 +253,36 @@ INT32 Cz80_Exec(cz80_struc *CPU, INT32 cycles)
|
|||
CPU->ICount = cycles - CPU->ExtraCycles;
|
||||
CPU->ExtraCycles = 0;
|
||||
|
||||
if (!CPU->HaltState)
|
||||
{
|
||||
Cz80_Exec:
|
||||
if (CPU->ICount > 0)
|
||||
if (CPU->Status)
|
||||
{
|
||||
if (CPU->Status & CZ80_HAS_NMI)
|
||||
{
|
||||
Cz80_Exec_nocheck:
|
||||
data = pzHL;
|
||||
Opcode = READ_OP();
|
||||
#if CZ80_EMULATE_R_EXACTLY
|
||||
zR++;
|
||||
#endif
|
||||
#include "cz80_op.c"
|
||||
zIFF1 = 0;
|
||||
CPU->Status &= ~(CZ80_HALTED | CZ80_HAS_NMI);
|
||||
CPU->ExtraCycles += 11;
|
||||
PUSH_16(zRealPC);
|
||||
SET_PC(0x66);
|
||||
} else if (CPU->Status & CZ80_HAS_INT)
|
||||
{
|
||||
CHECK_INT
|
||||
} else if (CPU->Status & CZ80_HALTED)
|
||||
{
|
||||
goto Cz80_Exec_End;
|
||||
}
|
||||
CPU->ICount -= CPU->ExtraCycles;
|
||||
CPU->ExtraCycles = 0;
|
||||
}
|
||||
|
||||
if (afterEI)
|
||||
{
|
||||
afterEI = 0;
|
||||
Cz80_Check_Interrupt:
|
||||
if (CPU->IRQState != CLEAR_LINE)
|
||||
{
|
||||
CHECK_INT
|
||||
}
|
||||
CPU->ICount -= CPU->ExtraCycles;
|
||||
CPU->ExtraCycles = 0;
|
||||
if (!CPU->HaltState)
|
||||
goto Cz80_Exec;
|
||||
}
|
||||
if (CPU->ICount > 0)
|
||||
{
|
||||
Cz80_Exec_nocheck:
|
||||
data = pzHL;
|
||||
Opcode = READ_OP();
|
||||
#if CZ80_EMULATE_R_EXACTLY
|
||||
zR++;
|
||||
#endif
|
||||
#include "cz80_op.c"
|
||||
}
|
||||
|
||||
Cz80_Exec_End:
|
||||
|
@ -289,7 +290,7 @@ Cz80_Exec_End:
|
|||
#if CZ80_ENCRYPTED_ROM
|
||||
CPU->OPBase = OPBase;
|
||||
#endif
|
||||
if (!(CPU->HaltState && CPU->ICount > 0))
|
||||
if (!((CPU->Status & CZ80_HALTED) && CPU->ICount > 0))
|
||||
cycles -= CPU->ICount;
|
||||
CPU->ICount = 0;
|
||||
#if !CZ80_EMULATE_R_EXACTLY
|
||||
|
@ -308,36 +309,23 @@ void Cz80_Set_IRQ(cz80_struc *CPU, INT32 line, INT32 state)
|
|||
{
|
||||
if (line == IRQ_LINE_NMI)
|
||||
{
|
||||
zIFF1 = 0;
|
||||
CPU->ExtraCycles += 11;
|
||||
CPU->HaltState = 0;
|
||||
PUSH_16(CPU->PC - CPU->BasePC)
|
||||
Cz80_Set_Reg(CPU, CZ80_PC, 0x66);
|
||||
}
|
||||
else
|
||||
if (state)
|
||||
CPU->Status |= CZ80_HAS_NMI;
|
||||
else
|
||||
CPU->Status &= ~CZ80_HAS_NMI;
|
||||
} else
|
||||
{
|
||||
CPU->IRQLine = line;
|
||||
CPU->IRQState = state;
|
||||
|
||||
if (state != CLEAR_LINE)
|
||||
if (state)
|
||||
{
|
||||
FPTR PC = CPU->PC;
|
||||
#if CZ80_ENCRYPTED_ROM
|
||||
FPTR OPBase = CPU->OPBase;
|
||||
#endif
|
||||
|
||||
CPU->IRQLine = line;
|
||||
CHECK_INT
|
||||
CPU->PC = PC;
|
||||
#if CZ80_ENCRYPTED_ROM
|
||||
CPU->OPBase = OPBase;
|
||||
#endif
|
||||
if (zIFF1)
|
||||
CPU->Status |= CZ80_HAS_INT;
|
||||
} else
|
||||
{
|
||||
CPU->Status &= ~CZ80_HAS_INT;
|
||||
}
|
||||
}
|
||||
if (CPU->ICount > 0)
|
||||
{
|
||||
CPU->ICount -= CPU->ExtraCycles;
|
||||
CPU->ExtraCycles = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -366,7 +354,7 @@ UINT32 Cz80_Get_Reg(cz80_struc *CPU, INT32 regnum)
|
|||
case CZ80_IM: return zIM;
|
||||
case CZ80_IFF1: return zIFF1;
|
||||
case CZ80_IFF2: return zIFF2;
|
||||
case CZ80_HALT: return CPU->HaltState;
|
||||
case CZ80_HALT: return CPU->Status & CZ80_HALTED;
|
||||
case CZ80_IRQ: return CPU->IRQState;
|
||||
default: return 0;
|
||||
}
|
||||
|
@ -405,7 +393,7 @@ void Cz80_Set_Reg(cz80_struc *CPU, INT32 regnum, UINT32 val)
|
|||
case CZ80_IM: zIM = val; break;
|
||||
case CZ80_IFF1: zIFF1 = val ? (1 << 2) : 0; break;
|
||||
case CZ80_IFF2: zIFF2 = val ? (1 << 2) : 0; break;
|
||||
case CZ80_HALT: CPU->HaltState = val; break;
|
||||
case CZ80_HALT: CPU->Status = !!val * CZ80_HALTED; break;
|
||||
case CZ80_IRQ: CPU->IRQState = val; break;
|
||||
default: break;
|
||||
}
|
||||
|
|
|
@ -170,6 +170,10 @@ extern "C" {
|
|||
#define CZ80_IFF_SFT CZ80_PF_SFT
|
||||
#define CZ80_IFF CZ80_PF
|
||||
|
||||
#define CZ80_HAS_INT 0x1
|
||||
#define CZ80_HAS_NMI 0x2
|
||||
#define CZ80_HALTED 0x4
|
||||
|
||||
#ifndef IRQ_LINE_STATE
|
||||
#define IRQ_LINE_STATE
|
||||
#define CLEAR_LINE 0 /* clear (a fired, held or pulsed) line */
|
||||
|
@ -247,7 +251,7 @@ typedef struct cz80_t
|
|||
|
||||
UINT8 I;
|
||||
UINT8 IM;
|
||||
UINT8 HaltState;
|
||||
UINT8 Status;
|
||||
UINT8 dummy;
|
||||
|
||||
INT32 IRQLine;
|
||||
|
|
|
@ -686,8 +686,8 @@ OP_CCF:
|
|||
|
||||
OP(0x76): // HALT
|
||||
OP_HALT:
|
||||
CPU->HaltState = 1;
|
||||
goto Cz80_Check_Interrupt;
|
||||
CPU->Status |= CZ80_HALTED;
|
||||
RET(4)
|
||||
|
||||
OP(0xf3): // DI
|
||||
OP_DI:
|
||||
|
@ -709,9 +709,12 @@ OP_EI:
|
|||
zR++;
|
||||
#endif
|
||||
}
|
||||
afterEI = 1;
|
||||
CPU->ExtraCycles += 1 - CPU->ICount;
|
||||
CPU->ICount = 1;
|
||||
if (CPU->IRQState)
|
||||
{
|
||||
CPU->Status |= CZ80_HAS_INT;
|
||||
CPU->ExtraCycles -= CPU->ICount;
|
||||
CPU->ICount = 0;
|
||||
}
|
||||
}
|
||||
else zIFF2 = (1 << 2);
|
||||
goto Cz80_Exec_nocheck;
|
||||
|
|
|
@ -421,8 +421,7 @@ OP_SBC16:
|
|||
zIFF1 = (1 << 2);
|
||||
if (CPU->IRQState)
|
||||
{
|
||||
USE_CYCLES(10)
|
||||
goto Cz80_Check_Interrupt;
|
||||
CPU->Status |= CZ80_HAS_INT;
|
||||
}
|
||||
}
|
||||
else zIFF1 = zIFF2;
|
||||
|
@ -492,23 +491,27 @@ OP_LDX:
|
|||
-----------------------------------------*/
|
||||
|
||||
OPED(0xb0): // LDIR
|
||||
if (zBC != 1)
|
||||
PC -= 2;
|
||||
do
|
||||
{
|
||||
val = READ_MEM8(zHL++);
|
||||
WRITE_MEM8(zDE++, val);
|
||||
zBC--;
|
||||
USE_CYCLES(17)
|
||||
} while (zBC && (CPU->ICount > 0));
|
||||
USE_CYCLES(21)
|
||||
} while (zBC > 1 && (CPU->ICount > 0) && !CPU->Status);
|
||||
goto OP_LDXR;
|
||||
|
||||
OPED(0xb8): // LDDR
|
||||
if (zBC != 1)
|
||||
PC -= 2;
|
||||
do
|
||||
{
|
||||
val = READ_MEM8(zHL--);
|
||||
WRITE_MEM8(zDE--, val);
|
||||
zBC--;
|
||||
USE_CYCLES(17)
|
||||
} while (zBC && (CPU->ICount > 0));
|
||||
USE_CYCLES(21)
|
||||
} while (zBC > 1 && (CPU->ICount > 0) && !CPU->Status);
|
||||
|
||||
OP_LDXR:
|
||||
F = zF & (SF | ZF | CF);
|
||||
|
@ -517,14 +520,14 @@ OP_LDXR:
|
|||
if (zBC)
|
||||
{
|
||||
zF = F | VF;
|
||||
PC -= 2;
|
||||
#if CZ80_EMULATE_R_EXACTLY
|
||||
zR--;
|
||||
#endif
|
||||
goto Cz80_Exec_End;
|
||||
ADD_CYCLES(4)
|
||||
goto Cz80_Exec;
|
||||
}
|
||||
zF = F;
|
||||
ADD_CYCLES(5)
|
||||
ADD_CYCLES(4+5)
|
||||
goto Cz80_Exec;
|
||||
|
||||
/*-----------------------------------------
|
||||
|
@ -553,6 +556,8 @@ OP_CPX:
|
|||
-----------------------------------------*/
|
||||
|
||||
OPED(0xb1): // CPIR
|
||||
if (zBC != 1)
|
||||
PC -= 2;
|
||||
do
|
||||
{
|
||||
val = READ_MEM8(zHL++);
|
||||
|
@ -564,11 +569,13 @@ OP_CPX:
|
|||
if (res & 0x08) F |= XF;
|
||||
if (zBC) F |= VF;
|
||||
zF = F;
|
||||
USE_CYCLES(17)
|
||||
} while (zBC && !(F & ZF) && (CPU->ICount > 0));
|
||||
USE_CYCLES(21)
|
||||
} while (zBC > 1 && !(F & ZF) && (CPU->ICount > 0) && !CPU->Status);
|
||||
goto OP_CPXR;
|
||||
|
||||
OPED(0xb9): // CPDR
|
||||
if (zBC != 1)
|
||||
PC -= 2;
|
||||
do
|
||||
{
|
||||
val = READ_MEM8(zHL--);
|
||||
|
@ -580,19 +587,19 @@ OP_CPX:
|
|||
if (res & 0x08) F |= XF;
|
||||
if (zBC) F |= VF;
|
||||
zF = F;
|
||||
USE_CYCLES(17)
|
||||
} while (zBC && !(F & ZF) && (CPU->ICount > 0));
|
||||
USE_CYCLES(21)
|
||||
} while (zBC > 1 && !(F & ZF) && (CPU->ICount > 0) && !CPU->Status);
|
||||
|
||||
OP_CPXR:
|
||||
if (zBC && !(F & ZF))
|
||||
{
|
||||
PC -= 2;
|
||||
#if CZ80_EMULATE_R_EXACTLY
|
||||
zR--;
|
||||
#endif
|
||||
goto Cz80_Exec_End;
|
||||
ADD_CYCLES(4)
|
||||
goto Cz80_Exec;
|
||||
}
|
||||
ADD_CYCLES(5)
|
||||
ADD_CYCLES(4+5)
|
||||
goto Cz80_Exec;
|
||||
|
||||
/*-----------------------------------------
|
||||
|
@ -614,7 +621,7 @@ OP_INX:
|
|||
F = SZ[zB];
|
||||
res = ((UINT32)(zC - 1) & 0xff) + (UINT32)val;
|
||||
if (val & SF) F |= NF;
|
||||
if (res & 0x100) F |= HF | CF;
|
||||
if (res < val) F |= HF | CF;
|
||||
F |= SZP[(UINT8)(res & 0x07) ^ zB] & PF;
|
||||
zF = F;
|
||||
RET(12)
|
||||
|
@ -624,40 +631,44 @@ OP_INX:
|
|||
-----------------------------------------*/
|
||||
|
||||
OPED(0xb2): // INIR
|
||||
if (zB != 1)
|
||||
PC -= 2;
|
||||
do
|
||||
{
|
||||
val = IN(zBC);
|
||||
zB--;
|
||||
WRITE_MEM8(zHL++, val);
|
||||
USE_CYCLES(17)
|
||||
} while (zB && (CPU->ICount > 0));
|
||||
USE_CYCLES(21)
|
||||
} while (zB > 1 && (CPU->ICount > 0) && !CPU->Status);
|
||||
goto OP_INXR;
|
||||
|
||||
OPED(0xba): // INDR
|
||||
if (zB != 1)
|
||||
PC -= 2;
|
||||
do
|
||||
{
|
||||
val = IN(zBC);
|
||||
zB--;
|
||||
WRITE_MEM8(zHL--, val);
|
||||
USE_CYCLES(17)
|
||||
} while (zB && (CPU->ICount > 0));
|
||||
USE_CYCLES(21)
|
||||
} while (zB > 1 && (CPU->ICount > 0) && !CPU->Status);
|
||||
|
||||
OP_INXR:
|
||||
F = SZ[zB];
|
||||
res = ((UINT32)(zC - 1) & 0xff) + (UINT32)val;
|
||||
if (val & SF) F |= NF;
|
||||
if (res & 0x100) F |= HF | CF;
|
||||
if (res < val) F |= HF | CF;
|
||||
F |= SZP[(UINT8)(res & 0x07) ^ zB] & PF;
|
||||
zF = F;
|
||||
if (zB)
|
||||
{
|
||||
PC -= 2;
|
||||
#if CZ80_EMULATE_R_EXACTLY
|
||||
zR--;
|
||||
#endif
|
||||
goto Cz80_Exec_End;
|
||||
ADD_CYCLES(4)
|
||||
goto Cz80_Exec;
|
||||
}
|
||||
ADD_CYCLES(5);
|
||||
ADD_CYCLES(4+5);
|
||||
goto Cz80_Exec;
|
||||
|
||||
/*-----------------------------------------
|
||||
|
@ -679,7 +690,7 @@ OP_OUTX:
|
|||
F = SZ[zB];
|
||||
res = (UINT32)zL + (UINT32)val;
|
||||
if (val & SF) F |= NF;
|
||||
if (res & 0x100) F |= HF | CF;
|
||||
if (res < val) F |= HF | CF;
|
||||
F |= SZP[(UINT8)(res & 0x07) ^ zB] & PF;
|
||||
zF = F;
|
||||
RET(12)
|
||||
|
@ -689,40 +700,44 @@ OP_OUTX:
|
|||
-----------------------------------------*/
|
||||
|
||||
OPED(0xb3): // OTIR
|
||||
if (zB != 1)
|
||||
PC -= 2;
|
||||
do
|
||||
{
|
||||
val = READ_MEM8(zHL++);
|
||||
zB--;
|
||||
OUT(zBC, val);
|
||||
USE_CYCLES(17)
|
||||
} while (zB && (CPU->ICount > 0));
|
||||
USE_CYCLES(21)
|
||||
} while (zB > 1 && (CPU->ICount > 0) && !CPU->Status);
|
||||
goto OP_OTXR;
|
||||
|
||||
OPED(0xbb): // OTDR
|
||||
if (zB != 1)
|
||||
PC -= 2;
|
||||
do
|
||||
{
|
||||
val = READ_MEM8(zHL--);
|
||||
zB--;
|
||||
OUT(zBC, val);
|
||||
USE_CYCLES(17)
|
||||
} while (zB && (CPU->ICount > 0));
|
||||
USE_CYCLES(21)
|
||||
} while (zB > 1 && (CPU->ICount > 0) && !CPU->Status);
|
||||
|
||||
OP_OTXR:
|
||||
F = SZ[zB];
|
||||
res = (UINT32)zL + (UINT32)val;
|
||||
if (val & SF) F |= NF;
|
||||
if (res & 0x100) F |= HF | CF;
|
||||
if (res < val) F |= HF | CF;
|
||||
F |= SZP[(UINT8)(res & 0x07) ^ zB] & PF;
|
||||
zF = F;
|
||||
if (zB)
|
||||
{
|
||||
PC -= 2;
|
||||
#if CZ80_EMULATE_R_EXACTLY
|
||||
zR--;
|
||||
#endif
|
||||
goto Cz80_Exec_End;
|
||||
ADD_CYCLES(4)
|
||||
goto Cz80_Exec;
|
||||
}
|
||||
ADD_CYCLES(5)
|
||||
ADD_CYCLES(4+5)
|
||||
goto Cz80_Exec;
|
||||
}
|
||||
|
||||
|
|
|
@ -90,7 +90,7 @@
|
|||
if (CPU->IRQState == HOLD_LINE) \
|
||||
CPU->IRQState = CLEAR_LINE; \
|
||||
\
|
||||
CPU->HaltState = 0; \
|
||||
CPU->Status &= ~(CZ80_HALTED|CZ80_HAS_INT); \
|
||||
zIFF1 = zIFF2 = 0; \
|
||||
IntVect = CPU->Interrupt_Callback(CPU->IRQLine); \
|
||||
\
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue