uPD7801 core changes:

- Fixed incorrect disassembly of some instructions.
- Updated the handling of interrupts to match the documentation.
This commit is contained in:
Wilbert Pol 2010-01-02 08:58:38 +00:00
parent cb6fcbbcfa
commit a83b755c7d
4 changed files with 210 additions and 115 deletions

View File

@ -4115,7 +4115,7 @@ static const struct dasm_s dasm4c_7801[256] = {
/* 0xC0 - 0xFF */
{ MOV, "A,PA" }, { MOV, "A,PB" }, { MOV, "A,PC" }, { MOV, "A,MK" },
{ MOV, "A,MB" }, { MOV, "A,MC" }, { MOV, "A,TM0" }, { MOV, "A,TM1" },
{ illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
{ MOV, "A,S" }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
{ illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
@ -4379,12 +4379,12 @@ static const struct dasm_s dasm64_7801[256] = {
{ ACI, "PA,%b" }, { ACI, "PB,%b" }, { ACI, "PC,%b" }, { ACI, "MK,%b" },
{ illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
{ SUI, "PA,%b" }, { SUI, "PB,%b" }, { SUI, "PC,%b" }, { SUI, "MK,%b" },
{ OFFI, "PA,%b" }, { OFFI, "PB,%b" }, { OFFI, "PC,%b" }, { OFFI, "MK,%b" },
{ illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
{ NEI, "PA,%b" }, { NEI, "PB,%b" }, { NEI, "PC,%b" }, { NEI, "MK,%b" },
{ SUI, "PA,%b" }, { SUI, "PB,%b" }, { SUI, "PC,%b" }, { SUI, "MK,%b" },
{ illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
{ SBI, "PA,%b" }, { SBI, "PB,%b" }, { SBI, "PC,%b" }, { SBI, "MK,%b" },
{ NEI, "PA,%b" }, { NEI, "PB,%b" }, { NEI, "PC,%b" }, { NEI, "MK,%b" },
{ illegal, 0 }, { illegal, 0 }, { illegal, 0 }, { illegal, 0 },
{ SBI, "PA,%b" }, { SBI, "PB,%b" }, { SBI, "PC,%b" }, { SBI, "MK,%b" },
@ -4600,7 +4600,7 @@ static const struct dasm_s dasmXX_7801[256] = {
{ 0, dasm60_7801 }, { DAA, 0 }, { RETI, 0 }, { CALB, 0 },
{ 0, dasm64_7801 }, { NEIW, "%a,%b" }, { SUI, "A,%b" }, { NEI, "A,%b" },
{ MVI, "V,%b?" }, { MVI, "A,%b" }, { MVI, "B,%b" }, { MVI, "C,%b" },
{ MVI, "V,%b" }, { MVI, "A,%b" }, { MVI, "B,%b" }, { MVI, "C,%b" },
{ MVI, "D,%b" }, { MVI, "E,%b" }, { MVI, "H,%b" }, { MVI, "L,%b" },
{ 0, dasm70_7801 }, { MVIW, "%a,%b" }, { SOFTI, 0 }, { JB, 0 },

View File

@ -3549,7 +3549,7 @@ static const struct opcode_s op48_7801[256] =
{illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
{SK_CY, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
{SK_Z, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
{PUSH_VA, 2,15,15,L0|L1}, {POP_VA, 2,15,15,L0|L1},
{PUSH_VA, 2,17,17,L0|L1}, {POP_VA, 2,15,15,L0|L1},
{SKNIT_F0, 2, 8, 8,L0|L1}, {SKNIT_FT0, 2, 8, 8,L0|L1},
{SKNIT_F1, 2, 8, 8,L0|L1}, {SKNIT_F2, 2, 8, 8,L0|L1},
@ -3575,7 +3575,7 @@ static const struct opcode_s op48_7801[256] =
{SLL_A, 2, 8, 8,L0|L1}, {SLR_A, 2, 8, 8,L0|L1},
{SLL_C, 2, 8, 8,L0|L1}, {SLR_C, 2, 8, 8,L0|L1},
{RLD, 2,17,17,L0|L1}, {RRD, 2,17,17,L0|L1},
{illegal2, 2, 8, 8,L0|L1}, {illegal2, 2,12,12,L0|L1},
{illegal2, 2, 8, 8,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
{PER, 2,11,11,L0|L1}, {illegal2, 2, 8, 8,L0|L1},
{PUSH_HL, 2,17,17,L0|L1}, {POP_HL, 2,15,15,L0|L1},

View File

@ -472,6 +472,8 @@ struct _upd7810_state
UINT8 co1;
UINT16 irr; /* interrupt request register */
UINT16 itf; /* interrupt test flag register */
int int1; /* keep track of current int1 state. Needed for 7801 irq checking. */
int int2; /* keep track to current int2 state. Needed for 7801 irq checking. */
/* internal helper variables */
UINT16 txs; /* transmitter shift register */
@ -538,6 +540,7 @@ INLINE upd7810_state *get_safe_token(const device_config *device)
#define INTFST 0x0400
#define INTER 0x0800
#define INTOV 0x1000
#define INTF0 0x2000
/* ITF flags */
#define INTAN4 0x0001
@ -843,97 +846,140 @@ static void upd7810_take_irq(upd7810_state *cpustate)
if (0 == IFF)
return;
/* check the interrupts in priority sequence */
if ((IRR & INTFT0) && 0 == (MKL & 0x02))
switch ( cpustate->config.type )
{
switch (cpustate->config.type)
case TYPE_7801:
/* 1 - SOFTI - vector at 0x0060 */
/* 2 - INT0 - Masked by MK0 bit */
if ( IRR & INTF0 && 0 == (MKL & 0x01 ) )
{
case TYPE_7810_GAMEMASTER:
vector = 0xff2a;
break;
default:
vector = 0x0008;
irqline = UPD7810_INTF0;
vector = 0x0004;
IRR &= ~INTF0;
}
if (!((IRR & INTFT1) && 0 == (MKL & 0x04)))
IRR&=~INTFT0;
}
else
if ((IRR & INTFT1) && 0 == (MKL & 0x04))
{
switch (cpustate->config.type)
/* 3 - INTT - Masked by MKT bit */
if ( IRR & INTFT0 && 0 == ( MKL & 0x02 ) )
{
case TYPE_7810_GAMEMASTER:
vector = 0xff2a;
break;
default:
vector = 0x0008;
vector = 0x0008;
IRR &= ~INTFT0;
}
IRR&=~INTFT1;
}
else
if ((IRR & INTF1) && 0 == (MKL & 0x08))
{
irqline = UPD7810_INTF1;
vector = 0x0010;
if (!((IRR & INTF2) && 0 == (MKL & 0x10)))
IRR&=~INTF1;
}
else
if ((IRR & INTF2) && 0 == (MKL & 0x10))
{
irqline = UPD7810_INTF2;
vector = 0x0010;
IRR&=~INTF2;
}
else
if ((IRR & INTFE0) && 0 == (MKL & 0x20))
{
switch (cpustate->config.type)
/* 4 - INT1 - Masked by MK1 bit */
if ( IRR & INTF1 && 0 == ( MKL & 0x04 ) )
{
case TYPE_7810_GAMEMASTER:
vector = 0xff2d;
break;
default:
vector = 0x0018;
irqline = UPD7810_INTF1;
vector = 0x0010;
IRR &= ~INTF1;
}
if (!((IRR & INTFE1) && 0 == (MKL & 0x40)))
IRR&=~INTFE0;
}
else
if ((IRR & INTFE1) && 0 == (MKL & 0x40))
{
switch (cpustate->config.type)
/* 5 - INT2 - Masked by MK2 bit */
if ( IRR & INTF2 && 0 == ( MKL & 0x08 ) )
{
case TYPE_7810_GAMEMASTER:
vector = 0xff2d;
break;
default:
vector = 0x0018;
irqline = UPD7810_INTF2;
vector = 0x0020;
IRR &= ~INTF2;
}
IRR&=~INTFE1;
}
else
if ((IRR & INTFEIN) && 0 == (MKL & 0x80))
{
vector = 0x0020;
}
else
if ((IRR & INTFAD) && 0 == (MKH & 0x01))
{
vector = 0x0020;
}
else
if ((IRR & INTFSR) && 0 == (MKH & 0x02))
{
vector = 0x0028;
IRR&=~INTFSR;
}
else
if ((IRR & INTFST) && 0 == (MKH & 0x04))
{
vector = 0x0028;
IRR&=~INTFST;
/* 6 - INTS - Masked by MKS bit */
if ( IRR & INTFST && 0 == ( MKL & 0x10 ) )
{
vector = 0x0040;
IRR &= ~INTFST;
}
break;
default:
/* check the interrupts in priority sequence */
if ((IRR & INTFT0) && 0 == (MKL & 0x02))
{
switch (cpustate->config.type)
{
case TYPE_7810_GAMEMASTER:
vector = 0xff2a;
break;
default:
vector = 0x0008;
}
if (!((IRR & INTFT1) && 0 == (MKL & 0x04)))
IRR&=~INTFT0;
}
else
if ((IRR & INTFT1) && 0 == (MKL & 0x04))
{
switch (cpustate->config.type)
{
case TYPE_7810_GAMEMASTER:
vector = 0xff2a;
break;
default:
vector = 0x0008;
}
IRR&=~INTFT1;
}
else
if ((IRR & INTF1) && 0 == (MKL & 0x08))
{
irqline = UPD7810_INTF1;
vector = 0x0010;
if (!((IRR & INTF2) && 0 == (MKL & 0x10)))
IRR&=~INTF1;
}
else
if ((IRR & INTF2) && 0 == (MKL & 0x10))
{
irqline = UPD7810_INTF2;
vector = 0x0010;
IRR&=~INTF2;
}
else
if ((IRR & INTFE0) && 0 == (MKL & 0x20))
{
switch (cpustate->config.type)
{
case TYPE_7810_GAMEMASTER:
vector = 0xff2d;
break;
default:
vector = 0x0018;
}
if (!((IRR & INTFE1) && 0 == (MKL & 0x40)))
IRR&=~INTFE0;
}
else
if ((IRR & INTFE1) && 0 == (MKL & 0x40))
{
switch (cpustate->config.type)
{
case TYPE_7810_GAMEMASTER:
vector = 0xff2d;
break;
default:
vector = 0x0018;
}
IRR&=~INTFE1;
}
else
if ((IRR & INTFEIN) && 0 == (MKL & 0x80))
{
vector = 0x0020;
}
else
if ((IRR & INTFAD) && 0 == (MKH & 0x01))
{
vector = 0x0020;
}
else
if ((IRR & INTFSR) && 0 == (MKH & 0x02))
{
vector = 0x0028;
IRR&=~INTFSR;
}
else
if ((IRR & INTFST) && 0 == (MKH & 0x04))
{
vector = 0x0028;
IRR&=~INTFST;
}
break;
}
if (vector)
{
/* acknowledge external IRQ */
@ -1704,6 +1750,8 @@ static CPU_INIT( upd7810 )
state_save_register_device_item(device, 0, cpustate->ovcf);
state_save_register_device_item(device, 0, cpustate->ovcs);
state_save_register_device_item(device, 0, cpustate->edges);
state_save_register_device_item(device, 0, cpustate->int1);
state_save_register_device_item(device, 0, cpustate->int2);
}
#include "7810tbl.c"
@ -1898,39 +1946,85 @@ static CPU_EXECUTE( upd7810 )
static void set_irq_line(upd7810_state *cpustate, int irqline, int state)
{
if (state != CLEAR_LINE)
/* The uPD7801 can check for falling and rising edges changes on the INT2 input */
switch ( cpustate->config.type )
{
if (irqline == INPUT_LINE_NMI)
case TYPE_7801:
switch ( irqline )
{
/* no nested NMIs ? */
// if (0 == (IRR & INTNMI))
case UPD7810_INTF0:
/* INT0 is level sensitive */
if ( state == ASSERT_LINE )
IRR |= INTF0;
else
IRR &= INTF0;
break;
case UPD7810_INTF1:
/* INT1 is rising edge sensitive */
if ( cpustate->int1 == CLEAR_LINE && state == ASSERT_LINE )
IRR |= INTF1;
cpustate->int1 = state;
break;
case UPD7810_INTF2:
/* INT2 is rising or falling edge sensitive */
/* Check if the ES bit is set then check for rising edge, otherwise falling edge */
if ( MKL & 0x20 )
{
IRR |= INTNMI;
SP--;
WM( SP, PSW );
SP--;
WM( SP, PCH );
SP--;
WM( SP, PCL );
IFF = 0;
PSW &= ~(SK|L0|L1);
PC = 0x0004;
if ( cpustate->int2 == CLEAR_LINE && state == ASSERT_LINE )
{
IRR |= INTF2;
}
}
else
{
if ( cpustate->int2 == ASSERT_LINE && state == CLEAR_LINE )
{
IRR |= INTF2;
}
}
cpustate->int2 = state;
break;
}
else
if (irqline == UPD7810_INTF1)
IRR |= INTF1;
else
if (irqline == UPD7810_INTF2)
IRR |= INTF2;
// gamemaster hack
else
if (irqline == UPD7810_INTFE1)
IRR |= INTFE1;
else
logerror("upd7810_set_irq_line invalid irq line #%d\n", irqline);
break;
default:
if (state != CLEAR_LINE)
{
if (irqline == INPUT_LINE_NMI)
{
/* no nested NMIs ? */
// if (0 == (IRR & INTNMI))
{
IRR |= INTNMI;
SP--;
WM( SP, PSW );
SP--;
WM( SP, PCH );
SP--;
WM( SP, PCL );
IFF = 0;
PSW &= ~(SK|L0|L1);
PC = 0x0004;
}
}
else
if (irqline == UPD7810_INTF1)
IRR |= INTF1;
else
if ( irqline == UPD7810_INTF2 && ( MKL & 0x20 ) )
IRR |= INTF2;
// gamemaster hack
else
if (irqline == UPD7810_INTFE1)
IRR |= INTFE1;
else
logerror("upd7810_set_irq_line invalid irq line #%d\n", irqline);
}
/* resetting interrupt requests is done with the SKIT/SKNIT opcodes only! */
}
/* resetting interrupt requests is done with the SKIT/SKNIT opcodes only! */
}

View File

@ -69,6 +69,7 @@ enum
/* IRQ lines */
#define UPD7810_INTF1 0
#define UPD7810_INTF2 1
#define UPD7810_INTF0 2
#define UPD7810_INTFE1 4
CPU_GET_INFO( upd7810 );