summaryrefslogtreecommitdiffstatshomepage
path: root/trunk/src/emu/cpu/m37710/m37710.c
diff options
context:
space:
mode:
Diffstat (limited to 'trunk/src/emu/cpu/m37710/m37710.c')
-rw-r--r--trunk/src/emu/cpu/m37710/m37710.c1130
1 files changed, 1130 insertions, 0 deletions
diff --git a/trunk/src/emu/cpu/m37710/m37710.c b/trunk/src/emu/cpu/m37710/m37710.c
new file mode 100644
index 00000000000..add2eabaf14
--- /dev/null
+++ b/trunk/src/emu/cpu/m37710/m37710.c
@@ -0,0 +1,1130 @@
+/*
+ Mitsubishi M37702/37710 CPU Emulator
+
+ The 7700 series is based on the WDC 65C816 core, with the following
+ notable changes:
+
+ - Second accumulator called "B" (on the 65816, "A" and "B" were the
+ two 8-bit halves of the 16-bit "C" accumulator).
+ - 6502 emulation mode and XCE instruction are not present.
+ - No NMI line. BRK and the watchdog interrupt are non-maskable, but there
+ is no provision for the traditional 6502/65816 NMI line.
+ - 3-bit interrupt priority levels like the 68000. Interrupts in general
+ are very different from the 65816.
+ - New single-instruction immediate-to-memory move instructions (LDM)
+ replaces STZ.
+ - CLM and SEM (clear and set "M" status bit) replace CLD/SED. Decimal
+ mode is still available via REP/SEP instructions.
+ - INC and DEC (0x1A and 0x3A) switch places for no particular reason.
+ - The microcode bug that caused MVN/NVP to take 2 extra cycles per byte
+ on the 65816 seems to have been fixed.
+ - The WDM (0x42) and BIT immediate (0x89) instructions are now prefixes.
+ 0x42 when used before an instruction involving the A accumulator makes
+ it use the B accumulator instead. 0x89 adds multiply and divide
+ opcodes, which the real 65816 doesn't have.
+ - The 65C816 preserves the upper 8 bits of A when in 8-bit M mode, but
+ not the upper 8 bits of X or Y when in 8-bit X. The 7700 preserves
+ the top bits of all registers in all modes (code in the C74 BIOS
+ starting at d881 requires this!).
+
+ The various 7700 series models differ primarily by their on board
+ peripherals. The 7750 and later models do include some additional
+ instructions, vs. the 770x/1x/2x, notably signed multiply/divide and
+ sign extension opcodes.
+
+ Peripherals common across the 7700 series include: programmable timers,
+ digital I/O ports, and analog to digital converters.
+
+ Reference: 7700 Family Software User's Manual (instruction set)
+ 7702/7703 Family User's Manual (on-board peripherals)
+ 7720 Family User's Manual
+
+ Emulator by R. Belmont.
+ Based on G65816 Emulator by Karl Stenrud.
+
+ History:
+ - v1.0 RB First version, basic operation OK, timers not complete
+ - v1.1 RB Data bus is 16-bit, dozens of bugfixes to IRQs, opcodes,
+ and opcode mapping. New opcodes added, internal timers added.
+ - v1.2 RB Fixed execution outside of bank 0, fixed LDM outside of bank 0,
+ fixed so top 8 bits of X & Y are preserved while in 8-bit mode,
+ added save state support.
+*/
+
+#include "emu.h"
+#include "debugger.h"
+#include "m37710.h"
+#include "m37710cm.h"
+
+#define M37710_DEBUG (0) // enables verbose logging for peripherals, etc.
+
+static void m37710_set_irq_line(m37710i_cpu_struct *cpustate, int line, int state);
+
+/* interrupt control mapping */
+
+extern const int m37710_irq_levels[M37710_LINE_MAX];
+const int m37710_irq_levels[M37710_LINE_MAX] =
+{
+ // maskable
+ 0x70, // ADC
+ 0x73, // UART 1 XMIT
+ 0x74, // UART 1 RECV
+ 0x71, // UART 0 XMIT
+ 0x72, // UART 0 RECV
+ 0x7c, // Timer B2
+ 0x7b, // Timer B1
+ 0x7a, // Timer B0
+ 0x79, // Timer A4
+ 0x78, // Timer A3
+ 0x77, // Timer A2
+ 0x76, // Timer A1
+ 0x75, // Timer A0
+ 0x7f, // IRQ 2
+ 0x7e, // IRQ 1
+ 0x7d, // IRQ 0
+
+ // non-maskable
+ 0, // watchdog
+ 0, // debugger control
+ 0, // BRK
+ 0, // divide by zero
+ 0, // reset
+};
+
+static const int m37710_irq_vectors[M37710_LINE_MAX] =
+{
+ // maskable C74
+ 0xffd6, // A-D converter c68b
+ 0xffd8, // UART1 transmit c68e
+ 0xffda, // UART1 receive c691
+ 0xffdc, // UART0 transmit c694
+ 0xffde, // UART0 receive c697
+ 0xffe0, // Timer B2 c69a
+ 0xffe2, // Timer B1 c69d
+ 0xffe4, // Timer B0 c6a0
+ 0xffe6, // Timer A4 c6a3
+ 0xffe8, // Timer A3 c6a6
+ 0xffea, // Timer A2 c6a9
+ 0xffec, // Timer A1 c6ac
+ 0xffee, // Timer A0 c6af
+ 0xfff0, // external INT2 pin c6b2
+ 0xfff2, // external INT1 pin c6b5
+ 0xfff4, // external INT0 pin c6b8
+
+ // non-maskable
+ 0xfff6, // watchdog timer
+ 0xfff8, // debugger control (not used in shipping ICs?)
+ 0xfffa, // BRK
+ 0xfffc, // divide by zero
+ 0xfffe, // RESET
+};
+
+// M37710 internal peripherals
+
+#if M37710_DEBUG
+static const char *const m37710_rnames[128] =
+{
+ "",
+ "",
+ "Port P0 reg",
+ "Port P1 reg",
+ "Port P0 dir reg",
+ "Port P1 dir reg",
+ "Port P2 reg",
+ "Port P3 reg",
+ "Port P2 dir reg",
+ "Port P3 dir reg",
+ "Port P4 reg",
+ "Port P5 reg",
+ "Port P4 dir reg",
+ "Port P5 dir reg",
+ "Port P6 reg",
+ "Port P7 reg",
+ "Port P6 dir reg", // 16
+ "Port P7 dir reg",
+ "Port P8 reg",
+ "",
+ "Port P8 dir reg",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "A/D control reg",
+ "A/D sweep pin select",
+ "A/D 0", // 32 (0x20)
+ "",
+ "A/D 1",
+ "",
+ "A/D 2",
+ "",
+ "A/D 3",
+ "",
+ "A/D 4",
+ "",
+ "A/D 5",
+ "",
+ "A/D 6",
+ "",
+ "A/D 7",
+ "",
+ "UART0 transmit/recv mode", // 48 (0x30)
+ "UART0 baud rate", // 0x31
+ "UART0 transmit buf L", // 0x32
+ "UART0 transmit buf H", // 0x33
+ "UART0 transmit/recv ctrl 0", // 0x34
+ "UART0 transmit/recv ctrl 1", // 0x35
+ "UART0 recv buf L", // 0x36
+ "UART0 recv buf H", // 0x37
+ "UART1 transmit/recv mode", // 0x38
+ "UART1 baud rate",
+ "UART1 transmit buf L",
+ "UART1 transmit buf H",
+ "UART1 transmit/recv ctrl 0",
+ "UART1 transmit/recv ctrl 1",
+ "UART1 recv buf L",
+ "UART1 recv buf H",
+ "Count start",
+ "",
+ "One-shot start",
+ "",
+ "Up-down register",
+ "",
+ "Timer A0 L",
+ "Timer A0 H",
+ "Timer A1 L",
+ "Timer A1 H",
+ "Timer A2 L",
+ "Timer A2 H",
+ "Timer A3 L",
+ "Timer A3 H",
+ "Timer A4 L",
+ "Timer A4 H",
+ "Timer B0 L",
+ "Timer B0 H",
+ "Timer B1 L",
+ "Timer B1 H",
+ "Timer B2 L",
+ "Timer B2 H",
+ "Timer A0 mode",
+ "Timer A1 mode",
+ "Timer A2 mode",
+ "Timer A3 mode",
+ "Timer A4 mode",
+ "Timer B0 mode",
+ "Timer B1 mode",
+ "Timer B2 mode",
+ "Processor mode",
+ "",
+ "Watchdog reset",
+ "Watchdog frequency",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "A/D IRQ ctrl",
+ "UART0 xmit IRQ ctrl",
+ "UART0 recv IRQ ctrl",
+ "UART1 xmit IRQ ctrl",
+ "UART1 recv IRQ ctrl",
+ "Timer A0 IRQ ctrl",
+ "Timer A1 IRQ ctrl",
+ "Timer A2 IRQ ctrl",
+ "Timer A3 IRQ ctrl",
+ "Timer A4 IRQ ctrl",
+ "Timer B0 IRQ ctrl",
+ "Timer B1 IRQ ctrl",
+ "Timer B2 IRQ ctrl",
+ "INT0 IRQ ctrl",
+ "INT1 IRQ ctrl",
+ "INT2 IRQ ctrl",
+};
+
+static const char *const m37710_tnames[8] =
+{
+ "A0", "A1", "A2", "A3", "A4", "B0", "B1", "B2"
+};
+#endif
+
+static TIMER_CALLBACK( m37710_timer_cb )
+{
+ m37710i_cpu_struct *cpustate = (m37710i_cpu_struct *)ptr;
+ int which = param;
+ int curirq = M37710_LINE_TIMERA0 - which;
+
+ cpustate->timers[which]->adjust(cpustate->reload[which], param);
+
+ cpustate->m37710_regs[m37710_irq_levels[curirq]] |= 0x04;
+ m37710_set_irq_line(cpustate, curirq, PULSE_LINE);
+ device_triggerint(cpustate->device);
+}
+
+static void m37710_external_tick(m37710i_cpu_struct *cpustate, int timer, int state)
+{
+ // we only care if the state is "on"
+ if (!state)
+ {
+ return;
+ }
+
+ // check if enabled
+ if (cpustate->m37710_regs[0x40] & (1<<timer))
+ {
+ if ((cpustate->m37710_regs[0x56+timer] & 0x3) == 1)
+ {
+ if (cpustate->m37710_regs[0x46+(timer*2)] == 0xff)
+ {
+ cpustate->m37710_regs[0x46+(timer*2)] = 0;
+ cpustate->m37710_regs[0x46+(timer*2)+1]++;
+ }
+ else
+ {
+ cpustate->m37710_regs[0x46+(timer*2)]++;
+ }
+ }
+ else
+ {
+ logerror("M37710: external tick for timer %d, not in event counter mode!\n", timer);
+ }
+ }
+}
+
+static void m37710_recalc_timer(m37710i_cpu_struct *cpustate, int timer)
+{
+ int tval;
+ static const int tcr[8] = { 0x56, 0x57, 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d };
+ attotime time;
+ static const int tscales[4] = { 2, 16, 64, 512 };
+
+ // check if enabled
+ if (cpustate->m37710_regs[0x40] & (1<<timer))
+ {
+ #if M37710_DEBUG
+ mame_printf_debug("Timer %d (%s) is enabled\n", timer, m37710_tnames[timer]);
+ #endif
+
+ // set the timer's value
+ tval = cpustate->m37710_regs[0x46+(timer*2)] | (cpustate->m37710_regs[0x47+(timer*2)]<<8);
+
+ // check timer's mode
+ // modes are slightly different between timer groups A and B
+ if (timer < 5)
+ {
+ switch (cpustate->m37710_regs[0x56+timer] & 0x3)
+ {
+ case 0: // timer mode
+ time = attotime::from_hz(cpustate->device->unscaled_clock()) * tscales[cpustate->m37710_regs[tcr[timer]]>>6];
+ time *= tval + 1;
+
+ #if M37710_DEBUG
+ mame_printf_debug("Timer %d in timer mode, %f Hz\n", timer, 1.0 / time.as_double());
+ #endif
+
+ cpustate->timers[timer]->adjust(time, timer);
+ cpustate->reload[timer] = time;
+ break;
+
+ case 1: // event counter mode
+ #if M37710_DEBUG
+ mame_printf_debug("Timer %d in event counter mode\n", timer);
+ #endif
+ break;
+
+ case 2: // one-shot pulse mode
+ #if M37710_DEBUG
+ mame_printf_debug("Timer %d in one-shot mode\n", timer);
+ #endif
+ break;
+
+ case 3: // PWM mode
+ #if M37710_DEBUG
+ mame_printf_debug("Timer %d in PWM mode\n", timer);
+ #endif
+ break;
+ }
+ }
+ else
+ {
+ switch (cpustate->m37710_regs[0x56+timer] & 0x3)
+ {
+ case 0: // timer mode
+ time = attotime::from_hz(cpustate->device->unscaled_clock()) * tscales[cpustate->m37710_regs[tcr[timer]]>>6];
+ time *= tval + 1;
+
+ #if M37710_DEBUG
+ mame_printf_debug("Timer %d in timer mode, %f Hz\n", timer, 1.0 / time.as_double());
+ #endif
+
+ cpustate->timers[timer]->adjust(time, timer);
+ cpustate->reload[timer] = time;
+ break;
+
+ case 1: // event counter mode
+ #if M37710_DEBUG
+ mame_printf_debug("Timer %d in event counter mode\n", timer);
+ #endif
+ break;
+
+ case 2: // pulse period/pulse width measurement mode
+ #if M37710_DEBUG
+ mame_printf_debug("Timer %d in pulse period/width measurement mode\n", timer);
+ #endif
+ break;
+
+ case 3:
+ #if M37710_DEBUG
+ mame_printf_debug("Timer %d in unknown mode!\n", timer);
+ #endif
+ break;
+ }
+ }
+ }
+}
+
+static UINT8 m37710_internal_r(m37710i_cpu_struct *cpustate, int offset)
+{
+ #if M37710_DEBUG
+ if (offset > 1)
+ logerror("m37710_internal_r from %02x: %s (PC=%x)\n", (int)offset, m37710_rnames[(int)offset], REG_PB<<16 | REG_PC);
+ #endif
+
+ switch (offset)
+ {
+ case 2: // p0
+ return cpustate->io->read_byte(M37710_PORT0);
+ case 3: // p1
+ return cpustate->io->read_byte(M37710_PORT1);
+ case 6: // p2
+ return cpustate->io->read_byte(M37710_PORT2);
+ case 7: // p3
+ return cpustate->io->read_byte(M37710_PORT3);
+ case 0xa: // p4
+ return cpustate->io->read_byte(M37710_PORT4);
+ case 0xb: // p5
+ return cpustate->io->read_byte(M37710_PORT5);
+ case 0xe: // p6
+ return cpustate->io->read_byte(M37710_PORT6);
+ case 0xf: // p7
+ return cpustate->io->read_byte(M37710_PORT7);
+ case 0x12: // p8
+ return cpustate->io->read_byte(M37710_PORT8);
+
+ case 0x20:
+ return cpustate->io->read_byte(M37710_ADC0_L);
+ case 0x21:
+ return cpustate->io->read_byte(M37710_ADC0_H);
+ case 0x22:
+ return cpustate->io->read_byte(M37710_ADC1_L);
+ case 0x23:
+ return cpustate->io->read_byte(M37710_ADC1_H);
+ case 0x24:
+ return cpustate->io->read_byte(M37710_ADC2_L);
+ case 0x25:
+ return cpustate->io->read_byte(M37710_ADC2_H);
+ case 0x26:
+ return cpustate->io->read_byte(M37710_ADC3_L);
+ case 0x27:
+ return cpustate->io->read_byte(M37710_ADC3_H);
+ case 0x28:
+ return cpustate->io->read_byte(M37710_ADC4_L);
+ case 0x29:
+ return cpustate->io->read_byte(M37710_ADC4_H);
+ case 0x2a:
+ return cpustate->io->read_byte(M37710_ADC5_L);
+ case 0x2b:
+ return cpustate->io->read_byte(M37710_ADC5_H);
+ case 0x2c:
+ return cpustate->io->read_byte(M37710_ADC6_L);
+ case 0x2d:
+ return cpustate->io->read_byte(M37710_ADC6_H);
+ case 0x2e:
+ return cpustate->io->read_byte(M37710_ADC7_L);
+ case 0x2f:
+ return cpustate->io->read_byte(M37710_ADC7_H);
+ case 0x35:
+ return 0xff; // UART control
+
+ case 0x70: // A/D IRQ control
+ return cpustate->m37710_regs[offset] | 8;
+ }
+
+ return cpustate->m37710_regs[offset];
+}
+
+static void m37710_internal_w(m37710i_cpu_struct *cpustate, int offset, UINT8 data)
+{
+ int i;
+
+ switch(offset)
+ {
+ case 2: // p0
+ cpustate->io->write_byte(M37710_PORT0, data);
+ return;
+ case 3: // p1
+ cpustate->io->write_byte(M37710_PORT1, data);
+ return;
+ case 6: // p2
+ cpustate->io->write_byte(M37710_PORT2, data);
+ return;
+ case 7: // p3
+ cpustate->io->write_byte(M37710_PORT3, data);
+ return;
+ case 0xa: // p4
+ cpustate->io->write_byte(M37710_PORT4, data);
+ return;
+ case 0xb: // p5
+ cpustate->io->write_byte(M37710_PORT5, data);
+ return;
+ case 0xe: // p6
+ cpustate->io->write_byte(M37710_PORT6, data);
+ return;
+ case 0xf: // p7
+ cpustate->io->write_byte(M37710_PORT7, data);
+ return;
+ case 0x12: // p8
+ cpustate->io->write_byte(M37710_PORT8, data);
+ return;
+
+ case 0x40: // count start
+ for (i = 0; i < 8; i++)
+ {
+ if ((data & (1<<i)) && !(cpustate->m37710_regs[offset] & (1<<i)))
+ {
+ cpustate->m37710_regs[offset] |= (1<<i);
+ m37710_recalc_timer(cpustate, i);
+ }
+ }
+
+ cpustate->m37710_regs[offset] = data;
+
+ return;
+
+ case 0x60: // watchdog reset
+ return;
+ }
+
+ cpustate->m37710_regs[offset] = data;
+
+ #if M37710_DEBUG
+ if (offset >= 0x1e && offset <= 0x40)
+ logerror("m37710_internal_w %x to %02x: %s = %x\n", data, (int)offset, m37710_rnames[(int)offset], cpustate->m37710_regs[offset]);
+ #endif
+}
+
+static READ16_HANDLER( m37710_internal_word_r )
+{
+ m37710i_cpu_struct *cpustate = get_safe_token(&space->device());
+
+ if (mem_mask == 0xffff)
+ {
+ return (m37710_internal_r(cpustate, offset*2) | m37710_internal_r(cpustate, (offset*2)+1)<<8);
+ }
+ else if (mem_mask == 0xff00)
+ {
+ return m37710_internal_r(cpustate, (offset*2)+1)<<8;
+ }
+ else if (mem_mask == 0x00ff)
+ {
+ return m37710_internal_r(cpustate, (offset*2));
+ }
+
+ return 0;
+}
+
+static WRITE16_HANDLER( m37710_internal_word_w )
+{
+ m37710i_cpu_struct *cpustate = get_safe_token(&space->device());
+
+ if (mem_mask == 0xffff)
+ {
+ m37710_internal_w(cpustate, (offset*2), data & 0xff);
+ m37710_internal_w(cpustate, (offset*2)+1, data>>8);
+ }
+ else if (mem_mask == 0xff00)
+ {
+ m37710_internal_w(cpustate, (offset*2)+1, data>>8);
+ }
+ else if (mem_mask == 0x00ff)
+ {
+ m37710_internal_w(cpustate, (offset*2), data & 0xff);
+ }
+}
+
+extern void (*const m37710i_opcodes_M0X0[])(m37710i_cpu_struct *cpustate);
+extern void (*const m37710i_opcodes42_M0X0[])(m37710i_cpu_struct *cpustate);
+extern void (*const m37710i_opcodes89_M0X0[])(m37710i_cpu_struct *cpustate);
+extern uint m37710i_get_reg_M0X0(m37710i_cpu_struct *cpustate, int regnum);
+extern void m37710i_set_reg_M0X0(m37710i_cpu_struct *cpustate, int regnum, uint val);
+extern void m37710i_set_line_M0X0(m37710i_cpu_struct *cpustate, int line, int state);
+extern int m37710i_execute_M0X0(m37710i_cpu_struct *cpustate, int cycles);
+
+extern void (*const m37710i_opcodes_M0X1[])(m37710i_cpu_struct *cpustate);
+extern void (*const m37710i_opcodes42_M0X1[])(m37710i_cpu_struct *cpustate);
+extern void (*const m37710i_opcodes89_M0X1[])(m37710i_cpu_struct *cpustate);
+extern uint m37710i_get_reg_M0X1(m37710i_cpu_struct *cpustate, int regnum);
+extern void m37710i_set_reg_M0X1(m37710i_cpu_struct *cpustate, int regnum, uint val);
+extern void m37710i_set_line_M0X1(m37710i_cpu_struct *cpustate, int line, int state);
+extern int m37710i_execute_M0X1(m37710i_cpu_struct *cpustate, int cycles);
+
+extern void (*const m37710i_opcodes_M1X0[])(m37710i_cpu_struct *cpustate);
+extern void (*const m37710i_opcodes42_M1X0[])(m37710i_cpu_struct *cpustate);
+extern void (*const m37710i_opcodes89_M1X0[])(m37710i_cpu_struct *cpustate);
+extern uint m37710i_get_reg_M1X0(m37710i_cpu_struct *cpustate, int regnum);
+extern void m37710i_set_reg_M1X0(m37710i_cpu_struct *cpustate, int regnum, uint val);
+extern void m37710i_set_line_M1X0(m37710i_cpu_struct *cpustate, int line, int state);
+extern int m37710i_execute_M1X0(m37710i_cpu_struct *cpustate, int cycles);
+
+extern void (*const m37710i_opcodes_M1X1[])(m37710i_cpu_struct *cpustate);
+extern void (*const m37710i_opcodes42_M1X1[])(m37710i_cpu_struct *cpustate);
+extern void (*const m37710i_opcodes89_M1X1[])(m37710i_cpu_struct *cpustate);
+extern uint m37710i_get_reg_M1X1(m37710i_cpu_struct *cpustate, int regnum);
+extern void m37710i_set_reg_M1X1(m37710i_cpu_struct *cpustate, int regnum, uint val);
+extern void m37710i_set_line_M1X1(m37710i_cpu_struct *cpustate, int line, int state);
+extern int m37710i_execute_M1X1(m37710i_cpu_struct *cpustate, int cycles);
+
+void (*const *const m37710i_opcodes[4])(m37710i_cpu_struct *cpustate) =
+{
+ m37710i_opcodes_M0X0,
+ m37710i_opcodes_M0X1,
+ m37710i_opcodes_M1X0,
+ m37710i_opcodes_M1X1,
+};
+
+void (*const *const m37710i_opcodes2[4])(m37710i_cpu_struct *cpustate) =
+{
+ m37710i_opcodes42_M0X0,
+ m37710i_opcodes42_M0X1,
+ m37710i_opcodes42_M1X0,
+ m37710i_opcodes42_M1X1,
+};
+
+void (*const *const m37710i_opcodes3[4])(m37710i_cpu_struct *cpustate) =
+{
+ m37710i_opcodes89_M0X0,
+ m37710i_opcodes89_M0X1,
+ m37710i_opcodes89_M1X0,
+ m37710i_opcodes89_M1X1,
+};
+
+uint (*const m37710i_get_reg[4])(m37710i_cpu_struct *cpustate, int regnum) =
+{
+ m37710i_get_reg_M0X0,
+ m37710i_get_reg_M0X1,
+ m37710i_get_reg_M1X0,
+ m37710i_get_reg_M1X1,
+};
+
+void (*const m37710i_set_reg[4])(m37710i_cpu_struct *cpustate, int regnum, uint val) =
+{
+ m37710i_set_reg_M0X0,
+ m37710i_set_reg_M0X1,
+ m37710i_set_reg_M1X0,
+ m37710i_set_reg_M1X1,
+};
+
+void (*const m37710i_set_line[4])(m37710i_cpu_struct *cpustate, int line, int state) =
+{
+ m37710i_set_line_M0X0,
+ m37710i_set_line_M0X1,
+ m37710i_set_line_M1X0,
+ m37710i_set_line_M1X1,
+};
+
+int (*const m37710i_execute[4])(m37710i_cpu_struct *cpustate, int cycles) =
+{
+ m37710i_execute_M0X0,
+ m37710i_execute_M0X1,
+ m37710i_execute_M1X0,
+ m37710i_execute_M1X1,
+};
+
+/* internal functions */
+
+INLINE void m37710i_push_8(m37710i_cpu_struct *cpustate, uint value)
+{
+ m37710_write_8(REG_S, value);
+ REG_S = MAKE_UINT_16(REG_S-1);
+}
+
+INLINE void m37710i_push_16(m37710i_cpu_struct *cpustate, uint value)
+{
+ m37710i_push_8(cpustate, value>>8);
+ m37710i_push_8(cpustate, value&0xff);
+}
+
+INLINE uint m37710i_get_reg_p(m37710i_cpu_struct *cpustate)
+{
+ return (FLAG_N&0x80) |
+ ((FLAG_V>>1)&0x40) |
+ FLAG_M |
+ FLAG_X |
+ FLAG_D |
+ FLAG_I |
+ ((!FLAG_Z)<<1) |
+ ((FLAG_C>>8)&1);
+}
+
+void m37710i_update_irqs(m37710i_cpu_struct *cpustate)
+{
+ int curirq, pending = LINE_IRQ;
+ int wantedIRQ, curpri;
+
+ if (FLAG_I)
+ {
+ return;
+ }
+
+ curpri = -1;
+ wantedIRQ = -1;
+
+ for (curirq = M37710_LINE_MAX - 1; curirq >= 0; curirq--)
+ {
+ if ((pending & (1 << curirq)))
+ {
+ // this IRQ is set
+ if (m37710_irq_levels[curirq])
+ {
+// logerror("line %d set, level %x curpri %x IPL %x\n", curirq, cpustate->m37710_regs[m37710_irq_levels[curirq]] & 7, curpri, cpustate->ipl);
+ // it's maskable, check if the level works
+ if ((cpustate->m37710_regs[m37710_irq_levels[curirq]] & 7) > curpri)
+ {
+ // also make sure it's acceptable for the current CPU level
+ if ((cpustate->m37710_regs[m37710_irq_levels[curirq]] & 7) > cpustate->ipl)
+ {
+ // mark us as the best candidate
+ wantedIRQ = curirq;
+ curpri = cpustate->m37710_regs[m37710_irq_levels[curirq]] & 7;
+ }
+ }
+ }
+ else
+ {
+ // non-maskable
+ wantedIRQ = curirq;
+ curirq = -1;
+ break; // no more processing, NMIs always win
+ }
+ }
+ }
+
+ if (wantedIRQ != -1)
+ {
+ if (INT_ACK) INT_ACK(cpustate->device, wantedIRQ);
+
+ // make sure we're running to service the interrupt
+ CPU_STOPPED &= ~STOP_LEVEL_WAI;
+
+ // indicate we're servicing it now
+ if (m37710_irq_levels[wantedIRQ])
+ {
+ cpustate->m37710_regs[m37710_irq_levels[wantedIRQ]] &= ~8;
+ }
+
+ // auto-clear if it's an internal line
+ if (wantedIRQ <= 12)
+ {
+ m37710_set_irq_line(cpustate, wantedIRQ, CLEAR_LINE);
+ }
+
+ // let's do it...
+ // push PB, then PC, then status
+ CLK(8);
+// mame_printf_debug("taking IRQ %d: PC = %06x, SP = %04x, IPL %d\n", wantedIRQ, REG_PB | REG_PC, REG_S, cpustate->ipl);
+ m37710i_push_8(cpustate, REG_PB>>16);
+ m37710i_push_16(cpustate, REG_PC);
+ m37710i_push_8(cpustate, cpustate->ipl);
+ m37710i_push_8(cpustate, m37710i_get_reg_p(cpustate));
+
+ // set I to 1, set IPL to the interrupt we're taking
+ FLAG_I = IFLAG_SET;
+ cpustate->ipl = curpri;
+ // then PB=0, PC=(vector)
+ REG_PB = 0;
+ REG_PC = m37710_read_8(m37710_irq_vectors[wantedIRQ]) |
+ m37710_read_8(m37710_irq_vectors[wantedIRQ]+1)<<8;
+// logerror("IRQ @ %06x\n", REG_PB | REG_PC);
+ m37710i_jumping(REG_PB | REG_PC);
+ }
+}
+
+/* external functions */
+
+static CPU_RESET( m37710 )
+{
+ m37710i_cpu_struct *cpustate = get_safe_token(device);
+
+ /* Start the CPU */
+ CPU_STOPPED = 0;
+
+ /* 37710 boots in full native mode */
+ REG_D = 0;
+ REG_PB = 0;
+ REG_DB = 0;
+ REG_S = (REG_S & 0xff) | 0x100;
+ REG_X &= 0xff;
+ REG_Y &= 0xff;
+ if(!FLAG_M)
+ {
+ REG_B = REG_A & 0xff00;
+ REG_A &= 0xff;
+ }
+ FLAG_M = MFLAG_CLEAR;
+ FLAG_X = XFLAG_CLEAR;
+
+ /* Clear D and set I */
+ FLAG_D = DFLAG_CLEAR;
+ FLAG_I = IFLAG_SET;
+
+ /* Clear all pending interrupts (should we really do this?) */
+ LINE_IRQ = 0;
+ IRQ_DELAY = 0;
+
+ /* Set the function tables to emulation mode */
+ m37710i_set_execution_mode(cpustate, EXECUTION_MODE_M0X0);
+
+ FLAG_Z = ZFLAG_CLEAR;
+ REG_S = 0x1ff;
+
+ /* Fetch the reset vector */
+ REG_PC = m37710_read_8(0xfffe) | (m37710_read_8(0xffff)<<8);
+ m37710i_jumping(REG_PB | REG_PC);
+}
+
+/* Exit and clean up */
+static CPU_EXIT( m37710 )
+{
+ /* nothing to do yet */
+}
+
+/* Execute some instructions */
+static CPU_EXECUTE( m37710 )
+{
+ m37710i_cpu_struct *m37710 = get_safe_token(device);
+
+ m37710i_update_irqs(m37710);
+
+ int clocks = m37710->ICount;
+ m37710->ICount = clocks - m37710->execute(m37710, m37710->ICount);
+}
+
+
+/* Set the Program Counter */
+static void m37710_set_pc(m37710i_cpu_struct *cpustate, unsigned val)
+{
+ REG_PC = MAKE_UINT_16(val);
+ m37710_jumping(REG_PB | REG_PC);
+}
+
+/* Get the current Stack Pointer */
+static unsigned m37710_get_sp(m37710i_cpu_struct *cpustate)
+{
+ return REG_S;
+}
+
+/* Set the Stack Pointer */
+static void m37710_set_sp(m37710i_cpu_struct *cpustate, unsigned val)
+{
+ REG_S = MAKE_UINT_16(val);
+}
+
+/* Get a register */
+static unsigned m37710_get_reg(m37710i_cpu_struct *cpustate, int regnum)
+{
+ return FTABLE_GET_REG(cpustate, regnum);
+}
+
+/* Set a register */
+static void m37710_set_reg(m37710i_cpu_struct *cpustate, int regnum, unsigned value)
+{
+ FTABLE_SET_REG(cpustate, regnum, value);
+}
+
+/* Set an interrupt line */
+static void m37710_set_irq_line(m37710i_cpu_struct *cpustate, int line, int state)
+{
+ FTABLE_SET_LINE(cpustate, line, state);
+}
+
+/* Set the callback that is called when servicing an interrupt */
+#ifdef UNUSED_FUNCTION
+void m37710_set_irq_callback(device_irq_callback callback)
+{
+ INT_ACK = callback;
+}
+#endif
+
+/* Disassemble an instruction */
+#include "m7700ds.h"
+
+static CPU_DISASSEMBLE( m37710 )
+{
+ m37710i_cpu_struct *cpustate = get_safe_token(device);
+
+ return m7700_disassemble(buffer, (pc&0xffff), pc>>16, oprom, FLAG_M, FLAG_X);
+}
+
+static void m37710_restore_state(m37710i_cpu_struct *cpustate)
+{
+ // restore proper function pointers
+ m37710i_set_execution_mode(cpustate, (FLAG_M>>4) | (FLAG_X>>4));
+
+ // make sure the memory system can keep up
+ m37710i_jumping(REG_PB | REG_PC);
+}
+
+static CPU_INIT( m37710 )
+{
+ m37710i_cpu_struct *cpustate = get_safe_token(device);
+ int i;
+
+ memset(cpustate, 0, sizeof(*cpustate));
+
+ INT_ACK = irqcallback;
+ cpustate->device = device;
+ cpustate->program = device->space(AS_PROGRAM);
+ cpustate->io = device->space(AS_IO);
+
+ cpustate->ICount = 0;
+
+ cpustate->source = 0;
+ cpustate->destination = 0;
+
+ for (i = 0; i < 8; i++)
+ cpustate->timers[i] = device->machine().scheduler().timer_alloc(FUNC(m37710_timer_cb), cpustate);
+
+ device->save_item(NAME(cpustate->a));
+ device->save_item(NAME(cpustate->b));
+ device->save_item(NAME(cpustate->ba));
+ device->save_item(NAME(cpustate->bb));
+ device->save_item(NAME(cpustate->x));
+ device->save_item(NAME(cpustate->y));
+ device->save_item(NAME(cpustate->s));
+ device->save_item(NAME(cpustate->pc));
+ device->save_item(NAME(cpustate->ppc));
+ device->save_item(NAME(cpustate->pb));
+ device->save_item(NAME(cpustate->db));
+ device->save_item(NAME(cpustate->d));
+ device->save_item(NAME(cpustate->flag_e));
+ device->save_item(NAME(cpustate->flag_m));
+ device->save_item(NAME(cpustate->flag_x));
+ device->save_item(NAME(cpustate->flag_n));
+ device->save_item(NAME(cpustate->flag_v));
+ device->save_item(NAME(cpustate->flag_d));
+ device->save_item(NAME(cpustate->flag_i));
+ device->save_item(NAME(cpustate->flag_z));
+ device->save_item(NAME(cpustate->flag_c));
+ device->save_item(NAME(cpustate->line_irq));
+ device->save_item(NAME(cpustate->ipl));
+ device->save_item(NAME(cpustate->ir));
+ device->save_item(NAME(cpustate->im));
+ device->save_item(NAME(cpustate->im2));
+ device->save_item(NAME(cpustate->im3));
+ device->save_item(NAME(cpustate->im4));
+ device->save_item(NAME(cpustate->irq_delay));
+ device->save_item(NAME(cpustate->irq_level));
+ device->save_item(NAME(cpustate->stopped));
+ device->save_item(NAME(cpustate->m37710_regs));
+ device->save_item(NAME(cpustate->reload[0]));
+ device->save_item(NAME(cpustate->reload[1]));
+ device->save_item(NAME(cpustate->reload[2]));
+ device->save_item(NAME(cpustate->reload[3]));
+ device->save_item(NAME(cpustate->reload[4]));
+ device->save_item(NAME(cpustate->reload[5]));
+ device->save_item(NAME(cpustate->reload[6]));
+ device->save_item(NAME(cpustate->reload[7]));
+
+ device->machine().save().register_postload(save_prepost_delegate(FUNC(m37710_restore_state), cpustate));
+}
+
+/**************************************************************************
+ * Generic set_info
+ **************************************************************************/
+
+static CPU_SET_INFO( m37710 )
+{
+ m37710i_cpu_struct *cpustate = get_safe_token(device);
+
+ switch (state)
+ {
+ /* --- the following bits of info are set as 64-bit signed integers --- */
+ case CPUINFO_INT_INPUT_STATE + M37710_LINE_ADC: m37710_set_irq_line(cpustate, M37710_LINE_ADC, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + M37710_LINE_IRQ0: m37710_set_irq_line(cpustate, M37710_LINE_IRQ0, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + M37710_LINE_IRQ1: m37710_set_irq_line(cpustate, M37710_LINE_IRQ1, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + M37710_LINE_IRQ2: m37710_set_irq_line(cpustate, M37710_LINE_IRQ2, info->i); break;
+
+ case CPUINFO_INT_INPUT_STATE + M37710_LINE_TIMERA0TICK: m37710_external_tick(cpustate, state - CPUINFO_INT_INPUT_STATE - M37710_LINE_TIMERA0TICK, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + M37710_LINE_TIMERA1TICK: m37710_external_tick(cpustate, state - CPUINFO_INT_INPUT_STATE - M37710_LINE_TIMERA0TICK, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + M37710_LINE_TIMERA2TICK: m37710_external_tick(cpustate, state - CPUINFO_INT_INPUT_STATE - M37710_LINE_TIMERA0TICK, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + M37710_LINE_TIMERA3TICK: m37710_external_tick(cpustate, state - CPUINFO_INT_INPUT_STATE - M37710_LINE_TIMERA0TICK, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + M37710_LINE_TIMERA4TICK: m37710_external_tick(cpustate, state - CPUINFO_INT_INPUT_STATE - M37710_LINE_TIMERA0TICK, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + M37710_LINE_TIMERB0TICK: m37710_external_tick(cpustate, state - CPUINFO_INT_INPUT_STATE - M37710_LINE_TIMERA0TICK, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + M37710_LINE_TIMERB1TICK: m37710_external_tick(cpustate, state - CPUINFO_INT_INPUT_STATE - M37710_LINE_TIMERA0TICK, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + M37710_LINE_TIMERB2TICK: m37710_external_tick(cpustate, state - CPUINFO_INT_INPUT_STATE - M37710_LINE_TIMERA0TICK, info->i); break;
+
+ case CPUINFO_INT_PC: REG_PB = info->i & 0xff0000; m37710_set_pc(cpustate, info->i & 0xffff); break;
+ case CPUINFO_INT_SP: m37710_set_sp(cpustate, info->i); break;
+
+ case CPUINFO_INT_REGISTER + M37710_PC: m37710_set_reg(cpustate, M37710_PC, info->i); break;
+ case CPUINFO_INT_REGISTER + M37710_S: m37710_set_reg(cpustate, M37710_S, info->i); break;
+ case CPUINFO_INT_REGISTER + M37710_P: m37710_set_reg(cpustate, M37710_P, info->i&0xff); cpustate->ipl = (info->i>>8)&0xff; break;
+ case CPUINFO_INT_REGISTER + M37710_A: m37710_set_reg(cpustate, M37710_A, info->i); break;
+ case CPUINFO_INT_REGISTER + M37710_X: m37710_set_reg(cpustate, M37710_X, info->i); break;
+ case CPUINFO_INT_REGISTER + M37710_Y: m37710_set_reg(cpustate, M37710_Y, info->i); break;
+ case CPUINFO_INT_REGISTER + M37710_PB: m37710_set_reg(cpustate, M37710_PB, info->i); break;
+ case CPUINFO_INT_REGISTER + M37710_DB: m37710_set_reg(cpustate, M37710_DB, info->i); break;
+ case CPUINFO_INT_REGISTER + M37710_D: m37710_set_reg(cpustate, M37710_D, info->i); break;
+ case CPUINFO_INT_REGISTER + M37710_E: m37710_set_reg(cpustate, M37710_E, info->i); break;
+ case CPUINFO_INT_REGISTER + M37710_NMI_STATE: m37710_set_reg(cpustate, M37710_NMI_STATE, info->i); break;
+ case CPUINFO_INT_REGISTER + M37710_IRQ_STATE: m37710_set_reg(cpustate, M37710_IRQ_STATE, info->i); break;
+ }
+}
+
+// On-board RAM and peripherals
+static ADDRESS_MAP_START( m37710_internal_map, AS_PROGRAM, 16 )
+ AM_RANGE(0x000000, 0x00007f) AM_READWRITE(m37710_internal_word_r, m37710_internal_word_w)
+ AM_RANGE(0x000080, 0x00027f) AM_RAM
+ADDRESS_MAP_END
+
+/**************************************************************************
+ * Generic get_info
+ **************************************************************************/
+
+CPU_GET_INFO( m37710 )
+{
+ m37710i_cpu_struct *cpustate = (device != NULL && device->token() != NULL) ? get_safe_token(device) : NULL;
+
+ switch (state)
+ {
+ /* --- the following bits of info are returned as 64-bit signed integers --- */
+ case CPUINFO_INT_CONTEXT_SIZE: info->i = sizeof(m37710i_cpu_struct); break;
+ case CPUINFO_INT_DEFAULT_IRQ_VECTOR: info->i = 0; break;
+ case DEVINFO_INT_ENDIANNESS: info->i = ENDIANNESS_LITTLE; break;
+ case CPUINFO_INT_CLOCK_MULTIPLIER: info->i = 1; 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 = 6; break;
+ case CPUINFO_INT_MIN_CYCLES: info->i = 1; break;
+ case CPUINFO_INT_MAX_CYCLES: info->i = 20; /* rough guess */ break;
+ case CPUINFO_INT_INPUT_LINES: info->i = M37710_LINE_MAX; break;
+
+ case DEVINFO_INT_DATABUS_WIDTH + AS_PROGRAM: info->i = 16; break;
+ case DEVINFO_INT_ADDRBUS_WIDTH + AS_PROGRAM: info->i = 24; break;
+ case DEVINFO_INT_ADDRBUS_SHIFT + AS_PROGRAM: info->i = 0; break;
+ case DEVINFO_INT_DATABUS_WIDTH + AS_DATA: info->i = 0; break;
+ case DEVINFO_INT_ADDRBUS_WIDTH + AS_DATA: info->i = 0; break;
+ case DEVINFO_INT_ADDRBUS_SHIFT + AS_DATA: info->i = 0; break;
+ case DEVINFO_INT_DATABUS_WIDTH + AS_IO: info->i = 8; break;
+ case DEVINFO_INT_ADDRBUS_WIDTH + AS_IO: info->i = 16; break;
+ case DEVINFO_INT_ADDRBUS_SHIFT + AS_IO: info->i = 0; break;
+
+ case CPUINFO_INT_INPUT_STATE + M37710_LINE_IRQ0: info->i = 0; break;
+ case CPUINFO_INT_INPUT_STATE + M37710_LINE_IRQ1: info->i = 0; break;
+ case CPUINFO_INT_INPUT_STATE + M37710_LINE_IRQ2: info->i = 0; break;
+ case CPUINFO_INT_INPUT_STATE + M37710_LINE_RESET: info->i = 0; break;
+
+ case CPUINFO_INT_PREVIOUSPC: info->i = REG_PPC; break;
+ case CPUINFO_INT_PC: info->i = (REG_PB | REG_PC); break;
+ case CPUINFO_INT_SP: info->i = m37710_get_sp(cpustate); break;
+
+ case CPUINFO_INT_REGISTER + M37710_PC: info->i = m37710_get_reg(cpustate, M37710_PC); break;
+ case CPUINFO_INT_REGISTER + M37710_S: info->i = m37710_get_reg(cpustate, M37710_S); break;
+ case CPUINFO_INT_REGISTER + M37710_P: info->i = m37710_get_reg(cpustate, M37710_P) | (cpustate->ipl<<8); break;
+ case CPUINFO_INT_REGISTER + M37710_A: info->i = m37710_get_reg(cpustate, M37710_A); break;
+ case CPUINFO_INT_REGISTER + M37710_B: info->i = m37710_get_reg(cpustate, M37710_B); break;
+ case CPUINFO_INT_REGISTER + M37710_X: info->i = m37710_get_reg(cpustate, M37710_X); break;
+ case CPUINFO_INT_REGISTER + M37710_Y: info->i = m37710_get_reg(cpustate, M37710_Y); break;
+ case CPUINFO_INT_REGISTER + M37710_PB: info->i = m37710_get_reg(cpustate, M37710_PB); break;
+ case CPUINFO_INT_REGISTER + M37710_DB: info->i = m37710_get_reg(cpustate, M37710_DB); break;
+ case CPUINFO_INT_REGISTER + M37710_D: info->i = m37710_get_reg(cpustate, M37710_D); break;
+ case CPUINFO_INT_REGISTER + M37710_E: info->i = m37710_get_reg(cpustate, M37710_E); break;
+ case CPUINFO_INT_REGISTER + M37710_NMI_STATE: info->i = m37710_get_reg(cpustate, M37710_NMI_STATE); break;
+ case CPUINFO_INT_REGISTER + M37710_IRQ_STATE: info->i = m37710_get_reg(cpustate, M37710_IRQ_STATE); break;
+
+ /* --- the following bits of info are returned as pointers to data or functions --- */
+ case CPUINFO_FCT_SET_INFO: info->setinfo = CPU_SET_INFO_NAME(m37710); break;
+ case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME(m37710); break;
+ case CPUINFO_FCT_RESET: info->reset = CPU_RESET_NAME(m37710); break;
+ case CPUINFO_FCT_EXIT: info->exit = CPU_EXIT_NAME(m37710); break;
+ case CPUINFO_FCT_EXECUTE: info->execute = CPU_EXECUTE_NAME(m37710); break;
+ case CPUINFO_FCT_BURN: info->burn = NULL; break;
+ case CPUINFO_FCT_DISASSEMBLE: info->disassemble = CPU_DISASSEMBLE_NAME(m37710); break;
+ case CPUINFO_PTR_INSTRUCTION_COUNTER: info->icount = &cpustate->ICount; break;
+
+ case DEVINFO_PTR_INTERNAL_MEMORY_MAP + AS_PROGRAM: info->internal_map16 = ADDRESS_MAP_NAME(m37710_internal_map); break;
+ case DEVINFO_PTR_INTERNAL_MEMORY_MAP + AS_DATA: info->internal_map16 = NULL; break;
+ case DEVINFO_PTR_INTERNAL_MEMORY_MAP + AS_IO: info->internal_map8 = NULL; break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case DEVINFO_STR_NAME: strcpy(info->s, "M37710"); break;
+ case DEVINFO_STR_FAMILY: strcpy(info->s, "M7700"); break;
+ case DEVINFO_STR_VERSION: strcpy(info->s, "1.2"); break;
+ case DEVINFO_STR_SOURCE_FILE: strcpy(info->s, __FILE__); break;
+ case DEVINFO_STR_CREDITS: strcpy(info->s, "Copyright R. Belmont, based on G65816 by Karl Stenerud"); break;
+
+ case CPUINFO_STR_FLAGS:
+ sprintf(info->s, "%c%c%c%c%c%c%c%c",
+ cpustate->flag_n & NFLAG_SET ? 'N':'.',
+ cpustate->flag_v & VFLAG_SET ? 'V':'.',
+ cpustate->flag_m & MFLAG_SET ? 'M':'.',
+ cpustate->flag_x & XFLAG_SET ? 'X':'.',
+ cpustate->flag_d & DFLAG_SET ? 'D':'.',
+ cpustate->flag_i & IFLAG_SET ? 'I':'.',
+ cpustate->flag_z == 0 ? 'Z':'.',
+ cpustate->flag_c & CFLAG_SET ? 'C':'.');
+ break;
+
+ case CPUINFO_STR_REGISTER + M37710_PC: sprintf(info->s, "PC:%04X", cpustate->pc); break;
+ case CPUINFO_STR_REGISTER + M37710_PB: sprintf(info->s, "PB:%02X", cpustate->pb>>16); break;
+ case CPUINFO_STR_REGISTER + M37710_DB: sprintf(info->s, "DB:%02X", cpustate->db>>16); break;
+ case CPUINFO_STR_REGISTER + M37710_D: sprintf(info->s, "D:%04X", cpustate->d); break;
+ case CPUINFO_STR_REGISTER + M37710_S: sprintf(info->s, "S:%04X", cpustate->s); break;
+ case CPUINFO_STR_REGISTER + M37710_P: sprintf(info->s, "P:%04X",
+ (cpustate->flag_n&0x80) |
+ ((cpustate->flag_v>>1)&0x40) |
+ cpustate->flag_m |
+ cpustate->flag_x |
+ cpustate->flag_d |
+ cpustate->flag_i |
+ ((!cpustate->flag_z)<<1) |
+ ((cpustate->flag_c>>8)&1) | (cpustate->ipl<<8)); break;
+ case CPUINFO_STR_REGISTER + M37710_E: sprintf(info->s, "E:%d", cpustate->flag_e); break;
+ case CPUINFO_STR_REGISTER + M37710_A: sprintf(info->s, "A:%04X", cpustate->a | cpustate->b); break;
+ case CPUINFO_STR_REGISTER + M37710_B: sprintf(info->s, "B:%04X", cpustate->ba | cpustate->bb); break;
+ case CPUINFO_STR_REGISTER + M37710_X: sprintf(info->s, "X:%04X", cpustate->x); break;
+ case CPUINFO_STR_REGISTER + M37710_Y: sprintf(info->s, "Y:%04X", cpustate->y); break;
+ case CPUINFO_STR_REGISTER + M37710_IRQ_STATE: sprintf(info->s, "IRQ:%X", cpustate->line_irq); break;
+ }
+}
+
+// 37702 is identical except with an internal ROM, so just change the name
+CPU_GET_INFO( m37702 )
+{
+ if (state == DEVINFO_STR_NAME)
+ {
+ strcpy(info->s, "M37702");
+ return;
+ }
+
+ CPU_GET_INFO_CALL(m37710);
+}
+
+DEFINE_LEGACY_CPU_DEVICE(M37710, m37710);
+DEFINE_LEGACY_CPU_DEVICE(M37702, m37702);
+
+/* ======================================================================== */
+/* ============================== END OF FILE ============================= */
+/* ======================================================================== */