mirror of
https://github.com/holub/mame
synced 2025-05-19 20:29:09 +03:00
Added NSC800 CPU emulation to the Z80 core [Sandro Ronco]
This commit is contained in:
parent
6e37021618
commit
0fb8703972
@ -145,6 +145,7 @@ struct _z80_state
|
||||
UINT8 nmi_state; /* nmi line state */
|
||||
UINT8 nmi_pending; /* nmi pending */
|
||||
UINT8 irq_state; /* irq line state */
|
||||
UINT8 nsc800_irq_state[4];/* state of NSC800 restart interrupts A, B, C */
|
||||
UINT8 after_ei; /* are we in the EI shadow? */
|
||||
UINT32 ea;
|
||||
cpu_irq_callback irq_callback;
|
||||
@ -405,6 +406,7 @@ static const UINT8 cc_ex[0x100] = {
|
||||
#define cc_fd cc_xy
|
||||
|
||||
static void take_interrupt(z80_state *z80);
|
||||
static void take_interrupt_nsc800(z80_state *z80);
|
||||
static CPU_BURN( z80 );
|
||||
|
||||
typedef void (*funcptr)(z80_state *z80);
|
||||
@ -3349,6 +3351,39 @@ static void take_interrupt(z80_state *z80)
|
||||
z80->WZ=z80->PCD;
|
||||
}
|
||||
|
||||
static void take_interrupt_nsc800(z80_state *z80)
|
||||
{
|
||||
/* there isn't a valid previous program counter */
|
||||
z80->PRVPC = -1;
|
||||
|
||||
/* Check if processor was halted */
|
||||
LEAVE_HALT(z80);
|
||||
|
||||
/* Clear both interrupt flip flops */
|
||||
z80->iff1 = z80->iff2 = 0;
|
||||
|
||||
if (z80->nsc800_irq_state[NSC800_RSTA])
|
||||
{
|
||||
PUSH(z80, pc);
|
||||
z80->PCD = 0x003c;
|
||||
}
|
||||
else if (z80->nsc800_irq_state[NSC800_RSTB])
|
||||
{
|
||||
PUSH(z80, pc);
|
||||
z80->PCD = 0x0034;
|
||||
}
|
||||
else if (z80->nsc800_irq_state[NSC800_RSTC])
|
||||
{
|
||||
PUSH(z80, pc);
|
||||
z80->PCD = 0x002c;
|
||||
}
|
||||
|
||||
/* 'interrupt latency' cycles */
|
||||
z80->icount -= z80->cc_op[0xff] + cc_ex[0xff];
|
||||
|
||||
z80->WZ=z80->PCD;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Processor initialization
|
||||
****************************************************************************/
|
||||
@ -3486,6 +3521,13 @@ static CPU_INIT( z80 )
|
||||
z80->cc_ex = cc_ex;
|
||||
}
|
||||
|
||||
static CPU_INIT( nsc800 )
|
||||
{
|
||||
z80_state *z80 = get_safe_token(device);
|
||||
state_save_register_device_item_array(device, 0, z80->nsc800_irq_state);
|
||||
CPU_INIT_CALL (z80);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Do a reset
|
||||
****************************************************************************/
|
||||
@ -3508,6 +3550,13 @@ static CPU_RESET( z80 )
|
||||
z80->WZ=z80->PCD;
|
||||
}
|
||||
|
||||
static CPU_RESET( nsc800 )
|
||||
{
|
||||
z80_state *z80 = get_safe_token(device);
|
||||
memset(z80->nsc800_irq_state, 0, sizeof(z80->nsc800_irq_state));
|
||||
CPU_RESET_CALL(z80);
|
||||
}
|
||||
|
||||
static CPU_EXIT( z80 )
|
||||
{
|
||||
global_free(SZHVC_add);
|
||||
@ -3558,6 +3607,52 @@ static CPU_EXECUTE( z80 )
|
||||
return cycles - z80->icount;
|
||||
}
|
||||
|
||||
static CPU_EXECUTE( nsc800 )
|
||||
{
|
||||
z80_state *z80 = get_safe_token(device);
|
||||
|
||||
z80->icount = cycles;
|
||||
|
||||
/* check for NMIs on the way in; they can only be set externally */
|
||||
/* via timers, and can't be dynamically enabled, so it is safe */
|
||||
/* to just check here */
|
||||
if (z80->nmi_pending)
|
||||
{
|
||||
LOG(("Z80 '%s' take NMI\n", z80->device->tag()));
|
||||
z80->PRVPC = -1; /* there isn't a valid previous program counter */
|
||||
LEAVE_HALT(z80); /* Check if processor was halted */
|
||||
|
||||
z80->iff1 = 0;
|
||||
PUSH(z80, pc);
|
||||
z80->PCD = 0x0066;
|
||||
z80->WZ=z80->PCD;
|
||||
z80->icount -= 11;
|
||||
z80->nmi_pending = FALSE;
|
||||
}
|
||||
|
||||
do
|
||||
{
|
||||
/* check for NSC800 IRQs line RSTA, RSTB, RSTC */
|
||||
if ((z80->nsc800_irq_state[NSC800_RSTA] != CLEAR_LINE ||
|
||||
z80->nsc800_irq_state[NSC800_RSTB] != CLEAR_LINE ||
|
||||
z80->nsc800_irq_state[NSC800_RSTC] != CLEAR_LINE) && z80->iff1 && !z80->after_ei)
|
||||
take_interrupt_nsc800(z80);
|
||||
|
||||
/* check for IRQs before each instruction */
|
||||
if (z80->irq_state != CLEAR_LINE && z80->iff1 && !z80->after_ei)
|
||||
take_interrupt(z80);
|
||||
|
||||
z80->after_ei = FALSE;
|
||||
|
||||
z80->PRVPC = z80->PCD;
|
||||
debugger_instruction_hook(device, z80->PCD);
|
||||
z80->r++;
|
||||
EXEC_INLINE(z80,op,ROP(z80));
|
||||
} while (z80->icount > 0);
|
||||
|
||||
return cycles - z80->icount;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Burn 'cycles' T-states. Adjust z80->r register for the lost time
|
||||
****************************************************************************/
|
||||
@ -3598,6 +3693,32 @@ static void set_irq_line(z80_state *z80, int irqline, int state)
|
||||
}
|
||||
|
||||
|
||||
static void set_irq_line_nsc800(z80_state *z80, int irqline, int state)
|
||||
{
|
||||
if (irqline == INPUT_LINE_NMI)
|
||||
{
|
||||
/* mark an NMI pending on the rising edge */
|
||||
if (z80->nmi_state == CLEAR_LINE && state != CLEAR_LINE)
|
||||
z80->nmi_pending = TRUE;
|
||||
z80->nmi_state = state;
|
||||
}
|
||||
else if (irqline == NSC800_RSTA)
|
||||
z80->nsc800_irq_state[NSC800_RSTA] = state;
|
||||
else if (irqline == NSC800_RSTB)
|
||||
z80->nsc800_irq_state[NSC800_RSTB] = state;
|
||||
else if (irqline == NSC800_RSTC)
|
||||
z80->nsc800_irq_state[NSC800_RSTC] = state;
|
||||
else
|
||||
{
|
||||
/* update the IRQ state via the daisy chain */
|
||||
z80->irq_state = state;
|
||||
if (z80->daisy)
|
||||
z80->irq_state = z80daisy_update_irq_state(z80->daisy);
|
||||
|
||||
/* the main execute loop will take the interrupt */
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**************************************************************************
|
||||
* STATE IMPORT/EXPORT
|
||||
@ -3653,6 +3774,20 @@ static CPU_SET_INFO( z80 )
|
||||
}
|
||||
}
|
||||
|
||||
static CPU_SET_INFO( nsc800 )
|
||||
{
|
||||
z80_state *z80 = get_safe_token(device);
|
||||
switch (state)
|
||||
{
|
||||
/* --- the following bits of info are set as 64-bit signed integers --- */
|
||||
case CPUINFO_INT_INPUT_STATE + INPUT_LINE_NMI: set_irq_line_nsc800(z80, INPUT_LINE_NMI, info->i); break;
|
||||
case CPUINFO_INT_INPUT_STATE + NSC800_RSTA: set_irq_line_nsc800(z80, NSC800_RSTA, info->i); break;
|
||||
case CPUINFO_INT_INPUT_STATE + NSC800_RSTB: set_irq_line_nsc800(z80, NSC800_RSTB, info->i); break;
|
||||
case CPUINFO_INT_INPUT_STATE + NSC800_RSTC: set_irq_line_nsc800(z80, NSC800_RSTC, info->i); break;
|
||||
case CPUINFO_INT_INPUT_STATE + 0: set_irq_line_nsc800(z80, 0, info->i); break;
|
||||
}
|
||||
}
|
||||
|
||||
void z80_set_cycle_tables(running_device *device, const UINT8 *op, const UINT8 *cb, const UINT8 *ed, const UINT8 *xy, const UINT8 *xycb, const UINT8 *ex)
|
||||
{
|
||||
z80_state *z80 = get_safe_token(device);
|
||||
@ -3731,3 +3866,25 @@ CPU_GET_INFO( z80 )
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
CPU_GET_INFO( nsc800 )
|
||||
{
|
||||
z80_state *z80 = (device != NULL && device->token != NULL) ? get_safe_token(device) : NULL;
|
||||
switch (state)
|
||||
{
|
||||
case CPUINFO_INT_INPUT_LINES: info->i = 4; break;
|
||||
|
||||
case CPUINFO_INT_INPUT_STATE + NSC800_RSTA: info->i = z80->nsc800_irq_state[NSC800_RSTA]; break;
|
||||
case CPUINFO_INT_INPUT_STATE + NSC800_RSTB: info->i = z80->nsc800_irq_state[NSC800_RSTB]; break;
|
||||
case CPUINFO_INT_INPUT_STATE + NSC800_RSTC: info->i = z80->nsc800_irq_state[NSC800_RSTC]; break;
|
||||
|
||||
case CPUINFO_FCT_SET_INFO: info->setinfo = CPU_SET_INFO_NAME(nsc800); break;
|
||||
case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME(nsc800); break;
|
||||
case CPUINFO_FCT_RESET: info->reset = CPU_RESET_NAME(nsc800); break;
|
||||
case CPUINFO_FCT_EXECUTE: info->execute = CPU_EXECUTE_NAME(nsc800); break;
|
||||
|
||||
case DEVINFO_STR_NAME: strcpy(info->s, "NSC800"); break;
|
||||
|
||||
default: CPU_GET_INFO_CALL(z80); break;
|
||||
}
|
||||
}
|
||||
|
@ -3,6 +3,12 @@
|
||||
#ifndef __Z80_H__
|
||||
#define __Z80_H__
|
||||
|
||||
enum
|
||||
{
|
||||
NSC800_RSTA = 1,
|
||||
NSC800_RSTB,
|
||||
NSC800_RSTC
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
@ -20,6 +26,8 @@ enum
|
||||
|
||||
CPU_GET_INFO( z80 );
|
||||
#define CPU_Z80 CPU_GET_INFO_NAME( z80 )
|
||||
CPU_GET_INFO( nsc800 );
|
||||
#define CPU_NSC800 CPU_GET_INFO_NAME( nsc800 )
|
||||
|
||||
CPU_DISASSEMBLE( z80 );
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user