From c67700a1c40ef8cbcc6c68e3381346b3e91a0a8c Mon Sep 17 00:00:00 2001 From: c1570 Date: Tue, 13 Jan 2026 12:05:15 +0100 Subject: [PATCH] m65c02 --- chips/m65c02.h | 3109 +++++++++++++++++++++++++++++++++++++++++ codegen/m6502_gen.sh | 1 + codegen/m65c02_gen.py | 1028 ++++++++++++++ 3 files changed, 4138 insertions(+) create mode 100644 chips/m65c02.h create mode 100644 codegen/m65c02_gen.py diff --git a/chips/m65c02.h b/chips/m65c02.h new file mode 100644 index 00000000..4972b784 --- /dev/null +++ b/chips/m65c02.h @@ -0,0 +1,3109 @@ +#pragma once +/*# + # m65c02.h + + WDC65C02 CPU emulator. + WIP! But runs 65C02_extended_opcodes_test.bin just fine. + https://github.com/floooh/chips/pull/113 + + Project repo: https://github.com/floooh/chips/ + + NOTE: this file is code-generated using m65c02_gen.py + in the 'codegen' directory. + + Do this: + ~~~C + #define CHIPS_IMPL + ~~~ + before you include this file in *one* C or C++ file to create the + implementation. + + Optionally provide the following macros with your own implementation + ~~~C + CHIPS_ASSERT(c) + ~~~ + + ## Emulated Pins + + *********************************** + * +-----------+ * + * IRQ --->| |---> A0 * + * NMI --->| |... * + * RDY--->| |---> A15 * + * RES--->| | * + * RW <---| | * + * SYNC <---| | * + * | |<--> D0 * + * (P0)<-->| |... * + * ...| |<--> D7 * + * (P5)<-->| | * + * +-----------+ * + *********************************** + + The input/output P0..P5 pins only exist on the __hidden_m6510. + + If the RDY pin is active (1) the CPU will loop on the next read + access until the pin goes inactive. + + ## Overview + + m65c02.h implements a cycle-stepped WDC65C02 CPU emulator, meaning + that the emulation state can be ticked forward in clock cycles instead + of full instructions. + + To initialize the emulator, fill out a m65c02_desc_t structure with + initialization parameters and then call m65c02_init(). + + ~~~C + typedef struct { + bool bcd_disabled; // set to true if BCD mode is disabled + __hidden_m6510_in_t in_cb; // only __hidden_m6510: port IO input callback + __hidden_m6510_out_t out_cb; // only __hidden_m6510: port IO output callback + uint8_t __hidden_m6510_io_pullup; // only __hidden_m6510: IO port bits that are 1 when reading + uint8_t __hidden_m6510_io_floating; // only __hidden_m6510: unconnected IO port pins + void* __hidden_m6510_user_data; // only __hidden_m6510: optional in/out callback user data + } m65c02_desc_t; + ~~~ + + At the end of m65c02_init(), the CPU emulation will be at the start of + RESET state, and the first 7 ticks will execute the reset sequence + (loading the reset vector at address 0xFFFC and continuing execution + there. + + m65c02_init() will return a 64-bit pin mask which must be the input argument + to the first call of m65c02_tick(). + + To execute instructions, call m65c02_tick() in a loop. m65c02_tick() takes + a 64-bit pin mask as input, executes one clock tick, and returns + a modified pin mask. + + After executing one tick, the pin mask must be inspected, a memory read + or write operation must be performed, and the modified pin mask must be + used for the next call to m65c02_tick(). This 64-bit pin mask is how + the CPU emulation communicates with the outside world. + + The simplest-possible execution loop would look like this: + + ~~~C + // setup 64 kBytes of memory + uint8_t mem[1<<16] = { ... }; + // initialize the CPU + m65c02_t cpu; + uint64_t pins = m65c02_init(&cpu, &(m65c02_desc_t){...}); + while (...) { + // run the CPU emulation for one tick + pins = m65c02_tick(&cpu, pins); + // extract 16-bit address from pin mask + const uint16_t addr = M65C02_GET_ADDR(pins); + // perform memory access + if (pins & M65C02_RW) { + // a memory read + M65C02_SET_DATA(pins, mem[addr]); + } + else { + // a memory write + mem[addr] = M65C02_GET_DATA(pins); + } + } + ~~~ + + To start a reset sequence, set the M65C02_RES bit in the pin mask and + continue calling the m65c02_tick() function. At the start of the next + instruction, the CPU will initiate the 7-tick reset sequence. You do NOT + need to clear the M65C02_RES bit, this will be cleared when the reset + sequence starts. + + To request an interrupt, set the M65C02_IRQ or M65C02_NMI bits in the pin + mask and continue calling the tick function. The interrupt sequence + will be initiated at the end of the current or next instruction + (depending on the exact cycle the interrupt pin has been set). + + Unlike the M65C02_RES pin, you are also responsible for clearing the + interrupt pins (typically, the interrupt lines are cleared by the chip + which requested the interrupt once the CPU reads a chip's interrupt + status register to check which chip requested the interrupt). + + To find out whether a new instruction is about to start, check if the + M65C02_SYNC pin is set. + + To "goto" a random address at any time, a 'prefetch' like this is + necessary (this basically simulates a normal instruction fetch from + address 'next_pc'). This is usually only needed in "trap code" which + intercepts operating system calls, executes some native code to emulate + the operating system call, and then continue execution somewhere else: + + ~~~C + pins = M65C02_SYNC; + M65C02_SET_ADDR(pins, next_pc); + M65C02_SET_DATA(pins, mem[next_pc]); + m65c02_set_pc(next_pc); + ~~~~ + + ## Functions + ~~~C + uint64_t m65c02_init(m65c02_t* cpu, const m65c02_desc_t* desc) + ~~~ + Initialize a m65c02_t instance, the desc structure provides + initialization attributes: + ~~~C + typedef struct { + bool bcd_disabled; // set to true if BCD mode is disabled + __hidden_m6510_in_t __hidden_m6510_in_cb; // __hidden_m6510 only: optional port IO input callback + __hidden_m6510_out_t __hidden_m6510_out_cb; // __hidden_m6510 only: optional port IO output callback + void* __hidden_m6510_user_data; // __hidden_m6510 only: optional callback user data + uint8_t __hidden_m6510_io_pullup; // __hidden_m6510 only: IO port bits that are 1 when reading + uint8_t __hidden_m6510_io_floating; // __hidden_m6510 only: unconnected IO port pins + } m65c02_desc_t; + ~~~ + + To emulate a __hidden_m6510 you must provide port IO callbacks in __hidden_m6510_in_cb + and __hidden_m6510_out_cb, and should initialize the __hidden_m6510_io_pullup and + __hidden_m6510_io_floating members to indicate which of the IO pins are + connected or hardwired to a 1-state. + + ~~~C + uint64_t m65c02_tick(m65c02_t* cpu, uint64_t pins) + ~~~ + Tick the CPU for one clock cycle. The 'pins' argument and return value + is the current state of the CPU pins used to communicate with the + outside world (see the Overview section above for details). + + ~~~C + uint64_t __hidden_m6510_iorq(m65c02_t* cpu, uint64_t pins) + ~~~ + For the 6510, call this function after the tick callback when memory + access to the special addresses 0 and 1 are requested. __hidden_m6510_iorq() + may call the input/output callback functions provided in m65c02_desc_t. + + ~~~C + void m65c02_set_x(m65c02_t* cpu, uint8_t val) + void m65c02_set_xx(m65c02_t* cpu, uint16_t val) + uint8_t m65c02_x(m65c02_t* cpu) + uint16_t m65c02_xx(m65c02_t* cpu) + ~~~ + Set and get 6502 registers and flags. + + + ## zlib/libpng license + + Copyright (c) 2018 Andre Weissflog + This software is provided 'as-is', without any express or implied warranty. + In no event will the authors be held liable for any damages arising from the + use of this software. + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software in a + product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not + be misrepresented as being the original software. + 3. This notice may not be removed or altered from any source + distribution. +#*/ +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +// address bus pins +#define M65C02_PIN_A0 (0) +#define M65C02_PIN_A1 (1) +#define M65C02_PIN_A2 (2) +#define M65C02_PIN_A3 (3) +#define M65C02_PIN_A4 (4) +#define M65C02_PIN_A5 (5) +#define M65C02_PIN_A6 (6) +#define M65C02_PIN_A7 (7) +#define M65C02_PIN_A8 (8) +#define M65C02_PIN_A9 (9) +#define M65C02_PIN_A10 (10) +#define M65C02_PIN_A11 (11) +#define M65C02_PIN_A12 (12) +#define M65C02_PIN_A13 (13) +#define M65C02_PIN_A14 (14) +#define M65C02_PIN_A15 (15) + +// data bus pins +#define M65C02_PIN_D0 (16) +#define M65C02_PIN_D1 (17) +#define M65C02_PIN_D2 (18) +#define M65C02_PIN_D3 (19) +#define M65C02_PIN_D4 (20) +#define M65C02_PIN_D5 (21) +#define M65C02_PIN_D6 (22) +#define M65C02_PIN_D7 (23) + +// control pins +#define M65C02_PIN_RW (24) // out: memory read or write access +#define M65C02_PIN_SYNC (25) // out: start of a new instruction +#define M65C02_PIN_IRQ (26) // in: maskable interrupt requested +#define M65C02_PIN_NMI (27) // in: non-maskable interrupt requested +#define M65C02_PIN_RDY (28) // in: freeze execution at next read cycle +#define __hidden_M6510_PIN_AEC (29) // in, __hidden_m6510 only, put bus lines into tristate mode, not implemented +#define M65C02_PIN_RES (30) // request RESET + +// __hidden_m6510 IO port pins +#define __hidden_M6510_PIN_P0 (32) +#define __hidden_M6510_PIN_P1 (33) +#define __hidden_M6510_PIN_P2 (34) +#define __hidden_M6510_PIN_P3 (35) +#define __hidden_M6510_PIN_P4 (36) +#define __hidden_M6510_PIN_P5 (37) + +// pin bit masks +#define M65C02_A0 (1ULL<>16)) +/* merge 8-bit data bus value into 64-bit pins */ +#define M65C02_SET_DATA(p,d) {p=(((p)&~0xFF0000ULL)|(((d)<<16)&0xFF0000ULL));} +/* copy data bus value from other pin mask */ +#define M65C02_COPY_DATA(p0,p1) (((p0)&~0xFF0000ULL)|((p1)&0xFF0000ULL)) +/* return a pin mask with control-pins, address and data bus */ +#define M65C02_MAKE_PINS(ctrl, addr, data) ((ctrl)|(((data)<<16)&0xFF0000ULL)|((addr)&0xFFFFULL)) +/* set the port bits on the 64-bit pin mask */ +#define __hidden_M6510_SET_PORT(p,d) {p=(((p)&~__hidden_M6510_PORT_BITS)|((((uint64_t)(d))<<32)&__hidden_M6510_PORT_BITS));} +/* __hidden_M6510: check for IO port access to address 0 or 1 */ +#define __hidden_M6510_CHECK_IO(p) (((p)&0xFFFEULL)==0) + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +/*-- IMPLEMENTATION ----------------------------------------------------------*/ +#ifdef CHIPS_IMPL +#include +#ifndef CHIPS_ASSERT + #include + #define CHIPS_ASSERT(c) assert(c) +#endif + +#if defined(__GNUC__) +#define _M65C02_UNREACHABLE __builtin_unreachable() +#elif defined(_MSC_VER) +#define _M65C02_UNREACHABLE __assume(0) +#else +#define _M65C02_UNREACHABLE +#endif + +/* register access functions */ +void m65c02_set_a(m65c02_t* cpu, uint8_t v) { cpu->A = v; } +void m65c02_set_x(m65c02_t* cpu, uint8_t v) { cpu->X = v; } +void m65c02_set_y(m65c02_t* cpu, uint8_t v) { cpu->Y = v; } +void m65c02_set_s(m65c02_t* cpu, uint8_t v) { cpu->S = v; } +void m65c02_set_p(m65c02_t* cpu, uint8_t v) { cpu->P = v; } +void m65c02_set_pc(m65c02_t* cpu, uint16_t v) { cpu->PC = v; } +uint8_t m65c02_a(m65c02_t* cpu) { return cpu->A; } +uint8_t m65c02_x(m65c02_t* cpu) { return cpu->X; } +uint8_t m65c02_y(m65c02_t* cpu) { return cpu->Y; } +uint8_t m65c02_s(m65c02_t* cpu) { return cpu->S; } +uint8_t m65c02_p(m65c02_t* cpu) { return cpu->P; } +uint16_t m65c02_pc(m65c02_t* cpu) { return cpu->PC; } + +/* helper macros and functions for code-generated instruction decoder */ +#define _M65C02_NZ(p,v) ((p&~(M65C02_NF|M65C02_ZF))|((v&0xFF)?(v&M65C02_NF):M65C02_ZF)) + +static inline void _m65c02_adc(m65c02_t* cpu, uint8_t val) { + if (cpu->bcd_enabled && (cpu->P & M65C02_DF)) { + /* decimal mode (credit goes to MAME) */ + uint8_t c = cpu->P & M65C02_CF ? 1 : 0; + cpu->P &= ~(M65C02_NF|M65C02_VF|M65C02_ZF|M65C02_CF); + uint8_t al = (cpu->A & 0x0F) + (val & 0x0F) + c; + if (al > 9) { + al += 6; + } + uint8_t ah = (cpu->A >> 4) + (val >> 4) + (al > 0x0F); + if (0 == (uint8_t)(cpu->A + val + c)) { + cpu->P |= M65C02_ZF; + } + else if (ah & 0x08) { + cpu->P |= M65C02_NF; + } + if (~(cpu->A^val) & (cpu->A^(ah<<4)) & 0x80) { + cpu->P |= M65C02_VF; + } + if (ah > 9) { + ah += 6; + } + if (ah > 15) { + cpu->P |= M65C02_CF; + } + cpu->A = (ah<<4) | (al & 0x0F); + } + else { + /* default mode */ + uint16_t sum = cpu->A + val + (cpu->P & M65C02_CF ? 1:0); + cpu->P &= ~(M65C02_VF|M65C02_CF); + cpu->P = _M65C02_NZ(cpu->P,sum); + if (~(cpu->A^val) & (cpu->A^sum) & 0x80) { + cpu->P |= M65C02_VF; + } + if (sum & 0xFF00) { + cpu->P |= M65C02_CF; + } + cpu->A = sum & 0xFF; + } +} + +static inline void _m65c02_sbc(m65c02_t* cpu, uint8_t val) { + if (cpu->bcd_enabled && (cpu->P & M65C02_DF)) { + /* decimal mode (credit goes to MAME) */ + uint8_t c = cpu->P & M65C02_CF ? 0 : 1; + cpu->P &= ~(M65C02_NF|M65C02_VF|M65C02_ZF|M65C02_CF); + uint16_t diff = cpu->A - val - c; + uint8_t al = (cpu->A & 0x0F) - (val & 0x0F) - c; + if ((int8_t)al < 0) { + al -= 6; + } + uint8_t ah = (cpu->A>>4) - (val>>4) - ((int8_t)al < 0); + if (0 == (uint8_t)diff) { + cpu->P |= M65C02_ZF; + } + else if (diff & 0x80) { + cpu->P |= M65C02_NF; + } + if ((cpu->A^val) & (cpu->A^diff) & 0x80) { + cpu->P |= M65C02_VF; + } + if (!(diff & 0xFF00)) { + cpu->P |= M65C02_CF; + } + if (ah & 0x80) { + ah -= 6; + } + cpu->A = (ah<<4) | (al & 0x0F); + } + else { + /* default mode */ + uint16_t diff = cpu->A - val - (cpu->P & M65C02_CF ? 0 : 1); + cpu->P &= ~(M65C02_VF|M65C02_CF); + cpu->P = _M65C02_NZ(cpu->P, (uint8_t)diff); + if ((cpu->A^val) & (cpu->A^diff) & 0x80) { + cpu->P |= M65C02_VF; + } + if (!(diff & 0xFF00)) { + cpu->P |= M65C02_CF; + } + cpu->A = diff & 0xFF; + } +} + +static inline void _m65c02_cmp(m65c02_t* cpu, uint8_t r, uint8_t v) { + uint16_t t = r - v; + cpu->P = (_M65C02_NZ(cpu->P, (uint8_t)t) & ~M65C02_CF) | ((t & 0xFF00) ? 0:M65C02_CF); +} + +static inline uint8_t _m65c02_asl(m65c02_t* cpu, uint8_t v) { + cpu->P = (_M65C02_NZ(cpu->P, v<<1) & ~M65C02_CF) | ((v & 0x80) ? M65C02_CF:0); + return v<<1; +} + +static inline uint8_t _m65c02_lsr(m65c02_t* cpu, uint8_t v) { + cpu->P = (_M65C02_NZ(cpu->P, v>>1) & ~M65C02_CF) | ((v & 0x01) ? M65C02_CF:0); + return v>>1; +} + +static inline uint8_t _m65c02_rol(m65c02_t* cpu, uint8_t v) { + bool carry = cpu->P & M65C02_CF; + cpu->P &= ~(M65C02_NF|M65C02_ZF|M65C02_CF); + if (v & 0x80) { + cpu->P |= M65C02_CF; + } + v <<= 1; + if (carry) { + v |= 1; + } + cpu->P = _M65C02_NZ(cpu->P, v); + return v; +} + +static inline uint8_t _m65c02_ror(m65c02_t* cpu, uint8_t v) { + bool carry = cpu->P & M65C02_CF; + cpu->P &= ~(M65C02_NF|M65C02_ZF|M65C02_CF); + if (v & 1) { + cpu->P |= M65C02_CF; + } + v >>= 1; + if (carry) { + v |= 0x80; + } + cpu->P = _M65C02_NZ(cpu->P, v); + return v; +} + +static inline void _m65c02_bit(m65c02_t* cpu, uint8_t v) { + uint8_t t = cpu->A & v; + cpu->P &= ~(M65C02_NF|M65C02_VF|M65C02_ZF); + if (!t) { + cpu->P |= M65C02_ZF; + } + cpu->P |= v & (M65C02_NF|M65C02_VF); +} + +static inline void _m65c02_arr(m65c02_t* cpu) { + /* undocumented, unreliable ARR instruction, but this is tested + by the Wolfgang Lorenz C64 test suite + implementation taken from MAME + */ + if (cpu->bcd_enabled && (cpu->P & M65C02_DF)) { + bool c = cpu->P & M65C02_CF; + cpu->P &= ~(M65C02_NF|M65C02_VF|M65C02_ZF|M65C02_CF); + uint8_t a = cpu->A>>1; + if (c) { + a |= 0x80; + } + cpu->P = _M65C02_NZ(cpu->P,a); + if ((a ^ cpu->A) & 0x40) { + cpu->P |= M65C02_VF; + } + if ((cpu->A & 0xF) >= 5) { + a = ((a + 6) & 0xF) | (a & 0xF0); + } + if ((cpu->A & 0xF0) >= 0x50) { + a += 0x60; + cpu->P |= M65C02_CF; + } + cpu->A = a; + } + else { + bool c = cpu->P & M65C02_CF; + cpu->P &= ~(M65C02_NF|M65C02_VF|M65C02_ZF|M65C02_CF); + cpu->A >>= 1; + if (c) { + cpu->A |= 0x80; + } + cpu->P = _M65C02_NZ(cpu->P,cpu->A); + if (cpu->A & 0x40) { + cpu->P |= M65C02_VF|M65C02_CF; + } + if (cpu->A & 0x20) { + cpu->P ^= M65C02_VF; + } + } +} + +/* undocumented SBX instruction: + AND X register with accumulator and store result in X register, then + subtract byte from X register (without borrow) where the + subtract works like a CMP instruction +*/ +static inline void _m65c02_sbx(m65c02_t* cpu, uint8_t v) { + uint16_t t = (cpu->A & cpu->X) - v; + cpu->P = _M65C02_NZ(cpu->P, t) & ~M65C02_CF; + if (!(t & 0xFF00)) { + cpu->P |= M65C02_CF; + } + cpu->X = (uint8_t)t; +} +#undef _M65C02_NZ + +uint64_t m65c02_init(m65c02_t* c, const m65c02_desc_t* desc) { + CHIPS_ASSERT(c && desc); + memset(c, 0, sizeof(*c)); + c->P = M65C02_ZF; + c->bcd_enabled = !desc->bcd_disabled; + c->PINS = M65C02_RW | M65C02_SYNC | M65C02_RES; + c->in_cb = desc->__hidden_m6510_in_cb; + c->out_cb = desc->__hidden_m6510_out_cb; + c->user_data = desc->__hidden_m6510_user_data; + c->io_pullup = desc->__hidden_m6510_io_pullup; + c->io_floating = desc->__hidden_m6510_io_floating; + return c->PINS; +} + +/* only call this when accessing address 0 or 1 (__hidden_M6510_CHECK_IO(pins) evaluates to true) */ +uint64_t __hidden_m6510_iorq(m65c02_t* c, uint64_t pins) { + CHIPS_ASSERT(c->in_cb && c->out_cb); + if ((pins & M65C02_A0) == 0) { + /* address 0: access to data direction register */ + if (pins & M65C02_RW) { + /* read IO direction bits */ + M65C02_SET_DATA(pins, c->io_ddr); + } + else { + /* write IO direction bits and update outside world */ + c->io_ddr = M65C02_GET_DATA(pins); + c->io_drive = (c->io_out & c->io_ddr) | (c->io_drive & ~c->io_ddr); + c->out_cb((c->io_out & c->io_ddr) | (c->io_pullup & ~c->io_ddr), c->user_data); + c->io_pins = (c->io_out & c->io_ddr) | (c->io_inp & ~c->io_ddr); + } + } + else { + /* address 1: perform I/O */ + if (pins & M65C02_RW) { + /* an input operation */ + c->io_inp = c->in_cb(c->user_data); + uint8_t val = ((c->io_inp | (c->io_floating & c->io_drive)) & ~c->io_ddr) | (c->io_out & c->io_ddr); + M65C02_SET_DATA(pins, val); + } + else { + /* an output operation */ + c->io_out = M65C02_GET_DATA(pins); + c->io_drive = (c->io_out & c->io_ddr) | (c->io_drive & ~c->io_ddr); + c->out_cb((c->io_out & c->io_ddr) | (c->io_pullup & ~c->io_ddr), c->user_data); + } + c->io_pins = (c->io_out & c->io_ddr) | (c->io_inp & ~c->io_ddr); + } + return pins; +} + +void m65c02_snapshot_onsave(m65c02_t* snapshot) { + CHIPS_ASSERT(snapshot); + snapshot->in_cb = 0; + snapshot->out_cb = 0; + snapshot->user_data = 0; +} + +void m65c02_snapshot_onload(m65c02_t* snapshot, m65c02_t* sys) { + CHIPS_ASSERT(snapshot && sys); + snapshot->in_cb = sys->in_cb; + snapshot->out_cb = sys->out_cb; + snapshot->user_data = sys->user_data; +} + +/* set 16-bit address in 64-bit pin mask */ +#define _SA(addr) pins=(pins&~0xFFFF)|((addr)&0xFFFFULL) +/* extract 16-bit addess from pin mask */ +#define _GA() ((uint16_t)(pins&0xFFFFULL)) +/* set 16-bit address and 8-bit data in 64-bit pin mask */ +#define _SAD(addr,data) pins=(pins&~0xFFFFFF)|((((data)&0xFF)<<16)&0xFF0000ULL)|((addr)&0xFFFFULL) +/* fetch next opcode byte */ +#define _FETCH() _SA(c->PC);_ON(M65C02_SYNC); +/* set 8-bit data in 64-bit pin mask */ +#define _SD(data) pins=((pins&~0xFF0000ULL)|((((data)&0xFF)<<16)&0xFF0000ULL)) +/* extract 8-bit data from 64-bit pin mask */ +#define _GD() ((uint8_t)((pins&0xFF0000ULL)>>16)) +/* enable control pins */ +#define _ON(m) pins|=(m) +/* disable control pins */ +#define _OFF(m) pins&=~(m) +/* a memory read tick */ +#define _RD() _ON(M65C02_RW); +/* a memory write tick */ +#define _WR() _OFF(M65C02_RW); +/* set N and Z flags depending on value */ +#define _NZ(v) c->P=((c->P&~(M65C02_NF|M65C02_ZF))|((v&0xFF)?(v&M65C02_NF):M65C02_ZF)) + +#if defined(_MSC_VER) +#pragma warning(push) +#pragma warning(disable:4244) /* conversion from 'uint16_t' to 'uint8_t', possible loss of data */ +#endif + +uint64_t m65c02_tick(m65c02_t* c, uint64_t pins) { + if (pins & (M65C02_SYNC|M65C02_IRQ|M65C02_NMI|M65C02_RDY|M65C02_RES)) { + // interrupt detection also works in RDY phases, but only NMI is "sticky" + + // NMI is edge-triggered + if (0 != ((pins & (pins ^ c->PINS)) & M65C02_NMI)) { + c->nmi_pip |= 0x100; + } + // IRQ test is level triggered + if ((pins & M65C02_IRQ) && (0 == (c->P & M65C02_IF))) { + c->irq_pip |= 0x100; + } + + // RDY pin is only checked during read cycles + if ((pins & (M65C02_RW|M65C02_RDY)) == (M65C02_RW|M65C02_RDY)) { + __hidden_M6510_SET_PORT(pins, c->io_pins); + c->PINS = pins; + c->irq_pip <<= 1; + return pins; + } + if (pins & M65C02_SYNC) { + // load new instruction into 'instruction register' and restart tick counter + c->IR = _GD()<<3; + _OFF(M65C02_SYNC); + + // check IRQ, NMI and RES state + // - IRQ is level-triggered and must be active in the full cycle + // before SYNC + // - NMI is edge-triggered, and the change must have happened in + // any cycle before SYNC + // - RES behaves slightly different than on a real 6502, we go + // into RES state as soon as the pin goes active, from there + // on, behaviour is 'standard' + if (0 != (c->irq_pip & 0x400)) { + c->brk_flags |= M65C02_BRK_IRQ; + } + if (0 != (c->nmi_pip & 0xFC00)) { + c->brk_flags |= M65C02_BRK_NMI; + } + if (0 != (pins & M65C02_RES)) { + c->brk_flags |= M65C02_BRK_RESET; + c->io_ddr = 0; + c->io_out = 0; + c->io_inp = 0; + c->io_pins = 0; + } + c->irq_pip &= 0x3FF; + c->nmi_pip &= 0x3FF; + + // if interrupt or reset was requested, force a BRK instruction + if (c->brk_flags) { + c->IR = 0; + c->P &= ~M65C02_BF; + pins &= ~M65C02_RES; + } + else { + c->PC++; + } + } + } + // reads are default, writes are special + _RD(); + switch (c->IR++) { + // <% decoder + /* BRK */ + case (0x00<<3)|0: _SA(c->PC);break; + case (0x00<<3)|1: if(0==(c->brk_flags&(M65C02_BRK_IRQ|M65C02_BRK_NMI))){c->PC++;}_SAD(0x0100|c->S--,c->PC>>8);if(0==(c->brk_flags&M65C02_BRK_RESET)){_WR();}break; + case (0x00<<3)|2: _SAD(0x0100|c->S--,c->PC);if(0==(c->brk_flags&M65C02_BRK_RESET)){_WR();}break; + case (0x00<<3)|3: _SAD(0x0100|c->S--,c->P|M65C02_XF);if(c->brk_flags&M65C02_BRK_RESET){c->AD=0xFFFC;}else{_WR();if(c->brk_flags&M65C02_BRK_NMI){c->AD=0xFFFA;}else{c->AD=0xFFFE;}}break; + case (0x00<<3)|4: _SA(c->AD++);c->P&=~M65C02_DF;c->P|=(M65C02_IF|M65C02_BF);c->brk_flags=0; /* RES/NMI hijacking */break; + case (0x00<<3)|5: _SA(c->AD);c->AD=_GD(); /* NMI "half-hijacking" not possible */break; + case (0x00<<3)|6: c->PC=(_GD()<<8)|c->AD;_FETCH();break; + case (0x00<<3)|7: assert(false);break; + /* ORA (zp,X) */ + case (0x01<<3)|0: _SA(c->PC++);break; + case (0x01<<3)|1: c->AD=_GD();_SA(c->AD);break; + case (0x01<<3)|2: c->AD=(c->AD+c->X)&0xFF;_SA(c->AD);break; + case (0x01<<3)|3: _SA((c->AD+1)&0xFF);c->AD=_GD();break; + case (0x01<<3)|4: _SA((_GD()<<8)|c->AD);break; + case (0x01<<3)|5: c->A|=_GD();_NZ(c->A);_FETCH();break; + case (0x01<<3)|6: assert(false);break; + case (0x01<<3)|7: assert(false);break; + /* LDD # */ + case (0x02<<3)|0: _SA(c->PC++);break; + case (0x02<<3)|1: _FETCH();break; + case (0x02<<3)|2: assert(false);break; + case (0x02<<3)|3: assert(false);break; + case (0x02<<3)|4: assert(false);break; + case (0x02<<3)|5: assert(false);break; + case (0x02<<3)|6: assert(false);break; + case (0x02<<3)|7: assert(false);break; + /* NOP (zp,X) */ + case (0x03<<3)|0: _SA(c->PC);break; + case (0x03<<3)|1: _FETCH();break; + case (0x03<<3)|2: assert(false);break; + case (0x03<<3)|3: assert(false);break; + case (0x03<<3)|4: assert(false);break; + case (0x03<<3)|5: assert(false);break; + case (0x03<<3)|6: assert(false);break; + case (0x03<<3)|7: assert(false);break; + /* TSB zp */ + case (0x04<<3)|0: _SA(c->PC++);break; + case (0x04<<3)|1: _SA(_GD());break; + case (0x04<<3)|2: c->AD=_GD();break; + case (0x04<<3)|3: if(c->AD&c->A){c->P&=~M65C02_ZF;}else{c->P|=M65C02_ZF;};_SD(c->AD|c->A);_WR();break; + case (0x04<<3)|4: _FETCH();break; + case (0x04<<3)|5: assert(false);break; + case (0x04<<3)|6: assert(false);break; + case (0x04<<3)|7: assert(false);break; + /* ORA zp */ + case (0x05<<3)|0: _SA(c->PC++);break; + case (0x05<<3)|1: _SA(_GD());break; + case (0x05<<3)|2: c->A|=_GD();_NZ(c->A);_FETCH();break; + case (0x05<<3)|3: assert(false);break; + case (0x05<<3)|4: assert(false);break; + case (0x05<<3)|5: assert(false);break; + case (0x05<<3)|6: assert(false);break; + case (0x05<<3)|7: assert(false);break; + /* ASL zp */ + case (0x06<<3)|0: _SA(c->PC++);break; + case (0x06<<3)|1: _SA(_GD());break; + case (0x06<<3)|2: c->AD=_GD();_WR();break; + case (0x06<<3)|3: _SD(_m65c02_asl(c,c->AD));_WR();break; + case (0x06<<3)|4: _FETCH();break; + case (0x06<<3)|5: assert(false);break; + case (0x06<<3)|6: assert(false);break; + case (0x06<<3)|7: assert(false);break; + /* RMB0 zp */ + case (0x07<<3)|0: _SA(c->PC++);break; + case (0x07<<3)|1: _SA(_GD());break; + case (0x07<<3)|2: _SD(_GD()&(~(1<<0)));_WR();break; + case (0x07<<3)|3: _FETCH();break; + case (0x07<<3)|4: assert(false);break; + case (0x07<<3)|5: assert(false);break; + case (0x07<<3)|6: assert(false);break; + case (0x07<<3)|7: assert(false);break; + /* PHP */ + case (0x08<<3)|0: _SA(c->PC);break; + case (0x08<<3)|1: _SAD(0x0100|c->S--,c->P|M65C02_XF);_WR();break; + case (0x08<<3)|2: _FETCH();break; + case (0x08<<3)|3: assert(false);break; + case (0x08<<3)|4: assert(false);break; + case (0x08<<3)|5: assert(false);break; + case (0x08<<3)|6: assert(false);break; + case (0x08<<3)|7: assert(false);break; + /* ORA # */ + case (0x09<<3)|0: _SA(c->PC++);break; + case (0x09<<3)|1: c->A|=_GD();_NZ(c->A);_FETCH();break; + case (0x09<<3)|2: assert(false);break; + case (0x09<<3)|3: assert(false);break; + case (0x09<<3)|4: assert(false);break; + case (0x09<<3)|5: assert(false);break; + case (0x09<<3)|6: assert(false);break; + case (0x09<<3)|7: assert(false);break; + /* ASLA */ + case (0x0A<<3)|0: _SA(c->PC);break; + case (0x0A<<3)|1: c->A=_m65c02_asl(c,c->A);_FETCH();break; + case (0x0A<<3)|2: assert(false);break; + case (0x0A<<3)|3: assert(false);break; + case (0x0A<<3)|4: assert(false);break; + case (0x0A<<3)|5: assert(false);break; + case (0x0A<<3)|6: assert(false);break; + case (0x0A<<3)|7: assert(false);break; + /* NOP # */ + case (0x0B<<3)|0: _SA(c->PC);break; + case (0x0B<<3)|1: _FETCH();break; + case (0x0B<<3)|2: assert(false);break; + case (0x0B<<3)|3: assert(false);break; + case (0x0B<<3)|4: assert(false);break; + case (0x0B<<3)|5: assert(false);break; + case (0x0B<<3)|6: assert(false);break; + case (0x0B<<3)|7: assert(false);break; + /* TSB abs */ + case (0x0C<<3)|0: _SA(c->PC++);break; + case (0x0C<<3)|1: _SA(c->PC++);c->AD=_GD();break; + case (0x0C<<3)|2: _SA((_GD()<<8)|c->AD);break; + case (0x0C<<3)|3: c->AD=_GD();break; + case (0x0C<<3)|4: if(c->AD&c->A){c->P&=~M65C02_ZF;}else{c->P|=M65C02_ZF;};_SD(c->AD|c->A);_WR();break; + case (0x0C<<3)|5: _FETCH();break; + case (0x0C<<3)|6: assert(false);break; + case (0x0C<<3)|7: assert(false);break; + /* ORA abs */ + case (0x0D<<3)|0: _SA(c->PC++);break; + case (0x0D<<3)|1: _SA(c->PC++);c->AD=_GD();break; + case (0x0D<<3)|2: _SA((_GD()<<8)|c->AD);break; + case (0x0D<<3)|3: c->A|=_GD();_NZ(c->A);_FETCH();break; + case (0x0D<<3)|4: assert(false);break; + case (0x0D<<3)|5: assert(false);break; + case (0x0D<<3)|6: assert(false);break; + case (0x0D<<3)|7: assert(false);break; + /* ASL abs */ + case (0x0E<<3)|0: _SA(c->PC++);break; + case (0x0E<<3)|1: _SA(c->PC++);c->AD=_GD();break; + case (0x0E<<3)|2: _SA((_GD()<<8)|c->AD);break; + case (0x0E<<3)|3: c->AD=_GD();_WR();break; + case (0x0E<<3)|4: _SD(_m65c02_asl(c,c->AD));_WR();break; + case (0x0E<<3)|5: _FETCH();break; + case (0x0E<<3)|6: assert(false);break; + case (0x0E<<3)|7: assert(false);break; + /* BBR0 zp,rel */ + case (0x0F<<3)|0: _SA(c->PC++);break; + case (0x0F<<3)|1: _SA(_GD());break; + case (0x0F<<3)|2: c->AD=_GD();_SA(c->PC++);break; + case (0x0F<<3)|3: if(!(c->AD&(1<<0))){c->PC=c->PC+(int8_t)_GD();_FETCH();};_FETCH();break; + case (0x0F<<3)|4: assert(false);break; + case (0x0F<<3)|5: assert(false);break; + case (0x0F<<3)|6: assert(false);break; + case (0x0F<<3)|7: assert(false);break; + /* BPL # */ + case (0x10<<3)|0: _SA(c->PC++);break; + case (0x10<<3)|1: _SA(c->PC);c->AD=c->PC+(int8_t)_GD();if((c->P&0x80)!=0x0){_FETCH();};break; + case (0x10<<3)|2: _SA((c->PC&0xFF00)|(c->AD&0x00FF));if((c->AD&0xFF00)==(c->PC&0xFF00)){c->PC=c->AD;c->irq_pip>>=1;c->nmi_pip>>=1;_FETCH();};break; + case (0x10<<3)|3: c->PC=c->AD;_FETCH();break; + case (0x10<<3)|4: assert(false);break; + case (0x10<<3)|5: assert(false);break; + case (0x10<<3)|6: assert(false);break; + case (0x10<<3)|7: assert(false);break; + /* ORA (zp),Y */ + case (0x11<<3)|0: _SA(c->PC++);break; + case (0x11<<3)|1: c->AD=_GD();_SA(c->AD);break; + case (0x11<<3)|2: _SA((c->AD+1)&0xFF);c->AD=_GD();break; + case (0x11<<3)|3: c->AD|=_GD()<<8;_SA((c->AD&0xFF00)|((c->AD+c->Y)&0xFF));c->IR+=(~((c->AD>>8)-((c->AD+c->Y)>>8)))&1;break; + case (0x11<<3)|4: _SA(c->AD+c->Y);break; + case (0x11<<3)|5: c->A|=_GD();_NZ(c->A);_FETCH();break; + case (0x11<<3)|6: assert(false);break; + case (0x11<<3)|7: assert(false);break; + /* ORA (zp) */ + case (0x12<<3)|0: _SA(c->PC++);break; + case (0x12<<3)|1: c->AD=_GD();_SA(c->AD);break; + case (0x12<<3)|2: _SA((c->AD+1)&0xFF);c->AD=_GD();break; + case (0x12<<3)|3: _SA((_GD()<<8)|c->AD);break; + case (0x12<<3)|4: c->A|=_GD();_NZ(c->A);_FETCH();break; + case (0x12<<3)|5: assert(false);break; + case (0x12<<3)|6: assert(false);break; + case (0x12<<3)|7: assert(false);break; + /* NOP (zp),Y */ + case (0x13<<3)|0: _SA(c->PC);break; + case (0x13<<3)|1: _FETCH();break; + case (0x13<<3)|2: assert(false);break; + case (0x13<<3)|3: assert(false);break; + case (0x13<<3)|4: assert(false);break; + case (0x13<<3)|5: assert(false);break; + case (0x13<<3)|6: assert(false);break; + case (0x13<<3)|7: assert(false);break; + /* TRB zp */ + case (0x14<<3)|0: _SA(c->PC++);break; + case (0x14<<3)|1: _SA(_GD());break; + case (0x14<<3)|2: c->AD=_GD();break; + case (0x14<<3)|3: if(c->AD&c->A){c->P&=~M65C02_ZF;}else{c->P|=M65C02_ZF;};_SD(c->AD&~c->A);_WR();break; + case (0x14<<3)|4: _FETCH();break; + case (0x14<<3)|5: assert(false);break; + case (0x14<<3)|6: assert(false);break; + case (0x14<<3)|7: assert(false);break; + /* ORA zp,X */ + case (0x15<<3)|0: _SA(c->PC++);break; + case (0x15<<3)|1: c->AD=_GD();_SA(c->AD);break; + case (0x15<<3)|2: _SA((c->AD+c->X)&0x00FF);break; + case (0x15<<3)|3: c->A|=_GD();_NZ(c->A);_FETCH();break; + case (0x15<<3)|4: assert(false);break; + case (0x15<<3)|5: assert(false);break; + case (0x15<<3)|6: assert(false);break; + case (0x15<<3)|7: assert(false);break; + /* ASL zp,X */ + case (0x16<<3)|0: _SA(c->PC++);break; + case (0x16<<3)|1: c->AD=_GD();_SA(c->AD);break; + case (0x16<<3)|2: _SA((c->AD+c->X)&0x00FF);break; + case (0x16<<3)|3: c->AD=_GD();_WR();break; + case (0x16<<3)|4: _SD(_m65c02_asl(c,c->AD));_WR();break; + case (0x16<<3)|5: _FETCH();break; + case (0x16<<3)|6: assert(false);break; + case (0x16<<3)|7: assert(false);break; + /* RMB1 zp */ + case (0x17<<3)|0: _SA(c->PC++);break; + case (0x17<<3)|1: _SA(_GD());break; + case (0x17<<3)|2: _SD(_GD()&(~(1<<1)));_WR();break; + case (0x17<<3)|3: _FETCH();break; + case (0x17<<3)|4: assert(false);break; + case (0x17<<3)|5: assert(false);break; + case (0x17<<3)|6: assert(false);break; + case (0x17<<3)|7: assert(false);break; + /* CLC */ + case (0x18<<3)|0: _SA(c->PC);break; + case (0x18<<3)|1: c->P&=~0x1;_FETCH();break; + case (0x18<<3)|2: assert(false);break; + case (0x18<<3)|3: assert(false);break; + case (0x18<<3)|4: assert(false);break; + case (0x18<<3)|5: assert(false);break; + case (0x18<<3)|6: assert(false);break; + case (0x18<<3)|7: assert(false);break; + /* ORA abs,Y */ + case (0x19<<3)|0: _SA(c->PC++);break; + case (0x19<<3)|1: _SA(c->PC++);c->AD=_GD();break; + case (0x19<<3)|2: c->AD|=_GD()<<8;_SA((c->AD&0xFF00)|((c->AD+c->Y)&0xFF));c->IR+=(~((c->AD>>8)-((c->AD+c->Y)>>8)))&1;break; + case (0x19<<3)|3: _SA(c->AD+c->Y);break; + case (0x19<<3)|4: c->A|=_GD();_NZ(c->A);_FETCH();break; + case (0x19<<3)|5: assert(false);break; + case (0x19<<3)|6: assert(false);break; + case (0x19<<3)|7: assert(false);break; + /* INC A */ + case (0x1A<<3)|0: _SA(c->PC);break; + case (0x1A<<3)|1: c->A++;_NZ(c->A);_FETCH();break; + case (0x1A<<3)|2: assert(false);break; + case (0x1A<<3)|3: assert(false);break; + case (0x1A<<3)|4: assert(false);break; + case (0x1A<<3)|5: assert(false);break; + case (0x1A<<3)|6: assert(false);break; + case (0x1A<<3)|7: assert(false);break; + /* NOP abs,Y */ + case (0x1B<<3)|0: _SA(c->PC);break; + case (0x1B<<3)|1: _FETCH();break; + case (0x1B<<3)|2: assert(false);break; + case (0x1B<<3)|3: assert(false);break; + case (0x1B<<3)|4: assert(false);break; + case (0x1B<<3)|5: assert(false);break; + case (0x1B<<3)|6: assert(false);break; + case (0x1B<<3)|7: assert(false);break; + /* TRB abs */ + case (0x1C<<3)|0: _SA(c->PC++);break; + case (0x1C<<3)|1: _SA(c->PC++);c->AD=_GD();break; + case (0x1C<<3)|2: _SA((_GD()<<8)|c->AD);break; + case (0x1C<<3)|3: c->AD=_GD();break; + case (0x1C<<3)|4: if(c->AD&c->A){c->P&=~M65C02_ZF;}else{c->P|=M65C02_ZF;};_SD(c->AD&~c->A);_WR();break; + case (0x1C<<3)|5: _FETCH();break; + case (0x1C<<3)|6: assert(false);break; + case (0x1C<<3)|7: assert(false);break; + /* ORA abs,X */ + case (0x1D<<3)|0: _SA(c->PC++);break; + case (0x1D<<3)|1: _SA(c->PC++);c->AD=_GD();break; + case (0x1D<<3)|2: c->AD|=_GD()<<8;_SA((c->AD&0xFF00)|((c->AD+c->X)&0xFF));c->IR+=(~((c->AD>>8)-((c->AD+c->X)>>8)))&1;break; + case (0x1D<<3)|3: _SA(c->AD+c->X);break; + case (0x1D<<3)|4: c->A|=_GD();_NZ(c->A);_FETCH();break; + case (0x1D<<3)|5: assert(false);break; + case (0x1D<<3)|6: assert(false);break; + case (0x1D<<3)|7: assert(false);break; + /* ASL abs,X */ + case (0x1E<<3)|0: _SA(c->PC++);break; + case (0x1E<<3)|1: _SA(c->PC++);c->AD=_GD();break; + case (0x1E<<3)|2: c->AD|=_GD()<<8;_SA((c->AD&0xFF00)|((c->AD+c->X)&0xFF));break; + case (0x1E<<3)|3: _SA(c->AD+c->X);break; + case (0x1E<<3)|4: c->AD=_GD();_WR();break; + case (0x1E<<3)|5: _SD(_m65c02_asl(c,c->AD));_WR();break; + case (0x1E<<3)|6: _FETCH();break; + case (0x1E<<3)|7: assert(false);break; + /* BBR1 zp,rel */ + case (0x1F<<3)|0: _SA(c->PC++);break; + case (0x1F<<3)|1: _SA(_GD());break; + case (0x1F<<3)|2: c->AD=_GD();_SA(c->PC++);break; + case (0x1F<<3)|3: if(!(c->AD&(1<<1))){c->PC=c->PC+(int8_t)_GD();_FETCH();};_FETCH();break; + case (0x1F<<3)|4: assert(false);break; + case (0x1F<<3)|5: assert(false);break; + case (0x1F<<3)|6: assert(false);break; + case (0x1F<<3)|7: assert(false);break; + /* JSR */ + case (0x20<<3)|0: _SA(c->PC++);break; + case (0x20<<3)|1: _SA(0x0100|c->S);c->AD=_GD();break; + case (0x20<<3)|2: _SAD(0x0100|c->S--,c->PC>>8);_WR();break; + case (0x20<<3)|3: _SAD(0x0100|c->S--,c->PC);_WR();break; + case (0x20<<3)|4: _SA(c->PC);break; + case (0x20<<3)|5: c->PC=(_GD()<<8)|c->AD;_FETCH();break; + case (0x20<<3)|6: assert(false);break; + case (0x20<<3)|7: assert(false);break; + /* AND (zp,X) */ + case (0x21<<3)|0: _SA(c->PC++);break; + case (0x21<<3)|1: c->AD=_GD();_SA(c->AD);break; + case (0x21<<3)|2: c->AD=(c->AD+c->X)&0xFF;_SA(c->AD);break; + case (0x21<<3)|3: _SA((c->AD+1)&0xFF);c->AD=_GD();break; + case (0x21<<3)|4: _SA((_GD()<<8)|c->AD);break; + case (0x21<<3)|5: c->A&=_GD();_NZ(c->A);_FETCH();break; + case (0x21<<3)|6: assert(false);break; + case (0x21<<3)|7: assert(false);break; + /* LDD # */ + case (0x22<<3)|0: _SA(c->PC++);break; + case (0x22<<3)|1: _FETCH();break; + case (0x22<<3)|2: assert(false);break; + case (0x22<<3)|3: assert(false);break; + case (0x22<<3)|4: assert(false);break; + case (0x22<<3)|5: assert(false);break; + case (0x22<<3)|6: assert(false);break; + case (0x22<<3)|7: assert(false);break; + /* NOP (zp,X) */ + case (0x23<<3)|0: _SA(c->PC);break; + case (0x23<<3)|1: _FETCH();break; + case (0x23<<3)|2: assert(false);break; + case (0x23<<3)|3: assert(false);break; + case (0x23<<3)|4: assert(false);break; + case (0x23<<3)|5: assert(false);break; + case (0x23<<3)|6: assert(false);break; + case (0x23<<3)|7: assert(false);break; + /* BIT zp */ + case (0x24<<3)|0: _SA(c->PC++);break; + case (0x24<<3)|1: _SA(_GD());break; + case (0x24<<3)|2: _m65c02_bit(c,_GD());_FETCH();break; + case (0x24<<3)|3: assert(false);break; + case (0x24<<3)|4: assert(false);break; + case (0x24<<3)|5: assert(false);break; + case (0x24<<3)|6: assert(false);break; + case (0x24<<3)|7: assert(false);break; + /* AND zp */ + case (0x25<<3)|0: _SA(c->PC++);break; + case (0x25<<3)|1: _SA(_GD());break; + case (0x25<<3)|2: c->A&=_GD();_NZ(c->A);_FETCH();break; + case (0x25<<3)|3: assert(false);break; + case (0x25<<3)|4: assert(false);break; + case (0x25<<3)|5: assert(false);break; + case (0x25<<3)|6: assert(false);break; + case (0x25<<3)|7: assert(false);break; + /* ROL zp */ + case (0x26<<3)|0: _SA(c->PC++);break; + case (0x26<<3)|1: _SA(_GD());break; + case (0x26<<3)|2: c->AD=_GD();_WR();break; + case (0x26<<3)|3: _SD(_m65c02_rol(c,c->AD));_WR();break; + case (0x26<<3)|4: _FETCH();break; + case (0x26<<3)|5: assert(false);break; + case (0x26<<3)|6: assert(false);break; + case (0x26<<3)|7: assert(false);break; + /* RMB2 zp */ + case (0x27<<3)|0: _SA(c->PC++);break; + case (0x27<<3)|1: _SA(_GD());break; + case (0x27<<3)|2: _SD(_GD()&(~(1<<2)));_WR();break; + case (0x27<<3)|3: _FETCH();break; + case (0x27<<3)|4: assert(false);break; + case (0x27<<3)|5: assert(false);break; + case (0x27<<3)|6: assert(false);break; + case (0x27<<3)|7: assert(false);break; + /* PLP */ + case (0x28<<3)|0: _SA(c->PC);break; + case (0x28<<3)|1: _SA(0x0100|c->S++);break; + case (0x28<<3)|2: _SA(0x0100|c->S);break; + case (0x28<<3)|3: c->P=(_GD()|M65C02_BF)&~M65C02_XF;_FETCH();break; + case (0x28<<3)|4: assert(false);break; + case (0x28<<3)|5: assert(false);break; + case (0x28<<3)|6: assert(false);break; + case (0x28<<3)|7: assert(false);break; + /* AND # */ + case (0x29<<3)|0: _SA(c->PC++);break; + case (0x29<<3)|1: c->A&=_GD();_NZ(c->A);_FETCH();break; + case (0x29<<3)|2: assert(false);break; + case (0x29<<3)|3: assert(false);break; + case (0x29<<3)|4: assert(false);break; + case (0x29<<3)|5: assert(false);break; + case (0x29<<3)|6: assert(false);break; + case (0x29<<3)|7: assert(false);break; + /* ROLA */ + case (0x2A<<3)|0: _SA(c->PC);break; + case (0x2A<<3)|1: c->A=_m65c02_rol(c,c->A);_FETCH();break; + case (0x2A<<3)|2: assert(false);break; + case (0x2A<<3)|3: assert(false);break; + case (0x2A<<3)|4: assert(false);break; + case (0x2A<<3)|5: assert(false);break; + case (0x2A<<3)|6: assert(false);break; + case (0x2A<<3)|7: assert(false);break; + /* NOP # */ + case (0x2B<<3)|0: _SA(c->PC);break; + case (0x2B<<3)|1: _FETCH();break; + case (0x2B<<3)|2: assert(false);break; + case (0x2B<<3)|3: assert(false);break; + case (0x2B<<3)|4: assert(false);break; + case (0x2B<<3)|5: assert(false);break; + case (0x2B<<3)|6: assert(false);break; + case (0x2B<<3)|7: assert(false);break; + /* BIT abs */ + case (0x2C<<3)|0: _SA(c->PC++);break; + case (0x2C<<3)|1: _SA(c->PC++);c->AD=_GD();break; + case (0x2C<<3)|2: _SA((_GD()<<8)|c->AD);break; + case (0x2C<<3)|3: _m65c02_bit(c,_GD());_FETCH();break; + case (0x2C<<3)|4: assert(false);break; + case (0x2C<<3)|5: assert(false);break; + case (0x2C<<3)|6: assert(false);break; + case (0x2C<<3)|7: assert(false);break; + /* AND abs */ + case (0x2D<<3)|0: _SA(c->PC++);break; + case (0x2D<<3)|1: _SA(c->PC++);c->AD=_GD();break; + case (0x2D<<3)|2: _SA((_GD()<<8)|c->AD);break; + case (0x2D<<3)|3: c->A&=_GD();_NZ(c->A);_FETCH();break; + case (0x2D<<3)|4: assert(false);break; + case (0x2D<<3)|5: assert(false);break; + case (0x2D<<3)|6: assert(false);break; + case (0x2D<<3)|7: assert(false);break; + /* ROL abs */ + case (0x2E<<3)|0: _SA(c->PC++);break; + case (0x2E<<3)|1: _SA(c->PC++);c->AD=_GD();break; + case (0x2E<<3)|2: _SA((_GD()<<8)|c->AD);break; + case (0x2E<<3)|3: c->AD=_GD();_WR();break; + case (0x2E<<3)|4: _SD(_m65c02_rol(c,c->AD));_WR();break; + case (0x2E<<3)|5: _FETCH();break; + case (0x2E<<3)|6: assert(false);break; + case (0x2E<<3)|7: assert(false);break; + /* BBR2 zp,rel */ + case (0x2F<<3)|0: _SA(c->PC++);break; + case (0x2F<<3)|1: _SA(_GD());break; + case (0x2F<<3)|2: c->AD=_GD();_SA(c->PC++);break; + case (0x2F<<3)|3: if(!(c->AD&(1<<2))){c->PC=c->PC+(int8_t)_GD();_FETCH();};_FETCH();break; + case (0x2F<<3)|4: assert(false);break; + case (0x2F<<3)|5: assert(false);break; + case (0x2F<<3)|6: assert(false);break; + case (0x2F<<3)|7: assert(false);break; + /* BMI # */ + case (0x30<<3)|0: _SA(c->PC++);break; + case (0x30<<3)|1: _SA(c->PC);c->AD=c->PC+(int8_t)_GD();if((c->P&0x80)!=0x80){_FETCH();};break; + case (0x30<<3)|2: _SA((c->PC&0xFF00)|(c->AD&0x00FF));if((c->AD&0xFF00)==(c->PC&0xFF00)){c->PC=c->AD;c->irq_pip>>=1;c->nmi_pip>>=1;_FETCH();};break; + case (0x30<<3)|3: c->PC=c->AD;_FETCH();break; + case (0x30<<3)|4: assert(false);break; + case (0x30<<3)|5: assert(false);break; + case (0x30<<3)|6: assert(false);break; + case (0x30<<3)|7: assert(false);break; + /* AND (zp),Y */ + case (0x31<<3)|0: _SA(c->PC++);break; + case (0x31<<3)|1: c->AD=_GD();_SA(c->AD);break; + case (0x31<<3)|2: _SA((c->AD+1)&0xFF);c->AD=_GD();break; + case (0x31<<3)|3: c->AD|=_GD()<<8;_SA((c->AD&0xFF00)|((c->AD+c->Y)&0xFF));c->IR+=(~((c->AD>>8)-((c->AD+c->Y)>>8)))&1;break; + case (0x31<<3)|4: _SA(c->AD+c->Y);break; + case (0x31<<3)|5: c->A&=_GD();_NZ(c->A);_FETCH();break; + case (0x31<<3)|6: assert(false);break; + case (0x31<<3)|7: assert(false);break; + /* AND (zp) */ + case (0x32<<3)|0: _SA(c->PC++);break; + case (0x32<<3)|1: c->AD=_GD();_SA(c->AD);break; + case (0x32<<3)|2: _SA((c->AD+1)&0xFF);c->AD=_GD();break; + case (0x32<<3)|3: _SA((_GD()<<8)|c->AD);break; + case (0x32<<3)|4: c->A&=_GD();_NZ(c->A);_FETCH();break; + case (0x32<<3)|5: assert(false);break; + case (0x32<<3)|6: assert(false);break; + case (0x32<<3)|7: assert(false);break; + /* NOP (zp),Y */ + case (0x33<<3)|0: _SA(c->PC);break; + case (0x33<<3)|1: _FETCH();break; + case (0x33<<3)|2: assert(false);break; + case (0x33<<3)|3: assert(false);break; + case (0x33<<3)|4: assert(false);break; + case (0x33<<3)|5: assert(false);break; + case (0x33<<3)|6: assert(false);break; + case (0x33<<3)|7: assert(false);break; + /* BIT zp,X */ + case (0x34<<3)|0: _SA(c->PC++);break; + case (0x34<<3)|1: c->AD=_GD();_SA(c->AD);break; + case (0x34<<3)|2: _SA((c->AD+c->X)&0x00FF);break; + case (0x34<<3)|3: _m65c02_bit(c,_GD());_FETCH();break; + case (0x34<<3)|4: assert(false);break; + case (0x34<<3)|5: assert(false);break; + case (0x34<<3)|6: assert(false);break; + case (0x34<<3)|7: assert(false);break; + /* AND zp,X */ + case (0x35<<3)|0: _SA(c->PC++);break; + case (0x35<<3)|1: c->AD=_GD();_SA(c->AD);break; + case (0x35<<3)|2: _SA((c->AD+c->X)&0x00FF);break; + case (0x35<<3)|3: c->A&=_GD();_NZ(c->A);_FETCH();break; + case (0x35<<3)|4: assert(false);break; + case (0x35<<3)|5: assert(false);break; + case (0x35<<3)|6: assert(false);break; + case (0x35<<3)|7: assert(false);break; + /* ROL zp,X */ + case (0x36<<3)|0: _SA(c->PC++);break; + case (0x36<<3)|1: c->AD=_GD();_SA(c->AD);break; + case (0x36<<3)|2: _SA((c->AD+c->X)&0x00FF);break; + case (0x36<<3)|3: c->AD=_GD();_WR();break; + case (0x36<<3)|4: _SD(_m65c02_rol(c,c->AD));_WR();break; + case (0x36<<3)|5: _FETCH();break; + case (0x36<<3)|6: assert(false);break; + case (0x36<<3)|7: assert(false);break; + /* RMB3 zp */ + case (0x37<<3)|0: _SA(c->PC++);break; + case (0x37<<3)|1: _SA(_GD());break; + case (0x37<<3)|2: _SD(_GD()&(~(1<<3)));_WR();break; + case (0x37<<3)|3: _FETCH();break; + case (0x37<<3)|4: assert(false);break; + case (0x37<<3)|5: assert(false);break; + case (0x37<<3)|6: assert(false);break; + case (0x37<<3)|7: assert(false);break; + /* SEC */ + case (0x38<<3)|0: _SA(c->PC);break; + case (0x38<<3)|1: c->P|=0x1;_FETCH();break; + case (0x38<<3)|2: assert(false);break; + case (0x38<<3)|3: assert(false);break; + case (0x38<<3)|4: assert(false);break; + case (0x38<<3)|5: assert(false);break; + case (0x38<<3)|6: assert(false);break; + case (0x38<<3)|7: assert(false);break; + /* AND abs,Y */ + case (0x39<<3)|0: _SA(c->PC++);break; + case (0x39<<3)|1: _SA(c->PC++);c->AD=_GD();break; + case (0x39<<3)|2: c->AD|=_GD()<<8;_SA((c->AD&0xFF00)|((c->AD+c->Y)&0xFF));c->IR+=(~((c->AD>>8)-((c->AD+c->Y)>>8)))&1;break; + case (0x39<<3)|3: _SA(c->AD+c->Y);break; + case (0x39<<3)|4: c->A&=_GD();_NZ(c->A);_FETCH();break; + case (0x39<<3)|5: assert(false);break; + case (0x39<<3)|6: assert(false);break; + case (0x39<<3)|7: assert(false);break; + /* DEC A */ + case (0x3A<<3)|0: _SA(c->PC);break; + case (0x3A<<3)|1: c->A--;_NZ(c->A);_FETCH();break; + case (0x3A<<3)|2: assert(false);break; + case (0x3A<<3)|3: assert(false);break; + case (0x3A<<3)|4: assert(false);break; + case (0x3A<<3)|5: assert(false);break; + case (0x3A<<3)|6: assert(false);break; + case (0x3A<<3)|7: assert(false);break; + /* NOP abs,Y */ + case (0x3B<<3)|0: _SA(c->PC);break; + case (0x3B<<3)|1: _FETCH();break; + case (0x3B<<3)|2: assert(false);break; + case (0x3B<<3)|3: assert(false);break; + case (0x3B<<3)|4: assert(false);break; + case (0x3B<<3)|5: assert(false);break; + case (0x3B<<3)|6: assert(false);break; + case (0x3B<<3)|7: assert(false);break; + /* BIT abs,X */ + case (0x3C<<3)|0: _SA(c->PC++);break; + case (0x3C<<3)|1: _SA(c->PC++);c->AD=_GD();break; + case (0x3C<<3)|2: c->AD|=_GD()<<8;_SA((c->AD&0xFF00)|((c->AD+c->X)&0xFF));c->IR+=(~((c->AD>>8)-((c->AD+c->X)>>8)))&1;break; + case (0x3C<<3)|3: _SA(c->AD+c->X);break; + case (0x3C<<3)|4: _m65c02_bit(c,_GD());_FETCH();break; + case (0x3C<<3)|5: assert(false);break; + case (0x3C<<3)|6: assert(false);break; + case (0x3C<<3)|7: assert(false);break; + /* AND abs,X */ + case (0x3D<<3)|0: _SA(c->PC++);break; + case (0x3D<<3)|1: _SA(c->PC++);c->AD=_GD();break; + case (0x3D<<3)|2: c->AD|=_GD()<<8;_SA((c->AD&0xFF00)|((c->AD+c->X)&0xFF));c->IR+=(~((c->AD>>8)-((c->AD+c->X)>>8)))&1;break; + case (0x3D<<3)|3: _SA(c->AD+c->X);break; + case (0x3D<<3)|4: c->A&=_GD();_NZ(c->A);_FETCH();break; + case (0x3D<<3)|5: assert(false);break; + case (0x3D<<3)|6: assert(false);break; + case (0x3D<<3)|7: assert(false);break; + /* ROL abs,X */ + case (0x3E<<3)|0: _SA(c->PC++);break; + case (0x3E<<3)|1: _SA(c->PC++);c->AD=_GD();break; + case (0x3E<<3)|2: c->AD|=_GD()<<8;_SA((c->AD&0xFF00)|((c->AD+c->X)&0xFF));break; + case (0x3E<<3)|3: _SA(c->AD+c->X);break; + case (0x3E<<3)|4: c->AD=_GD();_WR();break; + case (0x3E<<3)|5: _SD(_m65c02_rol(c,c->AD));_WR();break; + case (0x3E<<3)|6: _FETCH();break; + case (0x3E<<3)|7: assert(false);break; + /* BBR3 zp,rel */ + case (0x3F<<3)|0: _SA(c->PC++);break; + case (0x3F<<3)|1: _SA(_GD());break; + case (0x3F<<3)|2: c->AD=_GD();_SA(c->PC++);break; + case (0x3F<<3)|3: if(!(c->AD&(1<<3))){c->PC=c->PC+(int8_t)_GD();_FETCH();};_FETCH();break; + case (0x3F<<3)|4: assert(false);break; + case (0x3F<<3)|5: assert(false);break; + case (0x3F<<3)|6: assert(false);break; + case (0x3F<<3)|7: assert(false);break; + /* RTI */ + case (0x40<<3)|0: _SA(c->PC);break; + case (0x40<<3)|1: _SA(0x0100|c->S++);break; + case (0x40<<3)|2: _SA(0x0100|c->S++);break; + case (0x40<<3)|3: _SA(0x0100|c->S++);c->P=(_GD()|M65C02_BF)&~M65C02_XF;break; + case (0x40<<3)|4: _SA(0x0100|c->S);c->AD=_GD();break; + case (0x40<<3)|5: c->PC=(_GD()<<8)|c->AD;_FETCH();break; + case (0x40<<3)|6: assert(false);break; + case (0x40<<3)|7: assert(false);break; + /* EOR (zp,X) */ + case (0x41<<3)|0: _SA(c->PC++);break; + case (0x41<<3)|1: c->AD=_GD();_SA(c->AD);break; + case (0x41<<3)|2: c->AD=(c->AD+c->X)&0xFF;_SA(c->AD);break; + case (0x41<<3)|3: _SA((c->AD+1)&0xFF);c->AD=_GD();break; + case (0x41<<3)|4: _SA((_GD()<<8)|c->AD);break; + case (0x41<<3)|5: c->A^=_GD();_NZ(c->A);_FETCH();break; + case (0x41<<3)|6: assert(false);break; + case (0x41<<3)|7: assert(false);break; + /* LDD # */ + case (0x42<<3)|0: _SA(c->PC++);break; + case (0x42<<3)|1: _FETCH();break; + case (0x42<<3)|2: assert(false);break; + case (0x42<<3)|3: assert(false);break; + case (0x42<<3)|4: assert(false);break; + case (0x42<<3)|5: assert(false);break; + case (0x42<<3)|6: assert(false);break; + case (0x42<<3)|7: assert(false);break; + /* NOP (zp,X) */ + case (0x43<<3)|0: _SA(c->PC);break; + case (0x43<<3)|1: _FETCH();break; + case (0x43<<3)|2: assert(false);break; + case (0x43<<3)|3: assert(false);break; + case (0x43<<3)|4: assert(false);break; + case (0x43<<3)|5: assert(false);break; + case (0x43<<3)|6: assert(false);break; + case (0x43<<3)|7: assert(false);break; + /* LDD zp */ + case (0x44<<3)|0: _SA(c->PC++);break; + case (0x44<<3)|1: _SA(_GD());break; + case (0x44<<3)|2: _FETCH();break; + case (0x44<<3)|3: assert(false);break; + case (0x44<<3)|4: assert(false);break; + case (0x44<<3)|5: assert(false);break; + case (0x44<<3)|6: assert(false);break; + case (0x44<<3)|7: assert(false);break; + /* EOR zp */ + case (0x45<<3)|0: _SA(c->PC++);break; + case (0x45<<3)|1: _SA(_GD());break; + case (0x45<<3)|2: c->A^=_GD();_NZ(c->A);_FETCH();break; + case (0x45<<3)|3: assert(false);break; + case (0x45<<3)|4: assert(false);break; + case (0x45<<3)|5: assert(false);break; + case (0x45<<3)|6: assert(false);break; + case (0x45<<3)|7: assert(false);break; + /* LSR zp */ + case (0x46<<3)|0: _SA(c->PC++);break; + case (0x46<<3)|1: _SA(_GD());break; + case (0x46<<3)|2: c->AD=_GD();_WR();break; + case (0x46<<3)|3: _SD(_m65c02_lsr(c,c->AD));_WR();break; + case (0x46<<3)|4: _FETCH();break; + case (0x46<<3)|5: assert(false);break; + case (0x46<<3)|6: assert(false);break; + case (0x46<<3)|7: assert(false);break; + /* RMB4 zp */ + case (0x47<<3)|0: _SA(c->PC++);break; + case (0x47<<3)|1: _SA(_GD());break; + case (0x47<<3)|2: _SD(_GD()&(~(1<<4)));_WR();break; + case (0x47<<3)|3: _FETCH();break; + case (0x47<<3)|4: assert(false);break; + case (0x47<<3)|5: assert(false);break; + case (0x47<<3)|6: assert(false);break; + case (0x47<<3)|7: assert(false);break; + /* PHA */ + case (0x48<<3)|0: _SA(c->PC);break; + case (0x48<<3)|1: _SAD(0x0100|c->S--,c->A);_WR();break; + case (0x48<<3)|2: _FETCH();break; + case (0x48<<3)|3: assert(false);break; + case (0x48<<3)|4: assert(false);break; + case (0x48<<3)|5: assert(false);break; + case (0x48<<3)|6: assert(false);break; + case (0x48<<3)|7: assert(false);break; + /* EOR # */ + case (0x49<<3)|0: _SA(c->PC++);break; + case (0x49<<3)|1: c->A^=_GD();_NZ(c->A);_FETCH();break; + case (0x49<<3)|2: assert(false);break; + case (0x49<<3)|3: assert(false);break; + case (0x49<<3)|4: assert(false);break; + case (0x49<<3)|5: assert(false);break; + case (0x49<<3)|6: assert(false);break; + case (0x49<<3)|7: assert(false);break; + /* LSRA */ + case (0x4A<<3)|0: _SA(c->PC);break; + case (0x4A<<3)|1: c->A=_m65c02_lsr(c,c->A);_FETCH();break; + case (0x4A<<3)|2: assert(false);break; + case (0x4A<<3)|3: assert(false);break; + case (0x4A<<3)|4: assert(false);break; + case (0x4A<<3)|5: assert(false);break; + case (0x4A<<3)|6: assert(false);break; + case (0x4A<<3)|7: assert(false);break; + /* NOP # */ + case (0x4B<<3)|0: _SA(c->PC);break; + case (0x4B<<3)|1: _FETCH();break; + case (0x4B<<3)|2: assert(false);break; + case (0x4B<<3)|3: assert(false);break; + case (0x4B<<3)|4: assert(false);break; + case (0x4B<<3)|5: assert(false);break; + case (0x4B<<3)|6: assert(false);break; + case (0x4B<<3)|7: assert(false);break; + /* JMP */ + case (0x4C<<3)|0: _SA(c->PC++);break; + case (0x4C<<3)|1: _SA(c->PC++);c->AD=_GD();break; + case (0x4C<<3)|2: c->PC=(_GD()<<8)|c->AD;_FETCH();break; + case (0x4C<<3)|3: assert(false);break; + case (0x4C<<3)|4: assert(false);break; + case (0x4C<<3)|5: assert(false);break; + case (0x4C<<3)|6: assert(false);break; + case (0x4C<<3)|7: assert(false);break; + /* EOR abs */ + case (0x4D<<3)|0: _SA(c->PC++);break; + case (0x4D<<3)|1: _SA(c->PC++);c->AD=_GD();break; + case (0x4D<<3)|2: _SA((_GD()<<8)|c->AD);break; + case (0x4D<<3)|3: c->A^=_GD();_NZ(c->A);_FETCH();break; + case (0x4D<<3)|4: assert(false);break; + case (0x4D<<3)|5: assert(false);break; + case (0x4D<<3)|6: assert(false);break; + case (0x4D<<3)|7: assert(false);break; + /* LSR abs */ + case (0x4E<<3)|0: _SA(c->PC++);break; + case (0x4E<<3)|1: _SA(c->PC++);c->AD=_GD();break; + case (0x4E<<3)|2: _SA((_GD()<<8)|c->AD);break; + case (0x4E<<3)|3: c->AD=_GD();_WR();break; + case (0x4E<<3)|4: _SD(_m65c02_lsr(c,c->AD));_WR();break; + case (0x4E<<3)|5: _FETCH();break; + case (0x4E<<3)|6: assert(false);break; + case (0x4E<<3)|7: assert(false);break; + /* BBR4 zp,rel */ + case (0x4F<<3)|0: _SA(c->PC++);break; + case (0x4F<<3)|1: _SA(_GD());break; + case (0x4F<<3)|2: c->AD=_GD();_SA(c->PC++);break; + case (0x4F<<3)|3: if(!(c->AD&(1<<4))){c->PC=c->PC+(int8_t)_GD();_FETCH();};_FETCH();break; + case (0x4F<<3)|4: assert(false);break; + case (0x4F<<3)|5: assert(false);break; + case (0x4F<<3)|6: assert(false);break; + case (0x4F<<3)|7: assert(false);break; + /* BVC # */ + case (0x50<<3)|0: _SA(c->PC++);break; + case (0x50<<3)|1: _SA(c->PC);c->AD=c->PC+(int8_t)_GD();if((c->P&0x40)!=0x0){_FETCH();};break; + case (0x50<<3)|2: _SA((c->PC&0xFF00)|(c->AD&0x00FF));if((c->AD&0xFF00)==(c->PC&0xFF00)){c->PC=c->AD;c->irq_pip>>=1;c->nmi_pip>>=1;_FETCH();};break; + case (0x50<<3)|3: c->PC=c->AD;_FETCH();break; + case (0x50<<3)|4: assert(false);break; + case (0x50<<3)|5: assert(false);break; + case (0x50<<3)|6: assert(false);break; + case (0x50<<3)|7: assert(false);break; + /* EOR (zp),Y */ + case (0x51<<3)|0: _SA(c->PC++);break; + case (0x51<<3)|1: c->AD=_GD();_SA(c->AD);break; + case (0x51<<3)|2: _SA((c->AD+1)&0xFF);c->AD=_GD();break; + case (0x51<<3)|3: c->AD|=_GD()<<8;_SA((c->AD&0xFF00)|((c->AD+c->Y)&0xFF));c->IR+=(~((c->AD>>8)-((c->AD+c->Y)>>8)))&1;break; + case (0x51<<3)|4: _SA(c->AD+c->Y);break; + case (0x51<<3)|5: c->A^=_GD();_NZ(c->A);_FETCH();break; + case (0x51<<3)|6: assert(false);break; + case (0x51<<3)|7: assert(false);break; + /* EOR (zp) */ + case (0x52<<3)|0: _SA(c->PC++);break; + case (0x52<<3)|1: c->AD=_GD();_SA(c->AD);break; + case (0x52<<3)|2: _SA((c->AD+1)&0xFF);c->AD=_GD();break; + case (0x52<<3)|3: _SA((_GD()<<8)|c->AD);break; + case (0x52<<3)|4: c->A^=_GD();_NZ(c->A);_FETCH();break; + case (0x52<<3)|5: assert(false);break; + case (0x52<<3)|6: assert(false);break; + case (0x52<<3)|7: assert(false);break; + /* NOP (zp),Y */ + case (0x53<<3)|0: _SA(c->PC);break; + case (0x53<<3)|1: _FETCH();break; + case (0x53<<3)|2: assert(false);break; + case (0x53<<3)|3: assert(false);break; + case (0x53<<3)|4: assert(false);break; + case (0x53<<3)|5: assert(false);break; + case (0x53<<3)|6: assert(false);break; + case (0x53<<3)|7: assert(false);break; + /* LDD zp,X */ + case (0x54<<3)|0: _SA(c->PC++);break; + case (0x54<<3)|1: c->AD=_GD();_SA(c->AD);break; + case (0x54<<3)|2: _SA((c->AD+c->X)&0x00FF);break; + case (0x54<<3)|3: _FETCH();break; + case (0x54<<3)|4: assert(false);break; + case (0x54<<3)|5: assert(false);break; + case (0x54<<3)|6: assert(false);break; + case (0x54<<3)|7: assert(false);break; + /* EOR zp,X */ + case (0x55<<3)|0: _SA(c->PC++);break; + case (0x55<<3)|1: c->AD=_GD();_SA(c->AD);break; + case (0x55<<3)|2: _SA((c->AD+c->X)&0x00FF);break; + case (0x55<<3)|3: c->A^=_GD();_NZ(c->A);_FETCH();break; + case (0x55<<3)|4: assert(false);break; + case (0x55<<3)|5: assert(false);break; + case (0x55<<3)|6: assert(false);break; + case (0x55<<3)|7: assert(false);break; + /* LSR zp,X */ + case (0x56<<3)|0: _SA(c->PC++);break; + case (0x56<<3)|1: c->AD=_GD();_SA(c->AD);break; + case (0x56<<3)|2: _SA((c->AD+c->X)&0x00FF);break; + case (0x56<<3)|3: c->AD=_GD();_WR();break; + case (0x56<<3)|4: _SD(_m65c02_lsr(c,c->AD));_WR();break; + case (0x56<<3)|5: _FETCH();break; + case (0x56<<3)|6: assert(false);break; + case (0x56<<3)|7: assert(false);break; + /* RMB5 zp */ + case (0x57<<3)|0: _SA(c->PC++);break; + case (0x57<<3)|1: _SA(_GD());break; + case (0x57<<3)|2: _SD(_GD()&(~(1<<5)));_WR();break; + case (0x57<<3)|3: _FETCH();break; + case (0x57<<3)|4: assert(false);break; + case (0x57<<3)|5: assert(false);break; + case (0x57<<3)|6: assert(false);break; + case (0x57<<3)|7: assert(false);break; + /* CLI */ + case (0x58<<3)|0: _SA(c->PC);break; + case (0x58<<3)|1: c->P&=~0x4;_FETCH();break; + case (0x58<<3)|2: assert(false);break; + case (0x58<<3)|3: assert(false);break; + case (0x58<<3)|4: assert(false);break; + case (0x58<<3)|5: assert(false);break; + case (0x58<<3)|6: assert(false);break; + case (0x58<<3)|7: assert(false);break; + /* EOR abs,Y */ + case (0x59<<3)|0: _SA(c->PC++);break; + case (0x59<<3)|1: _SA(c->PC++);c->AD=_GD();break; + case (0x59<<3)|2: c->AD|=_GD()<<8;_SA((c->AD&0xFF00)|((c->AD+c->Y)&0xFF));c->IR+=(~((c->AD>>8)-((c->AD+c->Y)>>8)))&1;break; + case (0x59<<3)|3: _SA(c->AD+c->Y);break; + case (0x59<<3)|4: c->A^=_GD();_NZ(c->A);_FETCH();break; + case (0x59<<3)|5: assert(false);break; + case (0x59<<3)|6: assert(false);break; + case (0x59<<3)|7: assert(false);break; + /* PHY */ + case (0x5A<<3)|0: _SA(c->PC);break; + case (0x5A<<3)|1: _SAD(0x0100|c->S--,c->Y);_WR();break; + case (0x5A<<3)|2: _FETCH();break; + case (0x5A<<3)|3: assert(false);break; + case (0x5A<<3)|4: assert(false);break; + case (0x5A<<3)|5: assert(false);break; + case (0x5A<<3)|6: assert(false);break; + case (0x5A<<3)|7: assert(false);break; + /* NOP abs,Y */ + case (0x5B<<3)|0: _SA(c->PC);break; + case (0x5B<<3)|1: _FETCH();break; + case (0x5B<<3)|2: assert(false);break; + case (0x5B<<3)|3: assert(false);break; + case (0x5B<<3)|4: assert(false);break; + case (0x5B<<3)|5: assert(false);break; + case (0x5B<<3)|6: assert(false);break; + case (0x5B<<3)|7: assert(false);break; + /* LDD abs,X */ + case (0x5C<<3)|0: _SA(c->PC++);break; + case (0x5C<<3)|1: _SA(c->PC++);c->AD=_GD();break; + case (0x5C<<3)|2: c->AD|=_GD()<<8;_SA((c->AD&0xFF00)|((c->AD+c->X)&0xFF));c->IR+=(~((c->AD>>8)-((c->AD+c->X)>>8)))&1;break; + case (0x5C<<3)|3: _SA(c->AD+c->X);break; + case (0x5C<<3)|4: _FETCH();break; + case (0x5C<<3)|5: assert(false);break; + case (0x5C<<3)|6: assert(false);break; + case (0x5C<<3)|7: assert(false);break; + /* EOR abs,X */ + case (0x5D<<3)|0: _SA(c->PC++);break; + case (0x5D<<3)|1: _SA(c->PC++);c->AD=_GD();break; + case (0x5D<<3)|2: c->AD|=_GD()<<8;_SA((c->AD&0xFF00)|((c->AD+c->X)&0xFF));c->IR+=(~((c->AD>>8)-((c->AD+c->X)>>8)))&1;break; + case (0x5D<<3)|3: _SA(c->AD+c->X);break; + case (0x5D<<3)|4: c->A^=_GD();_NZ(c->A);_FETCH();break; + case (0x5D<<3)|5: assert(false);break; + case (0x5D<<3)|6: assert(false);break; + case (0x5D<<3)|7: assert(false);break; + /* LSR abs,X */ + case (0x5E<<3)|0: _SA(c->PC++);break; + case (0x5E<<3)|1: _SA(c->PC++);c->AD=_GD();break; + case (0x5E<<3)|2: c->AD|=_GD()<<8;_SA((c->AD&0xFF00)|((c->AD+c->X)&0xFF));break; + case (0x5E<<3)|3: _SA(c->AD+c->X);break; + case (0x5E<<3)|4: c->AD=_GD();_WR();break; + case (0x5E<<3)|5: _SD(_m65c02_lsr(c,c->AD));_WR();break; + case (0x5E<<3)|6: _FETCH();break; + case (0x5E<<3)|7: assert(false);break; + /* BBR5 zp,rel */ + case (0x5F<<3)|0: _SA(c->PC++);break; + case (0x5F<<3)|1: _SA(_GD());break; + case (0x5F<<3)|2: c->AD=_GD();_SA(c->PC++);break; + case (0x5F<<3)|3: if(!(c->AD&(1<<5))){c->PC=c->PC+(int8_t)_GD();_FETCH();};_FETCH();break; + case (0x5F<<3)|4: assert(false);break; + case (0x5F<<3)|5: assert(false);break; + case (0x5F<<3)|6: assert(false);break; + case (0x5F<<3)|7: assert(false);break; + /* RTS */ + case (0x60<<3)|0: _SA(c->PC);break; + case (0x60<<3)|1: _SA(0x0100|c->S++);break; + case (0x60<<3)|2: _SA(0x0100|c->S++);break; + case (0x60<<3)|3: _SA(0x0100|c->S);c->AD=_GD();break; + case (0x60<<3)|4: c->PC=(_GD()<<8)|c->AD;_SA(c->PC++);break; + case (0x60<<3)|5: _FETCH();break; + case (0x60<<3)|6: assert(false);break; + case (0x60<<3)|7: assert(false);break; + /* ADC (zp,X) */ + case (0x61<<3)|0: _SA(c->PC++);break; + case (0x61<<3)|1: c->AD=_GD();_SA(c->AD);break; + case (0x61<<3)|2: c->AD=(c->AD+c->X)&0xFF;_SA(c->AD);break; + case (0x61<<3)|3: _SA((c->AD+1)&0xFF);c->AD=_GD();break; + case (0x61<<3)|4: _SA((_GD()<<8)|c->AD);break; + case (0x61<<3)|5: _m65c02_adc(c,_GD());if(c->P&M65C02_DF){c->P=((c->P&~(M65C02_NF|M65C02_ZF))|((c->A&0xFF)?(c->A&M65C02_NF):M65C02_ZF));};_FETCH();break; + case (0x61<<3)|6: assert(false);break; + case (0x61<<3)|7: assert(false);break; + /* LDD # */ + case (0x62<<3)|0: _SA(c->PC++);break; + case (0x62<<3)|1: _FETCH();break; + case (0x62<<3)|2: assert(false);break; + case (0x62<<3)|3: assert(false);break; + case (0x62<<3)|4: assert(false);break; + case (0x62<<3)|5: assert(false);break; + case (0x62<<3)|6: assert(false);break; + case (0x62<<3)|7: assert(false);break; + /* NOP (zp,X) */ + case (0x63<<3)|0: _SA(c->PC);break; + case (0x63<<3)|1: _FETCH();break; + case (0x63<<3)|2: assert(false);break; + case (0x63<<3)|3: assert(false);break; + case (0x63<<3)|4: assert(false);break; + case (0x63<<3)|5: assert(false);break; + case (0x63<<3)|6: assert(false);break; + case (0x63<<3)|7: assert(false);break; + /* STZ zp */ + case (0x64<<3)|0: _SA(c->PC++);break; + case (0x64<<3)|1: _SA(_GD());_SD(0);_WR();break; + case (0x64<<3)|2: _FETCH();break; + case (0x64<<3)|3: assert(false);break; + case (0x64<<3)|4: assert(false);break; + case (0x64<<3)|5: assert(false);break; + case (0x64<<3)|6: assert(false);break; + case (0x64<<3)|7: assert(false);break; + /* ADC zp */ + case (0x65<<3)|0: _SA(c->PC++);break; + case (0x65<<3)|1: _SA(_GD());break; + case (0x65<<3)|2: _m65c02_adc(c,_GD());if(c->P&M65C02_DF){c->P=((c->P&~(M65C02_NF|M65C02_ZF))|((c->A&0xFF)?(c->A&M65C02_NF):M65C02_ZF));};_FETCH();break; + case (0x65<<3)|3: assert(false);break; + case (0x65<<3)|4: assert(false);break; + case (0x65<<3)|5: assert(false);break; + case (0x65<<3)|6: assert(false);break; + case (0x65<<3)|7: assert(false);break; + /* ROR zp */ + case (0x66<<3)|0: _SA(c->PC++);break; + case (0x66<<3)|1: _SA(_GD());break; + case (0x66<<3)|2: c->AD=_GD();_WR();break; + case (0x66<<3)|3: _SD(_m65c02_ror(c,c->AD));_WR();break; + case (0x66<<3)|4: _FETCH();break; + case (0x66<<3)|5: assert(false);break; + case (0x66<<3)|6: assert(false);break; + case (0x66<<3)|7: assert(false);break; + /* RMB6 zp */ + case (0x67<<3)|0: _SA(c->PC++);break; + case (0x67<<3)|1: _SA(_GD());break; + case (0x67<<3)|2: _SD(_GD()&(~(1<<6)));_WR();break; + case (0x67<<3)|3: _FETCH();break; + case (0x67<<3)|4: assert(false);break; + case (0x67<<3)|5: assert(false);break; + case (0x67<<3)|6: assert(false);break; + case (0x67<<3)|7: assert(false);break; + /* PLA */ + case (0x68<<3)|0: _SA(c->PC);break; + case (0x68<<3)|1: _SA(0x0100|c->S++);break; + case (0x68<<3)|2: _SA(0x0100|c->S);break; + case (0x68<<3)|3: c->A=_GD();_NZ(c->A);_FETCH();break; + case (0x68<<3)|4: assert(false);break; + case (0x68<<3)|5: assert(false);break; + case (0x68<<3)|6: assert(false);break; + case (0x68<<3)|7: assert(false);break; + /* ADC # */ + case (0x69<<3)|0: _SA(c->PC++);break; + case (0x69<<3)|1: _m65c02_adc(c,_GD());if(c->P&M65C02_DF){c->P=((c->P&~(M65C02_NF|M65C02_ZF))|((c->A&0xFF)?(c->A&M65C02_NF):M65C02_ZF));};_FETCH();break; + case (0x69<<3)|2: assert(false);break; + case (0x69<<3)|3: assert(false);break; + case (0x69<<3)|4: assert(false);break; + case (0x69<<3)|5: assert(false);break; + case (0x69<<3)|6: assert(false);break; + case (0x69<<3)|7: assert(false);break; + /* RORA */ + case (0x6A<<3)|0: _SA(c->PC);break; + case (0x6A<<3)|1: c->A=_m65c02_ror(c,c->A);_FETCH();break; + case (0x6A<<3)|2: assert(false);break; + case (0x6A<<3)|3: assert(false);break; + case (0x6A<<3)|4: assert(false);break; + case (0x6A<<3)|5: assert(false);break; + case (0x6A<<3)|6: assert(false);break; + case (0x6A<<3)|7: assert(false);break; + /* NOP # */ + case (0x6B<<3)|0: _SA(c->PC);break; + case (0x6B<<3)|1: _FETCH();break; + case (0x6B<<3)|2: assert(false);break; + case (0x6B<<3)|3: assert(false);break; + case (0x6B<<3)|4: assert(false);break; + case (0x6B<<3)|5: assert(false);break; + case (0x6B<<3)|6: assert(false);break; + case (0x6B<<3)|7: assert(false);break; + /* JMPI */ + case (0x6C<<3)|0: _SA(c->PC++);break; + case (0x6C<<3)|1: _SA(c->PC++);c->AD=_GD();break; + case (0x6C<<3)|2: c->AD|=_GD()<<8;_SA(c->AD);break; + case (0x6C<<3)|3: _SA(c->AD+1);c->AD=_GD();break; + case (0x6C<<3)|4: c->PC=(_GD()<<8)|c->AD;_FETCH();break; + case (0x6C<<3)|5: assert(false);break; + case (0x6C<<3)|6: assert(false);break; + case (0x6C<<3)|7: assert(false);break; + /* ADC abs */ + case (0x6D<<3)|0: _SA(c->PC++);break; + case (0x6D<<3)|1: _SA(c->PC++);c->AD=_GD();break; + case (0x6D<<3)|2: _SA((_GD()<<8)|c->AD);break; + case (0x6D<<3)|3: _m65c02_adc(c,_GD());if(c->P&M65C02_DF){c->P=((c->P&~(M65C02_NF|M65C02_ZF))|((c->A&0xFF)?(c->A&M65C02_NF):M65C02_ZF));};_FETCH();break; + case (0x6D<<3)|4: assert(false);break; + case (0x6D<<3)|5: assert(false);break; + case (0x6D<<3)|6: assert(false);break; + case (0x6D<<3)|7: assert(false);break; + /* ROR abs */ + case (0x6E<<3)|0: _SA(c->PC++);break; + case (0x6E<<3)|1: _SA(c->PC++);c->AD=_GD();break; + case (0x6E<<3)|2: _SA((_GD()<<8)|c->AD);break; + case (0x6E<<3)|3: c->AD=_GD();_WR();break; + case (0x6E<<3)|4: _SD(_m65c02_ror(c,c->AD));_WR();break; + case (0x6E<<3)|5: _FETCH();break; + case (0x6E<<3)|6: assert(false);break; + case (0x6E<<3)|7: assert(false);break; + /* BBR6 zp,rel */ + case (0x6F<<3)|0: _SA(c->PC++);break; + case (0x6F<<3)|1: _SA(_GD());break; + case (0x6F<<3)|2: c->AD=_GD();_SA(c->PC++);break; + case (0x6F<<3)|3: if(!(c->AD&(1<<6))){c->PC=c->PC+(int8_t)_GD();_FETCH();};_FETCH();break; + case (0x6F<<3)|4: assert(false);break; + case (0x6F<<3)|5: assert(false);break; + case (0x6F<<3)|6: assert(false);break; + case (0x6F<<3)|7: assert(false);break; + /* BVS # */ + case (0x70<<3)|0: _SA(c->PC++);break; + case (0x70<<3)|1: _SA(c->PC);c->AD=c->PC+(int8_t)_GD();if((c->P&0x40)!=0x40){_FETCH();};break; + case (0x70<<3)|2: _SA((c->PC&0xFF00)|(c->AD&0x00FF));if((c->AD&0xFF00)==(c->PC&0xFF00)){c->PC=c->AD;c->irq_pip>>=1;c->nmi_pip>>=1;_FETCH();};break; + case (0x70<<3)|3: c->PC=c->AD;_FETCH();break; + case (0x70<<3)|4: assert(false);break; + case (0x70<<3)|5: assert(false);break; + case (0x70<<3)|6: assert(false);break; + case (0x70<<3)|7: assert(false);break; + /* ADC (zp),Y */ + case (0x71<<3)|0: _SA(c->PC++);break; + case (0x71<<3)|1: c->AD=_GD();_SA(c->AD);break; + case (0x71<<3)|2: _SA((c->AD+1)&0xFF);c->AD=_GD();break; + case (0x71<<3)|3: c->AD|=_GD()<<8;_SA((c->AD&0xFF00)|((c->AD+c->Y)&0xFF));c->IR+=(~((c->AD>>8)-((c->AD+c->Y)>>8)))&1;break; + case (0x71<<3)|4: _SA(c->AD+c->Y);break; + case (0x71<<3)|5: _m65c02_adc(c,_GD());if(c->P&M65C02_DF){c->P=((c->P&~(M65C02_NF|M65C02_ZF))|((c->A&0xFF)?(c->A&M65C02_NF):M65C02_ZF));};_FETCH();break; + case (0x71<<3)|6: assert(false);break; + case (0x71<<3)|7: assert(false);break; + /* ADC (zp) */ + case (0x72<<3)|0: _SA(c->PC++);break; + case (0x72<<3)|1: c->AD=_GD();_SA(c->AD);break; + case (0x72<<3)|2: _SA((c->AD+1)&0xFF);c->AD=_GD();break; + case (0x72<<3)|3: _SA((_GD()<<8)|c->AD);break; + case (0x72<<3)|4: _m65c02_adc(c,_GD());if(c->P&M65C02_DF){c->P=((c->P&~(M65C02_NF|M65C02_ZF))|((c->A&0xFF)?(c->A&M65C02_NF):M65C02_ZF));};_FETCH();break; + case (0x72<<3)|5: assert(false);break; + case (0x72<<3)|6: assert(false);break; + case (0x72<<3)|7: assert(false);break; + /* NOP (zp),Y */ + case (0x73<<3)|0: _SA(c->PC);break; + case (0x73<<3)|1: _FETCH();break; + case (0x73<<3)|2: assert(false);break; + case (0x73<<3)|3: assert(false);break; + case (0x73<<3)|4: assert(false);break; + case (0x73<<3)|5: assert(false);break; + case (0x73<<3)|6: assert(false);break; + case (0x73<<3)|7: assert(false);break; + /* STZ zp,X */ + case (0x74<<3)|0: _SA(c->PC++);break; + case (0x74<<3)|1: c->AD=_GD();_SA(c->AD);break; + case (0x74<<3)|2: _SA((c->AD+c->X)&0x00FF);_SD(0);_WR();break; + case (0x74<<3)|3: _FETCH();break; + case (0x74<<3)|4: assert(false);break; + case (0x74<<3)|5: assert(false);break; + case (0x74<<3)|6: assert(false);break; + case (0x74<<3)|7: assert(false);break; + /* ADC zp,X */ + case (0x75<<3)|0: _SA(c->PC++);break; + case (0x75<<3)|1: c->AD=_GD();_SA(c->AD);break; + case (0x75<<3)|2: _SA((c->AD+c->X)&0x00FF);break; + case (0x75<<3)|3: _m65c02_adc(c,_GD());if(c->P&M65C02_DF){c->P=((c->P&~(M65C02_NF|M65C02_ZF))|((c->A&0xFF)?(c->A&M65C02_NF):M65C02_ZF));};_FETCH();break; + case (0x75<<3)|4: assert(false);break; + case (0x75<<3)|5: assert(false);break; + case (0x75<<3)|6: assert(false);break; + case (0x75<<3)|7: assert(false);break; + /* ROR zp,X */ + case (0x76<<3)|0: _SA(c->PC++);break; + case (0x76<<3)|1: c->AD=_GD();_SA(c->AD);break; + case (0x76<<3)|2: _SA((c->AD+c->X)&0x00FF);break; + case (0x76<<3)|3: c->AD=_GD();_WR();break; + case (0x76<<3)|4: _SD(_m65c02_ror(c,c->AD));_WR();break; + case (0x76<<3)|5: _FETCH();break; + case (0x76<<3)|6: assert(false);break; + case (0x76<<3)|7: assert(false);break; + /* RMB7 zp */ + case (0x77<<3)|0: _SA(c->PC++);break; + case (0x77<<3)|1: _SA(_GD());break; + case (0x77<<3)|2: _SD(_GD()&(~(1<<7)));_WR();break; + case (0x77<<3)|3: _FETCH();break; + case (0x77<<3)|4: assert(false);break; + case (0x77<<3)|5: assert(false);break; + case (0x77<<3)|6: assert(false);break; + case (0x77<<3)|7: assert(false);break; + /* SEI */ + case (0x78<<3)|0: _SA(c->PC);break; + case (0x78<<3)|1: c->P|=0x4;_FETCH();break; + case (0x78<<3)|2: assert(false);break; + case (0x78<<3)|3: assert(false);break; + case (0x78<<3)|4: assert(false);break; + case (0x78<<3)|5: assert(false);break; + case (0x78<<3)|6: assert(false);break; + case (0x78<<3)|7: assert(false);break; + /* ADC abs,Y */ + case (0x79<<3)|0: _SA(c->PC++);break; + case (0x79<<3)|1: _SA(c->PC++);c->AD=_GD();break; + case (0x79<<3)|2: c->AD|=_GD()<<8;_SA((c->AD&0xFF00)|((c->AD+c->Y)&0xFF));c->IR+=(~((c->AD>>8)-((c->AD+c->Y)>>8)))&1;break; + case (0x79<<3)|3: _SA(c->AD+c->Y);break; + case (0x79<<3)|4: _m65c02_adc(c,_GD());if(c->P&M65C02_DF){c->P=((c->P&~(M65C02_NF|M65C02_ZF))|((c->A&0xFF)?(c->A&M65C02_NF):M65C02_ZF));};_FETCH();break; + case (0x79<<3)|5: assert(false);break; + case (0x79<<3)|6: assert(false);break; + case (0x79<<3)|7: assert(false);break; + /* PLY */ + case (0x7A<<3)|0: _SA(c->PC);break; + case (0x7A<<3)|1: _SA(0x0100|c->S++);break; + case (0x7A<<3)|2: _SA(0x0100|c->S);break; + case (0x7A<<3)|3: c->Y=_GD();_NZ(c->Y);_FETCH();break; + case (0x7A<<3)|4: assert(false);break; + case (0x7A<<3)|5: assert(false);break; + case (0x7A<<3)|6: assert(false);break; + case (0x7A<<3)|7: assert(false);break; + /* NOP abs,Y */ + case (0x7B<<3)|0: _SA(c->PC);break; + case (0x7B<<3)|1: _FETCH();break; + case (0x7B<<3)|2: assert(false);break; + case (0x7B<<3)|3: assert(false);break; + case (0x7B<<3)|4: assert(false);break; + case (0x7B<<3)|5: assert(false);break; + case (0x7B<<3)|6: assert(false);break; + case (0x7B<<3)|7: assert(false);break; + /* JMPIX (abs,X) */ + case (0x7C<<3)|0: _SA(c->PC++);break; + case (0x7C<<3)|1: _SA(c->PC++);c->AD=_GD();break; + case (0x7C<<3)|2: c->AD|=_GD()<<8;c->AD+=c->X;_SA(c->AD);break; + case (0x7C<<3)|3: _SA(c->AD+1);c->AD=_GD();break; + case (0x7C<<3)|4: c->PC=(_GD()<<8)|c->AD;_FETCH();break; + case (0x7C<<3)|5: assert(false);break; + case (0x7C<<3)|6: assert(false);break; + case (0x7C<<3)|7: assert(false);break; + /* ADC abs,X */ + case (0x7D<<3)|0: _SA(c->PC++);break; + case (0x7D<<3)|1: _SA(c->PC++);c->AD=_GD();break; + case (0x7D<<3)|2: c->AD|=_GD()<<8;_SA((c->AD&0xFF00)|((c->AD+c->X)&0xFF));c->IR+=(~((c->AD>>8)-((c->AD+c->X)>>8)))&1;break; + case (0x7D<<3)|3: _SA(c->AD+c->X);break; + case (0x7D<<3)|4: _m65c02_adc(c,_GD());if(c->P&M65C02_DF){c->P=((c->P&~(M65C02_NF|M65C02_ZF))|((c->A&0xFF)?(c->A&M65C02_NF):M65C02_ZF));};_FETCH();break; + case (0x7D<<3)|5: assert(false);break; + case (0x7D<<3)|6: assert(false);break; + case (0x7D<<3)|7: assert(false);break; + /* ROR abs,X */ + case (0x7E<<3)|0: _SA(c->PC++);break; + case (0x7E<<3)|1: _SA(c->PC++);c->AD=_GD();break; + case (0x7E<<3)|2: c->AD|=_GD()<<8;_SA((c->AD&0xFF00)|((c->AD+c->X)&0xFF));break; + case (0x7E<<3)|3: _SA(c->AD+c->X);break; + case (0x7E<<3)|4: c->AD=_GD();_WR();break; + case (0x7E<<3)|5: _SD(_m65c02_ror(c,c->AD));_WR();break; + case (0x7E<<3)|6: _FETCH();break; + case (0x7E<<3)|7: assert(false);break; + /* BBR7 zp,rel */ + case (0x7F<<3)|0: _SA(c->PC++);break; + case (0x7F<<3)|1: _SA(_GD());break; + case (0x7F<<3)|2: c->AD=_GD();_SA(c->PC++);break; + case (0x7F<<3)|3: if(!(c->AD&(1<<7))){c->PC=c->PC+(int8_t)_GD();_FETCH();};_FETCH();break; + case (0x7F<<3)|4: assert(false);break; + case (0x7F<<3)|5: assert(false);break; + case (0x7F<<3)|6: assert(false);break; + case (0x7F<<3)|7: assert(false);break; + /* BRA # */ + case (0x80<<3)|0: _SA(c->PC++);break; + case (0x80<<3)|1: _SA(c->PC);c->AD=c->PC+(int8_t)_GD();break; + case (0x80<<3)|2: _SA((c->PC&0xFF00)|(c->AD&0x00FF));if((c->AD&0xFF00)==(c->PC&0xFF00)){c->PC=c->AD;c->irq_pip>>=1;c->nmi_pip>>=1;_FETCH();};break; + case (0x80<<3)|3: c->PC=c->AD;_FETCH();break; + case (0x80<<3)|4: assert(false);break; + case (0x80<<3)|5: assert(false);break; + case (0x80<<3)|6: assert(false);break; + case (0x80<<3)|7: assert(false);break; + /* STA (zp,X) */ + case (0x81<<3)|0: _SA(c->PC++);break; + case (0x81<<3)|1: c->AD=_GD();_SA(c->AD);break; + case (0x81<<3)|2: c->AD=(c->AD+c->X)&0xFF;_SA(c->AD);break; + case (0x81<<3)|3: _SA((c->AD+1)&0xFF);c->AD=_GD();break; + case (0x81<<3)|4: _SA((_GD()<<8)|c->AD);_SD(c->A);_WR();break; + case (0x81<<3)|5: _FETCH();break; + case (0x81<<3)|6: assert(false);break; + case (0x81<<3)|7: assert(false);break; + /* LDD # */ + case (0x82<<3)|0: _SA(c->PC++);break; + case (0x82<<3)|1: _FETCH();break; + case (0x82<<3)|2: assert(false);break; + case (0x82<<3)|3: assert(false);break; + case (0x82<<3)|4: assert(false);break; + case (0x82<<3)|5: assert(false);break; + case (0x82<<3)|6: assert(false);break; + case (0x82<<3)|7: assert(false);break; + /* NOP (zp,X) */ + case (0x83<<3)|0: _SA(c->PC);break; + case (0x83<<3)|1: _FETCH();break; + case (0x83<<3)|2: assert(false);break; + case (0x83<<3)|3: assert(false);break; + case (0x83<<3)|4: assert(false);break; + case (0x83<<3)|5: assert(false);break; + case (0x83<<3)|6: assert(false);break; + case (0x83<<3)|7: assert(false);break; + /* STY zp */ + case (0x84<<3)|0: _SA(c->PC++);break; + case (0x84<<3)|1: _SA(_GD());_SD(c->Y);_WR();break; + case (0x84<<3)|2: _FETCH();break; + case (0x84<<3)|3: assert(false);break; + case (0x84<<3)|4: assert(false);break; + case (0x84<<3)|5: assert(false);break; + case (0x84<<3)|6: assert(false);break; + case (0x84<<3)|7: assert(false);break; + /* STA zp */ + case (0x85<<3)|0: _SA(c->PC++);break; + case (0x85<<3)|1: _SA(_GD());_SD(c->A);_WR();break; + case (0x85<<3)|2: _FETCH();break; + case (0x85<<3)|3: assert(false);break; + case (0x85<<3)|4: assert(false);break; + case (0x85<<3)|5: assert(false);break; + case (0x85<<3)|6: assert(false);break; + case (0x85<<3)|7: assert(false);break; + /* STX zp */ + case (0x86<<3)|0: _SA(c->PC++);break; + case (0x86<<3)|1: _SA(_GD());_SD(c->X);_WR();break; + case (0x86<<3)|2: _FETCH();break; + case (0x86<<3)|3: assert(false);break; + case (0x86<<3)|4: assert(false);break; + case (0x86<<3)|5: assert(false);break; + case (0x86<<3)|6: assert(false);break; + case (0x86<<3)|7: assert(false);break; + /* SMB0 zp */ + case (0x87<<3)|0: _SA(c->PC++);break; + case (0x87<<3)|1: _SA(_GD());break; + case (0x87<<3)|2: _SD(_GD()|(1<<0));_WR();break; + case (0x87<<3)|3: _FETCH();break; + case (0x87<<3)|4: assert(false);break; + case (0x87<<3)|5: assert(false);break; + case (0x87<<3)|6: assert(false);break; + case (0x87<<3)|7: assert(false);break; + /* DEY */ + case (0x88<<3)|0: _SA(c->PC);break; + case (0x88<<3)|1: c->Y--;_NZ(c->Y);_FETCH();break; + case (0x88<<3)|2: assert(false);break; + case (0x88<<3)|3: assert(false);break; + case (0x88<<3)|4: assert(false);break; + case (0x88<<3)|5: assert(false);break; + case (0x88<<3)|6: assert(false);break; + case (0x88<<3)|7: assert(false);break; + /* BIT # */ + case (0x89<<3)|0: _SA(c->PC++);break; + case (0x89<<3)|1: c->P&=~M65C02_ZF;if(!(c->A&_GD())){c->P|=M65C02_ZF;};_FETCH();break; + case (0x89<<3)|2: assert(false);break; + case (0x89<<3)|3: assert(false);break; + case (0x89<<3)|4: assert(false);break; + case (0x89<<3)|5: assert(false);break; + case (0x89<<3)|6: assert(false);break; + case (0x89<<3)|7: assert(false);break; + /* TXA */ + case (0x8A<<3)|0: _SA(c->PC);break; + case (0x8A<<3)|1: c->A=c->X;_NZ(c->A);_FETCH();break; + case (0x8A<<3)|2: assert(false);break; + case (0x8A<<3)|3: assert(false);break; + case (0x8A<<3)|4: assert(false);break; + case (0x8A<<3)|5: assert(false);break; + case (0x8A<<3)|6: assert(false);break; + case (0x8A<<3)|7: assert(false);break; + /* NOP # */ + case (0x8B<<3)|0: _SA(c->PC);break; + case (0x8B<<3)|1: _FETCH();break; + case (0x8B<<3)|2: assert(false);break; + case (0x8B<<3)|3: assert(false);break; + case (0x8B<<3)|4: assert(false);break; + case (0x8B<<3)|5: assert(false);break; + case (0x8B<<3)|6: assert(false);break; + case (0x8B<<3)|7: assert(false);break; + /* STY abs */ + case (0x8C<<3)|0: _SA(c->PC++);break; + case (0x8C<<3)|1: _SA(c->PC++);c->AD=_GD();break; + case (0x8C<<3)|2: _SA((_GD()<<8)|c->AD);_SD(c->Y);_WR();break; + case (0x8C<<3)|3: _FETCH();break; + case (0x8C<<3)|4: assert(false);break; + case (0x8C<<3)|5: assert(false);break; + case (0x8C<<3)|6: assert(false);break; + case (0x8C<<3)|7: assert(false);break; + /* STA abs */ + case (0x8D<<3)|0: _SA(c->PC++);break; + case (0x8D<<3)|1: _SA(c->PC++);c->AD=_GD();break; + case (0x8D<<3)|2: _SA((_GD()<<8)|c->AD);_SD(c->A);_WR();break; + case (0x8D<<3)|3: _FETCH();break; + case (0x8D<<3)|4: assert(false);break; + case (0x8D<<3)|5: assert(false);break; + case (0x8D<<3)|6: assert(false);break; + case (0x8D<<3)|7: assert(false);break; + /* STX abs */ + case (0x8E<<3)|0: _SA(c->PC++);break; + case (0x8E<<3)|1: _SA(c->PC++);c->AD=_GD();break; + case (0x8E<<3)|2: _SA((_GD()<<8)|c->AD);_SD(c->X);_WR();break; + case (0x8E<<3)|3: _FETCH();break; + case (0x8E<<3)|4: assert(false);break; + case (0x8E<<3)|5: assert(false);break; + case (0x8E<<3)|6: assert(false);break; + case (0x8E<<3)|7: assert(false);break; + /* BBS0 zp,rel */ + case (0x8F<<3)|0: _SA(c->PC++);break; + case (0x8F<<3)|1: _SA(_GD());break; + case (0x8F<<3)|2: c->AD=_GD();_SA(c->PC++);break; + case (0x8F<<3)|3: if(c->AD&(1<<0)){c->PC=c->PC+(int8_t)_GD();_FETCH();};_FETCH();break; + case (0x8F<<3)|4: assert(false);break; + case (0x8F<<3)|5: assert(false);break; + case (0x8F<<3)|6: assert(false);break; + case (0x8F<<3)|7: assert(false);break; + /* BCC # */ + case (0x90<<3)|0: _SA(c->PC++);break; + case (0x90<<3)|1: _SA(c->PC);c->AD=c->PC+(int8_t)_GD();if((c->P&0x1)!=0x0){_FETCH();};break; + case (0x90<<3)|2: _SA((c->PC&0xFF00)|(c->AD&0x00FF));if((c->AD&0xFF00)==(c->PC&0xFF00)){c->PC=c->AD;c->irq_pip>>=1;c->nmi_pip>>=1;_FETCH();};break; + case (0x90<<3)|3: c->PC=c->AD;_FETCH();break; + case (0x90<<3)|4: assert(false);break; + case (0x90<<3)|5: assert(false);break; + case (0x90<<3)|6: assert(false);break; + case (0x90<<3)|7: assert(false);break; + /* STA (zp),Y */ + case (0x91<<3)|0: _SA(c->PC++);break; + case (0x91<<3)|1: c->AD=_GD();_SA(c->AD);break; + case (0x91<<3)|2: _SA((c->AD+1)&0xFF);c->AD=_GD();break; + case (0x91<<3)|3: c->AD|=_GD()<<8;_SA((c->AD&0xFF00)|((c->AD+c->Y)&0xFF));break; + case (0x91<<3)|4: _SA(c->AD+c->Y);_SD(c->A);_WR();break; + case (0x91<<3)|5: _FETCH();break; + case (0x91<<3)|6: assert(false);break; + case (0x91<<3)|7: assert(false);break; + /* STA (zp) */ + case (0x92<<3)|0: _SA(c->PC++);break; + case (0x92<<3)|1: c->AD=_GD();_SA(c->AD);break; + case (0x92<<3)|2: _SA((c->AD+1)&0xFF);c->AD=_GD();break; + case (0x92<<3)|3: _SA((_GD()<<8)|c->AD);_SD(c->A);_WR();break; + case (0x92<<3)|4: _FETCH();break; + case (0x92<<3)|5: assert(false);break; + case (0x92<<3)|6: assert(false);break; + case (0x92<<3)|7: assert(false);break; + /* NOP (zp),Y */ + case (0x93<<3)|0: _SA(c->PC);break; + case (0x93<<3)|1: _FETCH();break; + case (0x93<<3)|2: assert(false);break; + case (0x93<<3)|3: assert(false);break; + case (0x93<<3)|4: assert(false);break; + case (0x93<<3)|5: assert(false);break; + case (0x93<<3)|6: assert(false);break; + case (0x93<<3)|7: assert(false);break; + /* STY zp,X */ + case (0x94<<3)|0: _SA(c->PC++);break; + case (0x94<<3)|1: c->AD=_GD();_SA(c->AD);break; + case (0x94<<3)|2: _SA((c->AD+c->X)&0x00FF);_SD(c->Y);_WR();break; + case (0x94<<3)|3: _FETCH();break; + case (0x94<<3)|4: assert(false);break; + case (0x94<<3)|5: assert(false);break; + case (0x94<<3)|6: assert(false);break; + case (0x94<<3)|7: assert(false);break; + /* STA zp,X */ + case (0x95<<3)|0: _SA(c->PC++);break; + case (0x95<<3)|1: c->AD=_GD();_SA(c->AD);break; + case (0x95<<3)|2: _SA((c->AD+c->X)&0x00FF);_SD(c->A);_WR();break; + case (0x95<<3)|3: _FETCH();break; + case (0x95<<3)|4: assert(false);break; + case (0x95<<3)|5: assert(false);break; + case (0x95<<3)|6: assert(false);break; + case (0x95<<3)|7: assert(false);break; + /* STX zp,Y */ + case (0x96<<3)|0: _SA(c->PC++);break; + case (0x96<<3)|1: c->AD=_GD();_SA(c->AD);break; + case (0x96<<3)|2: _SA((c->AD+c->Y)&0x00FF);_SD(c->X);_WR();break; + case (0x96<<3)|3: _FETCH();break; + case (0x96<<3)|4: assert(false);break; + case (0x96<<3)|5: assert(false);break; + case (0x96<<3)|6: assert(false);break; + case (0x96<<3)|7: assert(false);break; + /* SMB1 zp */ + case (0x97<<3)|0: _SA(c->PC++);break; + case (0x97<<3)|1: _SA(_GD());break; + case (0x97<<3)|2: _SD(_GD()|(1<<1));_WR();break; + case (0x97<<3)|3: _FETCH();break; + case (0x97<<3)|4: assert(false);break; + case (0x97<<3)|5: assert(false);break; + case (0x97<<3)|6: assert(false);break; + case (0x97<<3)|7: assert(false);break; + /* TYA */ + case (0x98<<3)|0: _SA(c->PC);break; + case (0x98<<3)|1: c->A=c->Y;_NZ(c->A);_FETCH();break; + case (0x98<<3)|2: assert(false);break; + case (0x98<<3)|3: assert(false);break; + case (0x98<<3)|4: assert(false);break; + case (0x98<<3)|5: assert(false);break; + case (0x98<<3)|6: assert(false);break; + case (0x98<<3)|7: assert(false);break; + /* STA abs,Y */ + case (0x99<<3)|0: _SA(c->PC++);break; + case (0x99<<3)|1: _SA(c->PC++);c->AD=_GD();break; + case (0x99<<3)|2: c->AD|=_GD()<<8;_SA((c->AD&0xFF00)|((c->AD+c->Y)&0xFF));break; + case (0x99<<3)|3: _SA(c->AD+c->Y);_SD(c->A);_WR();break; + case (0x99<<3)|4: _FETCH();break; + case (0x99<<3)|5: assert(false);break; + case (0x99<<3)|6: assert(false);break; + case (0x99<<3)|7: assert(false);break; + /* TXS */ + case (0x9A<<3)|0: _SA(c->PC);break; + case (0x9A<<3)|1: c->S=c->X;_FETCH();break; + case (0x9A<<3)|2: assert(false);break; + case (0x9A<<3)|3: assert(false);break; + case (0x9A<<3)|4: assert(false);break; + case (0x9A<<3)|5: assert(false);break; + case (0x9A<<3)|6: assert(false);break; + case (0x9A<<3)|7: assert(false);break; + /* NOP abs,Y */ + case (0x9B<<3)|0: _SA(c->PC);break; + case (0x9B<<3)|1: _FETCH();break; + case (0x9B<<3)|2: assert(false);break; + case (0x9B<<3)|3: assert(false);break; + case (0x9B<<3)|4: assert(false);break; + case (0x9B<<3)|5: assert(false);break; + case (0x9B<<3)|6: assert(false);break; + case (0x9B<<3)|7: assert(false);break; + /* STZ abs */ + case (0x9C<<3)|0: _SA(c->PC++);break; + case (0x9C<<3)|1: _SA(c->PC++);c->AD=_GD();break; + case (0x9C<<3)|2: _SA((_GD()<<8)|c->AD);_SD(0);_WR();break; + case (0x9C<<3)|3: _FETCH();break; + case (0x9C<<3)|4: assert(false);break; + case (0x9C<<3)|5: assert(false);break; + case (0x9C<<3)|6: assert(false);break; + case (0x9C<<3)|7: assert(false);break; + /* STA abs,X */ + case (0x9D<<3)|0: _SA(c->PC++);break; + case (0x9D<<3)|1: _SA(c->PC++);c->AD=_GD();break; + case (0x9D<<3)|2: c->AD|=_GD()<<8;_SA((c->AD&0xFF00)|((c->AD+c->X)&0xFF));break; + case (0x9D<<3)|3: _SA(c->AD+c->X);_SD(c->A);_WR();break; + case (0x9D<<3)|4: _FETCH();break; + case (0x9D<<3)|5: assert(false);break; + case (0x9D<<3)|6: assert(false);break; + case (0x9D<<3)|7: assert(false);break; + /* STZ abs,X */ + case (0x9E<<3)|0: _SA(c->PC++);break; + case (0x9E<<3)|1: _SA(c->PC++);c->AD=_GD();break; + case (0x9E<<3)|2: c->AD|=_GD()<<8;_SA((c->AD&0xFF00)|((c->AD+c->X)&0xFF));break; + case (0x9E<<3)|3: _SA(c->AD+c->X);_SD(0);_WR();break; + case (0x9E<<3)|4: _FETCH();break; + case (0x9E<<3)|5: assert(false);break; + case (0x9E<<3)|6: assert(false);break; + case (0x9E<<3)|7: assert(false);break; + /* BBS1 zp,rel */ + case (0x9F<<3)|0: _SA(c->PC++);break; + case (0x9F<<3)|1: _SA(_GD());break; + case (0x9F<<3)|2: c->AD=_GD();_SA(c->PC++);break; + case (0x9F<<3)|3: if(c->AD&(1<<1)){c->PC=c->PC+(int8_t)_GD();_FETCH();};_FETCH();break; + case (0x9F<<3)|4: assert(false);break; + case (0x9F<<3)|5: assert(false);break; + case (0x9F<<3)|6: assert(false);break; + case (0x9F<<3)|7: assert(false);break; + /* LDY # */ + case (0xA0<<3)|0: _SA(c->PC++);break; + case (0xA0<<3)|1: c->Y=_GD();_NZ(c->Y);_FETCH();break; + case (0xA0<<3)|2: assert(false);break; + case (0xA0<<3)|3: assert(false);break; + case (0xA0<<3)|4: assert(false);break; + case (0xA0<<3)|5: assert(false);break; + case (0xA0<<3)|6: assert(false);break; + case (0xA0<<3)|7: assert(false);break; + /* LDA (zp,X) */ + case (0xA1<<3)|0: _SA(c->PC++);break; + case (0xA1<<3)|1: c->AD=_GD();_SA(c->AD);break; + case (0xA1<<3)|2: c->AD=(c->AD+c->X)&0xFF;_SA(c->AD);break; + case (0xA1<<3)|3: _SA((c->AD+1)&0xFF);c->AD=_GD();break; + case (0xA1<<3)|4: _SA((_GD()<<8)|c->AD);break; + case (0xA1<<3)|5: c->A=_GD();_NZ(c->A);_FETCH();break; + case (0xA1<<3)|6: assert(false);break; + case (0xA1<<3)|7: assert(false);break; + /* LDX # */ + case (0xA2<<3)|0: _SA(c->PC++);break; + case (0xA2<<3)|1: c->X=_GD();_NZ(c->X);_FETCH();break; + case (0xA2<<3)|2: assert(false);break; + case (0xA2<<3)|3: assert(false);break; + case (0xA2<<3)|4: assert(false);break; + case (0xA2<<3)|5: assert(false);break; + case (0xA2<<3)|6: assert(false);break; + case (0xA2<<3)|7: assert(false);break; + /* NOP (zp,X) */ + case (0xA3<<3)|0: _SA(c->PC);break; + case (0xA3<<3)|1: _FETCH();break; + case (0xA3<<3)|2: assert(false);break; + case (0xA3<<3)|3: assert(false);break; + case (0xA3<<3)|4: assert(false);break; + case (0xA3<<3)|5: assert(false);break; + case (0xA3<<3)|6: assert(false);break; + case (0xA3<<3)|7: assert(false);break; + /* LDY zp */ + case (0xA4<<3)|0: _SA(c->PC++);break; + case (0xA4<<3)|1: _SA(_GD());break; + case (0xA4<<3)|2: c->Y=_GD();_NZ(c->Y);_FETCH();break; + case (0xA4<<3)|3: assert(false);break; + case (0xA4<<3)|4: assert(false);break; + case (0xA4<<3)|5: assert(false);break; + case (0xA4<<3)|6: assert(false);break; + case (0xA4<<3)|7: assert(false);break; + /* LDA zp */ + case (0xA5<<3)|0: _SA(c->PC++);break; + case (0xA5<<3)|1: _SA(_GD());break; + case (0xA5<<3)|2: c->A=_GD();_NZ(c->A);_FETCH();break; + case (0xA5<<3)|3: assert(false);break; + case (0xA5<<3)|4: assert(false);break; + case (0xA5<<3)|5: assert(false);break; + case (0xA5<<3)|6: assert(false);break; + case (0xA5<<3)|7: assert(false);break; + /* LDX zp */ + case (0xA6<<3)|0: _SA(c->PC++);break; + case (0xA6<<3)|1: _SA(_GD());break; + case (0xA6<<3)|2: c->X=_GD();_NZ(c->X);_FETCH();break; + case (0xA6<<3)|3: assert(false);break; + case (0xA6<<3)|4: assert(false);break; + case (0xA6<<3)|5: assert(false);break; + case (0xA6<<3)|6: assert(false);break; + case (0xA6<<3)|7: assert(false);break; + /* SMB2 zp */ + case (0xA7<<3)|0: _SA(c->PC++);break; + case (0xA7<<3)|1: _SA(_GD());break; + case (0xA7<<3)|2: _SD(_GD()|(1<<2));_WR();break; + case (0xA7<<3)|3: _FETCH();break; + case (0xA7<<3)|4: assert(false);break; + case (0xA7<<3)|5: assert(false);break; + case (0xA7<<3)|6: assert(false);break; + case (0xA7<<3)|7: assert(false);break; + /* TAY */ + case (0xA8<<3)|0: _SA(c->PC);break; + case (0xA8<<3)|1: c->Y=c->A;_NZ(c->Y);_FETCH();break; + case (0xA8<<3)|2: assert(false);break; + case (0xA8<<3)|3: assert(false);break; + case (0xA8<<3)|4: assert(false);break; + case (0xA8<<3)|5: assert(false);break; + case (0xA8<<3)|6: assert(false);break; + case (0xA8<<3)|7: assert(false);break; + /* LDA # */ + case (0xA9<<3)|0: _SA(c->PC++);break; + case (0xA9<<3)|1: c->A=_GD();_NZ(c->A);_FETCH();break; + case (0xA9<<3)|2: assert(false);break; + case (0xA9<<3)|3: assert(false);break; + case (0xA9<<3)|4: assert(false);break; + case (0xA9<<3)|5: assert(false);break; + case (0xA9<<3)|6: assert(false);break; + case (0xA9<<3)|7: assert(false);break; + /* TAX */ + case (0xAA<<3)|0: _SA(c->PC);break; + case (0xAA<<3)|1: c->X=c->A;_NZ(c->X);_FETCH();break; + case (0xAA<<3)|2: assert(false);break; + case (0xAA<<3)|3: assert(false);break; + case (0xAA<<3)|4: assert(false);break; + case (0xAA<<3)|5: assert(false);break; + case (0xAA<<3)|6: assert(false);break; + case (0xAA<<3)|7: assert(false);break; + /* NOP # */ + case (0xAB<<3)|0: _SA(c->PC);break; + case (0xAB<<3)|1: _FETCH();break; + case (0xAB<<3)|2: assert(false);break; + case (0xAB<<3)|3: assert(false);break; + case (0xAB<<3)|4: assert(false);break; + case (0xAB<<3)|5: assert(false);break; + case (0xAB<<3)|6: assert(false);break; + case (0xAB<<3)|7: assert(false);break; + /* LDY abs */ + case (0xAC<<3)|0: _SA(c->PC++);break; + case (0xAC<<3)|1: _SA(c->PC++);c->AD=_GD();break; + case (0xAC<<3)|2: _SA((_GD()<<8)|c->AD);break; + case (0xAC<<3)|3: c->Y=_GD();_NZ(c->Y);_FETCH();break; + case (0xAC<<3)|4: assert(false);break; + case (0xAC<<3)|5: assert(false);break; + case (0xAC<<3)|6: assert(false);break; + case (0xAC<<3)|7: assert(false);break; + /* LDA abs */ + case (0xAD<<3)|0: _SA(c->PC++);break; + case (0xAD<<3)|1: _SA(c->PC++);c->AD=_GD();break; + case (0xAD<<3)|2: _SA((_GD()<<8)|c->AD);break; + case (0xAD<<3)|3: c->A=_GD();_NZ(c->A);_FETCH();break; + case (0xAD<<3)|4: assert(false);break; + case (0xAD<<3)|5: assert(false);break; + case (0xAD<<3)|6: assert(false);break; + case (0xAD<<3)|7: assert(false);break; + /* LDX abs */ + case (0xAE<<3)|0: _SA(c->PC++);break; + case (0xAE<<3)|1: _SA(c->PC++);c->AD=_GD();break; + case (0xAE<<3)|2: _SA((_GD()<<8)|c->AD);break; + case (0xAE<<3)|3: c->X=_GD();_NZ(c->X);_FETCH();break; + case (0xAE<<3)|4: assert(false);break; + case (0xAE<<3)|5: assert(false);break; + case (0xAE<<3)|6: assert(false);break; + case (0xAE<<3)|7: assert(false);break; + /* BBS2 zp,rel */ + case (0xAF<<3)|0: _SA(c->PC++);break; + case (0xAF<<3)|1: _SA(_GD());break; + case (0xAF<<3)|2: c->AD=_GD();_SA(c->PC++);break; + case (0xAF<<3)|3: if(c->AD&(1<<2)){c->PC=c->PC+(int8_t)_GD();_FETCH();};_FETCH();break; + case (0xAF<<3)|4: assert(false);break; + case (0xAF<<3)|5: assert(false);break; + case (0xAF<<3)|6: assert(false);break; + case (0xAF<<3)|7: assert(false);break; + /* BCS # */ + case (0xB0<<3)|0: _SA(c->PC++);break; + case (0xB0<<3)|1: _SA(c->PC);c->AD=c->PC+(int8_t)_GD();if((c->P&0x1)!=0x1){_FETCH();};break; + case (0xB0<<3)|2: _SA((c->PC&0xFF00)|(c->AD&0x00FF));if((c->AD&0xFF00)==(c->PC&0xFF00)){c->PC=c->AD;c->irq_pip>>=1;c->nmi_pip>>=1;_FETCH();};break; + case (0xB0<<3)|3: c->PC=c->AD;_FETCH();break; + case (0xB0<<3)|4: assert(false);break; + case (0xB0<<3)|5: assert(false);break; + case (0xB0<<3)|6: assert(false);break; + case (0xB0<<3)|7: assert(false);break; + /* LDA (zp),Y */ + case (0xB1<<3)|0: _SA(c->PC++);break; + case (0xB1<<3)|1: c->AD=_GD();_SA(c->AD);break; + case (0xB1<<3)|2: _SA((c->AD+1)&0xFF);c->AD=_GD();break; + case (0xB1<<3)|3: c->AD|=_GD()<<8;_SA((c->AD&0xFF00)|((c->AD+c->Y)&0xFF));c->IR+=(~((c->AD>>8)-((c->AD+c->Y)>>8)))&1;break; + case (0xB1<<3)|4: _SA(c->AD+c->Y);break; + case (0xB1<<3)|5: c->A=_GD();_NZ(c->A);_FETCH();break; + case (0xB1<<3)|6: assert(false);break; + case (0xB1<<3)|7: assert(false);break; + /* LDA (zp) */ + case (0xB2<<3)|0: _SA(c->PC++);break; + case (0xB2<<3)|1: c->AD=_GD();_SA(c->AD);break; + case (0xB2<<3)|2: _SA((c->AD+1)&0xFF);c->AD=_GD();break; + case (0xB2<<3)|3: _SA((_GD()<<8)|c->AD);break; + case (0xB2<<3)|4: c->A=_GD();_NZ(c->A);_FETCH();break; + case (0xB2<<3)|5: assert(false);break; + case (0xB2<<3)|6: assert(false);break; + case (0xB2<<3)|7: assert(false);break; + /* NOP (zp),Y */ + case (0xB3<<3)|0: _SA(c->PC);break; + case (0xB3<<3)|1: _FETCH();break; + case (0xB3<<3)|2: assert(false);break; + case (0xB3<<3)|3: assert(false);break; + case (0xB3<<3)|4: assert(false);break; + case (0xB3<<3)|5: assert(false);break; + case (0xB3<<3)|6: assert(false);break; + case (0xB3<<3)|7: assert(false);break; + /* LDY zp,X */ + case (0xB4<<3)|0: _SA(c->PC++);break; + case (0xB4<<3)|1: c->AD=_GD();_SA(c->AD);break; + case (0xB4<<3)|2: _SA((c->AD+c->X)&0x00FF);break; + case (0xB4<<3)|3: c->Y=_GD();_NZ(c->Y);_FETCH();break; + case (0xB4<<3)|4: assert(false);break; + case (0xB4<<3)|5: assert(false);break; + case (0xB4<<3)|6: assert(false);break; + case (0xB4<<3)|7: assert(false);break; + /* LDA zp,X */ + case (0xB5<<3)|0: _SA(c->PC++);break; + case (0xB5<<3)|1: c->AD=_GD();_SA(c->AD);break; + case (0xB5<<3)|2: _SA((c->AD+c->X)&0x00FF);break; + case (0xB5<<3)|3: c->A=_GD();_NZ(c->A);_FETCH();break; + case (0xB5<<3)|4: assert(false);break; + case (0xB5<<3)|5: assert(false);break; + case (0xB5<<3)|6: assert(false);break; + case (0xB5<<3)|7: assert(false);break; + /* LDX zp,Y */ + case (0xB6<<3)|0: _SA(c->PC++);break; + case (0xB6<<3)|1: c->AD=_GD();_SA(c->AD);break; + case (0xB6<<3)|2: _SA((c->AD+c->Y)&0x00FF);break; + case (0xB6<<3)|3: c->X=_GD();_NZ(c->X);_FETCH();break; + case (0xB6<<3)|4: assert(false);break; + case (0xB6<<3)|5: assert(false);break; + case (0xB6<<3)|6: assert(false);break; + case (0xB6<<3)|7: assert(false);break; + /* SMB3 zp */ + case (0xB7<<3)|0: _SA(c->PC++);break; + case (0xB7<<3)|1: _SA(_GD());break; + case (0xB7<<3)|2: _SD(_GD()|(1<<3));_WR();break; + case (0xB7<<3)|3: _FETCH();break; + case (0xB7<<3)|4: assert(false);break; + case (0xB7<<3)|5: assert(false);break; + case (0xB7<<3)|6: assert(false);break; + case (0xB7<<3)|7: assert(false);break; + /* CLV */ + case (0xB8<<3)|0: _SA(c->PC);break; + case (0xB8<<3)|1: c->P&=~0x40;_FETCH();break; + case (0xB8<<3)|2: assert(false);break; + case (0xB8<<3)|3: assert(false);break; + case (0xB8<<3)|4: assert(false);break; + case (0xB8<<3)|5: assert(false);break; + case (0xB8<<3)|6: assert(false);break; + case (0xB8<<3)|7: assert(false);break; + /* LDA abs,Y */ + case (0xB9<<3)|0: _SA(c->PC++);break; + case (0xB9<<3)|1: _SA(c->PC++);c->AD=_GD();break; + case (0xB9<<3)|2: c->AD|=_GD()<<8;_SA((c->AD&0xFF00)|((c->AD+c->Y)&0xFF));c->IR+=(~((c->AD>>8)-((c->AD+c->Y)>>8)))&1;break; + case (0xB9<<3)|3: _SA(c->AD+c->Y);break; + case (0xB9<<3)|4: c->A=_GD();_NZ(c->A);_FETCH();break; + case (0xB9<<3)|5: assert(false);break; + case (0xB9<<3)|6: assert(false);break; + case (0xB9<<3)|7: assert(false);break; + /* TSX */ + case (0xBA<<3)|0: _SA(c->PC);break; + case (0xBA<<3)|1: c->X=c->S;_NZ(c->X);_FETCH();break; + case (0xBA<<3)|2: assert(false);break; + case (0xBA<<3)|3: assert(false);break; + case (0xBA<<3)|4: assert(false);break; + case (0xBA<<3)|5: assert(false);break; + case (0xBA<<3)|6: assert(false);break; + case (0xBA<<3)|7: assert(false);break; + /* NOP abs,Y */ + case (0xBB<<3)|0: _SA(c->PC);break; + case (0xBB<<3)|1: _FETCH();break; + case (0xBB<<3)|2: assert(false);break; + case (0xBB<<3)|3: assert(false);break; + case (0xBB<<3)|4: assert(false);break; + case (0xBB<<3)|5: assert(false);break; + case (0xBB<<3)|6: assert(false);break; + case (0xBB<<3)|7: assert(false);break; + /* LDY abs,X */ + case (0xBC<<3)|0: _SA(c->PC++);break; + case (0xBC<<3)|1: _SA(c->PC++);c->AD=_GD();break; + case (0xBC<<3)|2: c->AD|=_GD()<<8;_SA((c->AD&0xFF00)|((c->AD+c->X)&0xFF));c->IR+=(~((c->AD>>8)-((c->AD+c->X)>>8)))&1;break; + case (0xBC<<3)|3: _SA(c->AD+c->X);break; + case (0xBC<<3)|4: c->Y=_GD();_NZ(c->Y);_FETCH();break; + case (0xBC<<3)|5: assert(false);break; + case (0xBC<<3)|6: assert(false);break; + case (0xBC<<3)|7: assert(false);break; + /* LDA abs,X */ + case (0xBD<<3)|0: _SA(c->PC++);break; + case (0xBD<<3)|1: _SA(c->PC++);c->AD=_GD();break; + case (0xBD<<3)|2: c->AD|=_GD()<<8;_SA((c->AD&0xFF00)|((c->AD+c->X)&0xFF));c->IR+=(~((c->AD>>8)-((c->AD+c->X)>>8)))&1;break; + case (0xBD<<3)|3: _SA(c->AD+c->X);break; + case (0xBD<<3)|4: c->A=_GD();_NZ(c->A);_FETCH();break; + case (0xBD<<3)|5: assert(false);break; + case (0xBD<<3)|6: assert(false);break; + case (0xBD<<3)|7: assert(false);break; + /* LDX abs,Y */ + case (0xBE<<3)|0: _SA(c->PC++);break; + case (0xBE<<3)|1: _SA(c->PC++);c->AD=_GD();break; + case (0xBE<<3)|2: c->AD|=_GD()<<8;_SA((c->AD&0xFF00)|((c->AD+c->Y)&0xFF));c->IR+=(~((c->AD>>8)-((c->AD+c->Y)>>8)))&1;break; + case (0xBE<<3)|3: _SA(c->AD+c->Y);break; + case (0xBE<<3)|4: c->X=_GD();_NZ(c->X);_FETCH();break; + case (0xBE<<3)|5: assert(false);break; + case (0xBE<<3)|6: assert(false);break; + case (0xBE<<3)|7: assert(false);break; + /* BBS3 zp,rel */ + case (0xBF<<3)|0: _SA(c->PC++);break; + case (0xBF<<3)|1: _SA(_GD());break; + case (0xBF<<3)|2: c->AD=_GD();_SA(c->PC++);break; + case (0xBF<<3)|3: if(c->AD&(1<<3)){c->PC=c->PC+(int8_t)_GD();_FETCH();};_FETCH();break; + case (0xBF<<3)|4: assert(false);break; + case (0xBF<<3)|5: assert(false);break; + case (0xBF<<3)|6: assert(false);break; + case (0xBF<<3)|7: assert(false);break; + /* CPY # */ + case (0xC0<<3)|0: _SA(c->PC++);break; + case (0xC0<<3)|1: _m65c02_cmp(c, c->Y, _GD());_FETCH();break; + case (0xC0<<3)|2: assert(false);break; + case (0xC0<<3)|3: assert(false);break; + case (0xC0<<3)|4: assert(false);break; + case (0xC0<<3)|5: assert(false);break; + case (0xC0<<3)|6: assert(false);break; + case (0xC0<<3)|7: assert(false);break; + /* CMP (zp,X) */ + case (0xC1<<3)|0: _SA(c->PC++);break; + case (0xC1<<3)|1: c->AD=_GD();_SA(c->AD);break; + case (0xC1<<3)|2: c->AD=(c->AD+c->X)&0xFF;_SA(c->AD);break; + case (0xC1<<3)|3: _SA((c->AD+1)&0xFF);c->AD=_GD();break; + case (0xC1<<3)|4: _SA((_GD()<<8)|c->AD);break; + case (0xC1<<3)|5: _m65c02_cmp(c, c->A, _GD());_FETCH();break; + case (0xC1<<3)|6: assert(false);break; + case (0xC1<<3)|7: assert(false);break; + /* LDD # */ + case (0xC2<<3)|0: _SA(c->PC++);break; + case (0xC2<<3)|1: _FETCH();break; + case (0xC2<<3)|2: assert(false);break; + case (0xC2<<3)|3: assert(false);break; + case (0xC2<<3)|4: assert(false);break; + case (0xC2<<3)|5: assert(false);break; + case (0xC2<<3)|6: assert(false);break; + case (0xC2<<3)|7: assert(false);break; + /* NOP (zp,X) */ + case (0xC3<<3)|0: _SA(c->PC);break; + case (0xC3<<3)|1: _FETCH();break; + case (0xC3<<3)|2: assert(false);break; + case (0xC3<<3)|3: assert(false);break; + case (0xC3<<3)|4: assert(false);break; + case (0xC3<<3)|5: assert(false);break; + case (0xC3<<3)|6: assert(false);break; + case (0xC3<<3)|7: assert(false);break; + /* CPY zp */ + case (0xC4<<3)|0: _SA(c->PC++);break; + case (0xC4<<3)|1: _SA(_GD());break; + case (0xC4<<3)|2: _m65c02_cmp(c, c->Y, _GD());_FETCH();break; + case (0xC4<<3)|3: assert(false);break; + case (0xC4<<3)|4: assert(false);break; + case (0xC4<<3)|5: assert(false);break; + case (0xC4<<3)|6: assert(false);break; + case (0xC4<<3)|7: assert(false);break; + /* CMP zp */ + case (0xC5<<3)|0: _SA(c->PC++);break; + case (0xC5<<3)|1: _SA(_GD());break; + case (0xC5<<3)|2: _m65c02_cmp(c, c->A, _GD());_FETCH();break; + case (0xC5<<3)|3: assert(false);break; + case (0xC5<<3)|4: assert(false);break; + case (0xC5<<3)|5: assert(false);break; + case (0xC5<<3)|6: assert(false);break; + case (0xC5<<3)|7: assert(false);break; + /* DEC zp */ + case (0xC6<<3)|0: _SA(c->PC++);break; + case (0xC6<<3)|1: _SA(_GD());break; + case (0xC6<<3)|2: c->AD=_GD();break; + case (0xC6<<3)|3: c->AD--;_NZ(c->AD);_SD(c->AD);_WR();break; + case (0xC6<<3)|4: _FETCH();break; + case (0xC6<<3)|5: assert(false);break; + case (0xC6<<3)|6: assert(false);break; + case (0xC6<<3)|7: assert(false);break; + /* SMB4 zp */ + case (0xC7<<3)|0: _SA(c->PC++);break; + case (0xC7<<3)|1: _SA(_GD());break; + case (0xC7<<3)|2: _SD(_GD()|(1<<4));_WR();break; + case (0xC7<<3)|3: _FETCH();break; + case (0xC7<<3)|4: assert(false);break; + case (0xC7<<3)|5: assert(false);break; + case (0xC7<<3)|6: assert(false);break; + case (0xC7<<3)|7: assert(false);break; + /* INY */ + case (0xC8<<3)|0: _SA(c->PC);break; + case (0xC8<<3)|1: c->Y++;_NZ(c->Y);_FETCH();break; + case (0xC8<<3)|2: assert(false);break; + case (0xC8<<3)|3: assert(false);break; + case (0xC8<<3)|4: assert(false);break; + case (0xC8<<3)|5: assert(false);break; + case (0xC8<<3)|6: assert(false);break; + case (0xC8<<3)|7: assert(false);break; + /* CMP # */ + case (0xC9<<3)|0: _SA(c->PC++);break; + case (0xC9<<3)|1: _m65c02_cmp(c, c->A, _GD());_FETCH();break; + case (0xC9<<3)|2: assert(false);break; + case (0xC9<<3)|3: assert(false);break; + case (0xC9<<3)|4: assert(false);break; + case (0xC9<<3)|5: assert(false);break; + case (0xC9<<3)|6: assert(false);break; + case (0xC9<<3)|7: assert(false);break; + /* DEX */ + case (0xCA<<3)|0: _SA(c->PC);break; + case (0xCA<<3)|1: c->X--;_NZ(c->X);_FETCH();break; + case (0xCA<<3)|2: assert(false);break; + case (0xCA<<3)|3: assert(false);break; + case (0xCA<<3)|4: assert(false);break; + case (0xCA<<3)|5: assert(false);break; + case (0xCA<<3)|6: assert(false);break; + case (0xCA<<3)|7: assert(false);break; + /* NOP # */ + case (0xCB<<3)|0: _SA(c->PC);break; + case (0xCB<<3)|1: _FETCH();break; + case (0xCB<<3)|2: assert(false);break; + case (0xCB<<3)|3: assert(false);break; + case (0xCB<<3)|4: assert(false);break; + case (0xCB<<3)|5: assert(false);break; + case (0xCB<<3)|6: assert(false);break; + case (0xCB<<3)|7: assert(false);break; + /* CPY abs */ + case (0xCC<<3)|0: _SA(c->PC++);break; + case (0xCC<<3)|1: _SA(c->PC++);c->AD=_GD();break; + case (0xCC<<3)|2: _SA((_GD()<<8)|c->AD);break; + case (0xCC<<3)|3: _m65c02_cmp(c, c->Y, _GD());_FETCH();break; + case (0xCC<<3)|4: assert(false);break; + case (0xCC<<3)|5: assert(false);break; + case (0xCC<<3)|6: assert(false);break; + case (0xCC<<3)|7: assert(false);break; + /* CMP abs */ + case (0xCD<<3)|0: _SA(c->PC++);break; + case (0xCD<<3)|1: _SA(c->PC++);c->AD=_GD();break; + case (0xCD<<3)|2: _SA((_GD()<<8)|c->AD);break; + case (0xCD<<3)|3: _m65c02_cmp(c, c->A, _GD());_FETCH();break; + case (0xCD<<3)|4: assert(false);break; + case (0xCD<<3)|5: assert(false);break; + case (0xCD<<3)|6: assert(false);break; + case (0xCD<<3)|7: assert(false);break; + /* DEC abs */ + case (0xCE<<3)|0: _SA(c->PC++);break; + case (0xCE<<3)|1: _SA(c->PC++);c->AD=_GD();break; + case (0xCE<<3)|2: _SA((_GD()<<8)|c->AD);break; + case (0xCE<<3)|3: c->AD=_GD();break; + case (0xCE<<3)|4: c->AD--;_NZ(c->AD);_SD(c->AD);_WR();break; + case (0xCE<<3)|5: _FETCH();break; + case (0xCE<<3)|6: assert(false);break; + case (0xCE<<3)|7: assert(false);break; + /* BBS4 zp,rel */ + case (0xCF<<3)|0: _SA(c->PC++);break; + case (0xCF<<3)|1: _SA(_GD());break; + case (0xCF<<3)|2: c->AD=_GD();_SA(c->PC++);break; + case (0xCF<<3)|3: if(c->AD&(1<<4)){c->PC=c->PC+(int8_t)_GD();_FETCH();};_FETCH();break; + case (0xCF<<3)|4: assert(false);break; + case (0xCF<<3)|5: assert(false);break; + case (0xCF<<3)|6: assert(false);break; + case (0xCF<<3)|7: assert(false);break; + /* BNE # */ + case (0xD0<<3)|0: _SA(c->PC++);break; + case (0xD0<<3)|1: _SA(c->PC);c->AD=c->PC+(int8_t)_GD();if((c->P&0x2)!=0x0){_FETCH();};break; + case (0xD0<<3)|2: _SA((c->PC&0xFF00)|(c->AD&0x00FF));if((c->AD&0xFF00)==(c->PC&0xFF00)){c->PC=c->AD;c->irq_pip>>=1;c->nmi_pip>>=1;_FETCH();};break; + case (0xD0<<3)|3: c->PC=c->AD;_FETCH();break; + case (0xD0<<3)|4: assert(false);break; + case (0xD0<<3)|5: assert(false);break; + case (0xD0<<3)|6: assert(false);break; + case (0xD0<<3)|7: assert(false);break; + /* CMP (zp),Y */ + case (0xD1<<3)|0: _SA(c->PC++);break; + case (0xD1<<3)|1: c->AD=_GD();_SA(c->AD);break; + case (0xD1<<3)|2: _SA((c->AD+1)&0xFF);c->AD=_GD();break; + case (0xD1<<3)|3: c->AD|=_GD()<<8;_SA((c->AD&0xFF00)|((c->AD+c->Y)&0xFF));c->IR+=(~((c->AD>>8)-((c->AD+c->Y)>>8)))&1;break; + case (0xD1<<3)|4: _SA(c->AD+c->Y);break; + case (0xD1<<3)|5: _m65c02_cmp(c, c->A, _GD());_FETCH();break; + case (0xD1<<3)|6: assert(false);break; + case (0xD1<<3)|7: assert(false);break; + /* CMP (zp) */ + case (0xD2<<3)|0: _SA(c->PC++);break; + case (0xD2<<3)|1: c->AD=_GD();_SA(c->AD);break; + case (0xD2<<3)|2: _SA((c->AD+1)&0xFF);c->AD=_GD();break; + case (0xD2<<3)|3: _SA((_GD()<<8)|c->AD);break; + case (0xD2<<3)|4: _m65c02_cmp(c, c->A, _GD());_FETCH();break; + case (0xD2<<3)|5: assert(false);break; + case (0xD2<<3)|6: assert(false);break; + case (0xD2<<3)|7: assert(false);break; + /* NOP (zp),Y */ + case (0xD3<<3)|0: _SA(c->PC);break; + case (0xD3<<3)|1: _FETCH();break; + case (0xD3<<3)|2: assert(false);break; + case (0xD3<<3)|3: assert(false);break; + case (0xD3<<3)|4: assert(false);break; + case (0xD3<<3)|5: assert(false);break; + case (0xD3<<3)|6: assert(false);break; + case (0xD3<<3)|7: assert(false);break; + /* LDD zp,X */ + case (0xD4<<3)|0: _SA(c->PC++);break; + case (0xD4<<3)|1: c->AD=_GD();_SA(c->AD);break; + case (0xD4<<3)|2: _SA((c->AD+c->X)&0x00FF);break; + case (0xD4<<3)|3: _FETCH();break; + case (0xD4<<3)|4: assert(false);break; + case (0xD4<<3)|5: assert(false);break; + case (0xD4<<3)|6: assert(false);break; + case (0xD4<<3)|7: assert(false);break; + /* CMP zp,X */ + case (0xD5<<3)|0: _SA(c->PC++);break; + case (0xD5<<3)|1: c->AD=_GD();_SA(c->AD);break; + case (0xD5<<3)|2: _SA((c->AD+c->X)&0x00FF);break; + case (0xD5<<3)|3: _m65c02_cmp(c, c->A, _GD());_FETCH();break; + case (0xD5<<3)|4: assert(false);break; + case (0xD5<<3)|5: assert(false);break; + case (0xD5<<3)|6: assert(false);break; + case (0xD5<<3)|7: assert(false);break; + /* DEC zp,X */ + case (0xD6<<3)|0: _SA(c->PC++);break; + case (0xD6<<3)|1: c->AD=_GD();_SA(c->AD);break; + case (0xD6<<3)|2: _SA((c->AD+c->X)&0x00FF);break; + case (0xD6<<3)|3: c->AD=_GD();break; + case (0xD6<<3)|4: c->AD--;_NZ(c->AD);_SD(c->AD);_WR();break; + case (0xD6<<3)|5: _FETCH();break; + case (0xD6<<3)|6: assert(false);break; + case (0xD6<<3)|7: assert(false);break; + /* SMB5 zp */ + case (0xD7<<3)|0: _SA(c->PC++);break; + case (0xD7<<3)|1: _SA(_GD());break; + case (0xD7<<3)|2: _SD(_GD()|(1<<5));_WR();break; + case (0xD7<<3)|3: _FETCH();break; + case (0xD7<<3)|4: assert(false);break; + case (0xD7<<3)|5: assert(false);break; + case (0xD7<<3)|6: assert(false);break; + case (0xD7<<3)|7: assert(false);break; + /* CLD */ + case (0xD8<<3)|0: _SA(c->PC);break; + case (0xD8<<3)|1: c->P&=~0x8;_FETCH();break; + case (0xD8<<3)|2: assert(false);break; + case (0xD8<<3)|3: assert(false);break; + case (0xD8<<3)|4: assert(false);break; + case (0xD8<<3)|5: assert(false);break; + case (0xD8<<3)|6: assert(false);break; + case (0xD8<<3)|7: assert(false);break; + /* CMP abs,Y */ + case (0xD9<<3)|0: _SA(c->PC++);break; + case (0xD9<<3)|1: _SA(c->PC++);c->AD=_GD();break; + case (0xD9<<3)|2: c->AD|=_GD()<<8;_SA((c->AD&0xFF00)|((c->AD+c->Y)&0xFF));c->IR+=(~((c->AD>>8)-((c->AD+c->Y)>>8)))&1;break; + case (0xD9<<3)|3: _SA(c->AD+c->Y);break; + case (0xD9<<3)|4: _m65c02_cmp(c, c->A, _GD());_FETCH();break; + case (0xD9<<3)|5: assert(false);break; + case (0xD9<<3)|6: assert(false);break; + case (0xD9<<3)|7: assert(false);break; + /* PHX */ + case (0xDA<<3)|0: _SA(c->PC);break; + case (0xDA<<3)|1: _SAD(0x0100|c->S--,c->X);_WR();break; + case (0xDA<<3)|2: _FETCH();break; + case (0xDA<<3)|3: assert(false);break; + case (0xDA<<3)|4: assert(false);break; + case (0xDA<<3)|5: assert(false);break; + case (0xDA<<3)|6: assert(false);break; + case (0xDA<<3)|7: assert(false);break; + /* NOP abs,Y */ + case (0xDB<<3)|0: _SA(c->PC);break; + case (0xDB<<3)|1: _FETCH();break; + case (0xDB<<3)|2: assert(false);break; + case (0xDB<<3)|3: assert(false);break; + case (0xDB<<3)|4: assert(false);break; + case (0xDB<<3)|5: assert(false);break; + case (0xDB<<3)|6: assert(false);break; + case (0xDB<<3)|7: assert(false);break; + /* LDD abs */ + case (0xDC<<3)|0: _SA(c->PC++);break; + case (0xDC<<3)|1: _SA(c->PC++);c->AD=_GD();break; + case (0xDC<<3)|2: _SA((_GD()<<8)|c->AD);break; + case (0xDC<<3)|3: _FETCH();break; + case (0xDC<<3)|4: assert(false);break; + case (0xDC<<3)|5: assert(false);break; + case (0xDC<<3)|6: assert(false);break; + case (0xDC<<3)|7: assert(false);break; + /* CMP abs,X */ + case (0xDD<<3)|0: _SA(c->PC++);break; + case (0xDD<<3)|1: _SA(c->PC++);c->AD=_GD();break; + case (0xDD<<3)|2: c->AD|=_GD()<<8;_SA((c->AD&0xFF00)|((c->AD+c->X)&0xFF));c->IR+=(~((c->AD>>8)-((c->AD+c->X)>>8)))&1;break; + case (0xDD<<3)|3: _SA(c->AD+c->X);break; + case (0xDD<<3)|4: _m65c02_cmp(c, c->A, _GD());_FETCH();break; + case (0xDD<<3)|5: assert(false);break; + case (0xDD<<3)|6: assert(false);break; + case (0xDD<<3)|7: assert(false);break; + /* DEC abs,X */ + case (0xDE<<3)|0: _SA(c->PC++);break; + case (0xDE<<3)|1: _SA(c->PC++);c->AD=_GD();break; + case (0xDE<<3)|2: c->AD|=_GD()<<8;_SA((c->AD&0xFF00)|((c->AD+c->X)&0xFF));break; + case (0xDE<<3)|3: _SA(c->AD+c->X);break; + case (0xDE<<3)|4: c->AD=_GD();break; + case (0xDE<<3)|5: c->AD--;_NZ(c->AD);_SD(c->AD);_WR();break; + case (0xDE<<3)|6: _FETCH();break; + case (0xDE<<3)|7: assert(false);break; + /* BBS5 zp,rel */ + case (0xDF<<3)|0: _SA(c->PC++);break; + case (0xDF<<3)|1: _SA(_GD());break; + case (0xDF<<3)|2: c->AD=_GD();_SA(c->PC++);break; + case (0xDF<<3)|3: if(c->AD&(1<<5)){c->PC=c->PC+(int8_t)_GD();_FETCH();};_FETCH();break; + case (0xDF<<3)|4: assert(false);break; + case (0xDF<<3)|5: assert(false);break; + case (0xDF<<3)|6: assert(false);break; + case (0xDF<<3)|7: assert(false);break; + /* CPX # */ + case (0xE0<<3)|0: _SA(c->PC++);break; + case (0xE0<<3)|1: _m65c02_cmp(c, c->X, _GD());_FETCH();break; + case (0xE0<<3)|2: assert(false);break; + case (0xE0<<3)|3: assert(false);break; + case (0xE0<<3)|4: assert(false);break; + case (0xE0<<3)|5: assert(false);break; + case (0xE0<<3)|6: assert(false);break; + case (0xE0<<3)|7: assert(false);break; + /* SBC (zp,X) */ + case (0xE1<<3)|0: _SA(c->PC++);break; + case (0xE1<<3)|1: c->AD=_GD();_SA(c->AD);break; + case (0xE1<<3)|2: c->AD=(c->AD+c->X)&0xFF;_SA(c->AD);break; + case (0xE1<<3)|3: _SA((c->AD+1)&0xFF);c->AD=_GD();break; + case (0xE1<<3)|4: _SA((_GD()<<8)|c->AD);break; + case (0xE1<<3)|5: _m65c02_sbc(c,_GD());if(c->P&M65C02_DF){c->P=((c->P&~(M65C02_NF|M65C02_ZF))|((c->A&0xFF)?(c->A&M65C02_NF):M65C02_ZF));};_FETCH();break; + case (0xE1<<3)|6: assert(false);break; + case (0xE1<<3)|7: assert(false);break; + /* LDD # */ + case (0xE2<<3)|0: _SA(c->PC++);break; + case (0xE2<<3)|1: _FETCH();break; + case (0xE2<<3)|2: assert(false);break; + case (0xE2<<3)|3: assert(false);break; + case (0xE2<<3)|4: assert(false);break; + case (0xE2<<3)|5: assert(false);break; + case (0xE2<<3)|6: assert(false);break; + case (0xE2<<3)|7: assert(false);break; + /* NOP (zp,X) */ + case (0xE3<<3)|0: _SA(c->PC);break; + case (0xE3<<3)|1: _FETCH();break; + case (0xE3<<3)|2: assert(false);break; + case (0xE3<<3)|3: assert(false);break; + case (0xE3<<3)|4: assert(false);break; + case (0xE3<<3)|5: assert(false);break; + case (0xE3<<3)|6: assert(false);break; + case (0xE3<<3)|7: assert(false);break; + /* CPX zp */ + case (0xE4<<3)|0: _SA(c->PC++);break; + case (0xE4<<3)|1: _SA(_GD());break; + case (0xE4<<3)|2: _m65c02_cmp(c, c->X, _GD());_FETCH();break; + case (0xE4<<3)|3: assert(false);break; + case (0xE4<<3)|4: assert(false);break; + case (0xE4<<3)|5: assert(false);break; + case (0xE4<<3)|6: assert(false);break; + case (0xE4<<3)|7: assert(false);break; + /* SBC zp */ + case (0xE5<<3)|0: _SA(c->PC++);break; + case (0xE5<<3)|1: _SA(_GD());break; + case (0xE5<<3)|2: _m65c02_sbc(c,_GD());if(c->P&M65C02_DF){c->P=((c->P&~(M65C02_NF|M65C02_ZF))|((c->A&0xFF)?(c->A&M65C02_NF):M65C02_ZF));};_FETCH();break; + case (0xE5<<3)|3: assert(false);break; + case (0xE5<<3)|4: assert(false);break; + case (0xE5<<3)|5: assert(false);break; + case (0xE5<<3)|6: assert(false);break; + case (0xE5<<3)|7: assert(false);break; + /* INC zp */ + case (0xE6<<3)|0: _SA(c->PC++);break; + case (0xE6<<3)|1: _SA(_GD());break; + case (0xE6<<3)|2: c->AD=_GD();break; + case (0xE6<<3)|3: c->AD++;_NZ(c->AD);_SD(c->AD);_WR();break; + case (0xE6<<3)|4: _FETCH();break; + case (0xE6<<3)|5: assert(false);break; + case (0xE6<<3)|6: assert(false);break; + case (0xE6<<3)|7: assert(false);break; + /* SMB6 zp */ + case (0xE7<<3)|0: _SA(c->PC++);break; + case (0xE7<<3)|1: _SA(_GD());break; + case (0xE7<<3)|2: _SD(_GD()|(1<<6));_WR();break; + case (0xE7<<3)|3: _FETCH();break; + case (0xE7<<3)|4: assert(false);break; + case (0xE7<<3)|5: assert(false);break; + case (0xE7<<3)|6: assert(false);break; + case (0xE7<<3)|7: assert(false);break; + /* INX */ + case (0xE8<<3)|0: _SA(c->PC);break; + case (0xE8<<3)|1: c->X++;_NZ(c->X);_FETCH();break; + case (0xE8<<3)|2: assert(false);break; + case (0xE8<<3)|3: assert(false);break; + case (0xE8<<3)|4: assert(false);break; + case (0xE8<<3)|5: assert(false);break; + case (0xE8<<3)|6: assert(false);break; + case (0xE8<<3)|7: assert(false);break; + /* SBC # */ + case (0xE9<<3)|0: _SA(c->PC++);break; + case (0xE9<<3)|1: _m65c02_sbc(c,_GD());if(c->P&M65C02_DF){c->P=((c->P&~(M65C02_NF|M65C02_ZF))|((c->A&0xFF)?(c->A&M65C02_NF):M65C02_ZF));};_FETCH();break; + case (0xE9<<3)|2: assert(false);break; + case (0xE9<<3)|3: assert(false);break; + case (0xE9<<3)|4: assert(false);break; + case (0xE9<<3)|5: assert(false);break; + case (0xE9<<3)|6: assert(false);break; + case (0xE9<<3)|7: assert(false);break; + /* NOP */ + case (0xEA<<3)|0: _SA(c->PC);break; + case (0xEA<<3)|1: _FETCH();break; + case (0xEA<<3)|2: assert(false);break; + case (0xEA<<3)|3: assert(false);break; + case (0xEA<<3)|4: assert(false);break; + case (0xEA<<3)|5: assert(false);break; + case (0xEA<<3)|6: assert(false);break; + case (0xEA<<3)|7: assert(false);break; + /* NOP # */ + case (0xEB<<3)|0: _SA(c->PC);break; + case (0xEB<<3)|1: _FETCH();break; + case (0xEB<<3)|2: assert(false);break; + case (0xEB<<3)|3: assert(false);break; + case (0xEB<<3)|4: assert(false);break; + case (0xEB<<3)|5: assert(false);break; + case (0xEB<<3)|6: assert(false);break; + case (0xEB<<3)|7: assert(false);break; + /* CPX abs */ + case (0xEC<<3)|0: _SA(c->PC++);break; + case (0xEC<<3)|1: _SA(c->PC++);c->AD=_GD();break; + case (0xEC<<3)|2: _SA((_GD()<<8)|c->AD);break; + case (0xEC<<3)|3: _m65c02_cmp(c, c->X, _GD());_FETCH();break; + case (0xEC<<3)|4: assert(false);break; + case (0xEC<<3)|5: assert(false);break; + case (0xEC<<3)|6: assert(false);break; + case (0xEC<<3)|7: assert(false);break; + /* SBC abs */ + case (0xED<<3)|0: _SA(c->PC++);break; + case (0xED<<3)|1: _SA(c->PC++);c->AD=_GD();break; + case (0xED<<3)|2: _SA((_GD()<<8)|c->AD);break; + case (0xED<<3)|3: _m65c02_sbc(c,_GD());if(c->P&M65C02_DF){c->P=((c->P&~(M65C02_NF|M65C02_ZF))|((c->A&0xFF)?(c->A&M65C02_NF):M65C02_ZF));};_FETCH();break; + case (0xED<<3)|4: assert(false);break; + case (0xED<<3)|5: assert(false);break; + case (0xED<<3)|6: assert(false);break; + case (0xED<<3)|7: assert(false);break; + /* INC abs */ + case (0xEE<<3)|0: _SA(c->PC++);break; + case (0xEE<<3)|1: _SA(c->PC++);c->AD=_GD();break; + case (0xEE<<3)|2: _SA((_GD()<<8)|c->AD);break; + case (0xEE<<3)|3: c->AD=_GD();break; + case (0xEE<<3)|4: c->AD++;_NZ(c->AD);_SD(c->AD);_WR();break; + case (0xEE<<3)|5: _FETCH();break; + case (0xEE<<3)|6: assert(false);break; + case (0xEE<<3)|7: assert(false);break; + /* BBS6 zp,rel */ + case (0xEF<<3)|0: _SA(c->PC++);break; + case (0xEF<<3)|1: _SA(_GD());break; + case (0xEF<<3)|2: c->AD=_GD();_SA(c->PC++);break; + case (0xEF<<3)|3: if(c->AD&(1<<6)){c->PC=c->PC+(int8_t)_GD();_FETCH();};_FETCH();break; + case (0xEF<<3)|4: assert(false);break; + case (0xEF<<3)|5: assert(false);break; + case (0xEF<<3)|6: assert(false);break; + case (0xEF<<3)|7: assert(false);break; + /* BEQ # */ + case (0xF0<<3)|0: _SA(c->PC++);break; + case (0xF0<<3)|1: _SA(c->PC);c->AD=c->PC+(int8_t)_GD();if((c->P&0x2)!=0x2){_FETCH();};break; + case (0xF0<<3)|2: _SA((c->PC&0xFF00)|(c->AD&0x00FF));if((c->AD&0xFF00)==(c->PC&0xFF00)){c->PC=c->AD;c->irq_pip>>=1;c->nmi_pip>>=1;_FETCH();};break; + case (0xF0<<3)|3: c->PC=c->AD;_FETCH();break; + case (0xF0<<3)|4: assert(false);break; + case (0xF0<<3)|5: assert(false);break; + case (0xF0<<3)|6: assert(false);break; + case (0xF0<<3)|7: assert(false);break; + /* SBC (zp),Y */ + case (0xF1<<3)|0: _SA(c->PC++);break; + case (0xF1<<3)|1: c->AD=_GD();_SA(c->AD);break; + case (0xF1<<3)|2: _SA((c->AD+1)&0xFF);c->AD=_GD();break; + case (0xF1<<3)|3: c->AD|=_GD()<<8;_SA((c->AD&0xFF00)|((c->AD+c->Y)&0xFF));c->IR+=(~((c->AD>>8)-((c->AD+c->Y)>>8)))&1;break; + case (0xF1<<3)|4: _SA(c->AD+c->Y);break; + case (0xF1<<3)|5: _m65c02_sbc(c,_GD());if(c->P&M65C02_DF){c->P=((c->P&~(M65C02_NF|M65C02_ZF))|((c->A&0xFF)?(c->A&M65C02_NF):M65C02_ZF));};_FETCH();break; + case (0xF1<<3)|6: assert(false);break; + case (0xF1<<3)|7: assert(false);break; + /* SBC (zp) */ + case (0xF2<<3)|0: _SA(c->PC++);break; + case (0xF2<<3)|1: c->AD=_GD();_SA(c->AD);break; + case (0xF2<<3)|2: _SA((c->AD+1)&0xFF);c->AD=_GD();break; + case (0xF2<<3)|3: _SA((_GD()<<8)|c->AD);break; + case (0xF2<<3)|4: _m65c02_sbc(c,_GD());if(c->P&M65C02_DF){c->P=((c->P&~(M65C02_NF|M65C02_ZF))|((c->A&0xFF)?(c->A&M65C02_NF):M65C02_ZF));};_FETCH();break; + case (0xF2<<3)|5: assert(false);break; + case (0xF2<<3)|6: assert(false);break; + case (0xF2<<3)|7: assert(false);break; + /* NOP (zp),Y */ + case (0xF3<<3)|0: _SA(c->PC);break; + case (0xF3<<3)|1: _FETCH();break; + case (0xF3<<3)|2: assert(false);break; + case (0xF3<<3)|3: assert(false);break; + case (0xF3<<3)|4: assert(false);break; + case (0xF3<<3)|5: assert(false);break; + case (0xF3<<3)|6: assert(false);break; + case (0xF3<<3)|7: assert(false);break; + /* LDD zp,X */ + case (0xF4<<3)|0: _SA(c->PC++);break; + case (0xF4<<3)|1: c->AD=_GD();_SA(c->AD);break; + case (0xF4<<3)|2: _SA((c->AD+c->X)&0x00FF);break; + case (0xF4<<3)|3: _FETCH();break; + case (0xF4<<3)|4: assert(false);break; + case (0xF4<<3)|5: assert(false);break; + case (0xF4<<3)|6: assert(false);break; + case (0xF4<<3)|7: assert(false);break; + /* SBC zp,X */ + case (0xF5<<3)|0: _SA(c->PC++);break; + case (0xF5<<3)|1: c->AD=_GD();_SA(c->AD);break; + case (0xF5<<3)|2: _SA((c->AD+c->X)&0x00FF);break; + case (0xF5<<3)|3: _m65c02_sbc(c,_GD());if(c->P&M65C02_DF){c->P=((c->P&~(M65C02_NF|M65C02_ZF))|((c->A&0xFF)?(c->A&M65C02_NF):M65C02_ZF));};_FETCH();break; + case (0xF5<<3)|4: assert(false);break; + case (0xF5<<3)|5: assert(false);break; + case (0xF5<<3)|6: assert(false);break; + case (0xF5<<3)|7: assert(false);break; + /* INC zp,X */ + case (0xF6<<3)|0: _SA(c->PC++);break; + case (0xF6<<3)|1: c->AD=_GD();_SA(c->AD);break; + case (0xF6<<3)|2: _SA((c->AD+c->X)&0x00FF);break; + case (0xF6<<3)|3: c->AD=_GD();break; + case (0xF6<<3)|4: c->AD++;_NZ(c->AD);_SD(c->AD);_WR();break; + case (0xF6<<3)|5: _FETCH();break; + case (0xF6<<3)|6: assert(false);break; + case (0xF6<<3)|7: assert(false);break; + /* SMB7 zp */ + case (0xF7<<3)|0: _SA(c->PC++);break; + case (0xF7<<3)|1: _SA(_GD());break; + case (0xF7<<3)|2: _SD(_GD()|(1<<7));_WR();break; + case (0xF7<<3)|3: _FETCH();break; + case (0xF7<<3)|4: assert(false);break; + case (0xF7<<3)|5: assert(false);break; + case (0xF7<<3)|6: assert(false);break; + case (0xF7<<3)|7: assert(false);break; + /* SED */ + case (0xF8<<3)|0: _SA(c->PC);break; + case (0xF8<<3)|1: c->P|=0x8;_FETCH();break; + case (0xF8<<3)|2: assert(false);break; + case (0xF8<<3)|3: assert(false);break; + case (0xF8<<3)|4: assert(false);break; + case (0xF8<<3)|5: assert(false);break; + case (0xF8<<3)|6: assert(false);break; + case (0xF8<<3)|7: assert(false);break; + /* SBC abs,Y */ + case (0xF9<<3)|0: _SA(c->PC++);break; + case (0xF9<<3)|1: _SA(c->PC++);c->AD=_GD();break; + case (0xF9<<3)|2: c->AD|=_GD()<<8;_SA((c->AD&0xFF00)|((c->AD+c->Y)&0xFF));c->IR+=(~((c->AD>>8)-((c->AD+c->Y)>>8)))&1;break; + case (0xF9<<3)|3: _SA(c->AD+c->Y);break; + case (0xF9<<3)|4: _m65c02_sbc(c,_GD());if(c->P&M65C02_DF){c->P=((c->P&~(M65C02_NF|M65C02_ZF))|((c->A&0xFF)?(c->A&M65C02_NF):M65C02_ZF));};_FETCH();break; + case (0xF9<<3)|5: assert(false);break; + case (0xF9<<3)|6: assert(false);break; + case (0xF9<<3)|7: assert(false);break; + /* PLX */ + case (0xFA<<3)|0: _SA(c->PC);break; + case (0xFA<<3)|1: _SA(0x0100|c->S++);break; + case (0xFA<<3)|2: _SA(0x0100|c->S);break; + case (0xFA<<3)|3: c->X=_GD();_NZ(c->X);_FETCH();break; + case (0xFA<<3)|4: assert(false);break; + case (0xFA<<3)|5: assert(false);break; + case (0xFA<<3)|6: assert(false);break; + case (0xFA<<3)|7: assert(false);break; + /* NOP abs,Y */ + case (0xFB<<3)|0: _SA(c->PC);break; + case (0xFB<<3)|1: _FETCH();break; + case (0xFB<<3)|2: assert(false);break; + case (0xFB<<3)|3: assert(false);break; + case (0xFB<<3)|4: assert(false);break; + case (0xFB<<3)|5: assert(false);break; + case (0xFB<<3)|6: assert(false);break; + case (0xFB<<3)|7: assert(false);break; + /* LDD abs */ + case (0xFC<<3)|0: _SA(c->PC++);break; + case (0xFC<<3)|1: _SA(c->PC++);c->AD=_GD();break; + case (0xFC<<3)|2: _SA((_GD()<<8)|c->AD);break; + case (0xFC<<3)|3: _FETCH();break; + case (0xFC<<3)|4: assert(false);break; + case (0xFC<<3)|5: assert(false);break; + case (0xFC<<3)|6: assert(false);break; + case (0xFC<<3)|7: assert(false);break; + /* SBC abs,X */ + case (0xFD<<3)|0: _SA(c->PC++);break; + case (0xFD<<3)|1: _SA(c->PC++);c->AD=_GD();break; + case (0xFD<<3)|2: c->AD|=_GD()<<8;_SA((c->AD&0xFF00)|((c->AD+c->X)&0xFF));c->IR+=(~((c->AD>>8)-((c->AD+c->X)>>8)))&1;break; + case (0xFD<<3)|3: _SA(c->AD+c->X);break; + case (0xFD<<3)|4: _m65c02_sbc(c,_GD());if(c->P&M65C02_DF){c->P=((c->P&~(M65C02_NF|M65C02_ZF))|((c->A&0xFF)?(c->A&M65C02_NF):M65C02_ZF));};_FETCH();break; + case (0xFD<<3)|5: assert(false);break; + case (0xFD<<3)|6: assert(false);break; + case (0xFD<<3)|7: assert(false);break; + /* INC abs,X */ + case (0xFE<<3)|0: _SA(c->PC++);break; + case (0xFE<<3)|1: _SA(c->PC++);c->AD=_GD();break; + case (0xFE<<3)|2: c->AD|=_GD()<<8;_SA((c->AD&0xFF00)|((c->AD+c->X)&0xFF));break; + case (0xFE<<3)|3: _SA(c->AD+c->X);break; + case (0xFE<<3)|4: c->AD=_GD();break; + case (0xFE<<3)|5: c->AD++;_NZ(c->AD);_SD(c->AD);_WR();break; + case (0xFE<<3)|6: _FETCH();break; + case (0xFE<<3)|7: assert(false);break; + /* BBS7 zp,rel */ + case (0xFF<<3)|0: _SA(c->PC++);break; + case (0xFF<<3)|1: _SA(_GD());break; + case (0xFF<<3)|2: c->AD=_GD();_SA(c->PC++);break; + case (0xFF<<3)|3: if(c->AD&(1<<7)){c->PC=c->PC+(int8_t)_GD();_FETCH();};_FETCH();break; + case (0xFF<<3)|4: assert(false);break; + case (0xFF<<3)|5: assert(false);break; + case (0xFF<<3)|6: assert(false);break; + case (0xFF<<3)|7: assert(false);break; + // %> + default: _M65C02_UNREACHABLE; + } + __hidden_M6510_SET_PORT(pins, c->io_pins); + c->PINS = pins; + c->irq_pip <<= 1; + c->nmi_pip <<= 1; + return pins; +} +#if defined(_MSC_VER) +#pragma warning(pop) +#endif + +#undef _SA +#undef _SAD +#undef _FETCH +#undef _SD +#undef _GD +#undef _ON +#undef _OFF +#undef _RD +#undef _WR +#undef _NZ +#endif /* CHIPS_IMPL */ diff --git a/codegen/m6502_gen.sh b/codegen/m6502_gen.sh index 1609c487..bea0ae98 100755 --- a/codegen/m6502_gen.sh +++ b/codegen/m6502_gen.sh @@ -2,3 +2,4 @@ python3 -m venv .venv source .venv/bin/activate python3 -m pip install pyyaml python3 m6502_gen.py +python3 m65c02_gen.py diff --git a/codegen/m65c02_gen.py b/codegen/m65c02_gen.py new file mode 100644 index 00000000..20386943 --- /dev/null +++ b/codegen/m65c02_gen.py @@ -0,0 +1,1028 @@ +#------------------------------------------------------------------------------- +# m65c02_decoder.py +# Generate instruction decoder for m65c02.h emulator. +# WIP! But runs 65C02_extended_opcodes_test.bin just fine. +#------------------------------------------------------------------------------- +import templ + +INOUT_PATH = '../chips/m65c02.h' + +# flag bits +CF = (1<<0) +ZF = (1<<1) +IF = (1<<2) +DF = (1<<3) +BF = (1<<4) +XF = (1<<5) +VF = (1<<6) +NF = (1<<7) + +def flag_name(f): + if f == CF: return 'C' + elif f == ZF: return 'Z' + elif f == IF: return 'I' + elif f == DF: return 'D' + elif f == BF: return 'B' + elif f == XF: return 'X' + elif f == VF: return 'V' + elif f == NF: return 'N' + +def branch_name(m, v): + if m == NF: + return 'BPL' if v==0 else 'BMI' + elif m == VF: + return 'BVC' if v==0 else 'BVS' + elif m == CF: + return 'BCC' if v==0 else 'BCS' + elif m == ZF: + return 'BNE' if v==0 else 'BEQ' + +# addressing mode constants +A____ = 0 # no addressing mode +A_IMM = 1 # immediate +A_ZER = 2 # zero-page +A_ZPX = 3 # zp,X +A_ZPY = 4 # zp,Y +A_ABS = 5 # abs +A_ABX = 6 # abs,X +A_ABY = 7 # abs,Y +A_IAI = 8 # (abs,X) "indexed absolute indirect" (65c02 jmp) +A_IDX = 9 # (zp,X) +A_IDY = 10 # (zp),Y +A_IND = 11 # (zp) +A_JMP = 12 # special JMP abs +A_JSR = 13 # special JSR abs +A_INV = 14 # an invalid instruction + +# addressing mode strings +addr_mode_str = ['', '#', 'zp', 'zp,X', 'zp,Y', 'abs', 'abs,X', 'abs,Y', '(abs,X)', '(zp,X)', '(zp),Y', '(zp)', '', '', 'INVALID'] + +# memory access modes +M___ = 0 # no memory access +M_R_ = 1 # read access +M__W = 2 # write access +M_RW = 3 # read-modify-write + +# addressing-modes and memory accesses for each instruction ([cc][bbb][aaa]) +ops = [ + # cc = 00 + [ + # --- BIT JMP JMP() STY LDY CPY CPX + [[A____,M___],[A_JSR,M_R_],[A____,M_R_],[A____,M_R_],[A_IMM,M_R_],[A_IMM,M_R_],[A_IMM,M_R_],[A_IMM,M_R_]], + [[A_ZER,M_RW],[A_ZER,M_R_],[A_ZER,M_R_],[A_ZER,M__W],[A_ZER,M__W],[A_ZER,M_R_],[A_ZER,M_R_],[A_ZER,M_R_]], + [[A____,M__W],[A____,M___],[A____,M__W],[A____,M___],[A____,M___],[A____,M___],[A____,M___],[A____,M___]], + [[A_ABS,M_RW],[A_ABS,M_R_],[A_JMP,M_R_],[A_JMP,M_R_],[A_ABS,M__W],[A_ABS,M_R_],[A_ABS,M_R_],[A_ABS,M_R_]], + [[A_IMM,M_R_],[A_IMM,M_R_],[A_IMM,M_R_],[A_IMM,M_R_],[A_IMM,M_R_],[A_IMM,M_R_],[A_IMM,M_R_],[A_IMM,M_R_]], # relative branches + [[A_ZER,M_RW],[A_ZPX,M_R_],[A_ZPX,M_R_],[A_ZPX,M__W],[A_ZPX,M__W],[A_ZPX,M_R_],[A_ZPX,M_R_],[A_ZPX,M_R_]], + [[A____,M___],[A____,M___],[A____,M___],[A____,M___],[A____,M___],[A____,M___],[A____,M___],[A____,M___]], + [[A_ABS,M_RW],[A_ABX,M_R_],[A_ABX,M_R_],[A_IAI,M_R_],[A_ABS,M__W],[A_ABX,M_R_],[A_ABS,M_R_],[A_ABS,M_R_]] + ], + # cc = 01 + [ + # ORA AND EOR ADC STA LDA CMP SBC + [[A_IDX,M_R_],[A_IDX,M_R_],[A_IDX,M_R_],[A_IDX,M_R_],[A_IDX,M__W],[A_IDX,M_R_],[A_IDX,M_R_],[A_IDX,M_R_]], + [[A_ZER,M_R_],[A_ZER,M_R_],[A_ZER,M_R_],[A_ZER,M_R_],[A_ZER,M__W],[A_ZER,M_R_],[A_ZER,M_R_],[A_ZER,M_R_]], + [[A_IMM,M_R_],[A_IMM,M_R_],[A_IMM,M_R_],[A_IMM,M_R_],[A_IMM,M_R_],[A_IMM,M_R_],[A_IMM,M_R_],[A_IMM,M_R_]], + [[A_ABS,M_R_],[A_ABS,M_R_],[A_ABS,M_R_],[A_ABS,M_R_],[A_ABS,M__W],[A_ABS,M_R_],[A_ABS,M_R_],[A_ABS,M_R_]], + [[A_IDY,M_R_],[A_IDY,M_R_],[A_IDY,M_R_],[A_IDY,M_R_],[A_IDY,M__W],[A_IDY,M_R_],[A_IDY,M_R_],[A_IDY,M_R_]], + [[A_ZPX,M_R_],[A_ZPX,M_R_],[A_ZPX,M_R_],[A_ZPX,M_R_],[A_ZPX,M__W],[A_ZPX,M_R_],[A_ZPX,M_R_],[A_ZPX,M_R_]], + [[A_ABY,M_R_],[A_ABY,M_R_],[A_ABY,M_R_],[A_ABY,M_R_],[A_ABY,M__W],[A_ABY,M_R_],[A_ABY,M_R_],[A_ABY,M_R_]], + [[A_ABX,M_R_],[A_ABX,M_R_],[A_ABX,M_R_],[A_ABX,M_R_],[A_ABX,M__W],[A_ABX,M_R_],[A_ABX,M_R_],[A_ABX,M_R_]] + ], + # cc = 02 + [ + # ASL ROL LSR ROR STX LDX DEC INC + [[A_IMM,M_R_],[A_IMM,M_R_],[A_IMM,M_R_],[A_IMM,M_R_],[A_IMM,M_R_],[A_IMM,M_R_],[A_IMM,M_R_],[A_IMM,M_R_]], + [[A_ZER,M_RW],[A_ZER,M_RW],[A_ZER,M_RW],[A_ZER,M_RW],[A_ZER,M__W],[A_ZER,M_R_],[A_ZER,M_RW],[A_ZER,M_RW]], + [[A____,M___],[A____,M___],[A____,M___],[A____,M___],[A____,M___],[A____,M___],[A____,M___],[A____,M___]], + [[A_ABS,M_RW],[A_ABS,M_RW],[A_ABS,M_RW],[A_ABS,M_RW],[A_ABS,M__W],[A_ABS,M_R_],[A_ABS,M_RW],[A_ABS,M_RW]], + [[A_IND,M_R_],[A_IND,M_R_],[A_IND,M_R_],[A_IND,M_R_],[A_IND,M__W],[A_IND,M_R_],[A_IND,M_R_],[A_IND,M_R_]], + [[A_ZPX,M_RW],[A_ZPX,M_RW],[A_ZPX,M_RW],[A_ZPX,M_RW],[A_ZPY,M__W],[A_ZPY,M_R_],[A_ZPX,M_RW],[A_ZPX,M_RW]], + [[A____,M_R_],[A____,M___],[A____,M__W],[A____,M_R_],[A____,M___],[A____,M___],[A____,M__W],[A____,M_R_]], + [[A_ABX,M_RW],[A_ABX,M_RW],[A_ABX,M_RW],[A_ABX,M_RW],[A_ABX,M__W],[A_ABY,M_R_],[A_ABX,M_RW],[A_ABX,M_RW]] + ], + # cc = 03 - NOTE this isn't really used but overridden at the beginning of enc_op + [ + [[A_IDX,M_RW],[A_IDX,M_RW],[A_IDX,M_RW],[A_IDX,M_RW],[A_IDX,M__W],[A_IDX,M_R_],[A_IDX,M_RW],[A_IDX,M_RW]], + [[A_ZER,M_RW],[A_ZER,M_RW],[A_ZER,M_RW],[A_ZER,M_RW],[A_ZER,M__W],[A_ZER,M_R_],[A_ZER,M_RW],[A_ZER,M_RW]], + [[A_IMM,M_R_],[A_IMM,M_R_],[A_IMM,M_R_],[A_IMM,M_R_],[A_IMM,M_R_],[A_IMM,M_R_],[A_IMM,M_R_],[A_IMM,M_R_]], + [[A_ABS,M_RW],[A_ABS,M_RW],[A_ABS,M_RW],[A_ABS,M_RW],[A_ABS,M__W],[A_ABS,M_R_],[A_ABS,M_RW],[A_ABS,M_RW]], + [[A_IDY,M_RW],[A_IDY,M_RW],[A_IDY,M_RW],[A_IDY,M_RW],[A_IDY,M_RW],[A_IDY,M_R_],[A_IDY,M_RW],[A_IDY,M_RW]], + [[A_ZPX,M_RW],[A_ZPX,M_RW],[A_ZPX,M_RW],[A_ZPX,M_RW],[A_ZPY,M__W],[A_ZPY,M_R_],[A_ZPX,M_RW],[A_ZPX,M_RW]], + [[A_ABY,M_RW],[A_ABY,M_RW],[A_ABY,M_RW],[A_ABY,M_RW],[A_ABY,M__W],[A_ABY,M_R_],[A_ABY,M_RW],[A_ABY,M_RW]], + [[A_ABX,M_RW],[A_ABX,M_RW],[A_ABX,M_RW],[A_ABX,M_RW],[A_ABY,M__W],[A_ABY,M_R_],[A_ABX,M_RW],[A_ABX,M_RW]] + ] +] + +class opcode: + def __init__(self, op): + self.code = op + self.cmt = None + self.i = 0 + self.src = [None] * 8 + def t(self, src): + self.src[self.i] = src + self.i += 1 + def ta(self, src): + self.src[self.i-1] += src + +#------------------------------------------------------------------------------- +# output a src line +# +out_lines = '' +def l(s) : + global out_lines + out_lines += s + '\n' + +#------------------------------------------------------------------------------- +def write_op(op): + if not op.cmt: + op.cmt = '???' + l(' /* {} */'.format(op.cmt if op.cmt else '???')) + for t in range(0, 8): + if t < op.i: + l(' case (0x{:02X}<<3)|{}: {}break;'.format(op.code, t, op.src[t])) + else: + l(' case (0x{:02X}<<3)|{}: assert(false);break;'.format(op.code, t)) + +#------------------------------------------------------------------------------- +def cmt(o,cmd): + cc = o.code & 3 + bbb = (o.code>>2) & 7 + aaa = (o.code>>5) & 7 + addr_mode = ops[cc][bbb][aaa][0] + o.cmt = cmd; + if addr_mode != '': + o.cmt += ' '+addr_mode_str[addr_mode] + +#------------------------------------------------------------------------------- +def u_cmt(o,cmd): + cmt(o,cmd) + o.cmt += ' (undoc)' + +#------------------------------------------------------------------------------- +def invalid_opcode(op): + cc = op & 3 + bbb = (op>>2) & 7 + aaa = (op>>5) & 7 + addr_mode = ops[cc][bbb][aaa][0] + return addr_mode == A_INV + +#------------------------------------------------------------------------------- +def enc_addr(op, addr_mode, mem_access): + if addr_mode == A____: + # no addressing, this still puts the PC on the address bus without + # incrementing the PC + op.t('_SA(c->PC);') + elif addr_mode == A_IMM: + # immediate mode + op.t('_SA(c->PC++);') + elif addr_mode == A_ZER: + # zero page + op.t('_SA(c->PC++);') + op.t('_SA(_GD());') + elif addr_mode == A_ZPX: + # zero page + X + op.t('_SA(c->PC++);') + op.t('c->AD=_GD();_SA(c->AD);') + op.t('_SA((c->AD+c->X)&0x00FF);') + elif addr_mode == A_ZPY: + # zero page + Y + op.t('_SA(c->PC++);') + op.t('c->AD=_GD();_SA(c->AD);') + op.t('_SA((c->AD+c->Y)&0x00FF);') + elif addr_mode == A_ABS: + # absolute + op.t('_SA(c->PC++);') + op.t('_SA(c->PC++);c->AD=_GD();') + op.t('_SA((_GD()<<8)|c->AD);') + elif addr_mode == A_ABX: + # TODO 65C02 reads opcode address on ind page boundary cross + # absolute + X + # this needs to check if a page boundary is crossed, which costs + # and additional cycle, but this early-out only happens when the + # instruction doesn't need to write back to memory + op.t('_SA(c->PC++);') + op.t('_SA(c->PC++);c->AD=_GD();') + op.t('c->AD|=_GD()<<8;_SA((c->AD&0xFF00)|((c->AD+c->X)&0xFF));') + if mem_access == M_R_: + # skip next tick if read access and page not crossed + op.ta('c->IR+=(~((c->AD>>8)-((c->AD+c->X)>>8)))&1;') + op.t('_SA(c->AD+c->X);') + elif addr_mode == A_ABY: + # absolute + Y + # same page-boundary-crossed special case as absolute+X + op.t('_SA(c->PC++);') + op.t('_SA(c->PC++);c->AD=_GD();') + op.t('c->AD|=_GD()<<8;_SA((c->AD&0xFF00)|((c->AD+c->Y)&0xFF));') + if mem_access == M_R_: + # skip next tick if read access and page not crossed + op.ta('c->IR+=(~((c->AD>>8)-((c->AD+c->Y)>>8)))&1;') + op.t('_SA(c->AD+c->Y);') + elif addr_mode == A_IND: + # (zp) + op.t('_SA(c->PC++);') + op.t('c->AD=_GD();_SA(c->AD);') + op.t('_SA((c->AD+1)&0xFF);c->AD=_GD();') + op.t('_SA((_GD()<<8)|c->AD);') + elif addr_mode == A_IDX: + # (zp,X) + op.t('_SA(c->PC++);') + op.t('c->AD=_GD();_SA(c->AD);') + op.t('c->AD=(c->AD+c->X)&0xFF;_SA(c->AD);') + op.t('_SA((c->AD+1)&0xFF);c->AD=_GD();') + op.t('_SA((_GD()<<8)|c->AD);') + elif addr_mode == A_IDY: + # (zp),Y + # same page-boundary-crossed special case as absolute+X + op.t('_SA(c->PC++);') + op.t('c->AD=_GD();_SA(c->AD);') + op.t('_SA((c->AD+1)&0xFF);c->AD=_GD();') + op.t('c->AD|=_GD()<<8;_SA((c->AD&0xFF00)|((c->AD+c->Y)&0xFF));') + if mem_access == M_R_: + # skip next tick if read access and page not crossed + op.ta('c->IR+=(~((c->AD>>8)-((c->AD+c->Y)>>8)))&1;') + op.t('_SA(c->AD+c->Y);') + elif addr_mode == A_JMP: + # jmp is completely handled in instruction decoding + pass + elif addr_mode == A_JSR: + # jsr is completely handled in instruction decoding + pass + else: + # invalid instruction + pass + +#------------------------------------------------------------------------------- +def i_brk(o): + cmt(o, 'BRK') # TODO 65C02 doesn't swallow BRKs on NMI + o.t('if(0==(c->brk_flags&(M6502_BRK_IRQ|M6502_BRK_NMI))){c->PC++;}_SAD(0x0100|c->S--,c->PC>>8);if(0==(c->brk_flags&M6502_BRK_RESET)){_WR();}') + o.t('_SAD(0x0100|c->S--,c->PC);if(0==(c->brk_flags&M6502_BRK_RESET)){_WR();}') + o.t('_SAD(0x0100|c->S--,c->P|M6502_XF);if(c->brk_flags&M6502_BRK_RESET){c->AD=0xFFFC;}else{_WR();if(c->brk_flags&M6502_BRK_NMI){c->AD=0xFFFA;}else{c->AD=0xFFFE;}}') + o.t('_SA(c->AD++);c->P&=~M6502_DF;c->P|=(M6502_IF|M6502_BF);c->brk_flags=0; /* RES/NMI hijacking */') + o.t('_SA(c->AD);c->AD=_GD(); /* NMI "half-hijacking" not possible */') + o.t('c->PC=(_GD()<<8)|c->AD;') + +#------------------------------------------------------------------------------- +def i_nop(o): + cmt(o,'NOP') + o.t('') + +#------------------------------------------------------------------------------- +def u_nop(o): + u_cmt(o,'NOP') + o.t('') + +#------------------------------------------------------------------------------- +def i_lda(o): + cmt(o,'LDA') + o.t('c->A=_GD();_NZ(c->A);') + +#------------------------------------------------------------------------------- +def i_ldx(o): + cmt(o,'LDX') + o.t('c->X=_GD();_NZ(c->X);') + +#------------------------------------------------------------------------------- +def i_ldy(o): + cmt(o,'LDY') + o.t('c->Y=_GD();_NZ(c->Y);') + +#------------------------------------------------------------------------------- +def i_ldd(o): + cmt(o,'LDD') + o.t('') + +#------------------------------------------------------------------------------- +def u_lax(o): + u_cmt(o,'LAX') + o.t('c->A=c->X=_GD();_NZ(c->A);') + +#------------------------------------------------------------------------------- +def x_lxa(o): + # undocumented LXA + # and immediate byte with A, then load X with A + u_cmt(o,'LXA') + o.t('c->A=c->X=(c->A|0xEE)&_GD();_NZ(c->A);') + +#------------------------------------------------------------------------------- +def i_sta(o): + cmt(o,'STA') + o.ta('_SD(c->A);_WR();') + +#------------------------------------------------------------------------------- +def i_stx(o): + cmt(o,'STX') + o.ta('_SD(c->X);_WR();') + +#------------------------------------------------------------------------------- +def i_sty(o): + cmt(o,'STY') + o.ta('_SD(c->Y);_WR();') + +#------------------------------------------------------------------------------- +def i_stz(o): + cmt(o,'STZ') + o.ta('_SD(0);_WR();') + +#------------------------------------------------------------------------------- +def u_sax(o): + u_cmt(o,'SAX') + o.ta('_SD(c->A&c->X);_WR();') + +#------------------------------------------------------------------------------- +def i_tax(o): + cmt(o,'TAX') + o.t('c->X=c->A;_NZ(c->X);') + +#------------------------------------------------------------------------------- +def i_tay(o): + cmt(o,'TAY') + o.t('c->Y=c->A;_NZ(c->Y);') + +#------------------------------------------------------------------------------- +def i_txa(o): + cmt(o,'TXA') + o.t('c->A=c->X;_NZ(c->A);') + +#------------------------------------------------------------------------------- +def i_tya(o): + cmt(o,'TYA') + o.t('c->A=c->Y;_NZ(c->A);') + +#------------------------------------------------------------------------------- +def i_txs(o): + cmt(o,'TXS') + o.t('c->S=c->X;') + +#------------------------------------------------------------------------------- +def i_tsx(o): + cmt(o,'TSX') + o.t('c->X=c->S;_NZ(c->X);') + +#------------------------------------------------------------------------------- +def i_php(o): + cmt(o,'PHP') + o.t('_SAD(0x0100|c->S--,c->P|M6502_XF);_WR();') + +#------------------------------------------------------------------------------- +def i_plp(o): + cmt(o,'PLP') + o.t('_SA(0x0100|c->S++);') # read junk byte from current SP + o.t('_SA(0x0100|c->S);') # read actual byte + o.t('c->P=(_GD()|M6502_BF)&~M6502_XF;'); + +#------------------------------------------------------------------------------- +def i_ph(o, f): + cmt(o,'PH'+f) + o.t('_SAD(0x0100|c->S--,c->'+f+');_WR();') + +#------------------------------------------------------------------------------- +def i_pl(o, f): + cmt(o,'PL'+f) + o.t('_SA(0x0100|c->S++);') # read junk byte from current SP + o.t('_SA(0x0100|c->S);') # read actual byte + o.t('c->'+f+'=_GD();_NZ(c->'+f+');') + +#------------------------------------------------------------------------------- +def i_se(o, f): + cmt(o,'SE'+flag_name(f)) + o.t('c->P|='+hex(f)+';') + +#------------------------------------------------------------------------------- +def i_cl(o, f): + cmt(o,'CL'+flag_name(f)) + o.t('c->P&=~'+hex(f)+';') + +#------------------------------------------------------------------------------- +def i_br(o, m, v): + cmt(o,branch_name(m,v)) + # if branch not taken? + o.t('_SA(c->PC);c->AD=c->PC+(int8_t)_GD();if((c->P&'+hex(m)+')!='+hex(v)+'){_FETCH();};') + # branch taken: shortcut if page not crossed, 'branchquirk' interrupt fix + o.t('_SA((c->PC&0xFF00)|(c->AD&0x00FF));if((c->AD&0xFF00)==(c->PC&0xFF00)){c->PC=c->AD;c->irq_pip>>=1;c->nmi_pip>>=1;_FETCH();};') + # page crossed extra cycle: + o.t('c->PC=c->AD;') + +#------------------------------------------------------------------------------- +def i_bra(o): + cmt(o,'BRA') + o.t('_SA(c->PC);c->AD=c->PC+(int8_t)_GD();') + # branch taken: shortcut if page not crossed, 'branchquirk' interrupt fix + o.t('_SA((c->PC&0xFF00)|(c->AD&0x00FF));if((c->AD&0xFF00)==(c->PC&0xFF00)){c->PC=c->AD;c->irq_pip>>=1;c->nmi_pip>>=1;_FETCH();};') + # page crossed extra cycle: + o.t('c->PC=c->AD;') + +#------------------------------------------------------------------------------- +def i_bbX(o, s, i): + cmt(o,f'BB{s}{i}') + # fetch branch target + o.t('c->AD=_GD();_SA(c->PC++);') + if s == 'S': + o.t('if(c->AD&(1<<'+str(i)+')){c->PC=c->PC+(int8_t)_GD();_FETCH();};') + else: + o.t('if(!(c->AD&(1<<'+str(i)+'))){c->PC=c->PC+(int8_t)_GD();_FETCH();};') + +#------------------------------------------------------------------------------- +def i_Xmb(o, s, i): + cmt(o,f'{s}MB{i}') + if s == 'S': + o.t(f'_SD(_GD()|(1<<{i}));_WR();') + else: + o.t(f'_SD(_GD()&(~(1<<{i})));_WR();') + +#------------------------------------------------------------------------------- +def i_jmp(o): + cmt(o,'JMP') + o.t('_SA(c->PC++);') + o.t('_SA(c->PC++);c->AD=_GD();') + o.t('c->PC=(_GD()<<8)|c->AD;') + +#------------------------------------------------------------------------------- +def i_jmpi(o): + cmt(o,'JMPI') + o.t('_SA(c->PC++);') + o.t('_SA(c->PC++);c->AD=_GD();') + o.t('c->AD|=_GD()<<8;_SA(c->AD);') + o.t('_SA(c->AD+1);c->AD=_GD();') # fixed the NMOS flaw + o.t('c->PC=(_GD()<<8)|c->AD;') + +#------------------------------------------------------------------------------- +def i_jmpix(o): + cmt(o,'JMPIX') + o.t('_SA(c->PC++);') + o.t('_SA(c->PC++);c->AD=_GD();') + o.t('c->AD|=_GD()<<8;c->AD+=c->X;_SA(c->AD);') + o.t('_SA(c->AD+1);c->AD=_GD();') + o.t('c->PC=(_GD()<<8)|c->AD;') + +#------------------------------------------------------------------------------- +def i_jsr(o): + cmt(o,'JSR') + # read low byte of target address + o.t('_SA(c->PC++);') + # put SP on addr bus, next cycle is a junk read + o.t('_SA(0x0100|c->S);c->AD=_GD();') + # write PC high byte to stack + o.t('_SAD(0x0100|c->S--,c->PC>>8);_WR();') + # write PC low byte to stack + o.t('_SAD(0x0100|c->S--,c->PC);_WR();') + # load target address high byte + o.t('_SA(c->PC);') + # load PC and done + o.t('c->PC=(_GD()<<8)|c->AD;') + +#------------------------------------------------------------------------------- +def i_rts(o): + cmt(o,'RTS') + # put SP on stack and do a junk read + o.t('_SA(0x0100|c->S++);') + # load return address low byte from stack + o.t('_SA(0x0100|c->S++);') + # load return address high byte from stack + o.t('_SA(0x0100|c->S);c->AD=_GD();') + # put return address in PC, this is one byte before next op, do junk read from PC + o.t('c->PC=(_GD()<<8)|c->AD;_SA(c->PC++);') + # next tick is opcode fetch + o.t(''); + +#------------------------------------------------------------------------------- +def i_rti(o): + cmt(o,'RTI') + # put SP on stack and do a junk read + o.t('_SA(0x0100|c->S++);') + # load processor status flag from stack + o.t('_SA(0x0100|c->S++);') + # load return address low byte from stack + o.t('_SA(0x0100|c->S++);c->P=(_GD()|M6502_BF)&~M6502_XF;') + # load return address high byte from stack + o.t('_SA(0x0100|c->S);c->AD=_GD();') + # update PC (which is already placed on the right return-to instruction) + o.t('c->PC=(_GD()<<8)|c->AD;') + +#------------------------------------------------------------------------------- +def i_ora(o): + cmt(o,'ORA') + o.t('c->A|=_GD();_NZ(c->A);') + +#------------------------------------------------------------------------------- +def i_and(o): + cmt(o,'AND') + o.t('c->A&=_GD();_NZ(c->A);') + +#------------------------------------------------------------------------------- +def i_eor(o): + cmt(o,'EOR') + o.t('c->A^=_GD();_NZ(c->A);') + +#------------------------------------------------------------------------------- +def i_adc(o): + cmt(o,'ADC') + o.t('_m6502_adc(c,_GD());if(c->P&M6502_DF){c->P=((c->P&~(M6502_NF|M6502_ZF))|((c->A&0xFF)?(c->A&M6502_NF):M6502_ZF));};') + +#------------------------------------------------------------------------------- +def i_sbc(o): + cmt(o,'SBC') + o.t('_m6502_sbc(c,_GD());if(c->P&M6502_DF){c->P=((c->P&~(M6502_NF|M6502_ZF))|((c->A&0xFF)?(c->A&M6502_NF):M6502_ZF));};') + +#------------------------------------------------------------------------------- +def u_sbc(o): + u_cmt(o,'SBC') + o.t('_m6502_sbc(c,_GD());') + +#------------------------------------------------------------------------------- +def i_cmp(o): + cmt(o,'CMP') + o.t('_m6502_cmp(c, c->A, _GD());') + +#------------------------------------------------------------------------------- +def i_cpx(o): + cmt(o,'CPX') + o.t('_m6502_cmp(c, c->X, _GD());') + +#------------------------------------------------------------------------------- +def i_cpy(o): + cmt(o,'CPY') + o.t('_m6502_cmp(c, c->Y, _GD());') + +#------------------------------------------------------------------------------- +def u_dcp(o): + # undocumented 'decrement and compare' + u_cmt(o,'DCP') + o.t('c->AD=_GD();_WR();') + o.t('c->AD--;_NZ(c->AD);_SD(c->AD);_m6502_cmp(c, c->A, c->AD);_WR();') + +#------------------------------------------------------------------------------- +def x_sbx(o): + u_cmt(o,'SBX') + o.t('_m6502_sbx(c, _GD());') + +#------------------------------------------------------------------------------- +def i_dec(o): + cmt(o,'DEC') + o.t('c->AD=_GD();') # CMOS: no dummy write + o.t('c->AD--;_NZ(c->AD);_SD(c->AD);_WR();') + +#------------------------------------------------------------------------------- +def i_inc(o): + cmt(o,'INC') + o.t('c->AD=_GD();') # CMOS: no dummy write + o.t('c->AD++;_NZ(c->AD);_SD(c->AD);_WR();') + +#------------------------------------------------------------------------------- +def i_deca(o): + cmt(o,'DEC A') + o.t('c->A--;_NZ(c->A);') + +#------------------------------------------------------------------------------- +def i_dex(o): + cmt(o,'DEX') + o.t('c->X--;_NZ(c->X);') + +#------------------------------------------------------------------------------- +def i_dey(o): + cmt(o,'DEY') + o.t('c->Y--;_NZ(c->Y);') + +#------------------------------------------------------------------------------- +def i_inca(o): + cmt(o,'INC A') + o.t('c->A++;_NZ(c->A);') + +#------------------------------------------------------------------------------- +def i_inx(o): + cmt(o,'INX') + o.t('c->X++;_NZ(c->X);') + +#------------------------------------------------------------------------------- +def i_iny(o): + cmt(o,'INY') + o.t('c->Y++;_NZ(c->Y);') + +#------------------------------------------------------------------------------- +def u_isb(o): + # undocumented INC+SBC instruction + u_cmt(o,'ISB') + o.t('c->AD=_GD();_WR();') + o.t('c->AD++;_SD(c->AD);_m6502_sbc(c,c->AD);_WR();') + +#------------------------------------------------------------------------------- +def i_asl(o): + cmt(o,'ASL') + o.t('c->AD=_GD();_WR();') + o.t('_SD(_m6502_asl(c,c->AD));_WR();') + +#------------------------------------------------------------------------------- +def i_asla(o): + cmt(o,'ASLA') + o.t('c->A=_m6502_asl(c,c->A);') + +#------------------------------------------------------------------------------- +def i_lsr(o): + cmt(o,'LSR') + o.t('c->AD=_GD();_WR();') + o.t('_SD(_m6502_lsr(c,c->AD));_WR();') + +#------------------------------------------------------------------------------- +def i_lsra(o): + cmt(o,'LSRA') + o.t('c->A=_m6502_lsr(c,c->A);') + +#------------------------------------------------------------------------------- +def u_slo(o): + # undocumented ASL+OR + u_cmt(o,'SLO') + o.t('c->AD=_GD();_WR();') + o.t('c->AD=_m6502_asl(c,c->AD);_SD(c->AD);c->A|=c->AD;_NZ(c->A);_WR();') + +#------------------------------------------------------------------------------- +def x_asr(o): + # undocumented AND+LSR + u_cmt(o, 'ASR') + o.t('c->A&=_GD();c->A=_m6502_lsr(c,c->A);') + +#------------------------------------------------------------------------------- +def u_sre(o): + # undocumented LSR+EOR + u_cmt(o,'SRE') + o.t('c->AD=_GD();_WR();') + o.t('c->AD=_m6502_lsr(c,c->AD);_SD(c->AD);c->A^=c->AD;_NZ(c->A);_WR();') + +#------------------------------------------------------------------------------- +def i_rol(o): + cmt(o,'ROL') + o.t('c->AD=_GD();_WR();') + o.t('_SD(_m6502_rol(c,c->AD));_WR();') + +#------------------------------------------------------------------------------- +def i_rola(o): + cmt(o,'ROLA') + o.t('c->A=_m6502_rol(c,c->A);') + +#------------------------------------------------------------------------------- +def u_rla(o): + # uncodumented ROL+AND + u_cmt(o,'RLA') + o.t('c->AD=_GD();_WR();') + o.t('c->AD=_m6502_rol(c,c->AD);_SD(c->AD);c->A&=c->AD;_NZ(c->A);_WR();') + +#------------------------------------------------------------------------------- +def i_ror(o): + cmt(o,'ROR') + o.t('c->AD=_GD();_WR();') + o.t('_SD(_m6502_ror(c,c->AD));_WR();') + +#------------------------------------------------------------------------------- +def i_rora(o): + cmt(o,'RORA') + o.t('c->A=_m6502_ror(c,c->A);') + +#------------------------------------------------------------------------------- +def u_rra(o): + # undocumented ROR+ADC + u_cmt(o,'RRA') + o.t('c->AD=_GD();_WR();') + o.t('c->AD=_m6502_ror(c,c->AD);_SD(c->AD);_m6502_adc(c,c->AD);_WR();') + +#------------------------------------------------------------------------------- +def x_arr(o): + # undocumented AND+ROR + u_cmt(o,'ARR') + o.t('c->A&=_GD();_m6502_arr(c);') + +#------------------------------------------------------------------------------- +def x_ane(o): + # undocumented ANE + u_cmt(o,'ANE') + o.t('c->A=(c->A|0xEE)&c->X&_GD();_NZ(c->A);') + +#------------------------------------------------------------------------------- +def x_sha(o): + # undocumented SHA + # stores the result of A AND X AND the high byte of the target address of + # the operand +1 in memory + # + u_cmt(o,'SHA') + o.ta('_SD(c->A&c->X&(uint8_t)((_GA()>>8)+1));_WR();') + +#------------------------------------------------------------------------------- +def x_shx(o): + # undocumented SHX + # AND X register with the high byte of the target address of the + # argument + 1. Store the result in memory. + # + u_cmt(o, 'SHX') + o.ta('_SD(c->X&(uint8_t)((_GA()>>8)+1));_WR();') + +#------------------------------------------------------------------------------- +def x_shy(o): + # undocumented SHX + # AND Y register with the high byte of the target address of the + # argument + 1. Store the result in memory. + # + u_cmt(o, 'SHY') + o.ta('_SD(c->Y&(uint8_t)((_GA()>>8)+1));_WR();') + +#------------------------------------------------------------------------------- +def x_shs(o): + # undocumented SHS + # AND X register with accumulator and store result in stack pointer, then + # AND stack pointer with the high byte of the target address of the + # argument + 1. Store result in memory. + # + u_cmt(o, 'SHS') + o.ta('c->S=c->A&c->X;_SD(c->S&(uint8_t)((_GA()>>8)+1));_WR();') + +#------------------------------------------------------------------------------- +def x_anc(o): + # undocumented ANC + # AND byte with accumulator. If result is negative then carry is set. + # + u_cmt(o, 'ANC') + o.t('c->A&=_GD();_NZ(c->A);if(c->A&0x80){c->P|=M6502_CF;}else{c->P&=~M6502_CF;}') + +#------------------------------------------------------------------------------- +def x_las(o): + # undocumented LAS + # AND memory with stack pointer, transfer result to accumulator, X + # register and stack pointer. + # + u_cmt(o, 'LAS') + o.t('c->A=c->X=c->S=_GD()&c->S;_NZ(c->A);') + +#------------------------------------------------------------------------------- +def x_jam(o): + # undocumented JAM, next opcode byte read, data and addr bus set to all 1, execution stops + u_cmt(o, 'JAM') + o.t('_SA(c->PC);') + o.t('_SAD(0xFFFF,0xFF);c->IR--;') + +#------------------------------------------------------------------------------- +def i_trb(o): # TODO check function and cycles + cmt(o,'TRB') + o.t('c->AD=_GD();') + o.t('if(c->AD&c->A){c->P&=~M6502_ZF;}else{c->P|=M6502_ZF;};_SD(c->AD&~c->A);_WR();') + +#------------------------------------------------------------------------------- +def i_tsb(o): # TODO check function and cycles + cmt(o,'TSB') + o.t('c->AD=_GD();') + o.t('if(c->AD&c->A){c->P&=~M6502_ZF;}else{c->P|=M6502_ZF;};_SD(c->AD|c->A);_WR();') + +#------------------------------------------------------------------------------- +def i_bit(o): + cmt(o,'BIT') + if o.code == 0x89: + # on 65C02, BIT #xx doesn't touch N and V + o.t('c->P&=~M6502_ZF;if(!(c->A&_GD())){c->P|=M6502_ZF;};') + else: + o.t('_m6502_bit(c,_GD());') + +#------------------------------------------------------------------------------- +def enc_op(op): + o = opcode(op) + if (op&0xf) == 7: + # RBM0-7/SMB0-7 + enc_addr(o, A_ZER, M_RW) + if (op>>4) < 8: + i_Xmb(o, "R", op>>4) + o.cmt = f"RMB{op>>4} zp" + else: + i_Xmb(o, "S", (op>>4) - 8) + o.cmt = f"SMB{(op>>4) - 8} zp" + o.t('_FETCH();') + return o + if (op&0xf) == 0xf: + # BBR0-7/BBS0-7 + enc_addr(o, A_ZER, M_R_) + if (op>>4) < 8: + i_bbX(o, "R", op>>4) + o.cmt = f"BBR{op>>4} zp,rel" + else: + i_bbX(o, "S", (op>>4) - 8) + o.cmt = f"BBS{(op>>4) - 8} zp,rel" + o.ta('_FETCH();') + return o + if (op&3) == 3: + enc_addr(o, A____, M___) + i_nop(o) + o.ta('_FETCH();') + return o + if invalid_opcode(op): + x_jam(o); + return o + + # decode the opcode byte + cc = op & 3 + bbb = (op>>2) & 7 + aaa = (op>>5) & 7 + addr_mode = ops[cc][bbb][aaa][0] + mem_access = ops[cc][bbb][aaa][1] + # addressing mode + enc_addr(o, addr_mode, mem_access); + # actual instruction + # XXX https://github.com/visrealm/vrEmu6502/blob/37d5dab79317468a7031fc68075d8529aea35a1a/src/vrEmu6502.c#L2061 + # XXX https://en.wikipedia.org/wiki/WDC_65C02#Bit_manipulation_instructions + # XXX https://www.westerndesigncenter.com/wdc/documentation/w65c02s.pdf + # TODO decimal ops flags: one additional cycle + # TODO int while BRK decoding: execute BRK then int (instead of ignore BRK) + # TODO WAI instruction, bidirectional RDY line + # TODO RMW abs ind same page: six cycles (instead of seven) + # op name a b c + # 80 bra 4 0 0 + # 02 ldd_imm 0 0 2 load and discard + # 12 ora zpi 0 4 2 + # 22 ldd imm 1 0 2 + # 32 and zpi 1 4 2 + # 42 ldd imm 2 0 2 + # 52 eor zpi 2 4 2 + # 62 ldd imm 3 0 2 + # 72 adc zpi 3 4 2 + # 82 ldd imm 4 0 2 + # 92 sta zpi 4 4 2 + # a2 ldx imm 5 0 2 + # b2 lda zpi 5 4 2 + # c2 ldd_imm 6 0 2 + # d2 cmp zpi 6 4 2 + # e2 ldd imm 7 0 2 + # f2 sbc zpi 7 4 2 + # _3 unnop + # 04 tsb zp 0 1 0 test and set bit + # 14 trb zp 0 5 0 test and clear bit + # 34 bit zpx 1 5 0 + # 44 ldd zp 2 1 0 + # 54 ldd zpx 2 5 0 + # 64 stz zp 3 1 0 store zero + # 74 stz zpx 3 5 0 + # D4 ldd zpx 6 5 0 + # F4 ldd zpx 7 5 0 + # _7 RMB/SMB + # 89 bit imm 4 2 1 + # 1A inc acc 0 6 2 + # 3A dec acc 1 6 2 + # 5A phy imp 2 6 2 push y + # 7A ply imp 3 6 2 pull y + # DA phx imp 6 6 2 + # FA plx imp 7 6 2 + # _B unnop + # 0C tsb ab 0 3 0 + # 1C trb ab 0 7 0 + # 3C bit abx 1 7 0 + # 5C ldd ab 2 7 0 + # 7C jmp indx 3 7 0 + # 9C stz ab 4 7 0 + # DC ldd ab 6 7 0 + # FC ldd ab 7 7 0 + # 9E stz abx 4 7 2 + # _F BBR/BBS + + if cc == 0: + if aaa == 0: + if bbb == 0: i_brk(o) + elif bbb == 1: i_tsb(o) + elif bbb == 2: i_php(o) + elif bbb == 3: i_tsb(o) + elif bbb == 4: i_br(o, NF, 0) # BPL + elif bbb == 5: i_trb(o) + elif bbb == 6: i_cl(o, CF) + elif bbb == 7: i_trb(o) + elif aaa == 1: + if bbb == 0: i_jsr(o) + elif bbb == 2: i_plp(o) + elif bbb == 4: i_br(o, NF, NF) # BMI + elif bbb == 5: i_bit(o) + elif bbb == 6: i_se(o, CF) + elif bbb == 7: i_bit(o) + else: i_bit(o) + elif aaa == 2: + if bbb == 0: i_rti(o) + elif bbb == 1: i_ldd(o) + elif bbb == 2: i_ph(o,'A') + elif bbb == 3: i_jmp(o) + elif bbb == 4: i_br(o, VF, 0) # BVC + elif bbb == 5: i_ldd(o) + elif bbb == 6: i_cl(o, IF) + elif bbb == 7: i_ldd(o) + else: u_nop(o) + elif aaa == 3: + if bbb == 0: i_rts(o) + elif bbb == 1: i_stz(o) + elif bbb == 2: i_pl(o,'A') + elif bbb == 3: i_jmpi(o) + elif bbb == 4: i_br(o, VF, VF) # BVS + elif bbb == 5: i_stz(o) + elif bbb == 6: i_se(o, IF) + elif bbb == 7: i_jmpix(o) # TODO jmp (abs,x) - check cycle count + else: u_nop(o) + elif aaa == 4: + if bbb == 0: i_bra(o) # BRA + elif bbb == 2: i_dey(o) + elif bbb == 4: i_br(o, CF, 0) # BCC + elif bbb == 6: i_tya(o) + elif bbb == 7: i_stz(o) + else: i_sty(o) + elif aaa == 5: + if bbb == 2: i_tay(o) + elif bbb == 4: i_br(o, CF, CF) # BCS + elif bbb == 6: i_cl(o, VF) + else: i_ldy(o) + elif aaa == 6: + if bbb == 2: i_iny(o) + elif bbb == 4: i_br(o, ZF, 0) # BNE + elif bbb == 5: i_ldd(o) + elif bbb == 6: i_cl(o, DF) + elif bbb == 7: i_ldd(o) + else: i_cpy(o) + elif aaa == 7: + if bbb == 2: i_inx(o) + elif bbb == 4: i_br(o, ZF, ZF) # BEQ + elif bbb == 5: i_ldd(o) + elif bbb == 6: i_se(o, DF) + elif bbb == 7: i_ldd(o) + else: i_cpx(o) + elif cc == 1: + if aaa == 0: i_ora(o) + elif aaa == 1: i_and(o) + elif aaa == 2: i_eor(o) + elif aaa == 3: i_adc(o) + elif aaa == 4: + if bbb == 2: i_bit(o) + else: i_sta(o) + elif aaa == 5: i_lda(o) + elif aaa == 6: i_cmp(o) + else: i_sbc(o) + elif cc == 2: + if aaa == 0: + if bbb == 0: i_ldd(o) + elif bbb == 2: i_asla(o) + elif bbb == 4: i_ora(o) + elif bbb == 6: i_inca(o) + else: i_asl(o) + elif aaa == 1: + if bbb == 0: i_ldd(o) + elif bbb == 2: i_rola(o) + elif bbb == 4: i_and(o) + elif bbb == 6: i_deca(o) + else: i_rol(o) + elif aaa == 2: + if bbb == 0: i_ldd(o) + elif bbb == 2: i_lsra(o) + elif bbb == 4: i_eor(o) + elif bbb == 6: i_ph(o,'Y') + else: i_lsr(o) + elif aaa == 3: + if bbb == 0: i_ldd(o) + elif bbb == 2: i_rora(o) + elif bbb == 4: i_adc(o) + elif bbb == 6: i_pl(o,'Y') + else: i_ror(o) + elif aaa == 4: + if bbb == 0: i_ldd(o) + elif bbb == 2: i_txa(o) + elif bbb == 4: i_sta(o) + elif bbb == 6: i_txs(o) + elif bbb == 7: i_stz(o) + else: i_stx(o) + elif aaa == 5: + if bbb == 0: i_ldx(o) + elif bbb == 2: i_tax(o) + elif bbb == 4: i_lda(o) + elif bbb == 6: i_tsx(o) + else: i_ldx(o) + elif aaa == 6: + if bbb == 0: i_ldd(o) + elif bbb == 2: i_dex(o) + elif bbb == 4: i_cmp(o) + elif bbb == 6: i_ph(o,'X') + else: i_dec(o) + elif aaa == 7: + if bbb == 0: i_ldd(o) + elif bbb == 2: i_nop(o) + elif bbb == 4: i_sbc(o) + elif bbb == 6: i_pl(o,'X') + else: i_inc(o) + elif cc == 3: + raise Exception("should not be reached") + # fetch next opcode byte + if mem_access in [M_R_,M___]: + o.ta('_FETCH();') + else: + o.t('_FETCH();') + return o + +def write_result(): + with open(INOUT_PATH, 'r') as f: + lines = f.read().splitlines() + lines = templ.replace(lines, 'decoder', out_lines) + out_str = '\n'.join(lines) + '\n' + out_str = out_str.replace("M6502", "M65C02") + out_str = out_str.replace("m6502", "m65c02") + # out_str = out_str.replace("M6510", "__hidden_M6510") # just hide those + # out_str = out_str.replace("m6510", "__hidden_m6510") # just hide those + with open(INOUT_PATH, 'w') as f: + f.write(out_str) + +if __name__ == '__main__': + for op in range(0, 256): + write_op(enc_op(op)) + write_result()