AltairZ80: Add support for Z80 Mode 2 interrupts.

Add support for Z80 Mode 2 interrupts to altairz80_cpu.c
Also implement interrupts for the WD179x floppd controller.
This commit is contained in:
Howard M. Harte 2021-10-09 19:35:00 -07:00
parent c73474df8d
commit 81afea160c
3 changed files with 46 additions and 4 deletions

View file

@ -241,6 +241,7 @@ UNIT cpu_unit = {
int32 IP_S; /* IP register (8086) */
int32 FLAGS_S; /* flags register (8086) */
int32 SR = 0; /* switch register */
int32 vectorInterrupt = 0; /* Vector Interrupt bitfield */
static int32 bankSelect = 0; /* determines selected memory bank */
static uint32 common = 0xc000; /* addresses >= 'common' are in common memory */
static uint32 common_low = 0; /* Common area is in low memory */
@ -2078,7 +2079,6 @@ void setClockFrequency(const uint32 Value) {
clockHasChanged = TRUE;
}
static t_stat sim_instr_mmu (void) {
extern int32 timerInterrupt;
extern int32 timerInterruptHandler;
@ -2135,7 +2135,7 @@ static t_stat sim_instr_mmu (void) {
SP = SP_S;
IX = IX_S;
IY = IY_S;
specialProcessing = clockFrequency | timerInterrupt | keyboardInterrupt | sim_brk_summ;
specialProcessing = clockFrequency | timerInterrupt | vectorInterrupt | keyboardInterrupt | sim_brk_summ;
tStates = 0;
if (rtc_avail) {
startTime = sim_os_msec();
@ -2157,7 +2157,7 @@ static t_stat sim_instr_mmu (void) {
} else /* make sure that sim_os_msec() is not called later */
clockFrequency = startTime = tStatesInSlice = 0;
}
specialProcessing = clockFrequency | timerInterrupt | keyboardInterrupt | sim_brk_summ;
specialProcessing = clockFrequency | timerInterrupt | vectorInterrupt | keyboardInterrupt | sim_brk_summ;
}
if (specialProcessing) { /* quick check for special processing */
@ -2186,6 +2186,35 @@ static t_stat sim_instr_mmu (void) {
PC = timerInterruptHandler & ADDRMASK;
}
if ((IM_S == 2) && vectorInterrupt && (IFF_S & 1)) {
int32 vectable = (IR_S & 0xFF00);
int32 vector;
uint32 tempVectorInterrupt = vectorInterrupt;
uint8 intVector = 0;
while ((tempVectorInterrupt & 1) == 0) {
tempVectorInterrupt >>= 1;
intVector++;
}
vectorInterrupt &= ~(1 << intVector);
specialProcessing = clockFrequency | sim_brk_summ;
IFF_S = 0; /* disable interrupts */
CHECK_BREAK_TWO_BYTES_EXTENDED(SP - 2, SP - 1, (vectorInterrupt |= (1 << intVector), IFF_S |= 1));
if ((GetBYTE(PC) == HALTINSTRUCTION) && ((cpu_unit.flags & UNIT_CPU_STOPONHALT) == 0)) {
PUSH(PC + 1);
PCQ_ENTRY(PC);
}
else {
PUSH(PC);
PCQ_ENTRY(PC - 1);
}
vector = GetBYTE(vectable + (intVector * 2)+1) << 8;
vector |= GetBYTE(vectable + (intVector * 2));
PC = vector & ADDRMASK;
}
if (keyboardInterrupt && (IFF_S & 1)) {
keyboardInterrupt = FALSE;
specialProcessing = clockFrequency | sim_brk_summ;

View file

@ -100,6 +100,8 @@ typedef struct {
typedef struct {
PNP_INFO pnp; /* Plug-n-Play Information */
uint16 fdctype; /* Default is 1793 */
uint8 intenable; /* Interrupt Enable */
uint8 intvector; /* Interrupt Vector */
uint8 intrq; /* WD179X Interrupt Request Output (EOJ) */
uint8 hld; /* WD179X Head Load Output */
uint8 drq; /* WD179X DMA Request Output */
@ -131,6 +133,8 @@ typedef struct {
WD179X_DRIVE_INFO drive[WD179X_MAX_DRIVES];
} WD179X_INFO;
extern int32 vectorInterrupt; /* FDC interrupt pending */
static SECTOR_FORMAT sdata;
extern uint32 PCX;
extern t_stat set_iobase(UNIT *uptr, int32 val, CONST char *cptr, void *desc);
@ -197,6 +201,8 @@ static UNIT wd179x_unit[] = {
static REG wd179x_reg[] = {
{ DRDATAD(FDCTYPE, wd179x_info_data.fdctype, 16, "Controller type"), },
{ FLDATAD(INTENABLE, wd179x_info_data.intenable, 1, "FDC Interrupt Enable"), },
{ DRDATAD(INTVECTOR, wd179x_info_data.intvector, 8, "FDC Interrupt Vector"), },
{ FLDATAD(INTRQ, wd179x_info_data.intrq, 1, "Interrupt Request"), },
{ FLDATAD(HLD, wd179x_info_data.hld, 1, "Head Load"), },
{ FLDATAD(DRQ, wd179x_info_data.drq, 1, "DMA Request"), },
@ -542,6 +548,7 @@ uint8 WD179X_Read(const uint32 Addr)
sim_debug(STATUS_MSG, &wd179x_dev, "WD179X: " ADDRESS_FORMAT
" RD STATUS = 0x%02x, CMDTYPE=%x\n", PCX, cData, wd179x_info->cmdtype);
wd179x_info->intrq = 0;
if (wd179x_info->intenable) vectorInterrupt &= ~(1 << wd179x_info->intvector);
break;
case WD179X_TRACK:
cData = pDrive->track;
@ -946,6 +953,7 @@ static uint8 Do1793Command(uint8 cCommand)
}
} else {
wd179x_info->intrq = 1;
if (wd179x_info->intenable) vectorInterrupt |= (1 << wd179x_info->intvector);
}
wd179x_info->fdc_status &= ~(WD179X_STAT_BUSY); /* Clear BUSY */
}
@ -989,6 +997,7 @@ static uint8 Do1793Command(uint8 cCommand)
wd179x_info->fdc_status &= ~(WD179X_STAT_BUSY); /* Clear BUSY */
wd179x_info->intrq = 1;
if (wd179x_info->intenable) vectorInterrupt |= (1 << wd179x_info->intvector);
wd179x_info->drq = 1;
break;
/* Type II Commands */
@ -1006,7 +1015,6 @@ static uint8 Do1793Command(uint8 cCommand)
break;
}
return result;
}
@ -1043,6 +1051,7 @@ uint8 WD179X_Write(const uint32 Addr, uint8 cData)
wd179x_info->fdc_write_track = FALSE;
wd179x_info->fdc_datacount = 0;
wd179x_info->fdc_dataindex = 0;
if (wd179x_info->intenable) vectorInterrupt |= (1 << wd179x_info->intvector);
Do1793Command(cData);
break;
@ -1068,6 +1077,7 @@ uint8 WD179X_Write(const uint32 Addr, uint8 cData)
wd179x_info->fdc_status &= ~(WD179X_STAT_DRQ | WD179X_STAT_BUSY); /* Clear DRQ, BUSY */
wd179x_info->drq = 0;
wd179x_info->intrq = 1;
if (wd179x_info->intenable) vectorInterrupt |= (1 << wd179x_info->intvector);
sim_debug(WR_DATA_MSG, &wd179x_dev, "WD179X[%d]: " ADDRESS_FORMAT
" Writing sector, T:%2d/S:%d/N:%2d, Len=%d\n", wd179x_info->sel_drive, PCX, pDrive->track, wd179x_info->fdc_head, wd179x_info->fdc_sector, 128 << wd179x_info->fdc_sec_len);
@ -1188,6 +1198,7 @@ uint8 WD179X_Write(const uint32 Addr, uint8 cData)
wd179x_info->fdc_status &= ~(WD179X_STAT_BUSY | WD179X_STAT_LOST_DATA); /* Clear BUSY, LOST_DATA */
wd179x_info->drq = 0;
wd179x_info->intrq = 1;
if (wd179x_info->intenable) vectorInterrupt |= (1 << wd179x_info->intvector);
/* Recalculate disk size */
pDrive->uptr->capac = sim_fsize(pDrive->uptr->fileref);

View file

@ -55,6 +55,8 @@ extern uint8 wd179x_get_nheads(void);
typedef struct {
PNP_INFO pnp; /* Plug-n-Play Information */
uint16 fdctype; /* Default is 1793 */
uint8 intenable; /* Interrupt Enable */
uint8 intvector; /* Interrupt Vector */
uint8 intrq; /* WD179X Interrupt Request Output (EOJ) */
uint8 hld; /* WD179X Head Load Output */
uint8 drq; /* WD179X DMA Request Output */