From 5784cc87a2b6db4a5b8ea3efc86992dead885d16 Mon Sep 17 00:00:00 2001 From: dinkc64 Date: Sat, 27 Feb 2021 09:59:40 -0500 Subject: [PATCH] add m377 series mcu for iq_132 --- makefile.burn_rules | 4 +- src/cpu/m377/m37710.cpp | 1382 +++++++++++++++++++++ src/cpu/m377/m37710.h | 87 ++ src/cpu/m377/m37710cm.h | 405 ++++++ src/cpu/m377/m37710il.h | 206 ++++ src/cpu/m377/m37710op.h | 2609 +++++++++++++++++++++++++++++++++++++++ 6 files changed, 4691 insertions(+), 2 deletions(-) create mode 100644 src/cpu/m377/m37710.cpp create mode 100644 src/cpu/m377/m37710.h create mode 100644 src/cpu/m377/m37710cm.h create mode 100644 src/cpu/m377/m37710il.h create mode 100644 src/cpu/m377/m37710op.h diff --git a/makefile.burn_rules b/makefile.burn_rules index cc6f6a32e..78bfbb554 100644 --- a/makefile.burn_rules +++ b/makefile.burn_rules @@ -1,7 +1,7 @@ alldir = burn burn/devices burn/snd burn/drv burn/drv/atari burn/drv/capcom burn/drv/cave burn/drv/coleco burn/drv/cps3 burn/drv/dataeast \ burn/drv/galaxian burn/drv/irem burn/drv/konami burn/drv/megadrive burn/drv/midway burn/drv/pce burn/drv/pst90s burn/drv/pre90s burn/drv/neogeo burn/drv/nes \ burn/drv/pgm burn/drv/psikyo burn/drv/sega burn/drv/sg1000 burn/drv/sms burn/drv/msx burn/drv/spectrum burn/drv/taito \ - burn/drv/toaplan cpu cpu/a68k cpu/arm cpu/arm7 cpu/e132xs cpu/h6280 cpu/hd6309 cpu/i8039 cpu/i8x41 cpu/i8051 cpu/adsp2100 cpu/konami cpu/mips3 cpu/m68k \ + burn/drv/toaplan cpu cpu/a68k cpu/arm cpu/arm7 cpu/e132xs cpu/h6280 cpu/hd6309 cpu/i8039 cpu/i8x41 cpu/i8051 cpu/adsp2100 cpu/konami cpu/m377 cpu/mips3 cpu/m68k \ cpu/m6502 cpu/m6800 cpu/m6805 cpu/m6809 cpu/nec cpu/pic16c5x cpu/s2650 cpu/tlcs90 cpu/tlcs900 cpu/sh2 cpu/tms32010 cpu/tms34 cpu/upd7725 cpu/upd7810 \ cpu/v60 cpu/z80 cpu/z180 @@ -114,7 +114,7 @@ depobj = burn.o burn_bitmap.o burn_gun.o burn_led.o burn_shift.o burn_memory.o m68000_intf.o mips3_intf.o nec_intf.o pic16c5x_intf.o s2650_intf.o tlcs90_intf.o tms34010.o tms34_intf.o z80_intf.o \ z180_intf.o \ \ - arm.o arm7.o e132xs.o h6280.o hd6309.o i8039.o mcs48.o mcs51.o konami.o m6502.o m6800.o m6805.o m6809.o nec.o pic16c5x.o s2650.o sh2.o tms32010.o tlcs90.o tlcs900.o \ + arm.o arm7.o e132xs.o h6280.o hd6309.o i8039.o m37710.o mcs48.o mcs51.o konami.o m6502.o m6800.o m6805.o m6809.o nec.o pic16c5x.o s2650.o sh2.o tms32010.o tlcs90.o tlcs900.o \ upd7725.o upd7810.o v25.o v60.o z80.o z80daisy.o z80ctc.o z80pio.o z180.o \ \ cop0.o cop1.o mips3.o \ diff --git a/src/cpu/m377/m37710.cpp b/src/cpu/m377/m37710.cpp new file mode 100644 index 000000000..cd2f6424a --- /dev/null +++ b/src/cpu/m377/m37710.cpp @@ -0,0 +1,1382 @@ +/* + 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 "burnint.h" +#include "driver.h" +#include "m37710.h" +#include "m377_intf.h" + +#define M37710_DEBUG (0) // enables verbose logging for peripherals, etc. + +// forwards +static void m37710_clock_timers(INT32 clkcnt); +static void m37710i_interrupt_software(UINT32 vector); +static void m37710i_set_execution_mode(UINT32 mode); +static void m37710_set_irq_line(int line, int state); +static void m37710i_update_irqs(); +static void m37710_internal_w(int offset, UINT8 data); +static UINT8 m37710_internal_r(int offset); + +// FBNeo notes: +// Auto-mapped by the core: +// Internal regs mapped @ 0x000000 - 0x00007f +// Internal RAM mapped @ 0x000080 - 0x00087f +// always maps 0x800 @ 0x80 to handle all chip variants. + +#if 0 +// On-board RAM, ROM, and peripherals + +// M37702M2: 512 bytes internal RAM, 16K internal mask ROM +// (M37702E2: same with EPROM instead of mask ROM) +DEVICE_ADDRESS_MAP_START( map, 16, m37702m2_device ) + AM_RANGE(0x000000, 0x00007f) AM_READWRITE(m37710_internal_word_r, m37710_internal_word_w) + AM_RANGE(0x000080, 0x00027f) AM_RAM + AM_RANGE(0x00c000, 0x00ffff) AM_ROM AM_REGION(M37710_INTERNAL_ROM_REGION, 0) +ADDRESS_MAP_END + + +// M37702S1: 512 bytes internal RAM, no internal ROM +DEVICE_ADDRESS_MAP_START( map, 16, m37702s1_device ) + AM_RANGE(0x000000, 0x00007f) AM_READWRITE(m37710_internal_word_r, m37710_internal_word_w) + AM_RANGE(0x000080, 0x00027f) AM_RAM +ADDRESS_MAP_END + + +// M37710S4: 2048 bytes internal RAM, no internal ROM +DEVICE_ADDRESS_MAP_START( map, 16, m37710s4_device ) + AM_RANGE(0x000000, 0x00007f) AM_READWRITE(m37710_internal_word_r, m37710_internal_word_w) + AM_RANGE(0x000080, 0x00087f) AM_RAM +ADDRESS_MAP_END + +#endif + +#define page_size 0x80 +#define page_mask 0x7f +#define address_mask 0xffffff + +static UINT8 **mem[3]; +static UINT8 *internal_ram = NULL; + +static UINT8 (*M377_read8)(UINT32) = NULL; +static UINT16 (*M377_read16)(UINT32) = NULL; +static void (*M377_write8)(UINT32,UINT8) = NULL; +static void (*M377_write16)(UINT32,UINT16) = NULL; + +static UINT8 (*M377_ioread8)(UINT32) = NULL; +static void (*M377_iowrite8)(UINT32,UINT8) = NULL; + +void M377SetWritePortHandler(void (*write)(UINT32,UINT8)) +{ + M377_iowrite8 = write; +} + +void M377SetReadPortHandler(UINT8 (*read)(UINT32)) +{ + M377_ioread8 = read; +} + +void M377SetWriteByteHandler(void (*write)(UINT32,UINT8)) +{ + M377_write8 = write; +} + +void M377SetWriteWordHandler(void (*write)(UINT32,UINT16)) +{ + M377_write16 = write; +} + +void M377SetReadByteHandler(UINT8 (*read)(UINT32)) +{ + M377_read8 = read; +} + +void M377SetReadWordHandler(UINT16 (*read)(UINT32)) +{ + M377_read16 = read; +} + +void M377MapMemory(UINT8 *ptr, UINT64 start, UINT64 end, UINT32 flags) +{ + for (UINT64 i = start; i < end; i+= page_size) + { + if (flags & 1) mem[0][i/page_size] = (ptr == NULL) ? NULL : (ptr + (i - start)); + if (flags & 2) mem[1][i/page_size] = (ptr == NULL) ? NULL : (ptr + (i - start)); + if (flags & 4) mem[2][i/page_size] = (ptr == NULL) ? NULL : (ptr + (i - start)); + } +} + +static UINT8 io_read_byte(UINT32 a) +{ + if (M377_ioread8) { + return M377_ioread8(a); + } + + return 0; +} + +static void io_write_byte(UINT32 a, UINT8 d) +{ + if (M377_iowrite8) { + return M377_iowrite8(a,d); + } +} + +static UINT16 program_read_word_16le(UINT32 a) +{ + a &= address_mask; + + UINT8 *p = mem[0][a / page_size]; + + if (p) { + UINT16 *z = (UINT16*)(p + (a & page_mask)); +#ifdef LOG_MEM + bprintf (0, _T("PRW: %6.6x %4.4x\n"), a, *z); +#endif + + return BURN_ENDIAN_SWAP_INT16(*z); + } + + if (M377_read16) { +#ifdef LOG_MEM + bprintf (0, _T("PRW: %6.6x %4.4x\n"), a, M377_read16(a)); +#endif + if (a < 0x80) { + UINT16 offset = a >> 1; + UINT16 ret = m37710_internal_r(offset * 2 + 0); + ret |= m37710_internal_r(offset * 2 + 1) << 8; + return ret; + } + + return M377_read16(a); + } + + return 0; +} + +static UINT8 program_read_byte_16le(UINT32 a) +{ + a &= address_mask; + +#ifdef LOG_MEM + bprintf (0, _T("PRB: %6.6x\n"), a); +#endif + + if (mem[0][a / page_size]) { + return mem[0][a / page_size][a & page_mask]; + } + + if (M377_read8) { + + if (a < 0x80) { + return m37710_internal_r(a); + } + + return M377_read8(a); + } + + return 0; +} + +static void program_write_word_16le(UINT32 a, UINT16 d) +{ + a &= address_mask; +#ifdef LOG_MEM + bprintf (0, _T("PWW: %6.6x %4.4x\n"), a,d); +#endif + + UINT8 *p = mem[1][a / page_size]; + + if (p) { + UINT16 *z = (UINT16*)(p + (a & page_mask)); + *z = BURN_ENDIAN_SWAP_INT16(d); + return; + } + + if (M377_write16) { + + if (a < 0x80) { + UINT16 offset = a >> 1; + m37710_internal_w(offset * 2 + 0, d & 0xff); + m37710_internal_w(offset * 2 + 1, d >> 8); + return; + } + + M377_write16(a,d); + return; + } +} + +static void program_write_byte_16le(UINT32 a, UINT8 d) +{ + a &= address_mask; +#ifdef LOG_MEM + bprintf (0, _T("PWB: %6.6x %2.2x\n"), a,d); +#endif + + if (mem[1][a / page_size]) { + mem[1][a / page_size][a & page_mask] = d; + return; + } + + if (M377_write8) { + + if (a < 0x80) { + m37710_internal_w(a, d); + return; + } + + return M377_write8(a,d); + } +} + +void M377WriteWord(UINT32 address, UINT16 data) +{ + program_write_word_16le(address, data); +} + +void M377WriteByte(UINT32 address, UINT8 data) +{ + program_write_byte_16le(address, data); +} + +UINT16 M377ReadWord(UINT32 address) +{ + return program_read_word_16le(address); +} + +UINT8 M377ReadByte(UINT32 address) +{ + return program_read_byte_16le(address); +} + +static void core_set_irq(INT32 /*cpu*/, INT32 line, INT32 state) +{ + M377SetIRQLine(line, state); +} + +cpu_core_config M377Config = +{ + "M377xx", + M377Open, + M377Close, + M377ReadByte, //M377CheatRead, + M377WriteByte, //M377WriteROM, + M377GetActive, + M377TotalCycles, + M377NewFrame, + M377Idle, + core_set_irq, + M377Run, + M377RunEnd, + M377Reset, + 0x1000000, + 0 +}; + +struct m377_struct { + UINT32 a; /* Accumulator */ + UINT32 b; /* holds high byte of accumulator */ + UINT32 ba; /* Secondary Accumulator */ + UINT32 bb; /* holds high byte of secondary accumulator */ + UINT32 x; /* Index Register X */ + UINT32 y; /* Index Register Y */ + UINT32 xh; /* holds high byte of x */ + UINT32 yh; /* holds high byte of y */ + UINT32 s; /* Stack Pointer */ + UINT32 pc; /* Program Counter */ + UINT32 ppc; /* Previous Program Counter */ + UINT32 pb; /* Program Bank (shifted left 16) */ + UINT32 db; /* Data Bank (shifted left 16) */ + UINT32 d; /* Direct Register */ + UINT32 flag_e; /* Emulation Mode Flag */ + UINT32 flag_m; /* Memory/Accumulator Select Flag */ + UINT32 flag_x; /* Index Select Flag */ + UINT32 flag_n; /* Negative Flag */ + UINT32 flag_v; /* Overflow Flag */ + UINT32 flag_d; /* Decimal Mode Flag */ + UINT32 flag_i; /* Interrupt Mask Flag */ + UINT32 flag_z; /* Zero Flag (inverted) */ + UINT32 flag_c; /* Carry Flag */ + UINT32 line_irq; /* Bitmask of pending IRQs */ + UINT32 ipl; /* Interrupt priority level (top of PSW) */ + UINT32 ir; /* Instruction Register */ + UINT32 im; /* Immediate load value */ + UINT32 im2; /* Immediate load target */ + UINT32 im3; /* Immediate load target */ + UINT32 im4; /* Immediate load target */ + UINT32 irq_delay; /* delay 1 instruction before checking irq */ + UINT32 irq_level; /* irq level */ + INT32 ICount; /* cycle count */ + UINT32 source; /* temp register */ + UINT32 destination; /* temp register */ + UINT32 stopped; /* Sets how the CPU is stopped */ + + // on-board peripheral stuff + UINT8 m37710_regs[128]; + INT32 reload[8]; + INT32 timers[8]; + + // for debugger + UINT32 debugger_pc; + UINT32 debugger_pb; + UINT32 debugger_db; + UINT32 debugger_p; + UINT32 debugger_a; + UINT32 debugger_b; + + // DINK + INT32 end_run; + INT32 total_cycles; + INT32 segment_cycles; +}; + +static m377_struct m377; // cpu! + +// Statics +typedef void (*opcode_func)(); +typedef UINT32 (*get_reg_func)(int regnum); +typedef void (*set_reg_func)(int regnum, UINT32 val); +typedef void (*set_line_func)(int line, int state); +typedef int (*execute_func)(int cycles); + +static const opcode_func *m_opcodes; /* opcodes with no prefix */ +static const opcode_func *m_opcodes42; /* opcodes with 0x42 prefix */ +static const opcode_func *m_opcodes89; /* opcodes with 0x89 prefix */ +static get_reg_func m_get_reg; +static set_reg_func m_set_reg; +static set_line_func m_set_line; +static execute_func m_execute; + + +/* interrupt control mapping */ + +static const int m37710_irq_levels[M37710_LINE_MAX] = +{ + // maskable + 0x70, // ADC 0 + 0x73, // UART 1 XMIT 1 + 0x74, // UART 1 RECV 2 + 0x71, // UART 0 XMIT 3 + 0x72, // UART 0 RECV 4 + 0x7c, // Timer B2 5 + 0x7b, // Timer B1 6 + 0x7a, // Timer B0 7 + 0x79, // Timer A4 8 + 0x78, // Timer A3 9 + 0x77, // Timer A2 10 + 0x76, // Timer A1 11 + 0x75, // Timer A0 12 + 0x7f, // IRQ 2 13 + 0x7e, // IRQ 1 14 + 0x7d, // IRQ 0 15 + + // 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 + 0xffd6, // A-D converter + 0xffd8, // UART1 transmit + 0xffda, // UART1 receive + 0xffdc, // UART0 transmit + 0xffde, // UART0 receive + 0xffe0, // Timer B2 + 0xffe2, // Timer B1 + 0xffe4, // Timer B0 + 0xffe6, // Timer A4 + 0xffe8, // Timer A3 + 0xffea, // Timer A2 + 0xffec, // Timer A1 + 0xffee, // Timer A0 + 0xfff0, // external INT2 pin + 0xfff2, // external INT1 pin + 0xfff4, // external INT0 pin + + // non-maskable + 0xfff6, // watchdog timer + 0xfff8, // debugger control (not used in shipping ICs?) + 0xfffa, // BRK + 0xfffc, // divide by zero + 0xfffe, // RESET +}; + +// M37710 internal peripherals + +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 (0x10) + "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", // 0x40 + "", + "One-shot start", + "", + "Up-down register", + "", + "Timer A0 L", // 0x46 + "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", // 0x50 + "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", // 0x60 + "Watchdog frequency", // 0x61 + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "A/D IRQ ctrl", + "UART0 xmit IRQ ctrl", // 0x70 + "UART0 recv IRQ ctrl", + "UART1 xmit IRQ ctrl", + "UART1 recv IRQ ctrl", + "Timer A0 IRQ ctrl", // 0x74 + "Timer A1 IRQ ctrl", // 0x75 + "Timer A2 IRQ ctrl", // 0x76 + "Timer A3 IRQ ctrl", + "Timer A4 IRQ ctrl", // 0x78 + "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" +}; + +#include "m37710cm.h" +#include "m37710il.h" +#define EXECUTION_MODE EXECUTION_MODE_M0X0 +#include "m37710op.h" +#undef EXECUTION_MODE +#define EXECUTION_MODE EXECUTION_MODE_M0X1 +#include "m37710op.h" +#undef EXECUTION_MODE +#define EXECUTION_MODE EXECUTION_MODE_M1X0 +#include "m37710op.h" +#undef EXECUTION_MODE +#define EXECUTION_MODE EXECUTION_MODE_M1X1 +#include "m37710op.h" + + +static void m37710_timer_cb(INT32 param) +{ + int which = param; + int curirq = M37710_LINE_TIMERA0 - which; + + m377.timers[which] = m377.reload[which]; + + m37710_set_irq_line(curirq, HOLD_LINE); +} + +static void m37710_external_tick(int timer, int state) +{ + // we only care if the state is "on" + if (!state) + { + return; + } + + // check if enabled + if (m377.m37710_regs[0x40] & (1<>6]; + time = tscales[m377.m37710_regs[0x56+timer]>>6]; + time *= (tval + 1); + + #if M37710_DEBUG + logerror("Timer %d in timer mode, %f Hz\n", timer, 1.0 / time.as_double()); + #endif + + //m377.timers[timer]->adjust(time, timer); + m377.timers[timer] = time; + m377.reload[timer] = time; + break; + + case 1: // event counter mode + #if M37710_DEBUG + logerror("Timer %d in event counter mode\n", timer); + #endif + break; + + case 2: // one-shot pulse mode + #if M37710_DEBUG + logerror("Timer %d in one-shot mode\n", timer); + #endif + break; + + case 3: // PWM mode + #if M37710_DEBUG + logerror("Timer %d in PWM mode\n", timer); + #endif + break; + } + } + else + { + switch (m377.m37710_regs[0x56+timer] & 0x3) + { + case 0: // timer mode + time = tscales[m377.m37710_regs[0x56+timer]>>6]; + time *= (tval + 1); + + #if M37710_DEBUG + logerror("Timer %d in timer mode, %f Hz\n", timer, 1.0 / time.as_double()); + #endif + + m377.timers[timer] = time; + m377.reload[timer] = time; + break; + + case 1: // event counter mode + #if M37710_DEBUG + logerror("Timer %d in event counter mode\n", timer); + #endif + break; + + case 2: // pulse period/pulse width measurement mode + #if M37710_DEBUG + logerror("Timer %d in pulse period/width measurement mode\n", timer); + #endif + break; + + case 3: + #if M37710_DEBUG + logerror("Timer %d in unknown mode!\n", timer); + #endif + break; + } + } + } +} + +static UINT8 m37710_internal_r(int offset) +{ + UINT8 d; + + #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) + { + // ports + case 0x02: // p0 + d = m377.m37710_regs[0x04]; + if (d != 0xff) + return (io_read_byte(M37710_PORT0)&~d) | (m377.m37710_regs[offset]&d); + break; + case 0x03: // p1 + d = m377.m37710_regs[0x05]; + if (d != 0xff) + return (io_read_byte(M37710_PORT1)&~d) | (m377.m37710_regs[offset]&d); + break; + case 0x06: // p2 + d = m377.m37710_regs[0x08]; + if (d != 0xff) + return (io_read_byte(M37710_PORT2)&~d) | (m377.m37710_regs[offset]&d); + break; + case 0x07: // p3 + d = m377.m37710_regs[0x09]; + if (d != 0xff) + return (io_read_byte(M37710_PORT3)&~d) | (m377.m37710_regs[offset]&d); + break; + case 0x0a: // p4 + d = m377.m37710_regs[0x0c]; + if (d != 0xff) + return (io_read_byte(M37710_PORT4)&~d) | (m377.m37710_regs[offset]&d); + break; + case 0x0b: // p5 + d = m377.m37710_regs[0x0d]; + if (d != 0xff) + return (io_read_byte(M37710_PORT5)&~d) | (m377.m37710_regs[offset]&d); + break; + case 0x0e: // p6 + d = m377.m37710_regs[0x10]; + if (d != 0xff) + return (io_read_byte(M37710_PORT6)&~d) | (m377.m37710_regs[offset]&d); + break; + case 0x0f: // p7 + d = m377.m37710_regs[0x11]; + if (d != 0xff) + return (io_read_byte(M37710_PORT7)&~d) | (m377.m37710_regs[offset]&d); + break; + case 0x12: // p8 + d = m377.m37710_regs[0x14]; + if (d != 0xff) + return (io_read_byte(M37710_PORT8)&~d) | (m377.m37710_regs[offset]&d); + break; + + // A-D regs + case 0x20: + return io_read_byte(M37710_ADC0_L); + case 0x21: + return io_read_byte(M37710_ADC0_H); + case 0x22: + return io_read_byte(M37710_ADC1_L); + case 0x23: + return io_read_byte(M37710_ADC1_H); + case 0x24: + return io_read_byte(M37710_ADC2_L); + case 0x25: + return io_read_byte(M37710_ADC2_H); + case 0x26: + return io_read_byte(M37710_ADC3_L); + case 0x27: + return io_read_byte(M37710_ADC3_H); + case 0x28: + return io_read_byte(M37710_ADC4_L); + case 0x29: + return io_read_byte(M37710_ADC4_H); + case 0x2a: + return io_read_byte(M37710_ADC5_L); + case 0x2b: + return io_read_byte(M37710_ADC5_H); + case 0x2c: + return io_read_byte(M37710_ADC6_L); + case 0x2d: + return io_read_byte(M37710_ADC6_H); + case 0x2e: + return io_read_byte(M37710_ADC7_L); + case 0x2f: + return io_read_byte(M37710_ADC7_H); + + // UART control (not hooked up yet) + case 0x34: case 0x3c: + return 0x08; + case 0x35: case 0x3d: + return 0xff; + + // A-D IRQ control (also not properly hooked up yet) + case 0x70: + return m377.m37710_regs[offset] | 8; + + default: + return m377.m37710_regs[offset]; + } + + return m377.m37710_regs[offset]; +} + +static void m37710_internal_w(int offset, UINT8 data) +{ + int i; + UINT8 prevdata; + UINT8 d; + + #if M37710_DEBUG + if (offset != 0x60) // filter out watchdog + logerror("m37710_internal_w %x to %02x: %s = %x\n", data, (int)offset, m37710_rnames[(int)offset], m377.m37710_regs[offset]); + #endif + + prevdata = m377.m37710_regs[offset]; + m377.m37710_regs[offset] = data; + + switch(offset) + { + // ports + case 0x02: // p0 + d = m377.m37710_regs[0x04]; + if (d != 0) + io_write_byte(M37710_PORT0, data&d); + break; + case 0x03: // p1 + d = m377.m37710_regs[0x05]; + if (d != 0) + io_write_byte(M37710_PORT1, data&d); + break; + case 0x06: // p2 + d = m377.m37710_regs[0x08]; + if (d != 0) + io_write_byte(M37710_PORT2, data&d); + break; + case 0x07: // p3 + d = m377.m37710_regs[0x09]; + if (d != 0) + io_write_byte(M37710_PORT3, data&d); + break; + case 0x0a: // p4 + d = m377.m37710_regs[0x0c]; + if (d != 0) + io_write_byte(M37710_PORT4, data&d); + break; + case 0x0b: // p5 + d = m377.m37710_regs[0x0d]; + if (d != 0) + io_write_byte(M37710_PORT5, data&d); + break; + case 0x0e: // p6 + d = m377.m37710_regs[0x10]; + if (d != 0) + io_write_byte(M37710_PORT6, data&d); + break; + case 0x0f: // p7 + d = m377.m37710_regs[0x11]; + if (d != 0) + io_write_byte(M37710_PORT7, data&d); + break; + case 0x12: // p8 + d = m377.m37710_regs[0x14]; + if (d != 0) + io_write_byte(M37710_PORT8, data&d); + break; + + case 0x40: // count start + for (i = 0; i < 8; i++) + { + if ((data & (1<= 0; curirq--) + { + if ((pending & (1 << curirq))) + { + // this IRQ is set + if (m37710_irq_levels[curirq]) + { + int control = m377.m37710_regs[m37710_irq_levels[curirq]]; + int thispri = control & 7; + // logerror("line %d set, level %x curpri %x IPL %x\n", curirq, thispri, curpri, m377.ipl); + // it's maskable, check if the level works, also make sure it's acceptable for the current CPU level + if (!FLAG_I && thispri > curpri && thispri > m377.ipl) + { + // mark us as the best candidate + wantedIRQ = curirq; + curpri = thispri; + } + } + else + { + // non-maskable + wantedIRQ = curirq; + curpri = 7; + break; // no more processing, NMIs always win + } + } + } + + if (wantedIRQ != -1) + { + //standard_irq_callback(wantedIRQ); + + // make sure we're running to service the interrupt + CPU_STOPPED &= ~STOP_LEVEL_WAI; + + // auto-clear line + m37710_set_irq_line(wantedIRQ, CLEAR_LINE); + + // let's do it... + // push PB, then PC, then status + CLK(13); +// osd_printf_debug("taking IRQ %d: PC = %06x, SP = %04x, IPL %d\n", wantedIRQ, REG_PB | REG_PC, REG_S, m377.ipl); + m37710i_push_8(REG_PB>>16); + m37710i_push_16(REG_PC); + m37710i_push_8(m377.ipl); + m37710i_push_8(m37710i_get_reg_p()); + + // set I to 1, set IPL to the interrupt we're taking + FLAG_I = IFLAG_SET; + m377.ipl = curpri; + // then PB=0, PC=(vector) + REG_PB = 0; + REG_PC = m37710_read_16(m37710_irq_vectors[wantedIRQ]); +// logerror("IRQ @ %06x\n", REG_PB | REG_PC); + } +} + +/* external functions */ + +void M377Reset() +{ + int i; + + /* Reset DINK timers */ + for (i = 0; i < 8; i++) + { + m377.timers[i] = -1; + m377.reload[i] = -1; + } + + /* Start the CPU */ + CPU_STOPPED = 0; + + /* Reset internal registers */ + // port direction + m377.m37710_regs[0x04] = 0; + m377.m37710_regs[0x05] = 0; + m377.m37710_regs[0x08] = 0; + m377.m37710_regs[0x09] = 0; + m377.m37710_regs[0x0c] = 0; + m377.m37710_regs[0x0d] = 0; + m377.m37710_regs[0x10] = 0; + m377.m37710_regs[0x11] = 0; + m377.m37710_regs[0x14] = 0; + + m377.m37710_regs[0x1e] &= 7; // A-D control + m377.m37710_regs[0x1f] |= 3; // A-D sweep + + // UART + m377.m37710_regs[0x30] = 0; + m377.m37710_regs[0x38] = 0; + m377.m37710_regs[0x34] = (m377.m37710_regs[0x34] & 0xf0) | 8; + m377.m37710_regs[0x3c] = (m377.m37710_regs[0x3c] & 0xf0) | 8; + m377.m37710_regs[0x35] = 2; + m377.m37710_regs[0x3d] = 2; + m377.m37710_regs[0x37]&= 1; + m377.m37710_regs[0x3f]&= 1; + + // timer + m377.m37710_regs[0x40] = 0; + m377.m37710_regs[0x42]&= 0x1f; + m377.m37710_regs[0x44] = 0; + for (i = 0x56; i < 0x5e; i++) + m377.m37710_regs[i] = 0; + + m377.m37710_regs[0x5e] = 0; // processor mode + m377.m37710_regs[0x61]&= 1; // watchdog frequency + + // interrupt control + m377.m37710_regs[0x7d] &= 0x3f; + m377.m37710_regs[0x7e] &= 0x3f; + m377.m37710_regs[0x7f] &= 0x3f; + for (i = 0x70; i < 0x7d; i++) + m377.m37710_regs[i] &= 0xf; + + /* Clear IPL, m, x, D and set I */ + m377.ipl = 0; + FLAG_M = MFLAG_CLEAR; + FLAG_X = XFLAG_CLEAR; + FLAG_D = DFLAG_CLEAR; + FLAG_I = IFLAG_SET; + + /* Clear all pending interrupts (should we really do this?) */ + LINE_IRQ = 0; + IRQ_DELAY = 0; + + /* 37710 boots in full native mode */ + REG_D = 0; + REG_PB = 0; + REG_DB = 0; + REG_S = (REG_S & 0xff) | 0x100; + REG_XH = REG_X & 0xff00; REG_X &= 0xff; + REG_YH = REG_Y & 0xff00; REG_Y &= 0xff; + REG_B = REG_A & 0xff00; REG_A &= 0xff; + REG_BB = REG_BA & 0xff00; REG_BA &= 0xff; + + /* Set the function tables to emulation mode */ + m37710i_set_execution_mode(EXECUTION_MODE_M0X0); + + /* Fetch the reset vector */ + REG_PC = m37710_read_16(0xfffe); +} + +static void m37710_clock_timers(INT32 clkcnt) +{ + for (INT32 c = 0; c < clkcnt; c++) { + for (INT32 i = 0; i < 8; i++) { + if (m377.timers[i] > 0) { // active + m377.timers[i]--; + if (m377.timers[i] <= 0) { // timer hits! + m377.timers[i] = -1; // disable this timer + + m37710_timer_cb(i); + } + } + } + } +} + +static INT32 current_cpu = -1; + +INT32 M377GetActive() +{ + return current_cpu; +} + +void M377Open(INT32 cpunum) +{ + current_cpu = cpunum; // dummy, currently single-cpu core +} + +void M377Close() +{ + current_cpu = -1; // dummy, currently single-cpu core +} + +void M377RunEnd() +{ + m377.end_run = 1; +} + +INT32 M377Idle(INT32 cycles) +{ + m377.total_cycles += cycles; + + return cycles; +} + +/* Execute some instructions */ +INT32 M377Run(INT32 cycles) +{ + m377.end_run = 0; + + m37710i_update_irqs(); + + (*m_execute)(m377.ICount); + + cycles = cycles - m377.ICount; + + m377.segment_cycles = m377.ICount = 0; + + m377.total_cycles += cycles; + + return cycles; +} + +void M377NewFrame() +{ + m377.total_cycles = 0; +} + +INT32 M377TotalCycles() +{ + return m377.total_cycles + (m377.segment_cycles - m377.ICount); +} + + +/* Set the Program Counter */ +void m37710_set_pc(unsigned val) +{ + REG_PC = MAKE_UINT_16(val); +} + +/* Get the current Stack Pointer */ +unsigned m37710_get_sp() +{ + return REG_S; +} + +/* Set the Stack Pointer */ +void m37710_set_sp(unsigned val) +{ + REG_S = MAKE_UINT_16(val); +} + +/* Get a register */ +unsigned m37710_get_reg(int regnum) +{ + return (*m_get_reg)(regnum); +} + +/* Set a register */ +void m37710_set_reg(int regnum, unsigned value) +{ + (*m_set_reg)(regnum, value); +} + +/* Set an interrupt line */ +static void m37710_set_irq_line(int line, int state) +{ + (*m_set_line)(line, state); +} + + +void m37710_restore_state() +{ + // restore proper function pointers + m37710i_set_execution_mode((FLAG_M>>4) | (FLAG_X>>4)); +} + +INT32 M377Scan(INT32 nAction) +{ + if ((nAction & ACB_DRIVER_DATA) == 0) { + return 1; + } + + ScanVar(internal_ram, 0x800, "M377xx Int.RAM"); + + SCAN_VAR(m377); + + if (nAction & ACB_WRITE) { + m37710_restore_state(); + } + + return 0; +} + +void M377Init(INT32 cpunum) +{ + cpunum = cpunum; // dummy + + for (INT32 i = 0; i < 3; i++) { + mem[i] = (UINT8**)BurnMalloc(((address_mask / page_size) + 1) * sizeof(UINT8**)); + memset (mem[i], 0, ((address_mask / page_size) + 1) * sizeof(UINT8**)); + } + + internal_ram = (UINT8*)BurnMalloc(0x800); + + M377MapMemory(internal_ram, 0x80, 0x87f, MAP_RAM); + + memset(&m377, 0, sizeof(m377)); + memset(internal_ram, 0, 0x800); + + for (int i = 0; i < 8; i++) + { + m377.timers[i] = -1; + m377.reload[i] = -1; + } + + CpuCheatRegister(0, &M377Config); +} + +void M377Exit() +{ + for (INT32 i = 0; i < 3; i++) { + BurnFree(mem[i]); + } + + BurnFree(internal_ram); +} + +void M377SetIRQLine(INT32 inputnum, INT32 state) +{ + switch( inputnum ) + { + case M37710_LINE_ADC: + case M37710_LINE_IRQ0: + case M37710_LINE_IRQ1: + case M37710_LINE_IRQ2: + m37710_set_irq_line(inputnum, state); + break; + + case M37710_LINE_TIMERA0TICK: + case M37710_LINE_TIMERA1TICK: + case M37710_LINE_TIMERA2TICK: + case M37710_LINE_TIMERA3TICK: + case M37710_LINE_TIMERA4TICK: + case M37710_LINE_TIMERB0TICK: + case M37710_LINE_TIMERB1TICK: + case M37710_LINE_TIMERB2TICK: + m37710_external_tick(inputnum - M37710_LINE_TIMERA0TICK, state); + break; + } +} + + +static void m37710i_set_execution_mode(UINT32 mode) +{ + m_opcodes = m37710i_opcodes[mode]; + m_opcodes42 = m37710i_opcodes2[mode]; + m_opcodes89 = m37710i_opcodes3[mode]; + m_get_reg = m37710i_get_reg[mode]; + m_set_reg = m37710i_set_reg[mode]; + m_set_line = m37710i_set_line[mode]; + m_execute = m37710i_execute[mode]; +} + + +/* ======================================================================== */ +/* =============================== INTERRUPTS ============================= */ +/* ======================================================================== */ + +static void m37710i_interrupt_software(UINT32 vector) +{ + CLK(13); + m37710i_push_8(REG_PB>>16); + m37710i_push_16(REG_PC); + m37710i_push_8(m377.ipl); + m37710i_push_8(m37710i_get_reg_p()); + FLAG_I = IFLAG_SET; + REG_PB = 0; + REG_PC = m37710_read_16(vector); +} + + + +/* ======================================================================== */ +/* ============================== END OF FILE ============================= */ +/* ======================================================================== */ diff --git a/src/cpu/m377/m37710.h b/src/cpu/m377/m37710.h new file mode 100644 index 000000000..f053b48b0 --- /dev/null +++ b/src/cpu/m377/m37710.h @@ -0,0 +1,87 @@ +#ifndef __M37710_H__ +#define __M37710_H__ + +/* ======================================================================== */ +/* =============================== COPYRIGHT ============================== */ +/* ======================================================================== */ +/* + +M37710 CPU Emulator v0.1 + +*/ + +/* ======================================================================== */ +/* =============================== DEFINES ================================ */ +/* ======================================================================== */ +/* + Input lines - used with cpunum_set_input_line() and the like. + WARNING: these are in the same order as the vector table for simplicity. + Do not alter this order! +*/ + +enum +{ + // these interrupts are maskable + M37710_LINE_ADC = 0, + M37710_LINE_UART1XMIT, + M37710_LINE_UART1RECV, + M37710_LINE_UART0XMIT, + M37710_LINE_UART0RECV, + M37710_LINE_TIMERB2, + M37710_LINE_TIMERB1, + M37710_LINE_TIMERB0, + M37710_LINE_TIMERA4, + M37710_LINE_TIMERA3, + M37710_LINE_TIMERA2, + M37710_LINE_TIMERA1, + M37710_LINE_TIMERA0, + M37710_LINE_IRQ2, + M37710_LINE_IRQ1, + M37710_LINE_IRQ0, + // these interrupts are non-maskable + M37710_LINE_WATCHDOG, + M37710_LINE_DEBUG, + M37710_LINE_BRK, + M37710_LINE_ZERODIV, + M37710_LINE_RESET, + + // these are not interrupts, they're signals external hardware can send + M37710_LINE_TIMERA0TICK, + M37710_LINE_TIMERA1TICK, + M37710_LINE_TIMERA2TICK, + M37710_LINE_TIMERA3TICK, + M37710_LINE_TIMERA4TICK, + M37710_LINE_TIMERB0TICK, + M37710_LINE_TIMERB1TICK, + M37710_LINE_TIMERB2TICK, + + M37710_LINE_MAX +}; + +/* Registers - used by m37710_set_reg() and m37710_get_reg() */ +enum +{ + M37710_PC=1, M37710_S, M37710_P, M37710_A, M37710_B, M37710_X, M37710_Y, + M37710_PB, M37710_DB, M37710_D, M37710_E, + M37710_NMI_STATE, M37710_IRQ_STATE, STATE_GENPCBASE +}; + + +/* I/O ports */ +enum +{ + M37710_PORT0 = 0, + M37710_PORT1, M37710_PORT2, M37710_PORT3, M37710_PORT4, + M37710_PORT5, M37710_PORT6, M37710_PORT7, M37710_PORT8, + + M37710_ADC0_L = 0x10, M37710_ADC0_H, + M37710_ADC1_L, M37710_ADC1_H, M37710_ADC2_L, M37710_ADC2_H, M37710_ADC3_L, M37710_ADC3_H, + M37710_ADC4_L, M37710_ADC4_H, M37710_ADC5_L, M37710_ADC5_H, M37710_ADC6_L, M37710_ADC6_H, + M37710_ADC7_L, M37710_ADC7_H, + + M37710_SER0_REC = 0x20, + M37710_SER0_XMIT, M37710_SER1_REC, M37710_SER1_XMIT +}; + + +#endif /* __M37710_H__ */ diff --git a/src/cpu/m377/m37710cm.h b/src/cpu/m377/m37710cm.h new file mode 100644 index 000000000..0d6612445 --- /dev/null +++ b/src/cpu/m377/m37710cm.h @@ -0,0 +1,405 @@ +#pragma once + +#ifndef __M37710CM_H__ +#define __M37710CM_H__ + + +/* ======================================================================== */ +/* ================================ INCLUDES ============================== */ +/* ======================================================================== */ + +#include +#include "m37710.h" + + +/* ======================================================================== */ +/* ================================= MAME ================================= */ +/* ======================================================================== */ + +#define m37710_read_8(addr) program_read_byte_16le(addr) +#define m37710_write_8(addr,data) program_write_byte_16le(addr,data) +#define m37710_read_8_immediate(A) program_read_byte_16le(A) +#define m37710_read_16(addr) program_read_word_16le(addr) +#define m37710_write_16(addr,data) program_write_word_16le(addr,data) +#define m37710_read_16_immediate(A) program_read_word_16le(A) + + +/* ======================================================================== */ +/* ================================ GENERAL =============================== */ +/* ======================================================================== */ + +#undef int8 + +/* Allow for architectures that don't have 8-bit sizes */ +#if UCHAR_MAX == 0xff +#define int8 char +#define MAKE_INT_8(A) (int8)((A)&0xff) +#else +#define int8 int +INLINE int MAKE_INT_8(int A) {return (A & 0x80) ? A | ~0xff : A & 0xff;} +#endif /* UCHAR_MAX == 0xff */ + +#define MAKE_UINT_8(A) ((A)&0xff) +#define MAKE_UINT_16(A) ((A)&0xffff) +#define MAKE_UINT_24(A) ((A)&0xffffff) + +/* Bits */ +#define BIT_0 0x01 +#define BIT_1 0x02 +#define BIT_2 0x04 +#define BIT_3 0x08 +#define BIT_4 0x10 +#define BIT_5 0x20 +#define BIT_6 0x40 +#define BIT_7 0x80 + +/* ======================================================================== */ +/* ================================== CPU ================================= */ +/* ======================================================================== */ + +#define REG_A m377.a /* Accumulator */ +#define REG_B m377.b /* Accumulator hi byte */ +#define REG_BA m377.ba /* Secondary Accumulator */ +#define REG_BB m377.bb /* Secondary Accumulator hi byte */ +#define REG_X m377.x /* Index X Register */ +#define REG_Y m377.y /* Index Y Register */ +#define REG_XH m377.xh /* X high byte */ +#define REG_YH m377.yh /* Y high byte */ +#define REG_S m377.s /* Stack Pointer */ +#define REG_PC m377.pc /* Program Counter */ +#define REG_PPC m377.ppc /* Previous Program Counter */ +#define REG_PB m377.pb /* Program Bank */ +#define REG_DB m377.db /* Data Bank */ +#define REG_D m377.d /* Direct Register */ +#define FLAG_M m377.flag_m /* Memory/Accumulator Select Flag */ +#define FLAG_X m377.flag_x /* Index Select Flag */ +#define FLAG_N m377.flag_n /* Negative Flag */ +#define FLAG_V m377.flag_v /* Overflow Flag */ +#define FLAG_D m377.flag_d /* Decimal Mode Flag */ +#define FLAG_I m377.flag_i /* Interrupt Mask Flag */ +#define FLAG_Z m377.flag_z /* Zero Flag (inverted) */ +#define FLAG_C m377.flag_c /* Carry Flag */ +#define LINE_IRQ m377.line_irq /* Status of the IRQ line */ +#define REG_IR m377.ir /* Instruction Register */ +#define REG_IM m377.im /* Immediate load value */ +#define REG_IM2 m377.im2 /* Immediate load target */ +#define REG_IM3 m377.im3 /* Immediate load target */ +#define REG_IM4 m377.im4 /* Immediate load target */ +#define INT_ACK m377.int_ack /* Interrupt Acknowledge function pointer */ +#define CLOCKS m377.ICount /* Clock cycles remaining */ +#define IRQ_DELAY m377.irq_delay /* Delay 1 instruction before checking IRQ */ +#define CPU_STOPPED m377.stopped /* Stopped status of the CPU */ + +#define FTABLE_GET_REG m_get_reg +#define FTABLE_SET_REG m_set_reg +#define FTABLE_SET_LINE m_set_line + +#define SRC m377.source /* Source Operand */ +#define DST m377.destination /* Destination Operand */ + +#define STOP_LEVEL_WAI 1 +#define STOP_LEVEL_STOP 2 + +#define EXECUTION_MODE_M0X0 0 +#define EXECUTION_MODE_M0X1 1 +#define EXECUTION_MODE_M1X0 2 +#define EXECUTION_MODE_M1X1 3 + + +/* ======================================================================== */ +/* ================================= CLOCK ================================ */ +/* ======================================================================== */ + +#define CLK_OP 1 +#define CLK_R8 1 +#define CLK_R16 2 +#define CLK_R24 3 +#define CLK_W8 1 +#define CLK_W16 2 +#define CLK_W24 3 +#define CLK_RMW8 3 +#define CLK_RMW16 5 + +#define CLK_IMPLIED 1 +#define CLK_IMPLIED 1 +#define CLK_RELATIVE_8 1 +#define CLK_RELATIVE_16 2 +#define CLK_IMM 0 +#define CLK_AI 4 +#define CLK_AXI 4 +#define CLK_A 2 +#define CLK_AL 3 +#define CLK_ALX 3 +#define CLK_AX 2 +#define CLK_AY 2 +#define CLK_D 1 +#define CLK_DI 3 +#define CLK_DIY 3 +#define CLK_DLI 4 +#define CLK_DLIY 4 +#define CLK_DX 2 +#define CLK_DXI 4 +#define CLK_DY 2 +#define CLK_S 2 +#define CLK_SIY 5 + +/* AX and AY addressing modes take 1 extra cycle when writing */ +#define CLK_W_IMM 0 +#define CLK_W_AI 4 +#define CLK_W_AXI 4 +#define CLK_W_A 2 +#define CLK_W_AL 3 +#define CLK_W_ALX 3 +#define CLK_W_AX 3 +#define CLK_W_AY 3 +#define CLK_W_D 1 +#define CLK_W_DI 3 +#define CLK_W_DIY 3 +#define CLK_W_DLI 4 +#define CLK_W_DLIY 4 +#define CLK_W_DX 2 +#define CLK_W_DXI 4 +#define CLK_W_DY 2 +#define CLK_W_S 2 +#define CLK_W_SIY 5 + +#define CLK(A) do { CLOCKS -= (A); m37710_clock_timers(A); } while (0) +#define USE_ALL_CLKS() do { m37710_clock_timers(CLOCKS); CLOCKS = 0; } while (0) + + +/* ======================================================================== */ +/* ============================ STATUS REGISTER =========================== */ +/* ======================================================================== */ + +/* Flag positions in Processor Status Register */ +/* common */ +#define FLAGPOS_N BIT_7 /* Negative */ +#define FLAGPOS_V BIT_6 /* Overflow */ +#define FLAGPOS_D BIT_3 /* Decimal Mode */ +#define FLAGPOS_I BIT_2 /* Interrupt Mask */ +#define FLAGPOS_Z BIT_1 /* Zero */ +#define FLAGPOS_C BIT_0 /* Carry */ +/* emulation */ +#define FLAGPOS_R BIT_5 /* Reserved */ +#define FLAGPOS_B BIT_4 /* BRK Instruction */ +/* native */ +#define FLAGPOS_M BIT_5 /* Mem/Reg Select */ +#define FLAGPOS_X BIT_4 /* Index Select */ + +#define EFLAG_SET 1 +#define EFLAG_CLEAR 0 +#define MFLAG_SET FLAGPOS_M +#define MFLAG_CLEAR 0 +#define XFLAG_SET FLAGPOS_X +#define XFLAG_CLEAR 0 +#define NFLAG_SET 0x80 +#define NFLAG_CLEAR 0 +#define VFLAG_SET 0x80 +#define VFLAG_CLEAR 0 +#define DFLAG_SET FLAGPOS_D +#define DFLAG_CLEAR 0 +#define IFLAG_SET FLAGPOS_I +#define IFLAG_CLEAR 0 +#define BFLAG_SET FLAGPOS_B +#define BFLAG_CLEAR 0 +#define ZFLAG_SET 0 +#define ZFLAG_CLEAR 1 +#define CFLAG_SET 0x100 +#define CFLAG_CLEAR 0 + +/* Codition code tests */ +#define COND_CC() (!(FLAG_C&0x100)) /* Carry Clear */ +#define COND_CS() (FLAG_C&0x100) /* Carry Set */ +#define COND_EQ() (!FLAG_Z) /* Equal */ +#define COND_NE() FLAG_Z /* Not Equal */ +#define COND_MI() (FLAG_N&0x80) /* Minus */ +#define COND_PL() (!(FLAG_N&0x80)) /* Plus */ +#define COND_VC() (!(FLAG_V&0x80)) /* Overflow Clear */ +#define COND_VS() (FLAG_V&0x80) /* Overflow Set */ + +/* Set Overflow flag in math operations */ +#define VFLAG_ADD_8(S, D, R) ((S^R) & (D^R)) +#define VFLAG_ADD_16(S, D, R) (((S^R) & (D^R))>>8) +#define VFLAG_SUB_8(S, D, R) ((S^D) & (R^D)) +#define VFLAG_SUB_16(S, D, R) (((S^D) & (R^D))>>8) + +#define CFLAG_8(A) (A) +#define CFLAG_16(A) ((A)>>8) +#define NFLAG_8(A) (A) +#define NFLAG_16(A) ((A)>>8) + +#define CFLAG_AS_1() ((FLAG_C>>8)&1) + +/* ======================================================================== */ +/* ========================== EFFECTIVE ADDRESSES ========================= */ +/* ======================================================================== */ + +/* Effective-address based memory access macros */ +#define read_8_NORM(A) m37710i_read_8_normal(A) +#define read_8_IMM(A) m37710i_read_8_immediate(A) +#define read_8_D(A) m37710i_read_8_direct(A) +#define read_8_A(A) m37710i_read_8_normal(A) +#define read_8_AL(A) m37710i_read_8_normal(A) +#define read_8_DX(A) m37710i_read_8_direct(A) +#define read_8_DY(A) m37710i_read_8_direct(A) +#define read_8_AX(A) m37710i_read_8_normal(A) +#define read_8_ALX(A) m37710i_read_8_normal(A) +#define read_8_AY(A) m37710i_read_8_normal(A) +#define read_8_DI(A) m37710i_read_8_normal(A) +#define read_8_DLI(A) m37710i_read_8_normal(A) +#define read_8_AI(A) m37710i_read_8_normal(A) +#define read_8_ALI(A) m37710i_read_8_normal(A) +#define read_8_DXI(A) m37710i_read_8_normal(A) +#define read_8_DIY(A) m37710i_read_8_normal(A) +#define read_8_DLIY(A) m37710i_read_8_normal(A) +#define read_8_AXI(A) m37710i_read_8_normal(A) +#define read_8_S(A) m37710i_read_8_normal(A) +#define read_8_SIY(A) m37710i_read_8_normal(A) + +#define read_16_NORM(A) m37710i_read_16_normal(A) +#define read_16_IMM(A) m37710i_read_16_immediate(A) +#define read_16_D(A) m37710i_read_16_direct(A) +#define read_16_A(A) m37710i_read_16_normal(A) +#define read_16_AL(A) m37710i_read_16_normal(A) +#define read_16_DX(A) m37710i_read_16_direct(A) +#define read_16_DY(A) m37710i_read_16_direct(A) +#define read_16_AX(A) m37710i_read_16_normal(A) +#define read_16_ALX(A) m37710i_read_16_normal(A) +#define read_16_AY(A) m37710i_read_16_normal(A) +#define read_16_DI(A) m37710i_read_16_normal(A) +#define read_16_DLI(A) m37710i_read_16_normal(A) +#define read_16_AI(A) m37710i_read_16_normal(A) +#define read_16_ALI(A) m37710i_read_16_normal(A) +#define read_16_DXI(A) m37710i_read_16_normal(A) +#define read_16_DIY(A) m37710i_read_16_normal(A) +#define read_16_DLIY(A) m37710i_read_16_normal(A) +#define read_16_AXI(A) m37710i_read_16_normal(A) +#define read_16_S(A) m37710i_read_16_normal(A) +#define read_16_SIY(A) m37710i_read_16_normal(A) + +#define read_24_NORM(A) m37710i_read_24_normal(A) +#define read_24_IMM(A) m37710i_read_24_immediate(A) +#define read_24_D(A) m37710i_read_24_direct(A) +#define read_24_A(A) m37710i_read_24_normal(A) +#define read_24_AL(A) m37710i_read_24_normal(A) +#define read_24_DX(A) m37710i_read_24_direct(A) +#define read_24_DY(A) m37710i_read_24_direct(A) +#define read_24_AX(A) m37710i_read_24_normal(A) +#define read_24_ALX(A) m37710i_read_24_normal(A) +#define read_24_AY(A) m37710i_read_24_normal(A) +#define read_24_DI(A) m37710i_read_24_normal(A) +#define read_24_DLI(A) m37710i_read_24_normal(A) +#define read_24_AI(A) m37710i_read_24_normal(A) +#define read_24_ALI(A) m37710i_read_24_normal(A) +#define read_24_DXI(A) m37710i_read_24_normal(A) +#define read_24_DIY(A) m37710i_read_24_normal(A) +#define read_24_DLIY(A) m37710i_read_24_normal(A) +#define read_24_AXI(A) m37710i_read_24_normal(A) +#define read_24_S(A) m37710i_read_24_normal(A) +#define read_24_SIY(A) m37710i_read_24_normal(A) + +#define write_8_NORM(A, V) m37710i_write_8_normal(A, V) +#define write_8_D(A, V) m37710i_write_8_direct(A, V) +#define write_8_A(A, V) m37710i_write_8_normal(A, V) +#define write_8_AL(A, V) m37710i_write_8_normal(A, V) +#define write_8_DX(A, V) m37710i_write_8_direct(A, V) +#define write_8_DY(A, V) m37710i_write_8_direct(A, V) +#define write_8_AX(A, V) m37710i_write_8_normal(A, V) +#define write_8_ALX(A, V) m37710i_write_8_normal(A, V) +#define write_8_AY(A, V) m37710i_write_8_normal(A, V) +#define write_8_DI(A, V) m37710i_write_8_normal(A, V) +#define write_8_DLI(A, V) m37710i_write_8_normal(A, V) +#define write_8_AI(A, V) m37710i_write_8_normal(A, V) +#define write_8_ALI(A, V) m37710i_write_8_normal(A, V) +#define write_8_DXI(A, V) m37710i_write_8_normal(A, V) +#define write_8_DIY(A, V) m37710i_write_8_normal(A, V) +#define write_8_DLIY(A, V) m37710i_write_8_normal(A, V) +#define write_8_AXI(A, V) m37710i_write_8_normal(A, V) +#define write_8_S(A, V) m37710i_write_8_normal(A, V) +#define write_8_SIY(A, V) m37710i_write_8_normal(A, V) + +#define write_16_NORM(A, V) m37710i_write_16_normal(A, V) +#define write_16_D(A, V) m37710i_write_16_direct(A, V) +#define write_16_A(A, V) m37710i_write_16_normal(A, V) +#define write_16_AL(A, V) m37710i_write_16_normal(A, V) +#define write_16_DX(A, V) m37710i_write_16_direct(A, V) +#define write_16_DY(A, V) m37710i_write_16_direct(A, V) +#define write_16_AX(A, V) m37710i_write_16_normal(A, V) +#define write_16_ALX(A, V) m37710i_write_16_normal(A, V) +#define write_16_AY(A, V) m37710i_write_16_normal(A, V) +#define write_16_DI(A, V) m37710i_write_16_normal(A, V) +#define write_16_DLI(A, V) m37710i_write_16_normal(A, V) +#define write_16_AI(A, V) m37710i_write_16_normal(A, V) +#define write_16_ALI(A, V) m37710i_write_16_normal(A, V) +#define write_16_DXI(A, V) m37710i_write_16_normal(A, V) +#define write_16_DIY(A, V) m37710i_write_16_normal(A, V) +#define write_16_DLIY(A, V) m37710i_write_16_normal(A, V) +#define write_16_AXI(A, V) m37710i_write_16_normal(A, V) +#define write_16_S(A, V) m37710i_write_16_normal(A, V) +#define write_16_SIY(A, V) m37710i_write_16_normal(A, V) + + +#define OPER_8_IMM() read_8_IMM(EA_IMM8()) +#define OPER_8_D() read_8_D(EA_D()) +#define OPER_8_A() read_8_A(EA_A()) +#define OPER_8_AL() read_8_AL(EA_AL()) +#define OPER_8_DX() read_8_DX(EA_DX()) +#define OPER_8_DY() read_8_DY(EA_DY()) +#define OPER_8_AX() read_8_AX(EA_AX()) +#define OPER_8_ALX() read_8_ALX(EA_ALX()) +#define OPER_8_AY() read_8_AY(EA_AY()) +#define OPER_8_DI() read_8_DI(EA_DI()) +#define OPER_8_DLI() read_8_DLI(EA_DLI()) +#define OPER_8_AI() read_8_AI(EA_AI()) +#define OPER_8_ALI() read_8_ALI(EA_ALI()) +#define OPER_8_DXI() read_8_DXI(EA_DXI()) +#define OPER_8_DIY() read_8_DIY(EA_DIY()) +#define OPER_8_DLIY() read_8_DLIY(EA_DLIY()) +#define OPER_8_AXI() read_8_AXI(EA_AXI()) +#define OPER_8_S() read_8_S(EA_S()) +#define OPER_8_SIY() read_8_SIY(EA_SIY()) + +#define OPER_16_IMM() read_16_IMM(EA_IMM16()) +#define OPER_16_D() read_16_D(EA_D()) +#define OPER_16_A() read_16_A(EA_A()) +#define OPER_16_AL() read_16_AL(EA_AL()) +#define OPER_16_DX() read_16_DX(EA_DX()) +#define OPER_16_DY() read_16_DY(EA_DY()) +#define OPER_16_AX() read_16_AX(EA_AX()) +#define OPER_16_ALX() read_16_ALX(EA_ALX()) +#define OPER_16_AY() read_16_AY(EA_AY()) +#define OPER_16_DI() read_16_DI(EA_DI()) +#define OPER_16_DLI() read_16_DLI(EA_DLI()) +#define OPER_16_AI() read_16_AI(EA_AI()) +#define OPER_16_ALI() read_16_ALI(EA_ALI()) +#define OPER_16_DXI() read_16_DXI(EA_DXI()) +#define OPER_16_DIY() read_16_DIY(EA_DIY()) +#define OPER_16_DLIY() read_16_DLIY(EA_DLIY()) +#define OPER_16_AXI() read_16_AXI(EA_AXI()) +#define OPER_16_S() read_16_S(EA_S()) +#define OPER_16_SIY() read_16_SIY(EA_SIY()) + +#define OPER_24_IMM() read_24_IMM(EA_IMM24()) +#define OPER_24_D() read_24_D(EA_D()) +#define OPER_24_A() read_24_A(EA_A()) +#define OPER_24_AL() read_24_AL(EA_AL()) +#define OPER_24_DX() read_24_DX(EA_DX()) +#define OPER_24_DY() read_24_DY(EA_DY()) +#define OPER_24_AX() read_24_AX(EA_AX()) +#define OPER_24_ALX() read_24_ALX(EA_ALX()) +#define OPER_24_AY() read_24_AY(EA_AY()) +#define OPER_24_DI() read_24_DI(EA_DI()) +#define OPER_24_DLI() read_24_DLI(EA_DLI()) +#define OPER_24_AI() read_24_AI(EA_AI()) +#define OPER_24_ALI() read_24_ALI(EA_ALI()) +#define OPER_24_DXI() read_24_DXI(EA_DXI()) +#define OPER_24_DIY() read_24_DIY(EA_DIY()) +#define OPER_24_DLIY() read_24_DLIY(EA_DLIY()) +#define OPER_24_AXI() read_24_AXI(EA_AXI()) +#define OPER_24_S() read_24_S(EA_S()) +#define OPER_24_SIY() read_24_SIY(EA_SIY()) + +/* ======================================================================== */ +/* ================================== CPU ================================= */ +/* ======================================================================== */ +#endif /* __M37710CM_H__ */ diff --git a/src/cpu/m377/m37710il.h b/src/cpu/m377/m37710il.h new file mode 100644 index 000000000..634cf4e16 --- /dev/null +++ b/src/cpu/m377/m37710il.h @@ -0,0 +1,206 @@ +#pragma once + +#ifndef __M37710IL_H__ +#define __M37710IL_H__ + + +/* ======================================================================== */ +/* ================================= MEMORY =============================== */ +/* ======================================================================== */ + +inline UINT32 m37710i_read_8_normal(UINT32 address) +{ + return m37710_read_8(address); +} + +inline UINT32 m37710i_read_8_immediate(UINT32 address) +{ + return m37710_read_8_immediate(address); +} + +inline UINT32 m37710i_read_8_direct(UINT32 address) +{ + return m37710_read_8(address); +} + +inline void m37710i_write_8_normal(UINT32 address, UINT32 value) +{ + m37710_write_8(address, value); +} + +inline void m37710i_write_8_direct(UINT32 address, UINT32 value) +{ + m37710_write_8(address, value); +} + +inline UINT32 m37710i_read_16_normal(UINT32 address) +{ + return m37710_read_16(address); +} + +inline UINT32 m37710i_read_16_immediate(UINT32 address) +{ + if (address & 1) + return m37710_read_8_immediate(address) | (m37710_read_8_immediate(address+1)<<8); + else + return m37710_read_16_immediate(address); +} + +inline UINT32 m37710i_read_16_direct(UINT32 address) +{ + return m37710_read_16(address); +} + +inline void m37710i_write_16_normal(UINT32 address, UINT32 value) +{ + m37710_write_16(address, value); +} + +inline void m37710i_write_16_direct(UINT32 address, UINT32 value) +{ + m37710_write_16(address, value); +} + +inline UINT32 m37710i_read_24_normal(UINT32 address) +{ + if (address & 1) + return m37710_read_8(address) | (m37710_read_16(address+1)<<8); + else + return m37710_read_16(address) | (m37710_read_8(address+2)<<16); +} + +inline UINT32 m37710i_read_24_immediate(UINT32 address) +{ + if (address & 1) + return m37710_read_8_immediate(address) | (m37710_read_16_immediate(address+1)<<8); + else + return m37710_read_16_immediate(address) | (m37710_read_8_immediate(address+2)<<16); +} + +inline UINT32 m37710i_read_24_direct(UINT32 address) +{ + if (address & 1) + return m37710_read_8(address) | (m37710_read_16(address+1)<<8); + else + return m37710_read_16(address) | (m37710_read_8(address+2)<<16); +} + + +/* ======================================================================== */ +/* ================================= STACK ================================ */ +/* ======================================================================== */ + +inline void m37710i_push_8(UINT32 value) +{ + m37710_write_8(REG_S, value); + REG_S = MAKE_UINT_16(REG_S-1); +} + +inline UINT32 m37710i_pull_8() +{ + REG_S = MAKE_UINT_16(REG_S+1); + return m37710_read_8(REG_S); +} + +inline void m37710i_push_16(UINT32 value) +{ + m37710i_push_8(value>>8); + m37710i_push_8(value); +} + +inline UINT32 m37710i_pull_16() +{ + UINT32 res = m37710i_pull_8(); + return res | (m37710i_pull_8() << 8); +} + +inline void m37710i_push_24(UINT32 value) +{ + m37710i_push_8(value>>16); + m37710i_push_8((value>>8)); + m37710i_push_8(value); +} + +inline UINT32 m37710i_pull_24() +{ + UINT32 res = m37710i_pull_8(); + res |= m37710i_pull_8() << 8; + return res | (m37710i_pull_8() << 16); +} + + +/* ======================================================================== */ +/* ============================ PROGRAM COUNTER =========================== */ +/* ======================================================================== */ + +inline void m37710i_jump_16(UINT32 address) +{ + REG_PC = MAKE_UINT_16(address); +} + +inline void m37710i_jump_24(UINT32 address) +{ + REG_PB = address&0xff0000; + REG_PC = MAKE_UINT_16(address); +} + +inline void m37710i_branch_8(UINT32 offset) +{ + REG_PC = MAKE_UINT_16(REG_PC + MAKE_INT_8(offset)); +} + +inline void m37710i_branch_16(UINT32 offset) +{ + REG_PC = MAKE_UINT_16(REG_PC + offset); +} + + +/* ======================================================================== */ +/* ============================ STATUS REGISTER =========================== */ +/* ======================================================================== */ + +inline UINT32 m37710i_get_reg_p() +{ + return (FLAG_N&0x80) | + ((FLAG_V>>1)&0x40) | + FLAG_M | + FLAG_X | + FLAG_D | + FLAG_I | + ((!FLAG_Z)<<1) | + ((FLAG_C>>8)&1); +} + +inline void m37710i_set_reg_ipl(UINT32 value) +{ + m377.ipl = value & 7; +} + + +/* ======================================================================== */ +/* ============================= ADDRESS MODES ============================ */ +/* ======================================================================== */ + +inline UINT32 EA_IMM8() {REG_PC += 1; return REG_PB | MAKE_UINT_16(REG_PC-1);} +inline UINT32 EA_IMM16() {REG_PC += 2; return REG_PB | MAKE_UINT_16(REG_PC-2);} +inline UINT32 EA_IMM24() {REG_PC += 3; return REG_PB | MAKE_UINT_16(REG_PC-3);} +inline UINT32 EA_D() {if(MAKE_UINT_8(REG_D)) CLK(1); return MAKE_UINT_16(REG_D + OPER_8_IMM());} +inline UINT32 EA_A() {return REG_DB | OPER_16_IMM();} +inline UINT32 EA_AL() {return OPER_24_IMM();} +inline UINT32 EA_DX() {return MAKE_UINT_16(REG_D + OPER_8_IMM() + REG_X);} +inline UINT32 EA_DY() {return MAKE_UINT_16(REG_D + OPER_8_IMM() + REG_Y);} +inline UINT32 EA_AX() {UINT32 tmp = EA_A(); if((tmp^(tmp+REG_X))&0xff00) CLK(1); return tmp + REG_X;} +inline UINT32 EA_ALX() {return EA_AL() + REG_X;} +inline UINT32 EA_AY() {UINT32 tmp = EA_A(); if((tmp^(tmp+REG_X))&0xff00) CLK(1); return tmp + REG_Y;} +inline UINT32 EA_DI() {return REG_DB | OPER_16_D();} +inline UINT32 EA_DLI() {return OPER_24_D();} +inline UINT32 EA_AI() {return read_16_A(OPER_16_IMM());} +inline UINT32 EA_ALI() {return OPER_24_A();} +inline UINT32 EA_DXI() {return REG_DB | OPER_16_DX();} +inline UINT32 EA_DIY() {UINT32 tmp = REG_DB | OPER_16_D(); if((tmp^(tmp+REG_X))&0xff00) CLK(1); return tmp + REG_Y;} +inline UINT32 EA_DLIY() {return OPER_24_D() + REG_Y;} +inline UINT32 EA_AXI() {return read_16_AXI(MAKE_UINT_16(OPER_16_IMM() + REG_X));} +inline UINT32 EA_S() {return MAKE_UINT_16(REG_S + OPER_8_IMM());} +inline UINT32 EA_SIY() {return MAKE_UINT_16(read_16_SIY(REG_S + OPER_8_IMM()) + REG_Y) | REG_DB;} + +#endif /* __M37710IL_H__ */ diff --git a/src/cpu/m377/m37710op.h b/src/cpu/m377/m37710op.h new file mode 100644 index 000000000..ea52c9853 --- /dev/null +++ b/src/cpu/m377/m37710op.h @@ -0,0 +1,2609 @@ +/* ======================================================================== */ +/* ============================= CONFIGURATION ============================ */ +/* ======================================================================== */ + +#undef FLAG_SET_M +#undef FLAG_SET_X +#undef m37710i_set_flag_mx +#undef m37710i_set_reg_p + +#if EXECUTION_MODE == EXECUTION_MODE_M0X0 +#define FLAG_SET_M 0 +#define FLAG_SET_X 0 +#define m37710i_set_flag_mx m37710i_set_flag_m0x0 +#define m37710i_set_reg_p m37710i_set_reg_p_m0x0 +#elif EXECUTION_MODE == EXECUTION_MODE_M0X1 +#define FLAG_SET_M 0 +#define FLAG_SET_X 1 +#define m37710i_set_flag_mx m37710i_set_flag_m0x1 +#define m37710i_set_reg_p m37710i_set_reg_p_m0x1 +#elif EXECUTION_MODE == EXECUTION_MODE_M1X0 +#define FLAG_SET_M 1 +#define FLAG_SET_X 0 +#define m37710i_set_flag_mx m37710i_set_flag_m1x0 +#define m37710i_set_reg_p m37710i_set_reg_p_m1x0 +#elif EXECUTION_MODE == EXECUTION_MODE_M1X1 +#define FLAG_SET_M 1 +#define FLAG_SET_X 1 +#define m37710i_set_flag_mx m37710i_set_flag_m1x1 +#define m37710i_set_reg_p m37710i_set_reg_p_m1x1 +#endif + +/* ======================================================================== */ +/* ============================ STATUS REGISTER =========================== */ +/* ======================================================================== */ + +/* note: difference from 65816. when switching to 8-bit X/Y, X and Y are *not* truncated + to 8 bits! */ + +void m37710i_set_flag_mx(UINT32 value) +{ +#if FLAG_SET_M + if(!(value & FLAGPOS_M)) + { + REG_A |= REG_B; + REG_B = 0; + REG_BA |= REG_BB; + REG_BB = 0; + FLAG_M = MFLAG_CLEAR; + } +#else + if(value & FLAGPOS_M) + { + REG_B = REG_A & 0xff00; + REG_A = MAKE_UINT_8(REG_A); + REG_BB = REG_BA & 0xff00; + REG_BA = MAKE_UINT_8(REG_BA); + FLAG_M = MFLAG_SET; + } +#endif +#if FLAG_SET_X + if(!(value & FLAGPOS_X)) + { + REG_X |= REG_XH; + REG_XH = 0; + REG_Y |= REG_YH; + REG_YH = 0; + FLAG_X = XFLAG_CLEAR; + } +#else + if(value & FLAGPOS_X) + { + REG_XH = REG_X & 0xff00; + REG_X = MAKE_UINT_8(REG_X); + REG_YH = REG_Y & 0xff00; + REG_Y = MAKE_UINT_8(REG_Y); + FLAG_X = XFLAG_SET; + } +#endif + m37710i_set_execution_mode((FLAG_M>>4) | (FLAG_X>>4)); +} + + +void m37710i_set_reg_p(UINT32 value) +{ + FLAG_N = value; + FLAG_V = value << 1; + FLAG_D = value & FLAGPOS_D; + FLAG_Z = !(value & FLAGPOS_Z); + FLAG_C = value << 8; + m37710i_set_flag_mx(value); + FLAG_I = value & FLAGPOS_I; +} + + +/* ======================================================================== */ +/* =========================== OPERATION MACROS =========================== */ +/* ======================================================================== */ + +/* M37710 Push all */ +#undef OP_PSH + +#if FLAG_SET_M +#if FLAG_SET_X +#define OP_PSH(MODE) \ + SRC = OPER_8_##MODE(); \ + CLK(12); \ + if (SRC&0x1) \ + { m37710i_push_8(REG_A); CLK(2); } \ + if (SRC&0x2) \ + { m37710i_push_8(REG_BA); CLK(2); } \ + if (SRC&0x4) \ + { m37710i_push_8(REG_X); CLK(2); } \ + if (SRC&0x8) \ + { m37710i_push_8(REG_Y); CLK(2); } \ + if (SRC&0x10) \ + { m37710i_push_16(REG_D); CLK(2); } \ + if (SRC&0x20) \ + { m37710i_push_8(REG_DB>>16); CLK(1); } \ + if (SRC&0x40) \ + { m37710i_push_8(REG_PB>>16); CLK(1); } \ + if (SRC&0x80) \ + { m37710i_push_8(m377.ipl); m37710i_push_8(m37710i_get_reg_p()); CLK(2); } +#else // FLAG_SET_X +#define OP_PSH(MODE) \ + SRC = OPER_8_##MODE(); \ + CLK(12); \ + if (SRC&0x1) \ + { m37710i_push_8(REG_A); CLK(2); } \ + if (SRC&0x2) \ + { m37710i_push_8(REG_BA); CLK(2); } \ + if (SRC&0x4) \ + { m37710i_push_16(REG_X); CLK(2); } \ + if (SRC&0x8) \ + { m37710i_push_16(REG_Y); CLK(2); } \ + if (SRC&0x10) \ + { m37710i_push_16(REG_D); CLK(2); } \ + if (SRC&0x20) \ + { m37710i_push_8(REG_DB>>16); CLK(1); } \ + if (SRC&0x40) \ + { m37710i_push_8(REG_PB>>16); CLK(1); } \ + if (SRC&0x80) \ + { m37710i_push_8(m377.ipl); m37710i_push_8(m37710i_get_reg_p()); CLK(2); } +#endif // FLAG_SET_X +#else // FLAG_SET_M +#if FLAG_SET_X +#define OP_PSH(MODE) \ + SRC = OPER_8_##MODE(); \ + CLK(12); \ + if (SRC&0x1) \ + { m37710i_push_16(REG_A); CLK(2); } \ + if (SRC&0x2) \ + { m37710i_push_16(REG_BA); CLK(2); } \ + if (SRC&0x4) \ + { m37710i_push_8(REG_X); CLK(2); } \ + if (SRC&0x8) \ + { m37710i_push_8(REG_Y); CLK(2); } \ + if (SRC&0x10) \ + { m37710i_push_16(REG_D); CLK(2); } \ + if (SRC&0x20) \ + { m37710i_push_8(REG_DB>>16); CLK(1); } \ + if (SRC&0x40) \ + { m37710i_push_8(REG_PB>>16); CLK(1); } \ + if (SRC&0x80) \ + { m37710i_push_8(m377.ipl); m37710i_push_8(m37710i_get_reg_p()); CLK(2); } +#else // FLAG_SET_X +#define OP_PSH(MODE) \ + SRC = OPER_8_##MODE(); \ + CLK(12); \ + if (SRC&0x1) \ + { m37710i_push_16(REG_A); CLK(2); } \ + if (SRC&0x2) \ + { m37710i_push_16(REG_BA); CLK(2);} \ + if (SRC&0x4) \ + { m37710i_push_16(REG_X); CLK(2); } \ + if (SRC&0x8) \ + { m37710i_push_16(REG_Y); CLK(2); } \ + if (SRC&0x10) \ + { m37710i_push_16(REG_D); CLK(2); } \ + if (SRC&0x20) \ + { m37710i_push_8(REG_DB>>16); CLK(1); } \ + if (SRC&0x40) \ + { m37710i_push_8(REG_PB>>16); CLK(1); } \ + if (SRC&0x80) \ + { m37710i_push_8(m377.ipl); m37710i_push_8(m37710i_get_reg_p()); CLK(2); } +#endif // FLAG_SET_X +#endif // FLAG_SET_M + +/* M37710 Pull all */ +/* Unusual behavior: bit 6 has no effect */ +#undef OP_PUL +#define OP_PUL(MODE) \ + SRC = OPER_8_##MODE(); \ + CLK(14); \ + if (SRC&0x80) \ + { m37710i_set_reg_p(m37710i_pull_8()); m37710i_set_reg_ipl(m37710i_pull_8()); CLK(3); } \ + if (SRC&0x20) \ + { REG_DB = m37710i_pull_8() << 16; CLK(3); } \ + if (SRC&0x10) \ + { REG_D = m37710i_pull_16(); CLK(4); } \ + if (m37710i_get_reg_p() & XFLAG_SET) \ + { \ + if (SRC&0x8) \ + { REG_Y = m37710i_pull_8(); CLK(3); } \ + if (SRC&0x4) \ + { REG_X = m37710i_pull_8(); CLK(3); } \ + } \ + else \ + { \ + if (SRC&0x8) \ + { REG_Y = m37710i_pull_16(); CLK(3); } \ + if (SRC&0x4) \ + { REG_X = m37710i_pull_16(); CLK(3); } \ + } \ + if (m37710i_get_reg_p() & MFLAG_SET) \ + { \ + if (SRC&0x2) \ + { REG_BA = m37710i_pull_8(); CLK(3); } \ + if (SRC&0x1) \ + { REG_A = m37710i_pull_8(); CLK(3); } \ + } \ + else \ + { \ + if (SRC&0x2) \ + { REG_BA = m37710i_pull_16(); CLK(3); } \ + if (SRC&0x1) \ + { REG_A = m37710i_pull_16(); CLK(3); } \ + } \ + m37710i_update_irqs() + +/* M37710 Multiply */ +#undef OP_MPY +#if FLAG_SET_M +#define OP_MPY(MODE) \ + CLK(CLK_OP + CLK_R8 + CLK_##MODE + 14); \ + SRC = OPER_8_##MODE(); \ + { UINT16 temp = SRC * (REG_A&0xff); REG_A = temp & 0xff; REG_BA = (temp>>8)&0xff; FLAG_Z = temp; FLAG_N = (temp & 0x8000) ? 1 : 0; FLAG_C = 0; } +#else +#define OP_MPY(MODE) \ + CLK(CLK_OP + CLK_R16 + CLK_##MODE + 14+8); \ + SRC = OPER_16_##MODE(); \ + { UINT32 temp = SRC * REG_A; REG_A = temp & 0xffff; REG_BA = (temp>>16)&0xffff; FLAG_Z = temp; FLAG_N = (temp & 0x80000000) ? 1 : 0; FLAG_C = 0; } +#endif + +/* M37710 Divide */ +#undef OP_DIV +#if FLAG_SET_M +#define OP_DIV(MODE) \ + CLK(CLK_OP + CLK_R8 + CLK_##MODE + 17); \ + SRC = (REG_BA&0xff)<<8 | (REG_A & 0xff); \ + DST = OPER_8_##MODE(); \ + if (DST != 0) \ + { \ + UINT16 tempa = SRC / DST; UINT16 tempb = SRC % DST; \ + FLAG_V = ((tempa | tempb) & 0xff00) ? VFLAG_SET : 0; \ + FLAG_C = FLAG_V ? CFLAG_SET : 0; \ + if (!FLAG_V) { FLAG_N = (tempa & 0x80) ? 1 : 0; } \ + FLAG_Z = REG_A = tempa & 0xff; REG_BA = tempb & 0xff; \ + CLK(8); \ + } else m37710i_interrupt_software(0xfffc) +#else +#define OP_DIV(MODE) \ + CLK(CLK_OP + CLK_R16 + CLK_##MODE + 17); \ + SRC = (REG_BA<<16) | REG_A; \ + DST = OPER_16_##MODE(); \ + if (DST != 0) \ + { \ + UINT32 tempa = SRC / DST; UINT32 tempb = SRC % DST; \ + FLAG_V = ((tempa | tempb) & 0xffff0000) ? VFLAG_SET : 0; \ + FLAG_C = FLAG_V ? CFLAG_SET : 0; \ + if (!FLAG_V) { FLAG_N = (tempa & 0x8000) ? 1 : 0; } \ + FLAG_Z = REG_A = tempa & 0xffff; REG_BA = tempb & 0xffff; \ + CLK(8+15); \ + } else m37710i_interrupt_software(0xfffc) +#endif + +/* M37710 Add With Carry */ +#undef OP_ADC +#if FLAG_SET_M +#define OP_ADC(MODE) \ + CLK(CLK_OP + CLK_R8 + CLK_##MODE); \ + SRC = OPER_8_##MODE(); \ + FLAG_C = REG_A + SRC + CFLAG_AS_1(); \ + if(FLAG_D) \ + { \ + if((FLAG_C & 0xf) > 9) \ + FLAG_C+=6; \ + if((FLAG_C & 0xf0) > 0x90) \ + FLAG_C+=0x60; \ + } \ + FLAG_V = VFLAG_ADD_8(SRC, REG_A, FLAG_C); \ + FLAG_N = FLAG_Z = REG_A = MAKE_UINT_8(FLAG_C) +#else +#define OP_ADC(MODE) \ + CLK(CLK_OP + CLK_R16 + CLK_##MODE); \ + SRC = OPER_16_##MODE(); \ + if(!FLAG_D) \ + { \ + FLAG_C = REG_A + SRC + CFLAG_AS_1(); \ + FLAG_V = VFLAG_ADD_16(SRC, REG_A, FLAG_C); \ + FLAG_Z = REG_A = MAKE_UINT_16(FLAG_C); \ + FLAG_N = NFLAG_16(REG_A); \ + FLAG_C = CFLAG_16(FLAG_C); \ + BREAKOUT; \ + } \ + FLAG_C = MAKE_UINT_8(REG_A) + MAKE_UINT_8(SRC) + CFLAG_AS_1(); \ + if((FLAG_C & 0xf) > 9) \ + FLAG_C+=6; \ + if((FLAG_C & 0xf0) > 0x90) \ + FLAG_C+=0x60; \ + FLAG_Z = MAKE_UINT_8(FLAG_C); \ + \ + FLAG_C = MAKE_UINT_8(REG_A>>8) + MAKE_UINT_8(SRC>>8) + CFLAG_AS_1(); \ + if((FLAG_C & 0xf) > 9) \ + FLAG_C+=6; \ + if((FLAG_C & 0xf0) > 0x90) \ + FLAG_C+=0x60; \ + FLAG_Z |= MAKE_UINT_8(FLAG_C) << 8; \ + FLAG_N = NFLAG_16(FLAG_Z); \ + FLAG_V = VFLAG_ADD_16(SRC, REG_A, FLAG_C); \ + REG_A = FLAG_Z +#endif + +/* M37710 Add With Carry - B accumulator*/ +#undef OP_ADCB +#if FLAG_SET_M +#define OP_ADCB(MODE) \ + CLK(CLK_OP + CLK_R8 + CLK_##MODE); \ + SRC = OPER_8_##MODE(); \ + FLAG_C = REG_BA + SRC + CFLAG_AS_1(); \ + if(FLAG_D) \ + { \ + if((FLAG_C & 0xf) > 9) \ + FLAG_C+=6; \ + if((FLAG_C & 0xf0) > 0x90) \ + FLAG_C+=0x60; \ + } \ + FLAG_V = VFLAG_ADD_8(SRC, REG_BA, FLAG_C); \ + FLAG_N = FLAG_Z = REG_BA = MAKE_UINT_8(FLAG_C) +#else +#define OP_ADCB(MODE) \ + CLK(CLK_OP + CLK_R16 + CLK_##MODE); \ + SRC = OPER_16_##MODE(); \ + if(!FLAG_D) \ + { \ + FLAG_C = REG_BA + SRC + CFLAG_AS_1(); \ + FLAG_V = VFLAG_ADD_16(SRC, REG_BA, FLAG_C); \ + FLAG_Z = REG_BA = MAKE_UINT_16(FLAG_C); \ + FLAG_N = NFLAG_16(REG_BA); \ + FLAG_C = CFLAG_16(FLAG_C); \ + BREAKOUT; \ + } \ + FLAG_C = MAKE_UINT_8(REG_BA) + MAKE_UINT_8(SRC) + CFLAG_AS_1(); \ + if((FLAG_C & 0xf) > 9) \ + FLAG_C+=6; \ + if((FLAG_C & 0xf0) > 0x90) \ + FLAG_C+=0x60; \ + FLAG_Z = MAKE_UINT_8(FLAG_C); \ + \ + FLAG_C = MAKE_UINT_8(REG_BA>>8) + MAKE_UINT_8(SRC>>8) + CFLAG_AS_1(); \ + if((FLAG_C & 0xf) > 9) \ + FLAG_C+=6; \ + if((FLAG_C & 0xf0) > 0x90) \ + FLAG_C+=0x60; \ + FLAG_Z |= MAKE_UINT_8(FLAG_C) << 8; \ + FLAG_N = NFLAG_16(FLAG_Z); \ + FLAG_V = VFLAG_ADD_16(SRC, REG_BA, FLAG_C); \ + REG_BA = FLAG_Z +#endif + +/* M37710 Logical AND with accumulator */ +#undef OP_AND +#if FLAG_SET_M +#define OP_AND(MODE) \ + CLK(CLK_OP + CLK_R8 + CLK_##MODE); \ + FLAG_N = FLAG_Z = REG_A &= OPER_8_##MODE() +#else +#define OP_AND(MODE) \ + CLK(CLK_OP + CLK_R16 + CLK_##MODE); \ + FLAG_Z = REG_A &= OPER_16_##MODE(); \ + FLAG_N = NFLAG_16(REG_A) +#endif + +/* M37710 Logical AND with B accumulator */ +#undef OP_ANDB +#if FLAG_SET_M +#define OP_ANDB(MODE) \ + CLK(CLK_OP + CLK_R8 + CLK_##MODE); \ + FLAG_N = FLAG_Z = REG_BA &= OPER_8_##MODE() +#else +#define OP_ANDB(MODE) \ + CLK(CLK_OP + CLK_R16 + CLK_##MODE); \ + FLAG_Z = REG_BA &= OPER_16_##MODE(); \ + FLAG_N = NFLAG_16(REG_BA) +#endif + +/* M37710 Arithmetic Shift Left accumulator */ +#undef OP_ASL +#if FLAG_SET_M +#define OP_ASL() \ + CLK(CLK_OP + CLK_IMPLIED); \ + FLAG_C = REG_A << 1; \ + FLAG_N = FLAG_Z = REG_A = MAKE_UINT_8(FLAG_C) +#else +#define OP_ASL() \ + CLK(CLK_OP + CLK_IMPLIED); \ + FLAG_C = REG_A << 1; \ + FLAG_Z = REG_A = MAKE_UINT_16(FLAG_C); \ + FLAG_N = NFLAG_16(FLAG_C); \ + FLAG_C = CFLAG_16(FLAG_C) +#endif + +/* M37710 Arithmetic Shift Left B accumulator */ +#undef OP_BSL +#if FLAG_SET_M +#define OP_BSL() \ + CLK(CLK_OP + CLK_IMPLIED); \ + FLAG_C = REG_BA << 1; \ + FLAG_N = FLAG_Z = REG_BA = MAKE_UINT_8(FLAG_C) +#else +#define OP_BSL() \ + CLK(CLK_OP + CLK_IMPLIED); \ + FLAG_C = REG_BA << 1; \ + FLAG_Z = REG_BA = MAKE_UINT_16(FLAG_C); \ + FLAG_N = NFLAG_16(FLAG_C); \ + FLAG_C = CFLAG_16(FLAG_C) +#endif + +/* M37710 Arithmetic Shift Left operand */ +#undef OP_ASLM +#if FLAG_SET_M +#define OP_ASLM(MODE) \ + CLK(CLK_OP + CLK_RMW8 + CLK_W_##MODE); \ + DST = EA_##MODE(); \ + FLAG_C = read_8_##MODE(DST) << 1; \ + FLAG_N = FLAG_Z = MAKE_UINT_8(FLAG_C); \ + write_8_##MODE(DST, FLAG_Z) +#else +#define OP_ASLM(MODE) \ + CLK(CLK_OP + CLK_RMW16 + CLK_W_##MODE); \ + DST = EA_##MODE(); \ + FLAG_C = read_16_##MODE(DST) << 1; \ + FLAG_Z = MAKE_UINT_16(FLAG_C); \ + FLAG_N = NFLAG_16(FLAG_C); \ + FLAG_C = CFLAG_16(FLAG_C); \ + write_16_##MODE(DST, FLAG_Z) +#endif + +/* M37710 Branch on Condition Code */ +#undef OP_BCC +#define OP_BCC(COND) \ + DST = OPER_8_IMM(); \ + if(COND) \ + { \ + CLK(CLK_OP + CLK_RELATIVE_8 + 1); \ + m37710i_branch_8(DST); \ + BREAKOUT; \ + } \ + CLK(CLK_OP + CLK_RELATIVE_8); +/* M37710 Cause a Break interrupt */ +#undef OP_BRK +#define OP_BRK() \ + REG_PC++; CLK(CLK_OP + CLK_R8 + CLK_IMM); \ + logerror("error M37710: BRK at PC=%06x\n", REG_PB|REG_PC); \ + m37710i_interrupt_software(0xfffa) + +/* M37710 Branch Always */ +#undef OP_BRA +#define OP_BRA() \ + CLK(CLK_OP + CLK_IMPLIED + CLK_RELATIVE_8); \ + m37710i_branch_8(OPER_8_IMM()) + +/* M37710 Branch Always Long */ +#undef OP_BRL +#define OP_BRL() \ + CLK(CLK_OP + CLK_IMPLIED + CLK_RELATIVE_16); \ + m37710i_branch_16(OPER_16_IMM()) + +/* M37710 Clear Carry flag */ +#undef OP_CLC +#define OP_CLC() \ + CLK(CLK_OP + CLK_IMPLIED); \ + FLAG_C = CFLAG_CLEAR + +/* M37710 Clear Interrupt Mask flag */ +#undef OP_CLI +#define OP_CLI() \ + CLK(CLK_OP + CLK_IMPLIED); \ + FLAG_I = IFLAG_CLEAR; \ + m37710i_update_irqs() + +/* M37710 Clear oVerflow flag */ +#undef OP_CLV +#define OP_CLV() \ + CLK(CLK_OP + CLK_IMPLIED); \ + FLAG_V = VFLAG_CLEAR + +/* M37710 Compare operand to accumulator */ +/* Unusual behavior: C flag is inverted */ +#undef OP_CMP +#if FLAG_SET_M +#define OP_CMP(MODE) \ + CLK(CLK_OP + CLK_R8 + CLK_##MODE); \ + FLAG_C = REG_A - OPER_8_##MODE(); \ + FLAG_N = FLAG_Z = MAKE_UINT_8(FLAG_C); \ + FLAG_C ^= CFLAG_SET +#else +#define OP_CMP(MODE) \ + CLK(CLK_OP + CLK_R16 + CLK_##MODE); \ + FLAG_C = REG_A - OPER_16_##MODE(); \ + FLAG_Z = MAKE_UINT_16(FLAG_C); \ + FLAG_N = NFLAG_16(FLAG_C); \ + FLAG_C = ~CFLAG_16(FLAG_C) +#endif + +/* M37710 Compare operand to B accumulator */ +/* Unusual behavior: C flag is inverted */ +#undef OP_CMPB +#if FLAG_SET_M +#define OP_CMPB(MODE) \ + CLK(CLK_OP + CLK_R8 + CLK_##MODE); \ + FLAG_C = REG_BA - OPER_8_##MODE(); \ + FLAG_N = FLAG_Z = MAKE_UINT_8(FLAG_C); \ + FLAG_C ^= CFLAG_SET +#else +#define OP_CMPB(MODE) \ + CLK(CLK_OP + CLK_R16 + CLK_##MODE); \ + FLAG_C = REG_BA - OPER_16_##MODE(); \ + FLAG_Z = MAKE_UINT_16(FLAG_C); \ + FLAG_N = NFLAG_16(FLAG_C); \ + FLAG_C = ~CFLAG_16(FLAG_C) +#endif + +/* M37710 Compare operand to index register */ +/* Unusual behavior: C flag is inverted */ +#undef OP_CMPX +#if FLAG_SET_X +#define OP_CMPX(REG, MODE) \ + CLK(CLK_OP + CLK_R8 + CLK_##MODE); \ + FLAG_C = REG - OPER_8_##MODE(); \ + FLAG_N = FLAG_Z = MAKE_UINT_8(FLAG_C); \ + FLAG_C ^= CFLAG_SET +#else +#define OP_CMPX(REG, MODE) \ + CLK(CLK_OP + CLK_R16 + CLK_##MODE); \ + FLAG_C = REG - OPER_16_##MODE(); \ + FLAG_Z = MAKE_UINT_16(FLAG_C); \ + FLAG_N = NFLAG_16(FLAG_C); \ + FLAG_C = ~CFLAG_16(FLAG_C) +#endif + +/* M37710 Decrement accumulator */ +#undef OP_DEC +#if FLAG_SET_M +#define OP_DEC() \ + CLK(CLK_OP + CLK_IMPLIED); \ + FLAG_N = FLAG_Z = REG_A = MAKE_UINT_8(REG_A - 1) +#else +#define OP_DEC() \ + CLK(CLK_OP + CLK_IMPLIED); \ + FLAG_Z = REG_A = MAKE_UINT_16(REG_A - 1); \ + FLAG_N = NFLAG_16(REG_A) +#endif + +/* M37710 Decrement B accumulator */ +#undef OP_DECB +#if FLAG_SET_M +#define OP_DECB() \ + CLK(CLK_OP + CLK_IMPLIED); \ + FLAG_N = FLAG_Z = REG_BA = MAKE_UINT_8(REG_BA - 1) +#else +#define OP_DECB() \ + CLK(CLK_OP + CLK_IMPLIED); \ + FLAG_Z = REG_BA = MAKE_UINT_16(REG_BA - 1); \ + FLAG_N = NFLAG_16(REG_BA) +#endif + +/* M37710 Decrement operand */ +#undef OP_DECM +#if FLAG_SET_M +#define OP_DECM(MODE) \ + CLK(CLK_OP + CLK_RMW8 + CLK_W_##MODE); \ + DST = EA_##MODE(); \ + FLAG_N = FLAG_Z = MAKE_UINT_8(read_8_##MODE(DST) - 1); \ + write_8_##MODE(DST, FLAG_Z) +#else +#define OP_DECM(MODE) \ + CLK(CLK_OP + CLK_RMW16 + CLK_W_##MODE); \ + DST = EA_##MODE(); \ + FLAG_Z = MAKE_UINT_16(read_16_##MODE(DST) - 1); \ + FLAG_N = NFLAG_16(FLAG_Z); \ + write_16_##MODE(DST, FLAG_Z) +#endif + +/* M37710 Decrement index register */ +#undef OP_DECX +#if FLAG_SET_X +#define OP_DECX(REG) \ + CLK(CLK_OP + CLK_IMPLIED); \ + FLAG_N = FLAG_Z = REG = MAKE_UINT_8(REG - 1) +#else +#define OP_DECX(REG) \ + CLK(CLK_OP + CLK_IMPLIED); \ + FLAG_Z = REG = MAKE_UINT_16(REG - 1); \ + FLAG_N = NFLAG_16(REG) +#endif + +/* M37710 Exclusive Or operand to accumulator */ +#undef OP_EOR +#if FLAG_SET_M +#define OP_EOR(MODE) \ + CLK(CLK_OP + CLK_R8 + CLK_##MODE); \ + FLAG_N = FLAG_Z = REG_A ^= OPER_8_##MODE() +#else +#define OP_EOR(MODE) \ + CLK(CLK_OP + CLK_R16 + CLK_##MODE); \ + FLAG_Z = REG_A ^= OPER_16_##MODE(); \ + FLAG_N = NFLAG_16(REG_A) +#endif + +/* M37710 Exclusive Or operand to accumulator B */ +#undef OP_EORB +#if FLAG_SET_M +#define OP_EORB(MODE) \ + CLK(CLK_OP + CLK_R8 + CLK_##MODE); \ + FLAG_N = FLAG_Z = REG_BA ^= OPER_8_##MODE() +#else +#define OP_EORB(MODE) \ + CLK(CLK_OP + CLK_R16 + CLK_##MODE); \ + FLAG_Z = REG_BA ^= OPER_16_##MODE(); \ + FLAG_N = NFLAG_16(REG_BA) +#endif + +/* M37710 Increment accumulator */ +#undef OP_INC +#if FLAG_SET_M +#define OP_INC() \ + CLK(CLK_OP + CLK_IMPLIED); \ + FLAG_N = FLAG_Z = REG_A = MAKE_UINT_8(REG_A + 1) +#else +#define OP_INC() \ + CLK(CLK_OP + CLK_IMPLIED); \ + FLAG_Z = REG_A = MAKE_UINT_16(REG_A + 1); \ + FLAG_N = NFLAG_16(REG_A) +#endif + +/* M37710 Increment B accumulator */ +#undef OP_INCB +#if FLAG_SET_M +#define OP_INCB() \ + CLK(CLK_OP + CLK_IMPLIED); \ + FLAG_N = FLAG_Z = REG_BA = MAKE_UINT_8(REG_BA + 1) +#else +#define OP_INCB() \ + CLK(CLK_OP + CLK_IMPLIED); \ + FLAG_Z = REG_BA = MAKE_UINT_16(REG_BA + 1); \ + FLAG_N = NFLAG_16(REG_BA) +#endif + +/* M37710 Increment operand */ +#undef OP_INCM +#if FLAG_SET_M +#define OP_INCM(MODE) \ + CLK(CLK_OP + CLK_RMW8 + CLK_W_##MODE); \ + DST = EA_##MODE(); \ + FLAG_N = FLAG_Z = MAKE_UINT_8(read_8_##MODE(DST) + 1); \ + write_8_##MODE(DST, FLAG_Z) +#else +#define OP_INCM(MODE) \ + CLK(CLK_OP + CLK_RMW16 + CLK_W_##MODE); \ + DST = EA_##MODE(); \ + FLAG_Z = MAKE_UINT_16(read_16_##MODE(DST) + 1); \ + FLAG_N = NFLAG_16(FLAG_Z); \ + write_16_##MODE(DST, FLAG_Z) +#endif + +/* M37710 Increment index register */ +#undef OP_INCX +#if FLAG_SET_X +#define OP_INCX(REG) \ + CLK(CLK_OP + CLK_IMPLIED); \ + FLAG_N = FLAG_Z = REG = MAKE_UINT_8(REG + 1) +#else +#define OP_INCX(REG) \ + CLK(CLK_OP + CLK_IMPLIED); \ + FLAG_Z = REG = MAKE_UINT_16(REG + 1); \ + FLAG_N = NFLAG_16(REG) +#endif + +/* M37710 Jump Long */ +#undef OP_JMLAI +#define OP_JMLAI() \ + CLK(CLK_OP + CLK_AI + 1); \ + m37710i_jump_24(read_24_A(OPER_16_IMM())) + +/* M37710 Jump */ +#undef OP_JMP +#define OP_JMP(MODE) \ + CLK(CLK_OP + CLK_##MODE); \ + m37710i_jump_16(EA_##MODE()) + +/* M37710 Jump absolute indexed indirect */ +#undef OP_JMPAXI +#define OP_JMPAXI() \ + CLK(CLK_OP + CLK_AXI); \ + m37710i_jump_16(read_16_AXI(REG_PB | (MAKE_UINT_16(OPER_16_IMM() + REG_X)))) + +/* M37710 Jump absolute long */ +#undef OP_JMPAL +#define OP_JMPAL() \ + CLK(CLK_OP + CLK_AL); \ + m37710i_jump_24(EA_AL()) + +/* M37710 Jump to Subroutine Long */ +#undef OP_JSL +#define OP_JSL(MODE) \ + CLK(CLK_OP + CLK_W24 + CLK_##MODE + 1); \ + DST = EA_##MODE(); \ + m37710i_push_8(REG_PB>>16); \ + m37710i_push_16(REG_PC); \ + m37710i_jump_24(DST) + +/* M37710 Jump to Subroutine */ +#undef OP_JSR +#define OP_JSR(MODE) \ + CLK(CLK_OP + CLK_W16 + CLK_##MODE); \ + DST = EA_##MODE(); \ + m37710i_push_16(REG_PC); \ + m37710i_jump_16(DST) + +/* M37710 Jump to Subroutine */ +#undef OP_JSRAXI +#define OP_JSRAXI() \ + CLK(CLK_OP + CLK_W16 + CLK_AXI); \ + DST = read_16_AXI(REG_PB | (MAKE_UINT_16(OPER_16_IMM() + REG_X))); \ + m37710i_push_16(REG_PC); \ + m37710i_jump_16(DST) + +/* M37710 Load accumulator with operand */ +#undef OP_LDA +#if FLAG_SET_M +#define OP_LDA(MODE) \ + CLK(CLK_OP + CLK_R8 + CLK_##MODE); \ + FLAG_N = FLAG_Z = REG_A = OPER_8_##MODE() +#else +#define OP_LDA(MODE) \ + CLK(CLK_OP + CLK_R16 + CLK_##MODE); \ + FLAG_Z = REG_A = OPER_16_##MODE(); \ + FLAG_N = NFLAG_16(REG_A) +#endif + +/* M37710 Load B accumulator with operand */ +#undef OP_LDB +#if FLAG_SET_M +#define OP_LDB(MODE) \ + CLK(CLK_OP + CLK_R8 + CLK_##MODE); \ + FLAG_N = FLAG_Z = REG_BA = OPER_8_##MODE() +#else +#define OP_LDB(MODE) \ + CLK(CLK_OP + CLK_R16 + CLK_##MODE); \ + FLAG_Z = REG_BA = OPER_16_##MODE(); \ + FLAG_N = NFLAG_16(REG_BA) +#endif + +/* M37710 Load memory with operand */ +#undef OP_LDM +#if FLAG_SET_M +#define OP_LDM(MODE) \ + CLK(CLK_OP + CLK_R8 + CLK_##MODE); \ + REG_IM2 = EA_##MODE(); \ + REG_IM = read_8_IMM(REG_PB | REG_PC); \ + REG_PC++; \ + write_8_##MODE(REG_IM2, REG_IM) +#else +#define OP_LDM(MODE) \ + CLK(CLK_OP + CLK_R16 + CLK_##MODE); \ + REG_IM2 = EA_##MODE(); \ + REG_IM = read_16_IMM(REG_PB | REG_PC); \ + REG_PC+=2; \ + write_16_##MODE(REG_IM2, REG_IM) +#endif + +/* M37710 Branch if bits set */ +#undef OP_BBS +#if FLAG_SET_M +#define OP_BBS(MODE) \ + CLK(CLK_OP + CLK_R8 + CLK_##MODE); \ + REG_IM2 = read_8_NORM(EA_##MODE()); \ + REG_IM = read_8_IMM(REG_PB | REG_PC); \ + REG_PC++; \ + DST = OPER_8_IMM(); \ + if ((REG_IM2 & REG_IM) == REG_IM) \ + { \ + CLK(CLK_OP + CLK_RELATIVE_8 + 1); \ + m37710i_branch_8(DST); \ + BREAKOUT; \ + } +#else +#define OP_BBS(MODE) \ + CLK(CLK_OP + CLK_R16 + CLK_##MODE); \ + REG_IM2 = read_16_NORM(EA_##MODE()); \ + REG_IM = read_16_IMM(REG_PB | REG_PC); \ + REG_PC++; \ + REG_PC++; \ + DST = OPER_8_IMM(); \ + if ((REG_IM2 & REG_IM) == REG_IM) \ + { \ + CLK(CLK_OP + CLK_RELATIVE_8 + 1); \ + m37710i_branch_8(DST); \ + BREAKOUT; \ + } +#endif + +/* M37710 Branch if bits clear */ +#undef OP_BBC +#if FLAG_SET_M +#define OP_BBC(MODE) \ + CLK(CLK_OP + CLK_R8 + CLK_##MODE); \ + REG_IM2 = read_8_NORM(EA_##MODE()); \ + REG_IM = read_8_IMM(REG_PB | REG_PC); \ + REG_PC++; \ + DST = OPER_8_IMM(); \ + if ((REG_IM2 & REG_IM) == 0) \ + { \ + CLK(CLK_OP + CLK_RELATIVE_8 + 1); \ + m37710i_branch_8(DST); \ + BREAKOUT; \ + } +#else +#define OP_BBC(MODE) \ + CLK(CLK_OP + CLK_R16 + CLK_##MODE); \ + REG_IM2 = read_16_NORM(EA_##MODE()); \ + REG_IM = read_16_IMM(REG_PB | REG_PC); \ + REG_PC++; \ + REG_PC++; \ + DST = OPER_8_IMM(); \ + if ((REG_IM2 & REG_IM) == 0) \ + { \ + CLK(CLK_OP + CLK_RELATIVE_8 + 1); \ + m37710i_branch_8(DST); \ + BREAKOUT; \ + } +#endif + +/* M37710 Swap accumulators */ +#undef OP_XAB +#if FLAG_SET_M +#define OP_XAB() \ + CLK(6); \ + DST = REG_A; \ + FLAG_N = FLAG_Z = REG_A = REG_BA; \ + REG_BA = DST; +#else +#define OP_XAB() \ + CLK(6); \ + DST = REG_A; \ + FLAG_Z = REG_A = REG_BA; \ + FLAG_N = NFLAG_16(REG_A); \ + REG_BA = DST; +#endif + +/* M37710 Load index register with operand */ +#undef OP_LDX +#if FLAG_SET_X +#define OP_LDX(REG, MODE) \ + CLK(CLK_OP + CLK_R8 + CLK_##MODE); \ + FLAG_N = FLAG_Z = REG = OPER_8_##MODE() +#else +#define OP_LDX(REG, MODE) \ + CLK(CLK_OP + CLK_R16 + CLK_##MODE); \ + FLAG_Z = REG = OPER_16_##MODE(); \ + FLAG_N = NFLAG_16(REG) +#endif + +/* M37710 Logical Shift Right accumulator */ +#undef OP_LSR +#if FLAG_SET_M +#define OP_LSR() \ + CLK(CLK_OP + CLK_IMPLIED); \ + FLAG_N = 0; \ + FLAG_C = REG_A << 8; \ + FLAG_Z = REG_A >>= 1 +#else +#define OP_LSR() \ + CLK(CLK_OP + CLK_IMPLIED); \ + FLAG_N = 0; \ + FLAG_C = REG_A << 8; \ + FLAG_Z = REG_A >>= 1 +#endif + +/* M37710 Logical Shift Right B accumulator */ +#undef OP_LSRB +#if FLAG_SET_M +#define OP_LSRB() \ + CLK(CLK_OP + CLK_IMPLIED); \ + FLAG_N = 0; \ + FLAG_C = REG_BA << 8; \ + FLAG_Z = REG_BA >>= 1 +#else +#define OP_LSRB() \ + CLK(CLK_OP + CLK_IMPLIED); \ + FLAG_N = 0; \ + FLAG_C = REG_BA << 8; \ + FLAG_Z = REG_BA >>= 1 +#endif + +/* M37710 Logical Shift Right operand */ +#undef OP_LSRM +#if FLAG_SET_M +#define OP_LSRM(MODE) \ + CLK(CLK_OP + CLK_RMW8 + CLK_W_##MODE); \ + DST = EA_##MODE(); \ + FLAG_N = 0; \ + FLAG_Z = read_8_##MODE(DST); \ + FLAG_C = FLAG_Z << 8; \ + FLAG_Z >>= 1; \ + write_8_##MODE(DST, FLAG_Z) +#else +#define OP_LSRM(MODE) \ + CLK(CLK_OP + CLK_RMW16 + CLK_W_##MODE); \ + DST = EA_##MODE(); \ + FLAG_N = 0; \ + FLAG_Z = read_16_##MODE(DST); \ + FLAG_C = FLAG_Z << 8; \ + FLAG_Z >>= 1; \ + write_16_##MODE(DST, FLAG_Z) +#endif + +/* M37710 Move Block Negative */ +#undef OP_MVN +#if FLAG_SET_X +#define OP_MVN() \ + DST = OPER_8_IMM()<<16; \ + SRC = OPER_8_IMM()<<16; \ + REG_DB = DST; \ + REG_A |= REG_B; \ + CLK(7); \ + if (REG_A > 0) \ + { \ + write_8_NORM(DST | REG_Y, read_8_NORM(SRC | REG_X)); \ + REG_X = MAKE_UINT_8(REG_X+1); \ + REG_Y = MAKE_UINT_8(REG_Y+1); \ + REG_A--; \ + if ((REG_A&0xffff) != 0) \ + {\ + REG_PC -= 3; \ + }\ + else \ + { \ + if (FLAG_M) \ + { \ + REG_A = 0xff; \ + REG_B = 0xff00; \ + } \ + else \ + { \ + REG_A = 0xffff; \ + } \ + } \ + } +#else +#define OP_MVN() \ + DST = OPER_8_IMM()<<16; \ + SRC = OPER_8_IMM()<<16; \ + REG_DB = DST; \ + REG_A |= REG_B; \ + CLK(7); \ + if (REG_A > 0) \ + { \ + write_8_NORM(DST | REG_Y, read_8_NORM(SRC | REG_X)); \ + REG_X = MAKE_UINT_16(REG_X+1); \ + REG_Y = MAKE_UINT_16(REG_Y+1); \ + REG_A--; \ + if ((REG_A&0xffff) != 0) \ + {\ + REG_PC -= 3; \ + }\ + else \ + { \ + if (FLAG_M) \ + { \ + REG_A = 0xff; \ + REG_B = 0xff00; \ + } \ + else \ + { \ + REG_A = 0xffff; \ + } \ + } \ + } +#endif + +/* M37710 Move Block Positive */ +#undef OP_MVP +#if FLAG_SET_X +#define OP_MVP() \ + DST = OPER_8_IMM()<<16; \ + SRC = OPER_8_IMM()<<16; \ + REG_DB = DST; \ + REG_A |= REG_B; \ + CLK(7); \ + if (REG_A > 0) \ + { \ + write_8_NORM(DST | REG_Y, read_8_NORM(SRC | REG_X)); \ + REG_X = MAKE_UINT_8(REG_X-1); \ + REG_Y = MAKE_UINT_8(REG_Y-1); \ + REG_A--; \ + if ((REG_A&0xffff) != 0) \ + {\ + REG_PC -= 3; \ + }\ + else \ + { \ + if (FLAG_M) \ + { \ + REG_A = 0xff; \ + REG_B = 0xff00; \ + } \ + else \ + { \ + REG_A = 0xffff; \ + } \ + } \ + } +#else +#define OP_MVP() \ + DST = OPER_8_IMM()<<16; \ + SRC = OPER_8_IMM()<<16; \ + REG_DB = DST; \ + REG_A |= REG_B; \ + CLK(7); \ + if (REG_A > 0) \ + { \ + write_8_NORM(DST | REG_Y, read_8_NORM(SRC | REG_X)); \ + REG_X = MAKE_UINT_16(REG_X-1); \ + REG_Y = MAKE_UINT_16(REG_Y-1); \ + REG_A--; \ + if ((REG_A&0xffff) != 0) \ + {\ + REG_PC -= 3; \ + }\ + else \ + { \ + if (FLAG_M) \ + { \ + REG_A = 0xff; \ + REG_B = 0xff00; \ + } \ + else \ + { \ + REG_A = 0xffff; \ + } \ + } \ + } +#endif + +/* M37710 No Operation */ +#undef OP_NOP +#define OP_NOP() \ + CLK(CLK_OP + CLK_IMPLIED) + +/* M37710 Logical OR operand to accumulator */ +#undef OP_ORA +#if FLAG_SET_M +#define OP_ORA(MODE) \ + CLK(CLK_OP + CLK_R8 + CLK_##MODE); \ + FLAG_N = FLAG_Z = REG_A |= OPER_8_ ## MODE() +#else +#define OP_ORA(MODE) \ + CLK(CLK_OP + CLK_R16 + CLK_##MODE); \ + FLAG_Z = REG_A |= OPER_16_##MODE(); \ + FLAG_N = NFLAG_16(REG_A) +#endif + +/* M37710 Logical OR operand to B accumulator */ +#undef OP_ORB +#if FLAG_SET_M +#define OP_ORB(MODE) \ + CLK(CLK_OP + CLK_R8 + CLK_##MODE); \ + FLAG_N = FLAG_Z = REG_BA |= OPER_8_ ## MODE() +#else +#define OP_ORB(MODE) \ + CLK(CLK_OP + CLK_R16 + CLK_##MODE); \ + FLAG_Z = REG_BA |= OPER_16_##MODE(); \ + FLAG_N = NFLAG_16(REG_BA) +#endif + +/* M37710 Push Effective Address */ +#undef OP_PEA +#define OP_PEA() \ + CLK(CLK_OP + CLK_R16 + CLK_W16); \ + m37710i_push_16(OPER_16_IMM()) + +/* M37710 Push Effective Indirect Address */ +#undef OP_PEI +#define OP_PEI() \ + CLK(CLK_OP + CLK_R16 + CLK_W16 + CLK_D); \ + m37710i_push_16(EA_DI()) + +/* M37710 Push Effective PC-Relative Address */ +#undef OP_PER +#define OP_PER() \ + CLK(CLK_OP + CLK_R16 + CLK_W16 + 1); \ + SRC = OPER_16_IMM(); \ + m37710i_push_16(REG_PC + SRC) + +/* M37710 Push accumulator to the stack */ +#undef OP_PHA +#if FLAG_SET_M +#define OP_PHA() \ + CLK(CLK_OP + CLK_W8 + 1); \ + m37710i_push_8(REG_A) +#else +#define OP_PHA() \ + CLK(CLK_OP + CLK_W16 + 1); \ + m37710i_push_16(REG_A) +#endif + +/* M37710 Push B accumulator to the stack */ +#undef OP_PHAB +#if FLAG_SET_M +#define OP_PHAB() \ + CLK(CLK_OP + CLK_W8 + 1); \ + m37710i_push_8(REG_BA) +#else +#define OP_PHAB() \ + CLK(CLK_OP + CLK_W16 + 1); \ + m37710i_push_16(REG_BA) +#endif + +/* M37710 Push index register to the stack */ +#undef OP_PHX +#if FLAG_SET_X +#define OP_PHX(REG) \ + CLK(CLK_OP + CLK_W8 + 1); \ + m37710i_push_8(REG) +#else +#define OP_PHX(REG) \ + CLK(CLK_OP + CLK_W16 + 1); \ + m37710i_push_16(REG) +#endif + +/* M37710 Push data bank register */ +#undef OP_PHT +#define OP_PHT() \ + CLK(CLK_OP + CLK_W8 + 1); \ + m37710i_push_8(REG_DB>>16) + +/* M37710 Push direct register */ +#undef OP_PHD +#define OP_PHD() \ + CLK(CLK_OP + CLK_W16 + 1); \ + m37710i_push_16(REG_D) + +/* M37710 Push program bank register */ +#undef OP_PHK +#define OP_PHK() \ + CLK(CLK_OP + CLK_W8 + 1); \ + m37710i_push_8(REG_PB>>16) + +/* M37710 Push the Processor Status Register to the stack */ +#undef OP_PHP +#define OP_PHP() \ + CLK(CLK_OP + CLK_W8 + 1); \ + m37710i_push_8(m377.ipl); \ + m37710i_push_8(m37710i_get_reg_p()) + +/* M37710 Pull accumulator from the stack */ +#undef OP_PLA +#if FLAG_SET_M +#define OP_PLA() \ + CLK(CLK_OP + CLK_R8 + 2); \ + FLAG_N = FLAG_Z = REG_A = m37710i_pull_8() +#else +#define OP_PLA() \ + CLK(CLK_OP + CLK_R16 + 2); \ + FLAG_Z = REG_A = m37710i_pull_16(); \ + FLAG_N = NFLAG_16(FLAG_Z) +#endif + +/* M37710 Pull B accumulator from the stack */ +#undef OP_PLAB +#if FLAG_SET_M +#define OP_PLAB() \ + CLK(CLK_OP + CLK_R8 + 2); \ + FLAG_N = FLAG_Z = REG_BA = m37710i_pull_8() +#else +#define OP_PLAB() \ + CLK(CLK_OP + CLK_R16 + 2); \ + FLAG_Z = REG_BA = m37710i_pull_16(); \ + FLAG_N = NFLAG_16(FLAG_Z) +#endif + +/* M37710 Pull index register from the stack */ +#undef OP_PLX +#if FLAG_SET_X +#define OP_PLX(REG) \ + CLK(CLK_OP + CLK_R8 + 2); \ + FLAG_N = FLAG_Z = REG = m37710i_pull_8() +#else +#define OP_PLX(REG) \ + CLK(CLK_OP + CLK_R16 + 2); \ + FLAG_Z = REG = m37710i_pull_16(); \ + FLAG_N = NFLAG_16(FLAG_Z) +#endif + +/* M37710 Pull data bank register */ +#undef OP_PLT +#define OP_PLT() \ + CLK(CLK_OP + CLK_R8 + 2); \ + FLAG_N = FLAG_Z = m37710i_pull_8(); \ + REG_DB = FLAG_Z << 16 + +/* M37710 Pull direct register */ +#undef OP_PLD +#define OP_PLD() \ + CLK(CLK_OP + CLK_R16 + 2); \ + REG_D = m37710i_pull_16() + +/* M37710 Pull the Processor Status Register from the stack */ +#undef OP_PLP +#define OP_PLP() \ + CLK(CLK_OP + CLK_R8 + 2); \ + m37710i_set_reg_p(m37710i_pull_8()); \ + m37710i_set_reg_ipl(m37710i_pull_8()); \ + m37710i_update_irqs() + +/* M37710 Reset Program status word */ +#undef OP_REP +#define OP_REP() \ + CLK(CLK_OP + CLK_R8 + 1); \ + m37710i_set_reg_p(m37710i_get_reg_p() & ~OPER_8_IMM()); \ + m37710i_update_irqs() + +/* M37710 Clear "M" status bit */ +#undef OP_CLM +#define OP_CLM() \ + CLK(CLK_OP + CLK_R8 + 1); \ + m37710i_set_reg_p(m37710i_get_reg_p() & ~FLAGPOS_M) + +/* M37710 Rotate Left the accumulator */ +#undef OP_ROL +#if FLAG_SET_M +#define OP_ROL() \ + CLK(CLK_OP + CLK_IMPLIED); \ + FLAG_C = (REG_A<<1) | CFLAG_AS_1(); \ + FLAG_N = FLAG_Z = REG_A = MAKE_UINT_8(FLAG_C) +#else +#define OP_ROL() \ + CLK(CLK_OP + CLK_IMPLIED); \ + FLAG_C = (REG_A<<1) | CFLAG_AS_1(); \ + FLAG_Z = REG_A = MAKE_UINT_16(FLAG_C); \ + FLAG_N = NFLAG_16(FLAG_C); \ + FLAG_C = CFLAG_16(FLAG_C) +#endif + +/* M37710 Rotate Left the B accumulator */ +#undef OP_ROLB +#if FLAG_SET_M +#define OP_ROLB() \ + CLK(CLK_OP + CLK_IMPLIED); \ + FLAG_C = (REG_BA<<1) | CFLAG_AS_1(); \ + FLAG_N = FLAG_Z = REG_BA = MAKE_UINT_8(FLAG_C) +#else +#define OP_ROLB() \ + CLK(CLK_OP + CLK_IMPLIED); \ + FLAG_C = (REG_BA<<1) | CFLAG_AS_1(); \ + FLAG_Z = REG_BA = MAKE_UINT_16(FLAG_C); \ + FLAG_N = NFLAG_16(FLAG_C); \ + FLAG_C = CFLAG_16(FLAG_C) +#endif + +/* M37710 Rotate Left the accumulator by a specified amount */ +#undef OP_RLA +#if FLAG_SET_M +#define OP_RLA(MODE) \ + { int cnt = OPER_8_##MODE(); while (cnt > 0) { CLK(6); REG_A=((REG_A<<1)|(REG_A>>7&1))&0xff; cnt--; } } +#else +#define OP_RLA(MODE) \ + { int cnt = OPER_16_##MODE(); while (cnt > 0) { CLK(6); REG_A=((REG_A<<1)|(REG_A>>15&1))&0xffff; cnt--; } } +#endif + +/* M37710 Rotate Left an operand */ +#undef OP_ROLM +#if FLAG_SET_M +#define OP_ROLM(MODE) \ + CLK(CLK_OP + CLK_RMW8 + CLK_W_##MODE); \ + DST = EA_##MODE(); \ + FLAG_C = (read_8_##MODE(DST)<<1) | CFLAG_AS_1(); \ + FLAG_N = FLAG_Z = MAKE_UINT_8(FLAG_C); \ + write_8_##MODE(DST, FLAG_Z) +#else +#define OP_ROLM(MODE) \ + CLK(CLK_OP + CLK_RMW16 + CLK_W_##MODE); \ + DST = EA_##MODE(); \ + FLAG_C = (read_16_##MODE(DST)<<1) | CFLAG_AS_1(); \ + FLAG_Z = MAKE_UINT_16(FLAG_C); \ + FLAG_N = NFLAG_16(FLAG_C); \ + FLAG_C = CFLAG_16(FLAG_C); \ + write_16_##MODE(DST, FLAG_Z) +#endif + +/* M37710 Rotate Right the accumulator */ +#undef OP_ROR +#if FLAG_SET_M +#define OP_ROR() \ + CLK(CLK_OP + CLK_IMPLIED); \ + REG_A |= FLAG_C & 0x100; \ + FLAG_C = REG_A << 8; \ + FLAG_N = FLAG_Z = REG_A >>= 1 +#else +#define OP_ROR() \ + CLK(CLK_OP + CLK_IMPLIED); \ + REG_A |= (FLAG_C<<8) & 0x10000; \ + FLAG_C = REG_A << 8; \ + FLAG_Z = REG_A >>= 1; \ + FLAG_N = NFLAG_16(REG_A) +#endif + +/* M37710 Rotate Right the B accumulator */ +#undef OP_RORB +#if FLAG_SET_M +#define OP_RORB() \ + CLK(CLK_OP + CLK_IMPLIED); \ + REG_BA |= FLAG_C & 0x100; \ + FLAG_C = REG_BA << 8; \ + FLAG_N = FLAG_Z = REG_BA >>= 1 +#else +#define OP_RORB() \ + CLK(CLK_OP + CLK_IMPLIED); \ + REG_BA |= (FLAG_C<<8) & 0x10000; \ + FLAG_C = REG_BA << 8; \ + FLAG_Z = REG_BA >>= 1; \ + FLAG_N = NFLAG_16(REG_BA) +#endif + +/* M37710 Rotate Right an operand */ +#undef OP_RORM +#if FLAG_SET_M +#define OP_RORM(MODE) \ + CLK(CLK_OP + CLK_RMW8 + CLK_W_##MODE); \ + DST = EA_##MODE(); \ + FLAG_Z = read_8_##MODE(DST) | (FLAG_C & 0x100); \ + FLAG_C = FLAG_Z << 8; \ + FLAG_N = FLAG_Z >>= 1; \ + write_8_##MODE(DST, FLAG_Z) +#else +#define OP_RORM(MODE) \ + CLK(CLK_OP + CLK_RMW16 + CLK_W_##MODE); \ + DST = EA_##MODE(); \ + FLAG_Z = read_16_##MODE(DST) | ((FLAG_C<<8) & 0x10000); \ + FLAG_C = FLAG_Z << 8; \ + FLAG_Z >>= 1; \ + FLAG_N = NFLAG_16(FLAG_Z); \ + write_16_##MODE(DST, FLAG_Z) +#endif + +/* M37710 Return from Interrupt */ +#undef OP_RTI +#define OP_RTI() \ + CLK(8); \ + m37710i_set_reg_p(m37710i_pull_8()); \ + m37710i_set_reg_ipl(m37710i_pull_8()); \ + m37710i_jump_16(m37710i_pull_16()); \ + REG_PB = m37710i_pull_8() << 16; \ + m37710i_update_irqs() + +/* M37710 Return from Subroutine Long */ +#undef OP_RTL +#define OP_RTL() \ + CLK(6); \ + m37710i_jump_24(m37710i_pull_24()) + +/* M37710 Return from Subroutine */ +#undef OP_RTS +#define OP_RTS() \ + CLK(6); \ + DST = m37710i_pull_16(); \ + m37710i_jump_16(DST) + +/* M37710 Subtract with Carry */ +/* Unusual behavior: C flag is inverted */ +#undef OP_SBC +#if FLAG_SET_M +#define OP_SBC(MODE) \ + CLK(CLK_OP + CLK_R8 + CLK_##MODE); \ + SRC = OPER_8_##MODE(); \ + FLAG_C = ~FLAG_C; \ + if(!FLAG_D) \ + { \ + FLAG_C = REG_A - SRC - CFLAG_AS_1(); \ + FLAG_V = VFLAG_SUB_8(SRC, REG_A, FLAG_C); \ + FLAG_N = FLAG_Z = REG_A = MAKE_UINT_8(FLAG_C); \ + FLAG_C = ~FLAG_C; \ + BREAKOUT; \ + } \ + DST = CFLAG_AS_1(); \ + FLAG_C = REG_A - SRC - DST; \ + FLAG_V = VFLAG_SUB_8(SRC, REG_A, FLAG_C); \ + if((FLAG_C & 0xf) > 9) \ + FLAG_C-=6; \ + if((FLAG_C & 0xf0) > 0x90) \ + FLAG_C-=0x60; \ + FLAG_N = FLAG_Z = REG_A = MAKE_UINT_8(FLAG_C); \ + FLAG_C = ~FLAG_C +#else +#define OP_SBC(MODE) \ + CLK(CLK_OP + CLK_R16 + CLK_##MODE); \ + SRC = OPER_16_##MODE(); \ + FLAG_C = ~FLAG_C; \ + if(!FLAG_D) \ + { \ + FLAG_C = REG_A - SRC - CFLAG_AS_1(); \ + FLAG_V = VFLAG_SUB_16(SRC, REG_A, FLAG_C); \ + FLAG_Z = REG_A = MAKE_UINT_16(FLAG_C); \ + FLAG_N = NFLAG_16(REG_A); \ + FLAG_C = ~CFLAG_16(FLAG_C); \ + BREAKOUT; \ + } \ + DST = CFLAG_AS_1(); \ + FLAG_C = MAKE_UINT_8(REG_A) - MAKE_UINT_8(SRC) - DST; \ + if((FLAG_C & 0xf) > 9) \ + FLAG_C-=6; \ + if((FLAG_C & 0xf0) > 0x90) \ + FLAG_C-=0x60; \ + FLAG_Z = MAKE_UINT_8(FLAG_C); \ + DST = CFLAG_AS_1(); \ + FLAG_C = MAKE_UINT_8(REG_A>>8) - MAKE_UINT_8(SRC>>8) - DST; \ + if((FLAG_C & 0xf) > 9) \ + FLAG_C-=6; \ + if((FLAG_C & 0xf0) > 0x90) \ + FLAG_C-=0x60; \ + FLAG_Z |= MAKE_UINT_8(FLAG_C) << 8; \ + FLAG_N = NFLAG_16(FLAG_Z); \ + FLAG_V = VFLAG_SUB_16(SRC, REG_A, FLAG_Z); \ + REG_A = FLAG_Z; \ + FLAG_C = ~FLAG_C +#endif + +/* M37710 Subtract with Carry - B accumulator */ +/* Unusual behavior: C flag is inverted */ +#undef OP_SBCB +#if FLAG_SET_M +#define OP_SBCB(MODE) \ + CLK(CLK_OP + CLK_R8 + CLK_##MODE); \ + SRC = OPER_8_##MODE(); \ + FLAG_C = ~FLAG_C; \ + if(!FLAG_D) \ + { \ + FLAG_C = REG_BA - SRC - CFLAG_AS_1(); \ + FLAG_V = VFLAG_SUB_8(SRC, REG_BA, FLAG_C); \ + FLAG_N = FLAG_Z = REG_BA = MAKE_UINT_8(FLAG_C); \ + FLAG_C = ~FLAG_C; \ + BREAKOUT; \ + } \ + DST = CFLAG_AS_1(); \ + FLAG_C = REG_BA - SRC - DST; \ + FLAG_V = VFLAG_SUB_8(SRC, REG_BA, FLAG_C); \ + if((FLAG_C & 0xf) > 9) \ + FLAG_C-=6; \ + if((FLAG_C & 0xf0) > 0x90) \ + FLAG_C-=0x60; \ + FLAG_N = FLAG_Z = REG_BA = MAKE_UINT_8(FLAG_C); \ + FLAG_C = ~FLAG_C +#else +#define OP_SBCB(MODE) \ + CLK(CLK_OP + CLK_R16 + CLK_##MODE); \ + SRC = OPER_16_##MODE(); \ + FLAG_C = ~FLAG_C; \ + if(!FLAG_D) \ + { \ + FLAG_C = REG_BA - SRC - CFLAG_AS_1(); \ + FLAG_V = VFLAG_SUB_16(SRC, REG_BA, FLAG_C); \ + FLAG_Z = REG_BA = MAKE_UINT_16(FLAG_C); \ + FLAG_N = NFLAG_16(REG_BA); \ + FLAG_C = ~CFLAG_16(FLAG_C); \ + BREAKOUT; \ + } \ + DST = CFLAG_AS_1(); \ + FLAG_C = MAKE_UINT_8(REG_BA) - MAKE_UINT_8(SRC) - DST; \ + if((FLAG_C & 0xf) > 9) \ + FLAG_C-=6; \ + if((FLAG_C & 0xf0) > 0x90) \ + FLAG_C-=0x60; \ + FLAG_Z = MAKE_UINT_8(FLAG_C); \ + DST = CFLAG_AS_1(); \ + FLAG_C = MAKE_UINT_8(REG_A>>8) - MAKE_UINT_8(SRC>>8) - DST; \ + if((FLAG_C & 0xf) > 9) \ + FLAG_C-=6; \ + if((FLAG_C & 0xf0) > 0x90) \ + FLAG_C-=0x60; \ + FLAG_Z |= MAKE_UINT_8(FLAG_C) << 8; \ + FLAG_N = NFLAG_16(FLAG_Z); \ + FLAG_V = VFLAG_SUB_16(SRC, REG_BA, FLAG_Z); \ + REG_BA = FLAG_Z; \ + FLAG_C = ~FLAG_C +#endif + +/* M37710 Set Carry flag */ +#undef OP_SEC +#define OP_SEC() \ + CLK(CLK_OP + CLK_IMPLIED); \ + FLAG_C = CFLAG_SET + +/* M37710 Set Interrupt Mask flag */ +#undef OP_SEI +#define OP_SEI() \ + CLK(CLK_OP + CLK_IMPLIED); \ + FLAG_I = IFLAG_SET + +/* M37710 Set Program status word */ +#undef OP_SEP +#define OP_SEP() \ + CLK(CLK_OP + CLK_R8 + 1); \ + m37710i_set_reg_p(m37710i_get_reg_p() | OPER_8_IMM()) + +/* M37710 Set "M" status bit */ +#undef OP_SEM +#define OP_SEM() \ + CLK(CLK_OP + CLK_R8 + 1); \ + m37710i_set_reg_p(m37710i_get_reg_p() | FLAGPOS_M) + +/* M37710 Store accumulator to memory */ +#undef OP_STA +#if FLAG_SET_M +#define OP_STA(MODE) \ + CLK(CLK_OP + CLK_W8 + CLK_W_##MODE); \ + write_8_##MODE(EA_##MODE(), REG_A) +#else +#define OP_STA(MODE) \ + CLK(CLK_OP + CLK_W16 + CLK_W_##MODE); \ + write_16_##MODE(EA_##MODE(), REG_A) +#endif + +/* M37710 Store B accumulator to memory */ +#undef OP_STB +#if FLAG_SET_M +#define OP_STB(MODE) \ + CLK(CLK_OP + CLK_W8 + CLK_W_##MODE); \ + write_8_##MODE(EA_##MODE(), REG_BA) +#else +#define OP_STB(MODE) \ + CLK(CLK_OP + CLK_W16 + CLK_W_##MODE); \ + write_16_##MODE(EA_##MODE(), REG_BA) +#endif + +/* M37710 Store index register to memory */ +#undef OP_STX +#if FLAG_SET_X +#define OP_STX(REG, MODE) \ + CLK(CLK_OP + CLK_W8 + CLK_W_##MODE); \ + write_8_##MODE(EA_##MODE(), REG) +#else +#define OP_STX(REG, MODE) \ + CLK(CLK_OP + CLK_W16 + CLK_W_##MODE); \ + write_16_##MODE(EA_##MODE(), REG) +#endif + +/* M37710 Stop the clock */ +#undef OP_STP +#define OP_STP() \ + USE_ALL_CLKS(); \ + CPU_STOPPED |= STOP_LEVEL_STOP + +/* M37710 Transfer accumulator to index */ +#undef OP_TAX +#if FLAG_SET_M +#if FLAG_SET_X +#define OP_TAX(REG) \ + CLK(CLK_OP + CLK_IMPLIED); \ + FLAG_Z = REG = REG_A; \ + FLAG_N = NFLAG_8(FLAG_Z) +#else /* FLAG_SET_X */ +#define OP_TAX(REG) \ + CLK(CLK_OP + CLK_IMPLIED); \ + FLAG_Z = REG = REG_B | REG_A; \ + FLAG_N = NFLAG_16(FLAG_Z) +#endif /* FLAG_SET_X */ +#else /* FLAG_SET_M */ +#if FLAG_SET_X +#define OP_TAX(REG) \ + CLK(CLK_OP + CLK_IMPLIED); \ + FLAG_Z = REG = MAKE_UINT_8(REG_A); \ + FLAG_N = NFLAG_8(FLAG_Z) +#else /* FLAG_SET_X */ +#define OP_TAX(REG) \ + CLK(CLK_OP + CLK_IMPLIED); \ + FLAG_Z = REG = REG_A; \ + FLAG_N = NFLAG_16(FLAG_Z) +#endif /* FLAG_SET_X */ +#endif /* FLAG_SET_M */ + + +/* M37710 Transfer accumulator B to index */ +#undef OP_TBX +#if FLAG_SET_M +#if FLAG_SET_X +#define OP_TBX(REG) \ + CLK(CLK_OP + CLK_IMPLIED); \ + FLAG_Z = REG = REG_BA; \ + FLAG_N = NFLAG_8(FLAG_Z) +#else /* FLAG_SET_X */ +#define OP_TBX(REG) \ + CLK(CLK_OP + CLK_IMPLIED); \ + FLAG_Z = REG = REG_BB | REG_BA; \ + FLAG_N = NFLAG_16(FLAG_Z) +#endif /* FLAG_SET_X */ +#else /* FLAG_SET_M */ +#if FLAG_SET_X +#define OP_TBX(REG) \ + CLK(CLK_OP + CLK_IMPLIED); \ + FLAG_Z = REG = MAKE_UINT_8(REG_BA); \ + FLAG_N = NFLAG_8(FLAG_Z) +#else /* FLAG_SET_X */ +#define OP_TBX(REG) \ + CLK(CLK_OP + CLK_IMPLIED); \ + FLAG_Z = REG = REG_BA; \ + FLAG_N = NFLAG_16(FLAG_Z) +#endif /* FLAG_SET_X */ +#endif /* FLAG_SET_M */ + +/* M37710 Transfer index to accumulator */ +#undef OP_TXA +#if FLAG_SET_M +#define OP_TXA(REG) \ + CLK(CLK_OP + CLK_IMPLIED); \ + FLAG_Z = REG_A = MAKE_UINT_8(REG); \ + FLAG_N = NFLAG_8(FLAG_Z) +#else +#define OP_TXA(REG) \ + CLK(CLK_OP + CLK_IMPLIED); \ + FLAG_Z = REG_A = REG; \ + FLAG_N = NFLAG_16(FLAG_Z) +#endif + +/* M37710 Transfer index to accumulator B */ +#undef OP_TXB +#if FLAG_SET_M +#define OP_TXB(REG) \ + CLK(CLK_OP + CLK_IMPLIED); \ + FLAG_Z = REG_BA = MAKE_UINT_8(REG); \ + FLAG_N = NFLAG_8(FLAG_Z) +#else +#define OP_TXB(REG) \ + CLK(CLK_OP + CLK_IMPLIED); \ + FLAG_Z = REG_BA = REG; \ + FLAG_N = NFLAG_16(FLAG_Z) +#endif + +/* M37710 Transfer accumulator to direct register */ +#undef OP_TAD +#if FLAG_SET_M +#define OP_TAD() \ + CLK(CLK_OP + CLK_IMPLIED); \ + REG_D = REG_A | REG_B +#else +#define OP_TAD() \ + CLK(CLK_OP + CLK_IMPLIED); \ + REG_D = REG_A +#endif + +/* M37710 Transfer accumulator B to direct register */ +#undef OP_TBD +#if FLAG_SET_M +#define OP_TBD() \ + CLK(CLK_OP + CLK_IMPLIED); \ + REG_D = REG_BA | REG_BB +#else +#define OP_TBD() \ + CLK(CLK_OP + CLK_IMPLIED); \ + REG_D = REG_BA +#endif + +/* M37710 Transfer direct register to accumulator */ +#undef OP_TDA +#if FLAG_SET_M +#define OP_TDA() \ + CLK(CLK_OP + CLK_IMPLIED); \ + FLAG_Z = REG_D; \ + FLAG_N = NFLAG_16(FLAG_Z); \ + REG_A = MAKE_UINT_8(REG_D); \ + REG_B = REG_D & 0xff00 +#else +#define OP_TDA() \ + CLK(CLK_OP + CLK_IMPLIED); \ + FLAG_Z = REG_A = REG_D; \ + FLAG_N = NFLAG_16(FLAG_Z) +#endif + +/* M37710 Transfer direct register to accumulator B */ +#undef OP_TDB +#if FLAG_SET_M +#define OP_TDB() \ + CLK(CLK_OP + CLK_IMPLIED); \ + FLAG_Z = REG_D; \ + FLAG_N = NFLAG_16(FLAG_Z); \ + REG_BA = MAKE_UINT_8(REG_D); \ + REG_BB = REG_D & 0xff00 +#else +#define OP_TDB() \ + CLK(CLK_OP + CLK_IMPLIED); \ + FLAG_Z = REG_BA = REG_D; \ + FLAG_N = NFLAG_16(FLAG_Z) +#endif + +/* M37710 Transfer accumulator to stack pointer */ +#undef OP_TAS +#if FLAG_SET_M +#define OP_TAS() \ + CLK(CLK_OP + CLK_IMPLIED); \ + REG_S = REG_A | REG_B +#else +#define OP_TAS() \ + CLK(CLK_OP + CLK_IMPLIED); \ + REG_S = REG_A +#endif + +/* M37710 Transfer accumulator B to stack pointer */ +#undef OP_TBS +#if FLAG_SET_M +#define OP_TBS() \ + CLK(CLK_OP + CLK_IMPLIED); \ + REG_S = REG_BA | REG_BB +#else +#define OP_TBS() \ + CLK(CLK_OP + CLK_IMPLIED); \ + REG_S = REG_BA +#endif + +/* M37710 Transfer stack pointer to accumulator */ +#undef OP_TSA +#if FLAG_SET_M +#define OP_TSA() \ + CLK(CLK_OP + CLK_IMPLIED); \ + FLAG_Z = REG_S; \ + FLAG_N = NFLAG_16(FLAG_Z); \ + REG_A = MAKE_UINT_8(REG_S); \ + REG_B = REG_S & 0xff00 +#else +#define OP_TSA() \ + CLK(CLK_OP + CLK_IMPLIED); \ + FLAG_Z = REG_A = REG_S; \ + FLAG_N = NFLAG_16(FLAG_Z) +#endif + +/* M37710 Transfer stack pointer to accumulator B */ +#undef OP_TSB +#if FLAG_SET_M +#define OP_TSB() \ + CLK(CLK_OP + CLK_IMPLIED); \ + FLAG_Z = REG_S; \ + FLAG_N = NFLAG_16(FLAG_Z); \ + REG_BA = MAKE_UINT_8(REG_S); \ + REG_BB = REG_S & 0xff00 +#else +#define OP_TSB() \ + CLK(CLK_OP + CLK_IMPLIED); \ + FLAG_Z = REG_BA = REG_S; \ + FLAG_N = NFLAG_16(FLAG_Z) +#endif + +/* M37710 Transfer stack pointer to X */ +#undef OP_TSX +#if FLAG_SET_X +#define OP_TSX() \ + CLK(CLK_OP + CLK_IMPLIED); \ + FLAG_Z = REG_X = MAKE_UINT_8(REG_S); \ + FLAG_N = NFLAG_8(FLAG_Z) +#else +#define OP_TSX() \ + CLK(CLK_OP + CLK_IMPLIED); \ + FLAG_Z = REG_X = REG_S; \ + FLAG_N = NFLAG_16(FLAG_Z) +#endif + +/* M37710 Transfer X to stack pointer */ +#undef OP_TXS +#if FLAG_SET_X +#define OP_TXS() \ + CLK(CLK_OP + CLK_IMPLIED); \ + REG_S = MAKE_UINT_8(REG_X) +#else +#define OP_TXS() \ + CLK(CLK_OP + CLK_IMPLIED); \ + REG_S = REG_X +#endif + +/* M37710 Transfer X to Y */ +#undef OP_TXY +#if FLAG_SET_X +#define OP_TXY() \ + CLK(CLK_OP + CLK_IMPLIED); \ + FLAG_Z = REG_Y = REG_X; \ + FLAG_N = NFLAG_8(FLAG_Z) +#else +#define OP_TXY() \ + CLK(CLK_OP + CLK_IMPLIED); \ + FLAG_Z = REG_Y = REG_X; \ + FLAG_N = NFLAG_16(FLAG_Z) +#endif + +/* M37710 Transfer Y to X */ +#undef OP_TYX +#if FLAG_SET_X +#define OP_TYX() \ + CLK(CLK_OP + CLK_IMPLIED); \ + FLAG_Z = REG_X = REG_Y; \ + FLAG_N = NFLAG_8(FLAG_Z) +#else +#define OP_TYX() \ + CLK(CLK_OP + CLK_IMPLIED); \ + FLAG_Z = REG_X = REG_Y; \ + FLAG_N = NFLAG_16(FLAG_Z) +#endif + +/* M37710 clear bit */ +#undef OP_CLB +#if FLAG_SET_M +#define OP_CLB(MODE) \ + CLK(CLK_OP + CLK_RMW8 + CLK_W_##MODE); \ + DST = EA_##MODE(); \ + REG_IM = read_8_##MODE(DST); \ + REG_IM2 = read_8_IMM(REG_PB | REG_PC); \ + REG_PC++; \ + write_8_##MODE(DST, REG_IM & ~REG_IM2); +#else +#define OP_CLB(MODE) \ + CLK(CLK_OP + CLK_RMW16 + CLK_W_##MODE); \ + DST = EA_##MODE(); \ + REG_IM = read_16_##MODE(DST); \ + REG_IM2 = read_16_IMM(REG_PB | REG_PC); \ + REG_PC+=2; \ + write_16_##MODE(DST, REG_IM & ~REG_IM2); +#endif + +/* M37710 set bit */ +#undef OP_SEB +#if FLAG_SET_M +#define OP_SEB(MODE) \ + CLK(CLK_OP + CLK_RMW8 + CLK_W_##MODE); \ + DST = EA_##MODE(); \ + REG_IM = read_8_##MODE(DST); \ + REG_IM2 = read_8_IMM(REG_PB | REG_PC); \ + REG_PC++; \ + write_8_##MODE(DST, REG_IM | REG_IM2); +#else +#define OP_SEB(MODE) \ + CLK(CLK_OP + CLK_RMW16 + CLK_W_##MODE); \ + DST = EA_##MODE(); \ + REG_IM = read_16_##MODE(DST); \ + REG_IM2 = read_16_IMM(REG_PB | REG_PC); \ + REG_PC+=2; \ + write_16_##MODE(DST, REG_IM | REG_IM2); +#endif + +/* M37710 Wait for interrupt */ +#undef OP_WAI +#define OP_WAI() \ + USE_ALL_CLKS(); \ + CPU_STOPPED |= STOP_LEVEL_WAI + +/* M37710 load data bank register */ +#undef OP_LDT +#define OP_LDT(MODE) \ + CLK(CLK_OP + CLK_R8 + CLK_##MODE); \ + REG_DB = OPER_8_##MODE()<<16; + + +/* M37710 prefix for B accumulator (0x42) */ +/* There is a 2 cycle penalty for all instructions using this prefix */ +#undef OP_PFB +#define OP_PFB() \ + CLK(2); \ + REG_IR = read_8_IMM(REG_PB | REG_PC); \ + REG_PC++; \ + (*m_opcodes42[REG_IR])(); + + +/* M37710 prefix for multiply / divide instructions (0x89) */ +#undef OP_PFXM +#define OP_PFXM() \ + REG_IR = read_8_IMM(REG_PB | REG_PC); \ + REG_PC++; \ + (*m_opcodes89[REG_IR])(); + + +/* M37710 unimplemented opcode */ +#undef OP_UNIMP +#define OP_UNIMP() \ + logerror("error M37710: UNIMPLEMENTED OPCODE! K=%x PC=%x\n", REG_PB, REG_PPC); + +/* ======================================================================== */ +/* ======================== OPCODE & FUNCTION TABLES ====================== */ +/* ======================================================================== */ + +#undef OP +#undef O +#undef TABLE_OPCODES +#undef TABLE_FUNCTION + +#if !FLAG_SET_M && !FLAG_SET_X +#define OP(CODE, OPERATION) void m37710i_ ## CODE ## _M0X0() {OPERATION;} +#define O(CODE) &m37710i_ ## CODE ## _M0X0 +#define TABLE_OPCODES const opcode_func m37710i_opcodes_M0X0[256] +#define TABLE_OPCODES2 const opcode_func m37710i_opcodes42_M0X0[256] +#define TABLE_OPCODES3 const opcode_func m37710i_opcodes89_M0X0[256] +#define TABLE_FUNCTION(RTYPE, NAME, ARGS) RTYPE m37710i_ ## NAME ## _M0X0 ARGS + +#elif !FLAG_SET_M && FLAG_SET_X + +#define OP(CODE, OPERATION) void m37710i_ ## CODE ## _M0X1() {OPERATION;} +#define O(CODE) &m37710i_ ## CODE ## _M0X1 +#define TABLE_OPCODES const opcode_func m37710i_opcodes_M0X1[256] +#define TABLE_OPCODES2 const opcode_func m37710i_opcodes42_M0X1[256] +#define TABLE_OPCODES3 const opcode_func m37710i_opcodes89_M0X1[256] +#define TABLE_FUNCTION(RTYPE, NAME, ARGS) RTYPE m37710i_ ## NAME ## _M0X1 ARGS + +#elif FLAG_SET_M && !FLAG_SET_X + +#define OP(CODE, OPERATION) void m37710i_ ## CODE ## _M1X0() {OPERATION;} +#define O(CODE) &m37710i_ ## CODE ## _M1X0 +#define TABLE_OPCODES const opcode_func m37710i_opcodes_M1X0[256] +#define TABLE_OPCODES2 const opcode_func m37710i_opcodes42_M1X0[256] +#define TABLE_OPCODES3 const opcode_func m37710i_opcodes89_M1X0[256] +#define TABLE_FUNCTION(RTYPE, NAME, ARGS) RTYPE m37710i_ ## NAME ## _M1X0 ARGS + +#elif FLAG_SET_M && FLAG_SET_X + +#define OP(CODE, OPERATION) void m37710i_ ## CODE ## _M1X1() {OPERATION;} +#define O(CODE) &m37710i_ ## CODE ## _M1X1 +#define TABLE_OPCODES const opcode_func m37710i_opcodes_M1X1[256] +#define TABLE_OPCODES2 const opcode_func m37710i_opcodes42_M1X1[256] +#define TABLE_OPCODES3 const opcode_func m37710i_opcodes89_M1X1[256] +#define TABLE_FUNCTION(RTYPE, NAME, ARGS) RTYPE m37710i_ ## NAME ## _M1X1 ARGS + +#endif + +#define BREAKOUT return + +/* OP FUNCTION Comment */ +OP(00, OP_BRK ( ) ) /* BRK */ +OP(01, OP_ORA ( DXI ) ) /* ORA dxi */ +OP(02, OP_NOP ( ) ) /* unused */ +OP(03, OP_ORA ( S ) ) /* ORA s (G) */ +OP(04, OP_SEB ( D ) ) /* SEB d (C) */ +OP(05, OP_ORA ( D ) ) /* ORA d */ +OP(06, OP_ASLM ( D ) ) /* ASL d */ +OP(07, OP_ORA ( DLI ) ) /* ORA dli (G) */ +OP(08, OP_PHP ( ) ) /* PHP */ +OP(09, OP_ORA ( IMM ) ) /* ORA imm */ +OP(0a, OP_ASL ( ) ) /* ASL acc */ +OP(0b, OP_PHD ( ) ) /* PHD (G) */ +OP(0c, OP_SEB ( A ) ) /* SEB a (C) */ +OP(0d, OP_ORA ( A ) ) /* ORA a */ +OP(0e, OP_ASLM ( A ) ) /* ASL a */ +OP(0f, OP_ORA ( AL ) ) /* ORA al (G) */ +OP(10, OP_BCC ( COND_PL() ) ) /* BPL */ +OP(11, OP_ORA ( DIY ) ) /* ORA diy */ +OP(12, OP_ORA ( DI ) ) /* ORA di (C) */ +OP(13, OP_ORA ( SIY ) ) /* ORA siy (G) */ +OP(14, OP_CLB ( D ) ) /* CLB d (C) */ +OP(15, OP_ORA ( DX ) ) /* ORA dx */ +OP(16, OP_ASLM ( DX ) ) /* ASL dx */ +OP(17, OP_ORA ( DLIY ) ) /* ORA dliy(C) */ +OP(18, OP_CLC ( ) ) /* CLC */ +OP(19, OP_ORA ( AY ) ) /* ORA ay */ +OP(1a, OP_DEC ( ) ) /* DEA (C) */ +OP(1b, OP_TAS ( ) ) /* TAS (G) */ +OP(1c, OP_CLB ( A ) ) /* CLB a (C) */ +OP(1d, OP_ORA ( AX ) ) /* ORA ax */ +OP(1e, OP_ASLM ( AX ) ) /* ASL ax */ +OP(1f, OP_ORA ( ALX ) ) /* ORA alx (G) */ +OP(20, OP_JSR ( A ) ) /* JSR a */ +OP(21, OP_AND ( DXI ) ) /* AND dxi */ +OP(22, OP_JSL ( AL ) ) /* JSL al (G) */ +OP(23, OP_AND ( S ) ) /* AND s (G) */ +OP(24, OP_BBS ( D ) ) /* BBS d */ +OP(25, OP_AND ( D ) ) /* AND d */ +OP(26, OP_ROLM ( D ) ) /* ROL d */ +OP(27, OP_AND ( DLI ) ) /* AND dli (G) */ +OP(28, OP_PLP ( ) ) /* PLP */ +OP(29, OP_AND ( IMM ) ) /* AND imm */ +OP(2a, OP_ROL ( ) ) /* ROL acc */ +OP(2b, OP_PLD ( ) ) /* PLD (G) */ +OP(2c, OP_BBS ( A ) ) /* BBS a */ +OP(2d, OP_AND ( A ) ) /* AND a */ +OP(2e, OP_ROLM ( A ) ) /* ROL a */ +OP(2f, OP_AND ( AL ) ) /* AND al (G) */ +OP(30, OP_BCC ( COND_MI() ) ) /* BMI */ +OP(31, OP_AND ( DIY ) ) /* AND diy */ +OP(32, OP_AND ( DI ) ) /* AND di (C) */ +OP(33, OP_AND ( SIY ) ) /* AND siy */ +OP(34, OP_BBC ( D ) ) /* BBC d */ +OP(35, OP_AND ( DX ) ) /* AND dx */ +OP(36, OP_ROLM ( DX ) ) /* ROL dx */ +OP(37, OP_AND ( DLIY ) ) /* AND dliy(G) */ +OP(38, OP_SEC ( ) ) /* SEC */ +OP(39, OP_AND ( AY ) ) /* AND ay */ +OP(3a, OP_INC ( ) ) /* INA (C) */ +OP(3b, OP_TSA ( ) ) /* TSA (G) */ +OP(3c, OP_BBC ( A ) ) /* BBC a */ +OP(3d, OP_AND ( AX ) ) /* AND ax */ +OP(3e, OP_ROLM ( AX ) ) /* ROL ax */ +OP(3f, OP_AND ( ALX ) ) /* AND alx (G) */ +OP(40, OP_RTI ( ) ) /* RTI */ +OP(41, OP_EOR ( DXI ) ) /* EOR dxi */ +OP(42, OP_PFB ( ) ) /* prefix for "B" accumulator */ +OP(43, OP_EOR ( S ) ) /* EOR s (G) */ +OP(44, OP_MVP ( ) ) /* MVP (G) */ +OP(45, OP_EOR ( D ) ) /* EOR d */ +OP(46, OP_LSRM ( D ) ) /* LSR d */ +OP(47, OP_EOR ( DLI ) ) /* EOR dli (G) */ +OP(48, OP_PHA ( ) ) /* PHA */ +OP(49, OP_EOR ( IMM ) ) /* EOR imm */ +OP(4a, OP_LSR ( ) ) /* LSR acc */ +OP(4b, OP_PHK ( ) ) /* PHK (G) */ +OP(4c, OP_JMP ( A ) ) /* JMP a */ +OP(4d, OP_EOR ( A ) ) /* EOR a */ +OP(4e, OP_LSRM ( A ) ) /* LSR a */ +OP(4f, OP_EOR ( AL ) ) /* EOR al (G) */ +OP(50, OP_BCC ( COND_VC() ) ) /* BVC */ +OP(51, OP_EOR ( DIY ) ) /* EOR diy */ +OP(52, OP_EOR ( DI ) ) /* EOR di (C) */ +OP(53, OP_EOR ( SIY ) ) /* EOR siy (G) */ +OP(54, OP_MVN ( ) ) /* MVN (G) */ +OP(55, OP_EOR ( DX ) ) /* EOR dx */ +OP(56, OP_LSRM ( DX ) ) /* LSR dx */ +OP(57, OP_EOR ( DLIY ) ) /* EOR dliy(G) */ +OP(58, OP_CLI ( ) ) /* CLI */ +OP(59, OP_EOR ( AY ) ) /* EOR ay */ +OP(5a, OP_PHX ( REG_Y ) ) /* PHY (C) */ +OP(5b, OP_TAD ( ) ) /* TAD (G) */ +OP(5c, OP_JMPAL( ) ) /* JMP al (G) */ +OP(5d, OP_EOR ( AX ) ) /* EOR ax */ +OP(5e, OP_LSRM ( AX ) ) /* LSR ax */ +OP(5f, OP_EOR ( ALX ) ) /* EOR alx (G) */ +OP(60, OP_RTS ( ) ) /* RTS */ +OP(61, OP_ADC ( DXI ) ) /* ADC dxi */ +OP(62, OP_PER ( ) ) /* PER (G) */ +OP(63, OP_ADC ( S ) ) /* ADC s (G) */ +OP(64, OP_LDM ( D ) ) /* LDM d (C) */ +OP(65, OP_ADC ( D ) ) /* ADC d */ +OP(66, OP_RORM ( D ) ) /* ROR d */ +OP(67, OP_ADC ( DLI ) ) /* ADC dli (G) */ +OP(68, OP_PLA ( ) ) /* PLA */ +OP(69, OP_ADC ( IMM ) ) /* ADC imm */ +OP(6a, OP_ROR ( ) ) /* ROR acc */ +OP(6b, OP_RTL ( ) ) /* RTL (G) */ +OP(6c, OP_JMP ( AI ) ) /* JMP ai */ +OP(6d, OP_ADC ( A ) ) /* ADC a */ +OP(6e, OP_RORM ( A ) ) /* ROR a */ +OP(6f, OP_ADC ( AL ) ) /* ADC al (G) */ +OP(70, OP_BCC ( COND_VS() ) ) /* BVS */ +OP(71, OP_ADC ( DIY ) ) /* ADC diy */ +OP(72, OP_ADC ( DI ) ) /* ADC di (G) */ +OP(73, OP_ADC ( SIY ) ) /* ADC siy (G) */ +OP(74, OP_LDM ( DX ) ) /* LDM dx (C) */ +OP(75, OP_ADC ( DX ) ) /* ADC dx */ +OP(76, OP_RORM ( DX ) ) /* ROR dx */ +OP(77, OP_ADC ( DLIY ) ) /* ADC dliy(G) */ +OP(78, OP_SEI ( ) ) /* SEI */ +OP(79, OP_ADC ( AY ) ) /* ADC ay */ +OP(7a, OP_PLX ( REG_Y ) ) /* PLY (C) */ +OP(7b, OP_TDA ( ) ) /* TDA (G) */ +OP(7c, OP_JMPAXI( ) ) /* JMP axi (C) */ +OP(7d, OP_ADC ( AX ) ) /* ADC ax */ +OP(7e, OP_RORM ( AX ) ) /* ROR ax */ +OP(7f, OP_ADC ( ALX ) ) /* ADC alx (G) */ +OP(80, OP_BRA ( ) ) /* BRA (C) */ +OP(81, OP_STA ( DXI ) ) /* STA dxi */ +OP(82, OP_BRL ( ) ) /* BRL (G) */ +OP(83, OP_STA ( S ) ) /* STA s (G) */ +OP(84, OP_STX ( REG_Y, D ) ) /* STY d */ +OP(85, OP_STA ( D ) ) /* STA d */ +OP(86, OP_STX ( REG_X, D ) ) /* STX d */ +OP(87, OP_STA ( DLI ) ) /* STA dli (G) */ +OP(88, OP_DECX ( REG_Y ) ) /* DEY */ +OP(89, OP_PFXM ( ) ) /* prefix for mul/div insns */ +OP(8a, OP_TXA ( REG_X ) ) /* TXA */ +OP(8b, OP_PHT ( ) ) /* PHT (G) */ +OP(8c, OP_STX ( REG_Y, A ) ) /* STY a */ +OP(8d, OP_STA ( A ) ) /* STA a */ +OP(8e, OP_STX ( REG_X, A ) ) /* STX a */ +OP(8f, OP_STA ( AL ) ) /* STA al (G) */ +OP(90, OP_BCC ( COND_CC() ) ) /* BCC */ +OP(91, OP_STA ( DIY ) ) /* STA diy */ +OP(92, OP_STA ( DI ) ) /* STA di (C) */ +OP(93, OP_STA ( SIY ) ) /* STA siy (G) */ +OP(94, OP_STX ( REG_Y, DX ) ) /* STY dx */ +OP(95, OP_STA ( DX ) ) /* STA dx */ +OP(96, OP_STX ( REG_X, DY ) ) /* STX dy */ +OP(97, OP_STA ( DLIY ) ) /* STA dliy(G) */ +OP(98, OP_TXA ( REG_Y ) ) /* TYA */ +OP(99, OP_STA ( AY ) ) /* STA ay */ +OP(9a, OP_TXS ( ) ) /* TXS */ +OP(9b, OP_TXY ( ) ) /* TXY (G) */ +OP(9c, OP_LDM ( A ) ) /* LDM a (C) */ +OP(9d, OP_STA ( AX ) ) /* STA ax */ +OP(9e, OP_LDM ( AX ) ) /* LDM ax (C) */ +OP(9f, OP_STA ( ALX ) ) /* STA alx (G) */ +OP(a0, OP_LDX ( REG_Y, IMM ) ) /* LDY imm */ +OP(a1, OP_LDA ( DXI ) ) /* LDA dxi */ +OP(a2, OP_LDX ( REG_X, IMM ) ) /* LDX imm */ +OP(a3, OP_LDA ( S ) ) /* LDA s (G) */ +OP(a4, OP_LDX ( REG_Y, D ) ) /* LDY d */ +OP(a5, OP_LDA ( D ) ) /* LDA d */ +OP(a6, OP_LDX ( REG_X, D ) ) /* LDX d */ +OP(a7, OP_LDA ( DLI ) ) /* LDA dli (G) */ +OP(a8, OP_TAX ( REG_Y ) ) /* TAY */ +OP(a9, OP_LDA ( IMM ) ) /* LDA imm */ +OP(aa, OP_TAX ( REG_X ) ) /* TAX */ +OP(ab, OP_PLT ( ) ) /* PLT (G) */ +OP(ac, OP_LDX ( REG_Y, A ) ) /* LDY a */ +OP(ad, OP_LDA ( A ) ) /* LDA a */ +OP(ae, OP_LDX ( REG_X, A ) ) /* LDX a */ +OP(af, OP_LDA ( AL ) ) /* LDA al (G) */ +OP(b0, OP_BCC ( COND_CS() ) ) /* BCS */ +OP(b1, OP_LDA ( DIY ) ) /* LDA diy */ +OP(b2, OP_LDA ( DI ) ) /* LDA di (C) */ +OP(b3, OP_LDA ( SIY ) ) /* LDA siy (G) */ +OP(b4, OP_LDX ( REG_Y, DX ) ) /* LDY dx */ +OP(b5, OP_LDA ( DX ) ) /* LDA dx */ +OP(b6, OP_LDX ( REG_X, DY ) ) /* LDX dy */ +OP(b7, OP_LDA ( DLIY ) ) /* LDA dliy(G) */ +OP(b8, OP_CLV ( ) ) /* CLV */ +OP(b9, OP_LDA ( AY ) ) /* LDA ay */ +OP(ba, OP_TSX ( ) ) /* TSX */ +OP(bb, OP_TYX ( ) ) /* TYX (G) */ +OP(bc, OP_LDX ( REG_Y, AX ) ) /* LDY ax */ +OP(bd, OP_LDA ( AX ) ) /* LDA ax */ +OP(be, OP_LDX ( REG_X, AY ) ) /* LDX ay */ +OP(bf, OP_LDA ( ALX ) ) /* LDA alx (G) */ +OP(c0, OP_CMPX ( REG_Y, IMM ) ) /* CPY imm */ +OP(c1, OP_CMP ( DXI ) ) /* CMP dxi */ +OP(c2, OP_REP ( ) ) /* REP (G) */ +OP(c3, OP_CMP ( S ) ) /* CMP s (G) */ +OP(c4, OP_CMPX ( REG_Y, D ) ) /* CPY d */ +OP(c5, OP_CMP ( D ) ) /* CMP d */ +OP(c6, OP_DECM ( D ) ) /* DEC d */ +OP(c7, OP_CMP ( DLI ) ) /* CMP dli (G) */ +OP(c8, OP_INCX ( REG_Y ) ) /* INY */ +OP(c9, OP_CMP ( IMM ) ) /* CMP imm */ +OP(ca, OP_DECX ( REG_X ) ) /* DEX */ +OP(cb, OP_WAI ( ) ) /* WAI (G) */ +OP(cc, OP_CMPX ( REG_Y, A ) ) /* CPY a */ +OP(cd, OP_CMP ( A ) ) /* CMP a */ +OP(ce, OP_DECM ( A ) ) /* DEC a */ +OP(cf, OP_CMP ( AL ) ) /* CMP al (G) */ +OP(d0, OP_BCC ( COND_NE() ) ) /* BNE */ +OP(d1, OP_CMP ( DIY ) ) /* CMP diy */ +OP(d2, OP_CMP ( DI ) ) /* CMP di (C) */ +OP(d3, OP_CMP ( SIY ) ) /* CMP siy (G) */ +OP(d4, OP_PEI ( ) ) /* PEI (G) */ +OP(d5, OP_CMP ( DX ) ) /* CMP dx */ +OP(d6, OP_DECM ( DX ) ) /* DEC dx */ +OP(d7, OP_CMP ( DLIY ) ) /* CMP dliy(G) */ +OP(d8, OP_CLM ( ) ) /* CLM */ +OP(d9, OP_CMP ( AY ) ) /* CMP ay */ +OP(da, OP_PHX ( REG_X ) ) /* PHX (C) */ +OP(db, OP_STP ( ) ) /* STP (G) */ +OP(dc, OP_JMLAI( ) ) /* JML ai (G) */ +OP(dd, OP_CMP ( AX ) ) /* CMP ax */ +OP(de, OP_DECM ( AX ) ) /* DEC ax */ +OP(df, OP_CMP ( ALX ) ) /* CMP alx (G) */ +OP(e0, OP_CMPX ( REG_X, IMM ) ) /* CPX imm */ +OP(e1, OP_SBC ( DXI ) ) /* SBC dxi */ +OP(e2, OP_SEP ( ) ) /* SEP imm (G) */ +OP(e3, OP_SBC ( S ) ) /* SBC s (G) */ +OP(e4, OP_CMPX ( REG_X, D ) ) /* CPX d */ +OP(e5, OP_SBC ( D ) ) /* SBC d */ +OP(e6, OP_INCM ( D ) ) /* INC d */ +OP(e7, OP_SBC ( DLI ) ) /* SBC dli (G) */ +OP(e8, OP_INCX ( REG_X ) ) /* INX */ +OP(e9, OP_SBC ( IMM ) ) /* SBC imm */ +OP(ea, OP_NOP ( ) ) /* NOP */ +OP(eb, OP_PSH ( IMM ) ) /* PSH imm */ +OP(ec, OP_CMPX ( REG_X, A ) ) /* CPX a */ +OP(ed, OP_SBC ( A ) ) /* SBC a */ +OP(ee, OP_INCM ( A ) ) /* INC a */ +OP(ef, OP_SBC ( AL ) ) /* SBC al (G) */ +OP(f0, OP_BCC ( COND_EQ() ) ) /* BEQ */ +OP(f1, OP_SBC ( DIY ) ) /* SBC diy */ +OP(f2, OP_SBC ( DI ) ) /* SBC di (C) */ +OP(f3, OP_SBC ( SIY ) ) /* SBC siy (G) */ +OP(f4, OP_PEA ( ) ) /* PEA (G) */ +OP(f5, OP_SBC ( DX ) ) /* SBC dx */ +OP(f6, OP_INCM ( DX ) ) /* INC dx */ +OP(f7, OP_SBC ( DLIY ) ) /* SBC dliy(G) */ +OP(f8, OP_SEM ( ) ) /* SEM */ +OP(f9, OP_SBC ( AY ) ) /* SBC ay */ +OP(fa, OP_PLX ( REG_X ) ) /* PLX (C) */ +OP(fb, OP_PUL ( IMM ) ) /* PUL imm */ +OP(fc, OP_JSRAXI( ) ) /* JSR axi (G) */ +OP(fd, OP_SBC ( AX ) ) /* SBC ax */ +OP(fe, OP_INCM ( AX ) ) /* INC ax */ +OP(ff, OP_SBC ( ALX ) ) /* SBC alx (G) */ + +/* B accumulator */ +OP(101,OP_ORB ( DXI ) ) /* ORB dxi */ +OP(103,OP_ORB ( S ) ) /* ORB s */ +OP(105,OP_ORB ( D ) ) /* ORB d */ +OP(107,OP_ORB ( DLI ) ) /* ORB dli */ +OP(109,OP_ORB ( IMM ) ) /* ORB imm */ +OP(10a,OP_BSL ( ) ) /* BSL acc */ +OP(10d,OP_ORB ( A ) ) /* ORB a */ +OP(10f,OP_ORB ( AL ) ) /* ORB al */ +OP(111,OP_ORB ( DIY ) ) /* ORB diy */ +OP(112,OP_ORB ( DI ) ) /* ORB di */ +OP(113,OP_ORB ( SIY ) ) /* ORB siy */ +OP(115,OP_ORB ( DX ) ) /* ORB dx */ +OP(117,OP_ORB ( DLIY ) ) /* ORB dliy */ +OP(119,OP_ORB ( AY ) ) /* ORB ay */ +OP(11a,OP_DECB ( ) ) /* DEB */ +OP(11b,OP_TBS ( ) ) /* TBS */ +OP(11d,OP_ORB ( AX ) ) /* ORB ax */ +OP(11f,OP_ORB ( ALX ) ) /* ORB alx */ +OP(121,OP_ANDB ( DXI ) ) /* ANDB dxi */ +OP(123,OP_ANDB ( S ) ) /* ANDB s */ +OP(125,OP_ANDB ( D ) ) /* ANDB d */ +OP(127,OP_ANDB ( DLI ) ) /* ANDB dli */ +OP(129,OP_ANDB ( IMM ) ) /* ANDB imm */ +OP(12a,OP_ROLB ( ) ) /* ROL Bacc */ +OP(12d,OP_ANDB ( A ) ) /* ANDB a */ +OP(12f,OP_ANDB ( AL ) ) /* ANDB al */ +OP(131,OP_ANDB ( DIY ) ) /* ANDB diy */ +OP(132,OP_ANDB ( DI ) ) /* ANDB di */ +OP(133,OP_ANDB ( SIY ) ) /* ANDB siy */ +OP(135,OP_ANDB ( DX ) ) /* ANDB dx */ +OP(137,OP_ANDB ( DLIY ) ) /* ANDB dliy */ +OP(139,OP_ANDB ( AY ) ) /* ANDB ay */ +OP(13a,OP_INCB ( ) ) /* INB */ +OP(13b,OP_TSB ( ) ) /* TSB */ +OP(13d,OP_ANDB ( AX ) ) /* ANDB ax */ +OP(13f,OP_ANDB ( ALX ) ) /* ANDB alx */ +OP(141,OP_EORB ( DXI ) ) /* EORB dxi */ +OP(143,OP_EORB ( S ) ) /* EORB s */ +OP(145,OP_EORB ( D ) ) /* EORB d */ +OP(147,OP_EORB ( DLI ) ) /* EORB dli */ +OP(148,OP_PHAB ( ) ) /* PHB */ +OP(149,OP_EORB ( IMM ) ) /* EORB imm */ +OP(14a,OP_LSRB ( ) ) /* LSRB acc */ +OP(14d,OP_EORB ( A ) ) /* EORB a */ +OP(14f,OP_EORB ( AL ) ) /* EORB al */ +OP(151,OP_EORB ( DIY ) ) /* EORB diy */ +OP(152,OP_EORB ( DI ) ) /* EORB di */ +OP(153,OP_EORB ( SIY ) ) /* EORB siy */ +OP(155,OP_EORB ( DX ) ) /* EORB dx */ +OP(157,OP_EORB ( DLIY ) ) /* EORB dliy */ +OP(159,OP_EORB ( AY ) ) /* EORB ay */ +OP(15b,OP_TBD ( ) ) /* TBD */ +OP(15d,OP_EORB ( AX ) ) /* EORB ax */ +OP(15f,OP_EORB ( ALX ) ) /* EORB alx */ +OP(161,OP_ADCB ( DXI ) ) /* ADCB dxi */ +OP(163,OP_ADCB ( S ) ) /* ADCB s */ +OP(165,OP_ADCB ( D ) ) /* ADCB d */ +OP(167,OP_ADCB ( DLI ) ) /* ADCB dli */ +OP(168,OP_PLAB ( ) ) /* PLB */ +OP(169,OP_ADCB ( IMM ) ) /* ADCB imm */ +OP(16a,OP_RORB ( ) ) /* ROR Bacc */ +OP(16d,OP_ADCB ( A ) ) /* ADCB a */ +OP(16f,OP_ADCB ( AL ) ) /* ADCB al */ +OP(171,OP_ADCB ( DIY ) ) /* ADCB diy */ +OP(172,OP_ADCB ( DI ) ) /* ADCB di */ +OP(173,OP_ADCB ( SIY ) ) /* ADCB siy */ +OP(175,OP_ADCB ( DX ) ) /* ADCB dx */ +OP(177,OP_ADCB ( DLIY ) ) /* ADCB dliy */ +OP(179,OP_ADCB ( AY ) ) /* ADCB ay */ +OP(17b,OP_TDB ( ) ) /* TDB */ +OP(17d,OP_ADCB ( AX ) ) /* ADCB ax */ +OP(17f,OP_ADCB ( ALX ) ) /* ADCB alx */ +OP(181,OP_STB ( DXI ) ) /* STB dxi */ +OP(183,OP_STB ( S ) ) /* STB s */ +OP(185,OP_STB ( D ) ) /* STB d */ +OP(187,OP_STB ( DLI ) ) /* STB dli */ +OP(18a,OP_TXB ( REG_X ) ) /* TXB */ +OP(18d,OP_STB ( A ) ) /* STB a */ +OP(18f,OP_STB ( AL ) ) /* STB al */ +OP(191,OP_STB ( DIY ) ) /* STB diy */ +OP(192,OP_STB ( DI ) ) /* STB di */ +OP(193,OP_STB ( SIY ) ) /* STB siy */ +OP(195,OP_STB ( DX ) ) /* STB dx */ +OP(197,OP_STB ( DLIY ) ) /* STB dliy */ +OP(198,OP_TXB ( REG_Y ) ) /* TYB */ +OP(199,OP_STB ( AY ) ) /* STB ay */ +OP(19d,OP_STB ( AX ) ) /* STB ax */ +OP(19f,OP_STB ( ALX ) ) /* STB alx */ +OP(1a1,OP_LDB ( DXI ) ) /* LDB dxi */ +OP(1a3,OP_LDB ( S ) ) /* LDB s */ +OP(1a5,OP_LDB ( D ) ) /* LDB d */ +OP(1a7,OP_LDB ( DLI ) ) /* LDB dli */ +OP(1a8,OP_TBX ( REG_Y ) ) /* TBY */ +OP(1a9,OP_LDB ( IMM ) ) /* LDB imm */ +OP(1aa,OP_TBX ( REG_X ) ) /* TBX */ +OP(1ad,OP_LDB ( A ) ) /* LDB a */ +OP(1af,OP_LDB ( AL ) ) /* LDB al */ +OP(1b1,OP_LDB ( DIY ) ) /* LDB diy */ +OP(1b2,OP_LDB ( DI ) ) /* LDB di */ +OP(1b3,OP_LDB ( SIY ) ) /* LDB siy */ +OP(1b5,OP_LDB ( DX ) ) /* LDB dx */ +OP(1b7,OP_LDB ( DLIY ) ) /* LDB dliy */ +OP(1b9,OP_LDB ( AY ) ) /* LDB ay */ +OP(1bd,OP_LDB ( AX ) ) /* LDB ax */ +OP(1bf,OP_LDB ( ALX ) ) /* LDB alx */ +OP(1c1,OP_CMPB ( DXI ) ) /* CMPB dxi */ +OP(1c3,OP_CMPB ( S ) ) /* CMPB s */ +OP(1c5,OP_CMPB ( D ) ) /* CMPB d */ +OP(1c7,OP_CMPB ( DLI ) ) /* CMPB dli */ +OP(1c9,OP_CMPB ( IMM ) ) /* CMPB imm */ +OP(1cd,OP_CMPB ( A ) ) /* CMPB a */ +OP(1cf,OP_CMPB ( AL ) ) /* CMPB al */ +OP(1d1,OP_CMPB ( DIY ) ) /* CMPB diy */ +OP(1d2,OP_CMPB ( DI ) ) /* CMPB di */ +OP(1d3,OP_CMPB ( SIY ) ) /* CMPB siy */ +OP(1d5,OP_CMPB ( DX ) ) /* CMPB dx */ +OP(1d7,OP_CMPB ( DLIY ) ) /* CMPB dliy */ +OP(1d9,OP_CMPB ( AY ) ) /* CMPB ay */ +OP(1dd,OP_CMPB ( AX ) ) /* CMPB ax */ +OP(1df,OP_CMPB ( ALX ) ) /* CMPB alx */ +OP(1e1,OP_SBCB ( DXI ) ) /* SBCB dxi */ +OP(1e3,OP_SBCB ( S ) ) /* SBCB s */ +OP(1e5,OP_SBCB ( D ) ) /* SBCB d */ +OP(1e7,OP_SBCB ( DLI ) ) /* SBCB dli */ +OP(1e9,OP_SBCB ( IMM ) ) /* SBCB imm */ +OP(1ed,OP_SBCB ( A ) ) /* SBCB a */ +OP(1ef,OP_SBCB ( AL ) ) /* SBCB al */ +OP(1f1,OP_SBCB ( DIY ) ) /* SBCB diy */ +OP(1f2,OP_SBCB ( DI ) ) /* SBCB di */ +OP(1f3,OP_SBCB ( SIY ) ) /* SBCB siy */ +OP(1f5,OP_SBCB ( DX ) ) /* SBCB dx */ +OP(1f7,OP_SBCB ( DLIY ) ) /* SBCB dliy */ +OP(1f9,OP_SBCB ( AY ) ) /* SBCB ay */ +OP(1fd,OP_SBCB ( AX ) ) /* SBCB ax */ +OP(1ff,OP_SBCB ( ALX ) ) /* SBCB alx */ + +OP(200,OP_UNIMP( ) ) /* unimplemented */ + +/* multiply/divide */ +OP(201,OP_MPY ( DXI ) ) /* MPY dxi */ +OP(203,OP_MPY ( S ) ) /* MPY s */ +OP(205,OP_MPY ( D ) ) /* MPY d */ +OP(207,OP_MPY ( DLI ) ) /* MPY dli */ +OP(209,OP_MPY ( IMM ) ) /* MPY imm */ +OP(20d,OP_MPY ( A ) ) /* MPY a */ +OP(20f,OP_MPY ( AL ) ) /* MPY al */ +OP(211,OP_MPY ( DIY ) ) /* MPY diy */ +OP(212,OP_MPY ( DI ) ) /* MPY di */ +OP(213,OP_MPY ( SIY ) ) /* MPY siy */ +OP(215,OP_MPY ( DX ) ) /* MPY dx */ +OP(217,OP_MPY ( DLIY ) ) /* MPY dliy */ +OP(219,OP_MPY ( AY ) ) /* MPY ay */ +OP(21d,OP_MPY ( AX ) ) /* MPY ax */ +OP(21f,OP_MPY ( ALX ) ) /* MPY alx */ +OP(221,OP_DIV ( DXI ) ) /* DIV dxi */ +OP(223,OP_DIV ( S ) ) /* DIV s */ +OP(225,OP_DIV ( D ) ) /* DIV d */ +OP(227,OP_DIV ( DLI ) ) /* DIV dli */ +OP(228,OP_XAB ( ) ) /* XAB */ +OP(229,OP_DIV ( IMM ) ) /* DIV imm */ +OP(22d,OP_DIV ( A ) ) /* DIV a */ +OP(22f,OP_DIV ( AL ) ) /* DIV al */ +OP(231,OP_DIV ( DIY ) ) /* DIV diy */ +OP(232,OP_DIV ( DI ) ) /* DIV di */ +OP(233,OP_DIV ( SIY ) ) /* DIV siy */ +OP(235,OP_DIV ( DX ) ) /* DIV dx */ +OP(237,OP_DIV ( DLIY ) ) /* DIV dliy */ +OP(239,OP_DIV ( AY ) ) /* DIV ay */ +OP(23d,OP_DIV ( AX ) ) /* DIV ax */ +OP(23f,OP_DIV ( ALX ) ) /* DIV alx */ +OP(249,OP_RLA ( IMM ) ) /* RLA imm */ +OP(2c2,OP_LDT ( IMM ) ) /* LDT imm */ +// note: block 28x-2bx is for 7750 opcodes, not implemented yet + +TABLE_OPCODES = +// 00 01 02 03 04 05 06 07 +// 08 09 0a 0b 0c 0d 0e 0f +{ + O(00), O(01), O(02), O(03), O(04), O(05), O(06), O(07), // 00 + O(08), O(09), O(0a), O(0b), O(0c), O(0d), O(0e), O(0f), + O(10), O(11), O(12), O(13), O(14), O(15), O(16), O(17), // 10 + O(18), O(19), O(1a), O(1b), O(1c), O(1d), O(1e), O(1f), + O(20), O(21), O(22), O(23), O(24), O(25), O(26), O(27), // 20 + O(28), O(29), O(2a), O(2b), O(2c), O(2d), O(2e), O(2f), + O(30), O(31), O(32), O(33), O(34), O(35), O(36), O(37), // 30 + O(38), O(39), O(3a), O(3b), O(3c), O(3d), O(3e), O(3f), + O(40), O(41), O(42), O(43), O(44), O(45), O(46), O(47), // 40 + O(48), O(49), O(4a), O(4b), O(4c), O(4d), O(4e), O(4f), + O(50), O(51), O(52), O(53), O(54), O(55), O(56), O(57), // 50 + O(58), O(59), O(5a), O(5b), O(5c), O(5d), O(5e), O(5f), + O(60), O(61), O(62), O(63), O(64), O(65), O(66), O(67), // 60 + O(68), O(69), O(6a), O(6b), O(6c), O(6d), O(6e), O(6f), + O(70), O(71), O(72), O(73), O(74), O(75), O(76), O(77), // 70 + O(78), O(79), O(7a), O(7b), O(7c), O(7d), O(7e), O(7f), + O(80), O(81), O(82), O(83), O(84), O(85), O(86), O(87), // 80 + O(88), O(89), O(8a), O(8b), O(8c), O(8d), O(8e), O(8f), + O(90), O(91), O(92), O(93), O(94), O(95), O(96), O(97), // 90 + O(98), O(99), O(9a), O(9b), O(9c), O(9d), O(9e), O(9f), + O(a0), O(a1), O(a2), O(a3), O(a4), O(a5), O(a6), O(a7), // a0 + O(a8), O(a9), O(aa), O(ab), O(ac), O(ad), O(ae), O(af), + O(b0), O(b1), O(b2), O(b3), O(b4), O(b5), O(b6), O(b7), // b0 + O(b8), O(b9), O(ba), O(bb), O(bc), O(bd), O(be), O(bf), + O(c0), O(c1), O(c2), O(c3), O(c4), O(c5), O(c6), O(c7), // c0 + O(c8), O(c9), O(ca), O(cb), O(cc), O(cd), O(ce), O(cf), + O(d0), O(d1), O(d2), O(d3), O(d4), O(d5), O(d6), O(d7), // d0 + O(d8), O(d9), O(da), O(db), O(dc), O(dd), O(de), O(df), + O(e0), O(e1), O(e2), O(e3), O(e4), O(e5), O(e6), O(e7), // e0 + O(e8), O(e9), O(ea), O(eb), O(ec), O(ed), O(ee), O(ef), + O(f0), O(f1), O(f2), O(f3), O(f4), O(f5), O(f6), O(f7), // f0 + O(f8), O(f9), O(fa), O(fb), O(fc), O(fd), O(fe), O(ff) +}; + +TABLE_OPCODES2 = +// 00 01 02 03 04 05 06 07 +// 08 09 0a 0b 0c 0d 0e 0f +{ + O(200),O(101),O(200),O(103),O(200),O(105),O(200),O(107), // 00 + O(200),O(109),O(10a),O(200),O(200),O(10d),O(200),O(10f), + O(200),O(111),O(112),O(113),O(200),O(115),O(200),O(117), // 10 + O(200),O(119),O(11a),O(11b),O(200),O(11d),O(200),O(11f), + O(200),O(121),O(200),O(123),O(200),O(125),O(200),O(127), // 20 + O(200),O(129),O(12a),O(200),O(200),O(12d),O(200),O(12f), + O(200),O(131),O(132),O(133),O(200),O(135),O(200),O(137), // 30 + O(200),O(139),O(13a),O(13b),O(200),O(13d),O(200),O(13f), + O(200),O(141),O(200),O(143),O(200),O(145),O(200),O(147), // 40 + O(148),O(149),O(14a),O(200),O(200),O(14d),O(200),O(14f), + O(200),O(151),O(152),O(153),O(200),O(155),O(200),O(157), // 50 + O(200),O(159),O(200),O(15b),O(200),O(15d),O(200),O(15f), + O(200),O(161),O(200),O(163),O(200),O(165),O(200),O(167), // 60 + O(168),O(169),O(16a),O(200),O(200),O(16d),O(200),O(16f), + O(200),O(171),O(172),O(173),O(200),O(175),O(200),O(177), // 70 + O(200),O(179),O(200),O(17b),O(200),O(17d),O(200),O(17f), + O(200),O(181),O(200),O(183),O(200),O(185),O(200),O(187), // 80 + O(200),O(200),O(18a),O(200),O(200),O(18d),O(200),O(18f), + O(200),O(191),O(192),O(193),O(200),O(195),O(200),O(197), // 90 + O(198),O(199),O(200),O(200),O(200),O(19d),O(200),O(19f), + O(200),O(1a1),O(200),O(1a3),O(200),O(1a5),O(200),O(1a7), // a0 + O(1a8),O(1a9),O(1aa),O(200),O(200),O(1ad),O(200),O(1af), + O(200),O(1b1),O(1b2),O(1b3),O(200),O(1b5),O(200),O(1b7), // b0 + O(200),O(1b9),O(200),O(200),O(200),O(1bd),O(200),O(1bf), + O(200),O(1c1),O(200),O(1c3),O(200),O(1c5),O(200),O(1c7), // c0 + O(200),O(1c9),O(200),O(200),O(200),O(1cd),O(200),O(1cf), + O(200),O(1d1),O(1d2),O(1d3),O(200),O(1d5),O(200),O(1d7), // d0 + O(200),O(1d9),O(200),O(200),O(200),O(1dd),O(200),O(1df), + O(200),O(1e1),O(200),O(1e3),O(200),O(1e5),O(200),O(1e7), // e0 + O(200),O(1e9),O(200),O(200),O(200),O(1ed),O(200),O(1ef), + O(200),O(1f1),O(1f2),O(1f3),O(200),O(1f5),O(200),O(1f7), // f0 + O(200),O(1f9),O(200),O(200),O(200),O(1fd),O(200),O(1ff) +}; + +TABLE_OPCODES3 = +// 00 01 02 03 04 05 06 07 +// 08 09 0a 0b 0c 0d 0e 0f +{ + O(200),O(201),O(200),O(203),O(200),O(205),O(200),O(207), // 00 + O(200),O(209),O(200),O(200),O(200),O(20d),O(200),O(20f), + O(200),O(211),O(212),O(213),O(200),O(215),O(200),O(217), // 10 + O(200),O(219),O(200),O(200),O(200),O(21d),O(200),O(21f), + O(200),O(221),O(200),O(223),O(200),O(225),O(200),O(227), // 20 + O(228),O(229),O(200),O(200),O(200),O(22d),O(200),O(22f), + O(200),O(231),O(232),O(233),O(200),O(235),O(200),O(237), // 30 + O(200),O(239),O(200),O(200),O(200),O(23d),O(200),O(23f), + O(200),O(200),O(200),O(200),O(200),O(200),O(200),O(200), // 40 + O(200),O(249),O(200),O(200),O(200),O(200),O(200),O(200), + O(200),O(200),O(200),O(200),O(200),O(200),O(200),O(200), // 50 + O(200),O(200),O(200),O(200),O(200),O(200),O(200),O(200), + O(200),O(200),O(200),O(200),O(200),O(200),O(200),O(200), // 60 + O(200),O(200),O(200),O(200),O(200),O(200),O(200),O(200), + O(200),O(200),O(200),O(200),O(200),O(200),O(200),O(200), // 70 + O(200),O(200),O(200),O(200),O(200),O(200),O(200),O(200), + O(200),O(200),O(200),O(200),O(200),O(200),O(200),O(200), // 80 + O(200),O(200),O(200),O(200),O(200),O(200),O(200),O(200), + O(200),O(200),O(200),O(200),O(200),O(200),O(200),O(200), // 90 + O(200),O(200),O(200),O(200),O(200),O(200),O(200),O(200), + O(200),O(200),O(200),O(200),O(200),O(200),O(200),O(200), // a0 + O(200),O(200),O(200),O(200),O(200),O(200),O(200),O(200), + O(200),O(200),O(200),O(200),O(200),O(200),O(200),O(200), // b0 + O(200),O(200),O(200),O(200),O(200),O(200),O(200),O(200), + O(200),O(200),O(2c2),O(200),O(200),O(200),O(200),O(200), // c0 + O(200),O(200),O(200),O(200),O(200),O(200),O(200),O(200), + O(200),O(200),O(200),O(200),O(200),O(200),O(200),O(200), // d0 + O(200),O(200),O(200),O(200),O(200),O(200),O(200),O(200), + O(200),O(200),O(200),O(200),O(200),O(200),O(200),O(200), // e0 + O(200),O(200),O(200),O(200),O(200),O(200),O(200),O(200), + O(200),O(200),O(200),O(200),O(200),O(200),O(200),O(200), // f0 + O(200),O(200),O(200),O(200),O(200),O(200),O(200),O(200) +}; + + +/* Assert or clear a line on the CPU */ +TABLE_FUNCTION(void, set_line, (int line, int state)) +{ + switch(line) + { + // maskable interrupts + case M37710_LINE_ADC: + case M37710_LINE_UART1XMIT: + case M37710_LINE_UART1RECV: + case M37710_LINE_UART0XMIT: + case M37710_LINE_UART0RECV: + case M37710_LINE_TIMERB2: + case M37710_LINE_TIMERB1: + case M37710_LINE_TIMERB0: + case M37710_LINE_TIMERA4: + case M37710_LINE_TIMERA3: + case M37710_LINE_TIMERA2: + case M37710_LINE_TIMERA1: + case M37710_LINE_TIMERA0: + case M37710_LINE_IRQ2: + case M37710_LINE_IRQ1: + case M37710_LINE_IRQ0: + switch(state) + { + case CLEAR_LINE: + LINE_IRQ &= ~(1 << line); + if (m37710_irq_levels[line]) + { + m377.m37710_regs[m37710_irq_levels[line]] &= ~8; + } + break; + + case ASSERT_LINE: + case PULSE_LINE: + case HOLD_LINE: + LINE_IRQ |= (1 << line); + if (m37710_irq_levels[line]) + { + m377.m37710_regs[m37710_irq_levels[line]] |= 8; + } + break; + + default: break; + } + break; + + default: break; + } +} + + + +/* Get a register from the CPU core */ +TABLE_FUNCTION(UINT32, get_reg, (int regnum)) +{ + switch(regnum) + { + case M37710_A: return REG_B | REG_A; + case M37710_B: return REG_BB | REG_BA; + case M37710_X: return REG_X; + case M37710_Y: return REG_Y; + case M37710_S: return REG_S; + case M37710_PC: return REG_PC; + case M37710_PB: return REG_PB >> 16; + case M37710_DB: return REG_DB >> 16; + case M37710_D: return REG_D; + case M37710_P: return m37710i_get_reg_p(); + case M37710_IRQ_STATE: return LINE_IRQ; + case STATE_GENPCBASE: return REG_PPC; + } + return 0; +} + +TABLE_FUNCTION(void, set_reg, (int regnum, UINT32 val)) +{ + switch(regnum) + { + case M37710_PC: REG_PC = MAKE_UINT_16(val); break; + case M37710_S: REG_S = MAKE_UINT_16(val); break; + case M37710_P: m37710i_set_reg_p(val); break; +#if FLAG_SET_M + case M37710_A: REG_A = MAKE_UINT_8(val); REG_B = val&0xff00; break; + case M37710_B: REG_BA = MAKE_UINT_8(val); REG_BB = val&0xff00; break; +#else + case M37710_A: REG_A = MAKE_UINT_16(val); break; + case M37710_B: REG_BA = MAKE_UINT_16(val); break; +#endif +#if FLAG_SET_X + case M37710_X: REG_X = MAKE_UINT_8(val); break; + case M37710_Y: REG_Y = MAKE_UINT_8(val); break; +#else + case M37710_X: REG_X = MAKE_UINT_16(val); break; + case M37710_Y: REG_Y = MAKE_UINT_16(val); break; +#endif + case M37710_IRQ_STATE: (*FTABLE_SET_LINE)(M37710_LINE_IRQ0, val == 0 ? CLEAR_LINE : ASSERT_LINE); break; + } +} + +TABLE_FUNCTION(int, execute, (int clocks)) +{ + if(!CPU_STOPPED) + { + CLOCKS = clocks; + do + { + REG_PPC = REG_PC; + //M37710_CALL_DEBUGGER(REG_PB | REG_PC); + REG_PC++; + REG_IR = read_8_IMM(REG_PB | REG_PPC); + (*m_opcodes[REG_IR])(); + } while(CLOCKS > 0 && !m377.end_run); + return CLOCKS; // CLOCKS is m377.ICount + } + CLOCKS = 0; + return 0; +} + + +/* ======================================================================== */ +/* ================================== EOF ================================= */ +/* ======================================================================== */ +#undef TABLE_OPCODES2 +#undef TABLE_OPCODES3