summaryrefslogtreecommitdiffstatshomepage
path: root/src
diff options
context:
space:
mode:
author Fabio Priuli <etabeta78@users.noreply.github.com>2010-05-25 05:33:13 +0000
committer Fabio Priuli <etabeta78@users.noreply.github.com>2010-05-25 05:33:13 +0000
commit0fb870397285a4ffa56f80db91f8d40613f60c05 (patch)
treee036a98309ed2453de592f4d8132a1a12fe00670 /src
parent6e37021618b1250ddad4aa06efabe362cfd5f2b8 (diff)
Added NSC800 CPU emulation to the Z80 core [Sandro Ronco]
Diffstat (limited to 'src')
-rw-r--r--src/emu/cpu/z80/z80.c157
-rw-r--r--src/emu/cpu/z80/z80.h8
2 files changed, 165 insertions, 0 deletions
diff --git a/src/emu/cpu/z80/z80.c b/src/emu/cpu/z80/z80.c
index 2701f01bb75..b9b384d6ee2 100644
--- a/src/emu/cpu/z80/z80.c
+++ b/src/emu/cpu/z80/z80.c
@@ -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;
+ }
+}
diff --git a/src/emu/cpu/z80/z80.h b/src/emu/cpu/z80/z80.h
index db633ff0eee..684424fe387 100644
--- a/src/emu/cpu/z80/z80.h
+++ b/src/emu/cpu/z80/z80.h
@@ -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 );