summaryrefslogtreecommitdiffstatshomepage
path: root/src/emu/cpu/m6502/m6502.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/emu/cpu/m6502/m6502.c')
-rw-r--r--src/emu/cpu/m6502/m6502.c1017
1 files changed, 1017 insertions, 0 deletions
diff --git a/src/emu/cpu/m6502/m6502.c b/src/emu/cpu/m6502/m6502.c
new file mode 100644
index 00000000000..89da4704784
--- /dev/null
+++ b/src/emu/cpu/m6502/m6502.c
@@ -0,0 +1,1017 @@
+/*****************************************************************************
+ *
+ * m6502.c
+ * Portable 6502/65c02/65sc02/6510/n2a03 emulator V1.2
+ *
+ * Copyright (c) 1998,1999,2000 Juergen Buchmueller, all rights reserved.
+ * 65sc02 core Copyright (c) 2000 Peter Trauner.
+ * Deco16 portions Copyright (c) 2001-2003 Bryan McPhail.
+ *
+ * - This source code is released as freeware for non-commercial purposes.
+ * - You are free to use and redistribute this code in modified or
+ * unmodified form, provided you list me in the credits.
+ * - If you modify this source code, you must add a notice to each modified
+ * source file that it has been changed. If you're a nice person, you
+ * will clearly mark each change too. :)
+ * - If you wish to use this for commercial purposes, please contact me at
+ * pullmoll@t-online.de
+ * - The author of this copywritten work reserves the right to change the
+ * terms of its usage and license at any time, including retroactively
+ * - This entire notice must remain in the source code.
+ *
+ *****************************************************************************/
+/* 2.February 2000 PeT added 65sc02 subtype */
+/* 10.March 2000 PeT added 6502 set overflow input line */
+/* 13.September 2000 PeT N2A03 jmp indirect */
+
+#if ((HAS_M65SC02 || HAS_DECO16) && !HAS_M65C02)
+#undef HAS_M65C02
+#define HAS_M65C02 1
+#endif
+
+#include "debugger.h"
+#include "m6502.h"
+#include "ops02.h"
+#include "ill02.h"
+
+
+#define M6502_NMI_VEC 0xfffa
+#define M6502_RST_VEC 0xfffc
+#define M6502_IRQ_VEC 0xfffe
+
+#define DECO16_RST_VEC 0xfff0
+#define DECO16_IRQ_VEC 0xfff2
+#define DECO16_NMI_VEC 0xfff4
+
+#define VERBOSE 0
+
+#if VERBOSE
+#define LOG(x) logerror x
+#else
+#define LOG(x)
+#endif
+
+
+
+/****************************************************************************
+ * The 6502 registers.
+ ****************************************************************************/
+typedef struct
+{
+ UINT8 subtype; /* currently selected cpu sub type */
+ void (**insn)(void); /* pointer to the function pointer table */
+ PAIR ppc; /* previous program counter */
+ PAIR pc; /* program counter */
+ PAIR sp; /* stack pointer (always 100 - 1FF) */
+ PAIR zp; /* zero page address */
+ PAIR ea; /* effective address */
+ UINT8 a; /* Accumulator */
+ UINT8 x; /* X index register */
+ UINT8 y; /* Y index register */
+ UINT8 p; /* Processor status */
+ UINT8 pending_irq; /* nonzero if an IRQ is pending */
+ UINT8 after_cli; /* pending IRQ and last insn cleared I */
+ UINT8 nmi_state;
+ UINT8 irq_state;
+ UINT8 so_state;
+ int (*irq_callback)(int irqline); /* IRQ callback */
+ read8_handler rdmem_id; /* readmem callback for indexed instructions */
+ write8_handler wrmem_id; /* writemem callback for indexed instructions */
+
+#if (HAS_M6510) || (HAS_M6510T) || (HAS_M8502) || (HAS_M7501)
+ UINT8 ddr;
+ UINT8 port;
+ UINT8 (*port_read)(UINT8 direction);
+ void (*port_write)(UINT8 direction, UINT8 data);
+#endif
+
+} m6502_Regs;
+
+int m6502_IntOccured = 0;
+int m6502_ICount = 0;
+
+static m6502_Regs m6502;
+
+/***************************************************************
+ * include the opcode macros, functions and tables
+ ***************************************************************/
+#include "t6502.c"
+
+#if (HAS_M6510)
+#include "t6510.c"
+#endif
+
+#include "opsn2a03.h"
+
+#if (HAS_N2A03)
+#include "tn2a03.c"
+#endif
+
+#include "opsc02.h"
+
+#if (HAS_M65C02)
+#include "t65c02.c"
+#endif
+
+#if (HAS_M65SC02)
+#include "t65sc02.c"
+#endif
+
+#if (HAS_DECO16)
+#include "tdeco16.c"
+#endif
+
+/*****************************************************************************
+ *
+ * 6502 CPU interface functions
+ *
+ *****************************************************************************/
+
+static void m6502_common_init(int index, int clock, const void *config, int (*irqcallback)(int), UINT8 subtype, void (**insn)(void), const char *type)
+{
+ memset(&m6502, 0, sizeof(m6502));
+ m6502.irq_callback = irqcallback;
+ m6502.subtype = subtype;
+ m6502.insn = insn;
+ m6502.rdmem_id = program_read_byte_8;
+ m6502.wrmem_id = program_write_byte_8;
+
+ state_save_register_item(type, index, m6502.pc.w.l);
+ state_save_register_item(type, index, m6502.sp.w.l);
+ state_save_register_item(type, index, m6502.p);
+ state_save_register_item(type, index, m6502.a);
+ state_save_register_item(type, index, m6502.x);
+ state_save_register_item(type, index, m6502.y);
+ state_save_register_item(type, index, m6502.pending_irq);
+ state_save_register_item(type, index, m6502.after_cli);
+ state_save_register_item(type, index, m6502.nmi_state);
+ state_save_register_item(type, index, m6502.irq_state);
+ state_save_register_item(type, index, m6502.so_state);
+
+#if (HAS_M6510) || (HAS_M6510T) || (HAS_M8502) || (HAS_M7501)
+ if (subtype == SUBTYPE_6510)
+ {
+ state_save_register_item(type, index, m6502.port);
+ state_save_register_item(type, index, m6502.ddr);
+ }
+#endif
+}
+
+static void m6502_init(int index, int clock, const void *config, int (*irqcallback)(int))
+{
+ m6502_common_init(index, clock, config, irqcallback, SUBTYPE_6502, insn6502, "m6502");
+}
+
+static void m6502_reset(void)
+{
+ /* wipe out the rest of the m6502 structure */
+ /* read the reset vector into PC */
+ PCL = RDMEM(M6502_RST_VEC);
+ PCH = RDMEM(M6502_RST_VEC+1);
+
+ m6502.sp.d = 0x01ff; /* stack pointer starts at page 1 offset FF */
+ m6502.p = F_T|F_I|F_Z|F_B|(P&F_D); /* set T, I and Z flags */
+ m6502.pending_irq = 0; /* nonzero if an IRQ is pending */
+ m6502.after_cli = 0; /* pending IRQ and last insn cleared I */
+ m6502.irq_state = 0;
+ m6502.nmi_state = 0;
+
+ change_pc(PCD);
+}
+
+static void m6502_exit(void)
+{
+ /* nothing to do yet */
+}
+
+static void m6502_get_context (void *dst)
+{
+ if( dst )
+ *(m6502_Regs*)dst = m6502;
+}
+
+static void m6502_set_context (void *src)
+{
+ if( src )
+ {
+ m6502 = *(m6502_Regs*)src;
+ change_pc(PCD);
+ }
+}
+
+INLINE void m6502_take_irq(void)
+{
+ if( !(P & F_I) )
+ {
+ EAD = M6502_IRQ_VEC;
+ m6502_ICount -= 2;
+ PUSH(PCH);
+ PUSH(PCL);
+ PUSH(P & ~F_B);
+ P |= F_I; /* set I flag */
+ PCL = RDMEM(EAD);
+ PCH = RDMEM(EAD+1);
+ LOG(("M6502#%d takes IRQ ($%04x)\n", cpu_getactivecpu(), PCD));
+ /* call back the cpuintrf to let it clear the line */
+ if (m6502.irq_callback) (*m6502.irq_callback)(0);
+ change_pc(PCD);
+ }
+ m6502.pending_irq = 0;
+}
+
+static int m6502_execute(int cycles)
+{
+ m6502_ICount = cycles;
+
+ change_pc(PCD);
+
+ do
+ {
+ UINT8 op;
+ PPC = PCD;
+
+ CALL_MAME_DEBUG;
+
+ /* if an irq is pending, take it now */
+ if( m6502.pending_irq )
+ m6502_take_irq();
+
+ op = RDOP();
+ (*m6502.insn[op])();
+
+ /* check if the I flag was just reset (interrupts enabled) */
+ if( m6502.after_cli )
+ {
+ LOG(("M6502#%d after_cli was >0", cpu_getactivecpu()));
+ m6502.after_cli = 0;
+ if (m6502.irq_state != CLEAR_LINE)
+ {
+ LOG((": irq line is asserted: set pending IRQ\n"));
+ m6502.pending_irq = 1;
+ }
+ else
+ {
+ LOG((": irq line is clear\n"));
+ }
+ }
+ else {
+ if ( m6502.pending_irq == 2 ) {
+ if ( m6502_IntOccured - m6502_ICount > 1 ) {
+ m6502.pending_irq = 1;
+ }
+ }
+ if( m6502.pending_irq == 1 )
+ m6502_take_irq();
+ if ( m6502.pending_irq == 2 ) {
+ m6502.pending_irq = 1;
+ }
+ }
+
+ } while (m6502_ICount > 0);
+
+ return cycles - m6502_ICount;
+}
+
+static void m6502_set_irq_line(int irqline, int state)
+{
+ if (irqline == INPUT_LINE_NMI)
+ {
+ if (m6502.nmi_state == state) return;
+ m6502.nmi_state = state;
+ if( state != CLEAR_LINE )
+ {
+ LOG(( "M6502#%d set_nmi_line(ASSERT)\n", cpu_getactivecpu()));
+ EAD = M6502_NMI_VEC;
+ m6502_ICount -= 2;
+ PUSH(PCH);
+ PUSH(PCL);
+ PUSH(P & ~F_B);
+ P |= F_I; /* set I flag */
+ PCL = RDMEM(EAD);
+ PCH = RDMEM(EAD+1);
+ LOG(("M6502#%d takes NMI ($%04x)\n", cpu_getactivecpu(), PCD));
+ change_pc(PCD);
+ }
+ }
+ else
+ {
+ if( irqline == M6502_SET_OVERFLOW )
+ {
+ if( m6502.so_state && !state )
+ {
+ LOG(( "M6502#%d set overflow\n", cpu_getactivecpu()));
+ P|=F_V;
+ }
+ m6502.so_state=state;
+ return;
+ }
+ m6502.irq_state = state;
+ if( state != CLEAR_LINE )
+ {
+ LOG(( "M6502#%d set_irq_line(ASSERT)\n", cpu_getactivecpu()));
+ m6502.pending_irq = 1;
+// m6502.pending_irq = 2;
+ m6502_IntOccured = m6502_ICount;
+ }
+ }
+}
+
+
+
+/****************************************************************************
+ * 2A03 section
+ ****************************************************************************/
+#if (HAS_N2A03)
+
+static void n2a03_init(int index, int clock, const void *config, int (*irqcallback)(int))
+{
+ m6502_common_init(index, clock, config, irqcallback, SUBTYPE_2A03, insn2a03, "n2a03");
+}
+
+/* The N2A03 is integrally tied to its PSG (they're on the same die).
+ Bit 7 of address $4011 (the PSG's DPCM control register), when set,
+ causes an IRQ to be generated. This function allows the IRQ to be called
+ from the PSG core when such an occasion arises. */
+void n2a03_irq(void)
+{
+ m6502_take_irq();
+}
+#endif
+
+
+/****************************************************************************
+ * 6510 section
+ ****************************************************************************/
+#if (HAS_M6510)
+
+static void m6510_init (int index, int clock, const void *config, int (*irqcallback)(int))
+{
+ m6502_common_init(index, clock, config, irqcallback, SUBTYPE_6510, insn6510, "m6510");
+}
+
+static void m6510_reset (void)
+{
+ m6502_reset();
+ m6502.port = 0xff;
+ m6502.ddr = 0x00;
+}
+
+static UINT8 m6510_get_port(void)
+{
+ return (m6502.port & m6502.ddr) | (m6502.ddr ^ 0xff);
+}
+
+static READ8_HANDLER( m6510_read_0000 )
+{
+ UINT8 result = 0x00;
+
+ switch(offset)
+ {
+ case 0x0000: /* DDR */
+ result = m6502.ddr;
+ break;
+ case 0x0001: /* Data Port */
+ if (m6502.port_read)
+ result = m6502.port_read( m6502.ddr );
+ result = (m6502.ddr & m6502.port) | (~m6502.ddr & result);
+ break;
+ }
+ return result;
+}
+
+static WRITE8_HANDLER( m6510_write_0000 )
+{
+ switch(offset)
+ {
+ case 0x0000: /* DDR */
+ m6502.ddr = data;
+ break;
+ case 0x0001: /* Data Port */
+ m6502.port = data;
+ break;
+ }
+
+ if (m6502.port_write)
+ m6502.port_write( m6502.ddr, m6502.port & m6502.ddr );
+}
+
+static ADDRESS_MAP_START(m6510_mem, ADDRESS_SPACE_PROGRAM, 8)
+ AM_RANGE(0x0000, 0x0001) AM_READWRITE(m6510_read_0000, m6510_write_0000)
+ADDRESS_MAP_END
+
+#endif
+
+
+/****************************************************************************
+ * 65C02 section
+ ****************************************************************************/
+#if (HAS_M65C02)
+
+static void m65c02_init(int index, int clock, const void *config, int (*irqcallback)(int))
+{
+ m6502_common_init(index, clock, config, irqcallback, SUBTYPE_65C02, insn65c02, "m65c02");
+}
+
+static void m65c02_reset (void)
+{
+ m6502_reset();
+ P &=~F_D;
+}
+
+INLINE void m65c02_take_irq(void)
+{
+ if( !(P & F_I) )
+ {
+ EAD = M6502_IRQ_VEC;
+ m6502_ICount -= 2;
+ PUSH(PCH);
+ PUSH(PCL);
+ PUSH(P & ~F_B);
+ P = (P & ~F_D) | F_I; /* knock out D and set I flag */
+ PCL = RDMEM(EAD);
+ PCH = RDMEM(EAD+1);
+ LOG(("M65c02#%d takes IRQ ($%04x)\n", cpu_getactivecpu(), PCD));
+ /* call back the cpuintrf to let it clear the line */
+ if (m6502.irq_callback) (*m6502.irq_callback)(0);
+ change_pc(PCD);
+ }
+ m6502.pending_irq = 0;
+}
+
+static int m65c02_execute(int cycles)
+{
+ m6502_ICount = cycles;
+
+ change_pc(PCD);
+
+ do
+ {
+ UINT8 op;
+ PPC = PCD;
+
+ CALL_MAME_DEBUG;
+
+ op = RDOP();
+ (*m6502.insn[op])();
+
+ /* if an irq is pending, take it now */
+ if( m6502.pending_irq )
+ m65c02_take_irq();
+
+
+ /* check if the I flag was just reset (interrupts enabled) */
+ if( m6502.after_cli )
+ {
+ LOG(("M6502#%d after_cli was >0", cpu_getactivecpu()));
+ m6502.after_cli = 0;
+ if (m6502.irq_state != CLEAR_LINE)
+ {
+ LOG((": irq line is asserted: set pending IRQ\n"));
+ m6502.pending_irq = 1;
+ }
+ else
+ {
+ LOG((": irq line is clear\n"));
+ }
+ }
+ else
+ if( m6502.pending_irq )
+ m65c02_take_irq();
+
+ } while (m6502_ICount > 0);
+
+ return cycles - m6502_ICount;
+}
+
+static void m65c02_set_irq_line(int irqline, int state)
+{
+ if (irqline == INPUT_LINE_NMI)
+ {
+ if (m6502.nmi_state == state) return;
+ m6502.nmi_state = state;
+ if( state != CLEAR_LINE )
+ {
+ LOG(( "M6502#%d set_nmi_line(ASSERT)\n", cpu_getactivecpu()));
+ EAD = M6502_NMI_VEC;
+ m6502_ICount -= 2;
+ PUSH(PCH);
+ PUSH(PCL);
+ PUSH(P & ~F_B);
+ P = (P & ~F_D) | F_I; /* knock out D and set I flag */
+ PCL = RDMEM(EAD);
+ PCH = RDMEM(EAD+1);
+ LOG(("M6502#%d takes NMI ($%04x)\n", cpu_getactivecpu(), PCD));
+ change_pc(PCD);
+ }
+ }
+ else
+ m6502_set_irq_line(irqline,state);
+}
+#endif
+
+/****************************************************************************
+ * 65SC02 section
+ ****************************************************************************/
+#if (HAS_M65SC02)
+static void m65sc02_init(int index, int clock, const void *config, int (*irqcallback)(int))
+{
+ m6502_common_init(index, clock, config, irqcallback, SUBTYPE_65SC02, insn65sc02, "m65sc02");
+}
+#endif
+
+/****************************************************************************
+ * DECO16 section
+ ****************************************************************************/
+#if (HAS_DECO16)
+
+static void deco16_init(int index, int clock, const void *config, int (*irqcallback)(int))
+{
+ m6502_common_init(index, clock, config, irqcallback, SUBTYPE_DECO16, insndeco16, "deco16");
+}
+
+
+static void deco16_reset (void)
+{
+ m6502_reset();
+ m6502.subtype = SUBTYPE_DECO16;
+ m6502.insn = insndeco16;
+
+ PCL = RDMEM(DECO16_RST_VEC+1);
+ PCH = RDMEM(DECO16_RST_VEC);
+
+ m6502.sp.d = 0x01ff; /* stack pointer starts at page 1 offset FF */
+ m6502.p = F_T|F_I|F_Z|F_B|(P&F_D); /* set T, I and Z flags */
+ m6502.pending_irq = 0; /* nonzero if an IRQ is pending */
+ m6502.after_cli = 0; /* pending IRQ and last insn cleared I */
+
+ change_pc(PCD);
+}
+
+INLINE void deco16_take_irq(void)
+{
+ if( !(P & F_I) )
+ {
+ EAD = DECO16_IRQ_VEC;
+ m6502_ICount -= 2;
+ PUSH(PCH);
+ PUSH(PCL);
+ PUSH(P & ~F_B);
+ P |= F_I; /* set I flag */
+ PCL = RDMEM(EAD+1);
+ PCH = RDMEM(EAD);
+ LOG(("M6502#%d takes IRQ ($%04x)\n", cpu_getactivecpu(), PCD));
+ /* call back the cpuintrf to let it clear the line */
+ if (m6502.irq_callback) (*m6502.irq_callback)(0);
+ change_pc(PCD);
+ }
+ m6502.pending_irq = 0;
+}
+
+static void deco16_set_irq_line(int irqline, int state)
+{
+ if (irqline == INPUT_LINE_NMI)
+ {
+ if (m6502.nmi_state == state) return;
+ m6502.nmi_state = state;
+ if( state != CLEAR_LINE )
+ {
+ LOG(( "M6502#%d set_nmi_line(ASSERT)\n", cpu_getactivecpu()));
+ EAD = DECO16_NMI_VEC;
+ m6502_ICount -= 7;
+ PUSH(PCH);
+ PUSH(PCL);
+ PUSH(P & ~F_B);
+ P |= F_I; /* set I flag */
+ PCL = RDMEM(EAD+1);
+ PCH = RDMEM(EAD);
+ LOG(("M6502#%d takes NMI ($%04x)\n", cpu_getactivecpu(), PCD));
+ change_pc(PCD);
+ }
+ }
+ else
+ {
+ if( irqline == M6502_SET_OVERFLOW )
+ {
+ if( m6502.so_state && !state )
+ {
+ LOG(( "M6502#%d set overflow\n", cpu_getactivecpu()));
+ P|=F_V;
+ }
+ m6502.so_state=state;
+ return;
+ }
+ m6502.irq_state = state;
+ if( state != CLEAR_LINE )
+ {
+ LOG(( "M6502#%d set_irq_line(ASSERT)\n", cpu_getactivecpu()));
+ m6502.pending_irq = 1;
+ }
+ }
+}
+
+static int deco16_execute(int cycles)
+{
+ m6502_ICount = cycles;
+
+ change_pc(PCD);
+
+ do
+ {
+ UINT8 op;
+ PPC = PCD;
+
+ CALL_MAME_DEBUG;
+
+ op = RDOP();
+ (*m6502.insn[op])();
+
+ /* if an irq is pending, take it now */
+ if( m6502.pending_irq )
+ deco16_take_irq();
+
+
+ /* check if the I flag was just reset (interrupts enabled) */
+ if( m6502.after_cli )
+ {
+ LOG(("M6502#%d after_cli was >0", cpu_getactivecpu()));
+ m6502.after_cli = 0;
+ if (m6502.irq_state != CLEAR_LINE)
+ {
+ LOG((": irq line is asserted: set pending IRQ\n"));
+ m6502.pending_irq = 1;
+ }
+ else
+ {
+ LOG((": irq line is clear\n"));
+ }
+ }
+ else
+ if( m6502.pending_irq )
+ deco16_take_irq();
+
+ } while (m6502_ICount > 0);
+
+ return cycles - m6502_ICount;
+}
+
+#endif
+
+
+
+/**************************************************************************
+ * Generic set_info
+ **************************************************************************/
+
+static void m6502_set_info(UINT32 state, cpuinfo *info)
+{
+ switch (state)
+ {
+ /* --- the following bits of info are set as 64-bit signed integers --- */
+ case CPUINFO_INT_INPUT_STATE + M6502_IRQ_LINE: m6502_set_irq_line(M6502_IRQ_LINE, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + M6502_SET_OVERFLOW: m6502_set_irq_line(M6502_SET_OVERFLOW, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + INPUT_LINE_NMI: m6502_set_irq_line(INPUT_LINE_NMI, info->i); break;
+
+ case CPUINFO_INT_PC: PCW = info->i; change_pc(PCD); break;
+ case CPUINFO_INT_REGISTER + M6502_PC: m6502.pc.w.l = info->i; break;
+ case CPUINFO_INT_SP: S = info->i; break;
+ case CPUINFO_INT_REGISTER + M6502_S: m6502.sp.b.l = info->i; break;
+ case CPUINFO_INT_REGISTER + M6502_P: m6502.p = info->i; break;
+ case CPUINFO_INT_REGISTER + M6502_A: m6502.a = info->i; break;
+ case CPUINFO_INT_REGISTER + M6502_X: m6502.x = info->i; break;
+ case CPUINFO_INT_REGISTER + M6502_Y: m6502.y = info->i; break;
+ case CPUINFO_INT_REGISTER + M6502_EA: m6502.ea.w.l = info->i; break;
+ case CPUINFO_INT_REGISTER + M6502_ZP: m6502.zp.w.l = info->i; break;
+
+ /* --- the following bits of info are set as pointers to data or functions --- */
+ case CPUINFO_PTR_M6502_READINDEXED_CALLBACK: m6502.rdmem_id = (read8_handler) info->f; break;
+ case CPUINFO_PTR_M6502_WRITEINDEXED_CALLBACK: m6502.wrmem_id = (write8_handler) info->f; break;
+ }
+}
+
+
+
+/**************************************************************************
+ * Generic get_info
+ **************************************************************************/
+
+void m6502_get_info(UINT32 state, cpuinfo *info)
+{
+ switch (state)
+ {
+ /* --- the following bits of info are returned as 64-bit signed integers --- */
+ case CPUINFO_INT_CONTEXT_SIZE: info->i = sizeof(m6502); break;
+ case CPUINFO_INT_INPUT_LINES: info->i = 2; break;
+ case CPUINFO_INT_DEFAULT_IRQ_VECTOR: info->i = 0; break;
+ case CPUINFO_INT_ENDIANNESS: info->i = CPU_IS_LE; break;
+ case CPUINFO_INT_CLOCK_DIVIDER: info->i = 1; break;
+ case CPUINFO_INT_MIN_INSTRUCTION_BYTES: info->i = 1; break;
+ case CPUINFO_INT_MAX_INSTRUCTION_BYTES: info->i = 4; break;
+ case CPUINFO_INT_MIN_CYCLES: info->i = 1; break;
+ case CPUINFO_INT_MAX_CYCLES: info->i = 10; break;
+
+ case CPUINFO_INT_DATABUS_WIDTH + ADDRESS_SPACE_PROGRAM: info->i = 8; break;
+ case CPUINFO_INT_ADDRBUS_WIDTH + ADDRESS_SPACE_PROGRAM: info->i = 16; break;
+ case CPUINFO_INT_ADDRBUS_SHIFT + ADDRESS_SPACE_PROGRAM: info->i = 0; break;
+ case CPUINFO_INT_DATABUS_WIDTH + ADDRESS_SPACE_DATA: info->i = 0; break;
+ case CPUINFO_INT_ADDRBUS_WIDTH + ADDRESS_SPACE_DATA: info->i = 0; break;
+ case CPUINFO_INT_ADDRBUS_SHIFT + ADDRESS_SPACE_DATA: info->i = 0; break;
+ case CPUINFO_INT_DATABUS_WIDTH + ADDRESS_SPACE_IO: info->i = 0; break;
+ case CPUINFO_INT_ADDRBUS_WIDTH + ADDRESS_SPACE_IO: info->i = 0; break;
+ case CPUINFO_INT_ADDRBUS_SHIFT + ADDRESS_SPACE_IO: info->i = 0; break;
+
+ case CPUINFO_INT_INPUT_STATE + M6502_IRQ_LINE: info->i = m6502.irq_state; break;
+ case CPUINFO_INT_INPUT_STATE + M6502_SET_OVERFLOW: info->i = m6502.so_state; break;
+ case CPUINFO_INT_INPUT_STATE + INPUT_LINE_NMI: info->i = m6502.nmi_state; break;
+
+ case CPUINFO_INT_PREVIOUSPC: info->i = m6502.ppc.w.l; break;
+
+ case CPUINFO_INT_PC: info->i = PCD; break;
+ case CPUINFO_INT_REGISTER + M6502_PC: info->i = m6502.pc.w.l; break;
+ case CPUINFO_INT_SP: info->i = S; break;
+ case CPUINFO_INT_REGISTER + M6502_S: info->i = m6502.sp.b.l; break;
+ case CPUINFO_INT_REGISTER + M6502_P: info->i = m6502.p; break;
+ case CPUINFO_INT_REGISTER + M6502_A: info->i = m6502.a; break;
+ case CPUINFO_INT_REGISTER + M6502_X: info->i = m6502.x; break;
+ case CPUINFO_INT_REGISTER + M6502_Y: info->i = m6502.y; break;
+ case CPUINFO_INT_REGISTER + M6502_EA: info->i = m6502.ea.w.l; break;
+ case CPUINFO_INT_REGISTER + M6502_ZP: info->i = m6502.zp.w.l; break;
+ case CPUINFO_INT_REGISTER + M6502_SUBTYPE: info->i = m6502.subtype; break;
+
+ /* --- the following bits of info are returned as pointers to data or functions --- */
+ case CPUINFO_PTR_SET_INFO: info->setinfo = m6502_set_info; break;
+ case CPUINFO_PTR_GET_CONTEXT: info->getcontext = m6502_get_context; break;
+ case CPUINFO_PTR_SET_CONTEXT: info->setcontext = m6502_set_context; break;
+ case CPUINFO_PTR_INIT: info->init = m6502_init; break;
+ case CPUINFO_PTR_RESET: info->reset = m6502_reset; break;
+ case CPUINFO_PTR_EXIT: info->exit = m6502_exit; break;
+ case CPUINFO_PTR_EXECUTE: info->execute = m6502_execute; break;
+ case CPUINFO_PTR_BURN: info->burn = NULL; break;
+#ifdef MAME_DEBUG
+ case CPUINFO_PTR_DISASSEMBLE: info->disassemble = m6502_dasm; break;
+#endif
+ case CPUINFO_PTR_INSTRUCTION_COUNTER: info->icount = &m6502_ICount; break;
+ case CPUINFO_PTR_M6502_READINDEXED_CALLBACK: info->f = (genf *) m6502.rdmem_id; break;
+ case CPUINFO_PTR_M6502_WRITEINDEXED_CALLBACK: info->f = (genf *) m6502.wrmem_id; break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case CPUINFO_STR_NAME: strcpy(info->s, "M6502"); break;
+ case CPUINFO_STR_CORE_FAMILY: strcpy(info->s, "Mostek 6502"); break;
+ case CPUINFO_STR_CORE_VERSION: strcpy(info->s, "1.2"); break;
+ case CPUINFO_STR_CORE_FILE: strcpy(info->s, __FILE__); break;
+ case CPUINFO_STR_CORE_CREDITS: strcpy(info->s, "Copyright (c) 1998 Juergen Buchmueller, all rights reserved."); break;
+
+ case CPUINFO_STR_FLAGS:
+ sprintf(info->s, "%c%c%c%c%c%c%c%c",
+ m6502.p & 0x80 ? 'N':'.',
+ m6502.p & 0x40 ? 'V':'.',
+ m6502.p & 0x20 ? 'R':'.',
+ m6502.p & 0x10 ? 'B':'.',
+ m6502.p & 0x08 ? 'D':'.',
+ m6502.p & 0x04 ? 'I':'.',
+ m6502.p & 0x02 ? 'Z':'.',
+ m6502.p & 0x01 ? 'C':'.');
+ break;
+
+ case CPUINFO_STR_REGISTER + M6502_PC: sprintf(info->s, "PC:%04X", m6502.pc.w.l); break;
+ case CPUINFO_STR_REGISTER + M6502_S: sprintf(info->s, "S:%02X", m6502.sp.b.l); break;
+ case CPUINFO_STR_REGISTER + M6502_P: sprintf(info->s, "P:%02X", m6502.p); break;
+ case CPUINFO_STR_REGISTER + M6502_A: sprintf(info->s, "A:%02X", m6502.a); break;
+ case CPUINFO_STR_REGISTER + M6502_X: sprintf(info->s, "X:%02X", m6502.x); break;
+ case CPUINFO_STR_REGISTER + M6502_Y: sprintf(info->s, "Y:%02X", m6502.y); break;
+ case CPUINFO_STR_REGISTER + M6502_EA: sprintf(info->s, "EA:%04X", m6502.ea.w.l); break;
+ case CPUINFO_STR_REGISTER + M6502_ZP: sprintf(info->s, "ZP:%03X", m6502.zp.w.l); break;
+ }
+}
+
+
+#if (HAS_N2A03)
+/**************************************************************************
+ * CPU-specific set_info
+ **************************************************************************/
+
+void n2a03_get_info(UINT32 state, cpuinfo *info)
+{
+ switch (state)
+ {
+ /* --- the following bits of info are returned as pointers to data or functions --- */
+ case CPUINFO_PTR_INIT: info->init = n2a03_init; break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case CPUINFO_STR_NAME: strcpy(info->s, "N2A03"); break;
+
+ default: m6502_get_info(state, info); break;
+ }
+}
+#endif
+
+
+#if (HAS_M6510) || (HAS_M6510T) || (HAS_M8502) || (HAS_M7501)
+/**************************************************************************
+ * CPU-specific set_info
+ **************************************************************************/
+
+static void m6510_set_info(UINT32 state, cpuinfo *info)
+{
+ switch (state)
+ {
+ /* --- the following bits of info are set as pointers to data or functions --- */
+ case CPUINFO_PTR_M6510_PORTREAD: m6502.port_read = (UINT8 (*)(UINT8)) info->f; break;
+ case CPUINFO_PTR_M6510_PORTWRITE: m6502.port_write = (void (*)(UINT8,UINT8)) info->f; break;
+
+ default: m6502_set_info(state, info); break;
+ }
+}
+
+void m6510_get_info(UINT32 state, cpuinfo *info)
+{
+ switch (state)
+ {
+ /* --- the following bits of info are returned as pointers to data or functions --- */
+ case CPUINFO_PTR_SET_INFO: info->setinfo = m6510_set_info; break;
+ case CPUINFO_PTR_INIT: info->init = m6510_init; break;
+ case CPUINFO_PTR_RESET: info->reset = m6510_reset; break;
+#ifdef MAME_DEBUG
+ case CPUINFO_PTR_DISASSEMBLE: info->disassemble = m6510_dasm; break;
+#endif
+ case CPUINFO_PTR_INTERNAL_MEMORY_MAP: info->internal_map = construct_map_m6510_mem; break;
+ case CPUINFO_PTR_M6510_PORTREAD: info->f = (genf *) m6502.port_read; break;
+ case CPUINFO_PTR_M6510_PORTWRITE: info->f = (genf *) m6502.port_write; break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case CPUINFO_STR_NAME: strcpy(info->s, "M6510"); break;
+
+ /* --- the following bits of info are set as 64-bit signed integers --- */
+ case CPUINFO_INT_M6510_PORT: info->i = m6510_get_port(); break;
+
+ default: m6502_get_info(state, info); break;
+ }
+}
+#endif
+
+
+#if (HAS_M6510T)
+/**************************************************************************
+ * CPU-specific set_info
+ **************************************************************************/
+
+void m6510t_get_info(UINT32 state, cpuinfo *info)
+{
+ switch (state)
+ {
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case CPUINFO_STR_NAME: strcpy(info->s, "M6510T"); break;
+
+ default: m6510_get_info(state, info); break;
+ }
+}
+#endif
+
+
+#if (HAS_M7501)
+/**************************************************************************
+ * CPU-specific set_info
+ **************************************************************************/
+
+void m7501_get_info(UINT32 state, cpuinfo *info)
+{
+ switch (state)
+ {
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case CPUINFO_STR_NAME: strcpy(info->s, "M7501"); break;
+
+ default: m6510_get_info(state, info); break;
+ }
+}
+#endif
+
+
+#if (HAS_M8502)
+/**************************************************************************
+ * CPU-specific set_info
+ **************************************************************************/
+
+void m8502_get_info(UINT32 state, cpuinfo *info)
+{
+ switch (state)
+ {
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case CPUINFO_STR_NAME: strcpy(info->s, "M8502"); break;
+
+ default: m6510_get_info(state, info); break;
+ }
+}
+#endif
+
+
+#if (HAS_M65C02)
+/**************************************************************************
+ * CPU-specific set_info
+ **************************************************************************/
+
+static void m65c02_set_info(UINT32 state, cpuinfo *info)
+{
+ switch (state)
+ {
+ /* --- the following bits of info are set as 64-bit signed integers --- */
+ case CPUINFO_INT_INPUT_STATE + INPUT_LINE_NMI: m65c02_set_irq_line(INPUT_LINE_NMI, info->i); break;
+
+ default: m6502_set_info(state, info); break;
+ }
+}
+
+void m65c02_get_info(UINT32 state, cpuinfo *info)
+{
+ switch (state)
+ {
+ /* --- the following bits of info are returned as pointers to data or functions --- */
+ case CPUINFO_PTR_SET_INFO: info->setinfo = m65c02_set_info; break;
+ case CPUINFO_PTR_INIT: info->init = m65c02_init; break;
+ case CPUINFO_PTR_RESET: info->reset = m65c02_reset; break;
+ case CPUINFO_PTR_EXECUTE: info->execute = m65c02_execute; break;
+#ifdef MAME_DEBUG
+ case CPUINFO_PTR_DISASSEMBLE: info->disassemble = m65c02_dasm; break;
+#endif
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case CPUINFO_STR_NAME: strcpy(info->s, "M65C02"); break;
+
+ default: m6502_get_info(state, info); break;
+ }
+}
+#endif
+
+
+#if (HAS_M65SC02)
+/**************************************************************************
+ * CPU-specific set_info
+ **************************************************************************/
+
+void m65sc02_get_info(UINT32 state, cpuinfo *info)
+{
+ switch (state)
+ {
+ /* --- the following bits of info are returned as pointers to data or functions --- */
+ case CPUINFO_PTR_INIT: info->init = m65sc02_init; break;
+#ifdef MAME_DEBUG
+ case CPUINFO_PTR_DISASSEMBLE: info->disassemble = m65sc02_dasm; break;
+#endif
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case CPUINFO_STR_NAME: strcpy(info->s, "M65SC02"); break;
+ case CPUINFO_STR_CORE_FAMILY: strcpy(info->s, "Metal Oxid Semiconductor MOS 6502"); break;
+ case CPUINFO_STR_CORE_VERSION: strcpy(info->s, "1.0beta"); break;
+ case CPUINFO_STR_CORE_FILE: strcpy(info->s, __FILE__); break;
+ case CPUINFO_STR_CORE_CREDITS: strcpy(info->s, "Copyright (c) 1998 Juergen Buchmueller\nCopyright (c) 2000 Peter Trauner\nall rights reserved."); break;
+
+ default: m65c02_get_info(state, info); break;
+ }
+}
+#endif
+
+
+#if (HAS_DECO16)
+/**************************************************************************
+ * CPU-specific set_info
+ **************************************************************************/
+
+static void deco16_set_info(UINT32 state, cpuinfo *info)
+{
+ switch (state)
+ {
+ /* --- the following bits of info are set as 64-bit signed integers --- */
+ case CPUINFO_INT_INPUT_STATE + M6502_IRQ_LINE: deco16_set_irq_line(M6502_IRQ_LINE, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + M6502_SET_OVERFLOW: deco16_set_irq_line(M6502_SET_OVERFLOW, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + INPUT_LINE_NMI: deco16_set_irq_line(INPUT_LINE_NMI, info->i); break;
+
+ default: m6502_set_info(state, info); break;
+ }
+}
+
+void deco16_get_info(UINT32 state, cpuinfo *info)
+{
+ switch (state)
+ {
+ /* --- the following bits of info are returned as 64-bit signed integers --- */
+ case CPUINFO_INT_DATABUS_WIDTH + ADDRESS_SPACE_IO: info->i = 8; break;
+ case CPUINFO_INT_ADDRBUS_WIDTH + ADDRESS_SPACE_IO: info->i = 8; break;
+
+ /* --- the following bits of info are returned as pointers to data or functions --- */
+ case CPUINFO_PTR_SET_INFO: info->setinfo = deco16_set_info; break;
+ case CPUINFO_PTR_INIT: info->init = deco16_init; break;
+ case CPUINFO_PTR_RESET: info->reset = deco16_reset; break;
+ case CPUINFO_PTR_EXECUTE: info->execute = deco16_execute; break;
+#ifdef MAME_DEBUG
+ case CPUINFO_PTR_DISASSEMBLE: info->disassemble = deco16_dasm; break;
+#endif
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case CPUINFO_STR_NAME: strcpy(info->s, "DECO CPU16"); break;
+ case CPUINFO_STR_CORE_FAMILY: strcpy(info->s, "DECO"); break;
+ case CPUINFO_STR_CORE_VERSION: strcpy(info->s, "0.1"); break;
+ case CPUINFO_STR_CORE_FILE: strcpy(info->s, __FILE__); break;
+ case CPUINFO_STR_CORE_CREDITS: strcpy(info->s, "Copyright (c) 1998 Juergen Buchmueller\nCopyright (c) 2001-2003 Bryan McPhail\nall rights reserved."); break;
+
+ default: m6502_get_info(state, info); break;
+ }
+}
+#endif