--- /dev/null
+# license:BSD-3-Clause
+# copyright-holders:Olivier Galibert
+# m6502_family_device - 6502, 6504
+brk_imp ora_idx kil_non slo_idx nop_zpg ora_zpg asl_zpg slo_zpg php_imp ora_imm asl_acc anc_imm nop_aba ora_aba asl_aba slo_aba
+bpl_rel ora_idy kil_non slo_idy nop_zpx ora_zpx asl_zpx slo_zpx clc_imp ora_aby nop_imp slo_aby nop_abx ora_abx asl_abx slo_abx
+jsr_adr and_idx kil_non rla_idx bit_zpg and_zpg rol_zpg rla_zpg plp_imp and_imm rol_acc anc_imm bit_aba and_aba rol_aba rla_aba
+bmi_rel and_idy kil_non rla_idy nop_zpx and_zpx rol_zpx rla_zpx sec_imp and_aby nop_imp rla_aby nop_abx and_abx rol_abx rla_abx
+rti_imp eor_idx kil_non sre_idx nop_zpg eor_zpg lsr_zpg sre_zpg pha_imp eor_imm lsr_acc asr_imm jmp_adr eor_aba lsr_aba sre_aba
+bvc_rel eor_idy kil_non sre_idy nop_zpx eor_zpx lsr_zpx sre_zpx cli_imp eor_aby nop_imp sre_aby nop_abx eor_abx lsr_abx sre_abx
+rts_imp adc_idx kil_non rra_idx nop_zpg adc_zpg ror_zpg rra_zpg pla_imp adc_imm ror_acc arr_imm jmp_ind adc_aba ror_aba rra_aba
+bvs_rel adc_idy kil_non rra_idy nop_zpx adc_zpx ror_zpx rra_zpx sei_imp adc_aby nop_imp rra_aby nop_abx adc_abx ror_abx rra_abx
+nop_imm sta_idx nop_imm sax_idx sty_zpg sta_zpg stx_zpg sax_zpg dey_imp nop_imm txa_imp ane_imm sty_aba sta_aba stx_aba sax_aba
+bcc_rel sta_idy kil_non sha_idy sty_zpx sta_zpx stx_zpy sax_zpy tya_imp sta_aby txs_imp shs_aby shy_abx sta_abx shx_aby sha_aby
+ldy_imm lda_idx ldx_imm lax_idx ldy_zpg lda_zpg ldx_zpg lax_zpg tay_imp lda_imm tax_imp lxa_imm ldy_aba lda_aba ldx_aba lax_aba
+bcs_rel lda_idy kil_non lax_idy ldy_zpx lda_zpx ldx_zpy lax_zpy clv_imp lda_aby tsx_imp las_aby ldy_abx lda_abx ldx_aby lax_aby
+cpy_imm cmp_idx nop_imm dcp_idx cpy_zpg cmp_zpg dec_zpg dcp_zpg iny_imp cmp_imm dex_imp sbx_imm cpy_aba cmp_aba dec_aba dcp_aba
+bne_rel cmp_idy kil_non dcp_idy nop_zpx cmp_zpx dec_zpx dcp_zpx cld_imp cmp_aby nop_imp dcp_aby nop_abx cmp_abx dec_abx dcp_abx
+cpx_imm sbc_idx nop_imm isb_idx cpx_zpg sbc_zpg inc_zpg isb_zpg inx_imp sbc_imm nop_imp sbc_imm cpx_aba sbc_aba inc_aba isb_aba
+beq_rel sbc_idy kil_non isb_idy nop_zpx sbc_zpx inc_zpx isb_zpx sed_imp sbc_aby nop_imp isb_aby nop_abx sbc_abx inc_abx isb_abx
+reset
--- /dev/null
+# license:BSD-3-Clause
+# copyright-holders:Olivier Galibert
+# m65c02
+brk_c_imp ora_idx nop_imm nop_c_imp tsb_zpg ora_zpg asl_zpg nop_c_imp php_imp ora_imm asl_acc nop_c_imp tsb_aba ora_aba asl_aba nop_c_imp
+bpl_rel ora_idy ora_zpi nop_c_imp trb_zpg ora_zpx asl_zpx nop_c_imp clc_imp ora_aby inc_acc nop_c_imp trb_aba ora_abx asl_c_abx nop_c_imp
+jsr_adr and_idx nop_imm nop_c_imp bit_zpg and_zpg rol_zpg nop_c_imp plp_imp and_imm rol_acc nop_c_imp bit_aba and_aba rol_aba nop_c_imp
+bmi_rel and_idy and_zpi nop_c_imp bit_zpx and_zpx rol_zpx nop_c_imp sec_imp and_aby dec_acc nop_c_imp bit_abx and_abx rol_c_abx nop_c_imp
+rti_imp eor_idx nop_imm nop_c_imp nop_zpg eor_zpg lsr_zpg nop_c_imp pha_imp eor_imm lsr_acc nop_c_imp jmp_adr eor_aba lsr_aba nop_c_imp
+bvc_rel eor_idy eor_zpi nop_c_imp nop_zpx eor_zpx lsr_zpx nop_c_imp cli_imp eor_aby phy_imp nop_c_imp nop_c_aba eor_abx lsr_c_abx nop_c_imp
+rts_imp adc_c_idx nop_imm nop_c_imp stz_zpg adc_c_zpg ror_zpg nop_c_imp pla_imp adc_c_imm ror_acc nop_c_imp jmp_c_ind adc_c_aba ror_aba nop_c_imp
+bvs_rel adc_c_idy adc_c_zpi nop_c_imp stz_zpx adc_c_zpx ror_zpx nop_c_imp sei_imp adc_c_aby ply_imp nop_c_imp jmp_iax adc_c_abx ror_c_abx nop_c_imp
+bra_rel sta_idx nop_imm nop_c_imp sty_zpg sta_zpg stx_zpg nop_c_imp dey_imp bit_imm txa_imp nop_c_imp sty_aba sta_aba stx_aba nop_c_imp
+bcc_rel sta_idy sta_zpi nop_c_imp sty_zpx sta_zpx stx_zpy nop_c_imp tya_imp sta_aby txs_imp nop_c_imp stz_aba sta_abx stz_abx nop_c_imp
+ldy_imm lda_idx ldx_imm nop_c_imp ldy_zpg lda_zpg ldx_zpg nop_c_imp tay_imp lda_imm tax_imp nop_c_imp ldy_aba lda_aba ldx_aba nop_c_imp
+bcs_rel lda_idy lda_zpi nop_c_imp ldy_zpx lda_zpx ldx_zpy nop_c_imp clv_imp lda_aby tsx_imp nop_c_imp ldy_abx lda_abx ldx_aby nop_c_imp
+cpy_imm cmp_idx nop_imm nop_c_imp cpy_zpg cmp_zpg dec_zpg nop_c_imp iny_imp cmp_imm dex_imp nop_c_imp cpy_aba cmp_aba dec_aba nop_c_imp
+bne_rel cmp_idy cmp_zpi nop_c_imp nop_zpx cmp_zpx dec_zpx nop_c_imp cld_imp cmp_aby phx_imp nop_c_imp nop_c_abx cmp_abx dec_abx nop_c_imp
+cpx_imm sbc_c_idx nop_imm nop_c_imp cpx_zpg sbc_c_zpg inc_zpg nop_c_imp inx_imp sbc_c_imm nop_imp nop_c_imp cpx_aba sbc_c_aba inc_aba nop_c_imp
+beq_rel sbc_c_idy sbc_c_zpi nop_c_imp nop_zpx sbc_c_zpx inc_zpx nop_c_imp sed_imp sbc_c_aby plx_imp nop_c_imp nop_c_abx sbc_c_abx inc_abx nop_c_imp
+reset
--- /dev/null
+// license:BSD-3-Clause
+// copyright-holders:Olivier Galibert
+/***************************************************************************
+
+ m6502.c
+
+ MOS Technology 6502, original NMOS variant
+
+***************************************************************************/
+
+#include "emu.h"
+#include "debugger.h"
+#include "m6502.h"
+#include "m6502d.h"
+
+DEFINE_DEVICE_TYPE(M6502, m6502_device, "m6502", "MOS Technology M6502")
+
+m6502_device::m6502_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+ m6502_device(mconfig, M6502, tag, owner, clock)
+{
+}
+
+m6502_device::m6502_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock) :
+ cpu_device(mconfig, type, tag, owner, clock),
+ sync_w(*this),
+ program_config("program", ENDIANNESS_LITTLE, 8, 16),
+ sprogram_config("decrypted_opcodes", ENDIANNESS_LITTLE, 8, 16), PPC(0), NPC(0), PC(0), SP(0), TMP(0), TMP2(0), A(0), X(0), Y(0), P(0), IR(0), inst_state_base(0), mintf(nullptr),
+ inst_state(0), inst_substate(0), icount(0), nmi_state(false), irq_state(false), apu_irq_state(false), v_state(false), irq_taken(false), sync(false), inhibit_interrupts(false)
+{
+ cache_disabled = false;
+}
+
+void m6502_device::device_start()
+{
+ if(cache_disabled)
+ mintf = std::make_unique<mi_default_nd>();
+ else
+ mintf = std::make_unique<mi_default_normal>();
+
+ init();
+}
+
+void m6502_device::init()
+{
+ mintf->program = &space(AS_PROGRAM);
+ mintf->sprogram = has_space(AS_OPCODES) ? &space(AS_OPCODES) : mintf->program;
+
+ mintf->cache = mintf->program->cache<0, 0, ENDIANNESS_LITTLE>();
+ mintf->scache = mintf->sprogram->cache<0, 0, ENDIANNESS_LITTLE>();
+
+ sync_w.resolve_safe();
+
+ XPC = 0;
+
+ state_add(STATE_GENPC, "GENPC", XPC).callexport().noshow();
+ state_add(STATE_GENPCBASE, "CURPC", XPC).callexport().noshow();
+ state_add(STATE_GENSP, "GENSP", SP).noshow();
+ state_add(STATE_GENFLAGS, "GENFLAGS", P).callimport().formatstr("%6s").noshow();
+ state_add(M6502_PC, "PC", NPC).callimport();
+ state_add(M6502_A, "A", A);
+ state_add(M6502_X, "X", X);
+ state_add(M6502_Y, "Y", Y);
+ state_add(M6502_P, "P", P).callimport();
+ state_add(M6502_S, "SP", SP);
+ state_add(M6502_IR, "IR", IR);
+
+ save_item(NAME(PC));
+ save_item(NAME(NPC));
+ save_item(NAME(PPC));
+ save_item(NAME(A));
+ save_item(NAME(X));
+ save_item(NAME(Y));
+ save_item(NAME(P));
+ save_item(NAME(SP));
+ save_item(NAME(TMP));
+ save_item(NAME(TMP2));
+ save_item(NAME(IR));
+ save_item(NAME(nmi_state));
+ save_item(NAME(irq_state));
+ save_item(NAME(apu_irq_state));
+ save_item(NAME(v_state));
+ save_item(NAME(inst_state));
+ save_item(NAME(inst_substate));
+ save_item(NAME(inst_state_base));
+ save_item(NAME(irq_taken));
+ save_item(NAME(inhibit_interrupts));
+
+ set_icountptr(icount);
+
+ PC = 0x0000;
+ NPC = 0x0000;
+ A = 0x00;
+ X = 0x80;
+ Y = 0x00;
+ P = 0x36;
+ SP = 0x01bd;
+ TMP = 0x0000;
+ TMP2 = 0x00;
+ IR = 0x00;
+ nmi_state = false;
+ irq_state = false;
+ apu_irq_state = false;
+ irq_taken = false;
+ v_state = false;
+ inst_state = STATE_RESET;
+ inst_substate = 0;
+ inst_state_base = 0;
+ sync = false;
+ inhibit_interrupts = false;
+ count_before_instruction_step = 0;
+}
+
+void m6502_device::device_reset()
+{
+ inst_state = STATE_RESET;
+ inst_substate = 0;
+ inst_state_base = 0;
+ nmi_state = false;
+ irq_state = false;
+ apu_irq_state = false;
+ irq_taken = false;
+ v_state = false;
+ sync = false;
+ sync_w(CLEAR_LINE);
+ inhibit_interrupts = false;
+}
+
+
+uint32_t m6502_device::execute_min_cycles() const
+{
+ return 1;
+}
+
+uint32_t m6502_device::execute_max_cycles() const
+{
+ return 10;
+}
+
+uint32_t m6502_device::execute_input_lines() const
+{
+ return NMI_LINE+1;
+}
+
+bool m6502_device::execute_input_edge_triggered(int inputnum) const
+{
+ return inputnum == NMI_LINE;
+}
+
+void m6502_device::do_adc_d(uint8_t val)
+{
+ uint8_t c = P & F_C ? 1 : 0;
+ P &= ~(F_N|F_V|F_Z|F_C);
+ uint8_t al = (A & 15) + (val & 15) + c;
+ if(al > 9)
+ al += 6;
+ uint8_t ah = (A >> 4) + (val >> 4) + (al > 15);
+ if(!uint8_t(A + val + c))
+ P |= F_Z;
+ else if(ah & 8)
+ P |= F_N;
+ if(~(A^val) & (A^(ah << 4)) & 0x80)
+ P |= F_V;
+ if(ah > 9)
+ ah += 6;
+ if(ah > 15)
+ P |= F_C;
+ A = (ah << 4) | (al & 15);
+}
+
+void m6502_device::do_adc_nd(uint8_t val)
+{
+ uint16_t sum;
+ sum = A + val + (P & F_C ? 1 : 0);
+ P &= ~(F_N|F_V|F_Z|F_C);
+ if(!uint8_t(sum))
+ P |= F_Z;
+ else if(int8_t(sum) < 0)
+ P |= F_N;
+ if(~(A^val) & (A^sum) & 0x80)
+ P |= F_V;
+ if(sum & 0xff00)
+ P |= F_C;
+ A = sum;
+}
+
+void m6502_device::do_adc(uint8_t val)
+{
+ if(P & F_D)
+ do_adc_d(val);
+ else
+ do_adc_nd(val);
+}
+
+void m6502_device::do_arr_nd()
+{
+ bool c = P & F_C;
+ P &= ~(F_N|F_Z|F_C|F_V);
+ A >>= 1;
+ if(c)
+ A |= 0x80;
+ if(!A)
+ P |= F_Z;
+ else if(int8_t(A)<0)
+ P |= F_N;
+ if(A & 0x40)
+ P |= F_V|F_C;
+ if(A & 0x20)
+ P ^= F_V;
+}
+
+void m6502_device::do_arr_d()
+{
+ // The adc/ror interaction gives an extremely weird result
+ bool c = P & F_C;
+ P &= ~(F_N|F_Z|F_C|F_V);
+ uint8_t a = A >> 1;
+ if(c)
+ a |= 0x80;
+ if(!a)
+ P |= F_Z;
+ else if(int8_t(a) < 0)
+ P |= F_N;
+ if((a ^ A) & 0x40)
+ P |= F_V;
+
+ if((A & 0x0f) >= 0x05)
+ a = ((a + 6) & 0x0f) | (a & 0xf0);
+
+ if((A & 0xf0) >= 0x50) {
+ a += 0x60;
+ P |= F_C;
+ }
+ A = a;
+}
+
+void m6502_device::do_arr()
+{
+ if(P & F_D)
+ do_arr_d();
+ else
+ do_arr_nd();
+}
+
+void m6502_device::do_cmp(uint8_t val1, uint8_t val2)
+{
+ P &= ~(F_N|F_Z|F_C);
+ uint16_t r = val1-val2;
+ if(!r)
+ P |= F_Z;
+ else if(int8_t(r) < 0)
+ P |= F_N;
+ if(!(r & 0xff00))
+ P |= F_C;
+}
+
+void m6502_device::do_sbc_d(uint8_t val)
+{
+ uint8_t c = P & F_C ? 0 : 1;
+ P &= ~(F_N|F_V|F_Z|F_C);
+ uint16_t diff = A - val - c;
+ uint8_t al = (A & 15) - (val & 15) - c;
+ if(int8_t(al) < 0)
+ al -= 6;
+ uint8_t ah = (A >> 4) - (val >> 4) - (int8_t(al) < 0);
+ if(!uint8_t(diff))
+ P |= F_Z;
+ else if(diff & 0x80)
+ P |= F_N;
+ if((A^val) & (A^diff) & 0x80)
+ P |= F_V;
+ if(!(diff & 0xff00))
+ P |= F_C;
+ if(int8_t(ah) < 0)
+ ah -= 6;
+ A = (ah << 4) | (al & 15);
+}
+
+void m6502_device::do_sbc_nd(uint8_t val)
+{
+ uint16_t diff = A - val - (P & F_C ? 0 : 1);
+ P &= ~(F_N|F_V|F_Z|F_C);
+ if(!uint8_t(diff))
+ P |= F_Z;
+ else if(int8_t(diff) < 0)
+ P |= F_N;
+ if((A^val) & (A^diff) & 0x80)
+ P |= F_V;
+ if(!(diff & 0xff00))
+ P |= F_C;
+ A = diff;
+}
+
+void m6502_device::do_sbc(uint8_t val)
+{
+ if(P & F_D)
+ do_sbc_d(val);
+ else
+ do_sbc_nd(val);
+}
+
+void m6502_device::do_bit(uint8_t val)
+{
+ P &= ~(F_N|F_Z|F_V);
+ uint8_t r = A & val;
+ if(!r)
+ P |= F_Z;
+ if(val & 0x80)
+ P |= F_N;
+ if(val & 0x40)
+ P |= F_V;
+}
+
+uint8_t m6502_device::do_asl(uint8_t v)
+{
+ P &= ~(F_N|F_Z|F_C);
+ uint8_t r = v<<1;
+ if(!r)
+ P |= F_Z;
+ else if(int8_t(r) < 0)
+ P |= F_N;
+ if(v & 0x80)
+ P |= F_C;
+ return r;
+}
+
+uint8_t m6502_device::do_lsr(uint8_t v)
+{
+ P &= ~(F_N|F_Z|F_C);
+ if(v & 1)
+ P |= F_C;
+ v >>= 1;
+ if(!v)
+ P |= F_Z;
+ return v;
+}
+
+uint8_t m6502_device::do_ror(uint8_t v)
+{
+ bool c = P & F_C;
+ P &= ~(F_N|F_Z|F_C);
+ if(v & 1)
+ P |= F_C;
+ v >>= 1;
+ if(c)
+ v |= 0x80;
+ if(!v)
+ P |= F_Z;
+ else if(int8_t(v)<0)
+ P |= F_N;
+ return v;
+}
+
+uint8_t m6502_device::do_rol(uint8_t v)
+{
+ bool c = P & F_C;
+ P &= ~(F_N|F_Z|F_C);
+ if(v & 0x80)
+ P |= F_C;
+ v <<= 1;
+ if(c)
+ v |= 0x01;
+ if(!v)
+ P |= F_Z;
+ else if(int8_t(v)<0)
+ P |= F_N;
+ return v;
+}
+
+uint8_t m6502_device::do_asr(uint8_t v)
+{
+ P &= ~(F_N|F_Z|F_C);
+ if(v & 1)
+ P |= F_C;
+ v >>= 1;
+ if(!v)
+ P |= F_Z;
+ else if(v & 0x40) {
+ P |= F_N;
+ v |= 0x80;
+ }
+ return v;
+}
+
+offs_t m6502_device::pc_to_external(u16 pc)
+{
+ return pc;
+}
+
+void m6502_device::execute_run()
+{
+ if(inst_substate)
+ do_exec_partial();
+
+ while(icount > 0) {
+ if(inst_state < 0xff00) {
+ PPC = NPC;
+ inst_state = IR | inst_state_base;
+ if(machine().debug_flags & DEBUG_FLAG_ENABLED)
+ debugger_instruction_hook(pc_to_external(NPC));
+ }
+ do_exec_full();
+ }
+}
+
+void m6502_device::execute_set_input(int inputnum, int state)
+{
+ switch(inputnum) {
+ case IRQ_LINE: irq_state = state == ASSERT_LINE; break;
+ case APU_IRQ_LINE: apu_irq_state = state == ASSERT_LINE; break;
+ case NMI_LINE: nmi_state = nmi_state || (state == ASSERT_LINE); break;
+ case V_LINE:
+ if(!v_state && state == ASSERT_LINE)
+ P |= F_V;
+ v_state = state == ASSERT_LINE;
+ break;
+ }
+}
+
+
+device_memory_interface::space_config_vector m6502_device::memory_space_config() const
+{
+ if(has_configured_map(AS_OPCODES))
+ return space_config_vector {
+ std::make_pair(AS_PROGRAM, &program_config),
+ std::make_pair(AS_OPCODES, &sprogram_config)
+ };
+ else
+ return space_config_vector {
+ std::make_pair(AS_PROGRAM, &program_config)
+ };
+}
+
+
+void m6502_device::state_import(const device_state_entry &entry)
+{
+ switch(entry.index()) {
+ case STATE_GENFLAGS:
+ case M6502_P:
+ P = P | (F_B|F_E);
+ break;
+ case M6502_PC:
+ PC = NPC;
+ irq_taken = false;
+ prefetch();
+ PPC = NPC;
+ inst_state = IR | inst_state_base;
+ break;
+ }
+}
+
+void m6502_device::state_export(const device_state_entry &entry)
+{
+ switch(entry.index()) {
+ case STATE_GENPC: XPC = pc_to_external(PPC); break;
+ case STATE_GENPCBASE: XPC = pc_to_external(NPC); break;
+ }
+}
+
+void m6502_device::state_string_export(const device_state_entry &entry, std::string &str) const
+{
+ switch(entry.index()) {
+ case STATE_GENFLAGS:
+ case M6502_P:
+ str = string_format("%c%c%c%c%c%c",
+ P & F_N ? 'N' : '.',
+ P & F_V ? 'V' : '.',
+ P & F_D ? 'D' : '.',
+ P & F_I ? 'I' : '.',
+ P & F_Z ? 'Z' : '.',
+ P & F_C ? 'C' : '.');
+ break;
+ }
+}
+
+void m6502_device::prefetch()
+{
+ sync = true;
+ sync_w(ASSERT_LINE);
+ NPC = PC;
+ IR = mintf->read_sync(PC);
+ sync = false;
+ sync_w(CLEAR_LINE);
+
+ if((nmi_state || ((irq_state || apu_irq_state) && !(P & F_I))) && !inhibit_interrupts) {
+ irq_taken = true;
+ IR = 0x00;
+ } else
+ PC++;
+}
+
+void m6502_device::prefetch_noirq()
+{
+ sync = true;
+ sync_w(ASSERT_LINE);
+ NPC = PC;
+ IR = mintf->read_sync(PC);
+ sync = false;
+ sync_w(CLEAR_LINE);
+ PC++;
+}
+
+void m6502_device::set_nz(uint8_t v)
+{
+ P &= ~(F_Z|F_N);
+ if(v & 0x80)
+ P |= F_N;
+ if(!v)
+ P |= F_Z;
+}
+
+std::unique_ptr<util::disasm_interface> m6502_device::create_disassembler()
+{
+ return std::make_unique<m6502_disassembler>();
+}
+
+uint8_t m6502_device::memory_interface::read_9(uint16_t adr)
+{
+ return read(adr);
+}
+
+void m6502_device::memory_interface::write_9(uint16_t adr, uint8_t val)
+{
+ write(adr, val);
+}
+
+
+uint8_t m6502_device::mi_default_normal::read(uint16_t adr)
+{
+ return program->read_byte(adr);
+}
+
+uint8_t m6502_device::mi_default_normal::read_sync(uint16_t adr)
+{
+ return scache->read_byte(adr);
+}
+
+uint8_t m6502_device::mi_default_normal::read_arg(uint16_t adr)
+{
+ return cache->read_byte(adr);
+}
+
+
+void m6502_device::mi_default_normal::write(uint16_t adr, uint8_t val)
+{
+ program->write_byte(adr, val);
+}
+
+uint8_t m6502_device::mi_default_nd::read_sync(uint16_t adr)
+{
+ return sprogram->read_byte(adr);
+}
+
+uint8_t m6502_device::mi_default_nd::read_arg(uint16_t adr)
+{
+ return program->read_byte(adr);
+}
+
+m6502_mcu_device::m6502_mcu_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock) :
+ m6502_device(mconfig, type, tag, owner, clock)
+{
+}
+
+
+void m6502_mcu_device::recompute_bcount(uint64_t event_time)
+{
+ if(!event_time || event_time >= total_cycles() + icount) {
+ bcount = 0;
+ return;
+ }
+ bcount = total_cycles() + icount - event_time;
+}
+
+void m6502_mcu_device::execute_run()
+{
+ internal_update(total_cycles());
+
+ icount -= count_before_instruction_step;
+ if(icount < 0) {
+ count_before_instruction_step = -icount;
+ icount = 0;
+ } else
+ count_before_instruction_step = 0;
+
+ while(bcount && icount <= bcount)
+ internal_update(total_cycles() + icount - bcount);
+
+ if(icount > 0 && inst_substate)
+ do_exec_partial();
+
+ while(icount > 0) {
+ while(icount > bcount) {
+ if(inst_state < 0xff00) {
+ PPC = NPC;
+ inst_state = IR | inst_state_base;
+ if(machine().debug_flags & DEBUG_FLAG_ENABLED)
+ debugger_instruction_hook(NPC);
+ }
+ do_exec_full();
+ }
+ if(icount > 0)
+ while(bcount && icount <= bcount)
+ internal_update(total_cycles() + icount - bcount);
+ if(icount > 0 && inst_substate)
+ do_exec_partial();
+ }
+ if(icount < 0) {
+ count_before_instruction_step = -icount;
+ icount = 0;
+ }
+}
+
+void m6502_mcu_device::add_event(uint64_t &event_time, uint64_t new_event)
+{
+ if(!new_event)
+ return;
+ if(!event_time || event_time > new_event)
+ event_time = new_event;
+}
+
+
+#include "cpu/m6502/m6502.hxx"
--- /dev/null
+// license:BSD-3-Clause
+// copyright-holders:Olivier Galibert
+/***************************************************************************
+
+ m6502.h
+
+ MOS Technology 6502, original NMOS variant
+
+***************************************************************************/
+
+#ifndef MAME_CPU_M6502_M6502_H
+#define MAME_CPU_M6502_M6502_H
+
+class m6502_device : public cpu_device {
+public:
+ enum {
+ IRQ_LINE = INPUT_LINE_IRQ0,
+ APU_IRQ_LINE = INPUT_LINE_IRQ1,
+ NMI_LINE = INPUT_LINE_NMI,
+ V_LINE = INPUT_LINE_IRQ0 + 16
+ };
+
+ m6502_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+ bool get_sync() const { return sync; }
+ void disable_cache() { cache_disabled = true; }
+
+ auto sync_cb() { return sync_w.bind(); }
+
+ devcb_write_line sync_w;
+
+protected:
+ m6502_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
+
+ class memory_interface {
+ public:
+ address_space *program, *sprogram;
+ memory_access_cache<0, 0, ENDIANNESS_LITTLE> *cache, *scache;
+
+ virtual ~memory_interface() {}
+ virtual uint8_t read(uint16_t adr) = 0;
+ virtual uint8_t read_9(uint16_t adr);
+ virtual uint8_t read_sync(uint16_t adr) = 0;
+ virtual uint8_t read_arg(uint16_t adr) = 0;
+ virtual void write(uint16_t adr, uint8_t val) = 0;
+ virtual void write_9(uint16_t adr, uint8_t val);
+ };
+
+ class mi_default_normal : public memory_interface {
+ public:
+ virtual ~mi_default_normal() {}
+ virtual uint8_t read(uint16_t adr) override;
+ virtual uint8_t read_sync(uint16_t adr) override;
+ virtual uint8_t read_arg(uint16_t adr) override;
+ virtual void write(uint16_t adr, uint8_t val) override;
+ };
+
+ class mi_default_nd : public mi_default_normal {
+ public:
+ virtual ~mi_default_nd() {}
+ virtual uint8_t read_sync(uint16_t adr) override;
+ virtual uint8_t read_arg(uint16_t adr) override;
+ };
+
+ enum {
+ STATE_RESET = 0xff00
+ };
+
+ enum {
+ F_N = 0x80,
+ F_V = 0x40,
+ F_E = 0x20, // 65ce02
+ F_T = 0x20, // M740: replaces A with $00,X in some opcodes when set
+ F_B = 0x10,
+ F_D = 0x08,
+ F_I = 0x04,
+ F_Z = 0x02,
+ F_C = 0x01
+ };
+
+ virtual void init();
+
+ // device-level overrides
+ virtual void device_start() override;
+ virtual void device_reset() override;
+
+ // device_execute_interface overrides
+ virtual uint32_t execute_min_cycles() const override;
+ virtual uint32_t execute_max_cycles() const override;
+ virtual uint32_t execute_input_lines() const override;
+ virtual void execute_run() override;
+ virtual void execute_set_input(int inputnum, int state) override;
+ virtual bool execute_input_edge_triggered(int inputnum) const override;
+
+ // device_memory_interface overrides
+ virtual space_config_vector memory_space_config() const override;
+
+ // device_state_interface overrides
+ virtual void state_import(const device_state_entry &entry) override;
+ virtual void state_export(const device_state_entry &entry) override;
+ virtual void state_string_export(const device_state_entry &entry, std::string &str) const override;
+
+ // device_disasm_interface overrides
+ virtual std::unique_ptr<util::disasm_interface> create_disassembler() override;
+
+ address_space_config program_config, sprogram_config;
+
+ uint16_t PPC; /* previous program counter */
+ uint16_t NPC; /* next start-of-instruction program counter */
+ uint16_t PC; /* program counter */
+ uint16_t SP; /* stack pointer (always 100 - 1FF) */
+ uint16_t TMP; /* temporary internal values */
+ uint8_t TMP2; /* another temporary internal value, 8 bits this time */
+ uint8_t A; /* Accumulator */
+ uint8_t X; /* X index register */
+ uint8_t Y; /* Y index register */
+ uint8_t P; /* Processor status */
+ uint8_t IR; /* Prefetched instruction register */
+ int inst_state_base; /* Current instruction bank */
+
+ std::unique_ptr<memory_interface> mintf;
+ int inst_state, inst_substate;
+ int icount, bcount, count_before_instruction_step;
+ bool nmi_state, irq_state, apu_irq_state, v_state;
+ bool irq_taken, sync, cache_disabled, inhibit_interrupts;
+
+ uint8_t read(uint16_t adr) { return mintf->read(adr); }
+ uint8_t read_9(uint16_t adr) { return mintf->read_9(adr); }
+ void write(uint16_t adr, uint8_t val) { mintf->write(adr, val); }
+ void write_9(uint16_t adr, uint8_t val) { mintf->write_9(adr, val); }
+ uint8_t read_arg(uint16_t adr) { return mintf->read_arg(adr); }
+ uint8_t read_pc() { return mintf->read_arg(PC++); }
+ uint8_t read_pc_noinc() { return mintf->read_arg(PC); }
+ void prefetch();
+ void prefetch_noirq();
+ void set_nz(uint8_t v);
+
+ u32 XPC;
+ virtual offs_t pc_to_external(u16 pc); // For paged PCs
+ virtual void do_exec_full();
+ virtual void do_exec_partial();
+
+ // inline helpers
+ static inline bool page_changing(uint16_t base, int delta) { return ((base + delta) ^ base) & 0xff00; }
+ static inline uint16_t set_l(uint16_t base, uint8_t val) { return (base & 0xff00) | val; }
+ static inline uint16_t set_h(uint16_t base, uint8_t val) { return (base & 0x00ff) | (val << 8); }
+
+ inline void dec_SP() { SP = set_l(SP, SP-1); }
+ inline void inc_SP() { SP = set_l(SP, SP+1); }
+
+ void do_adc_d(uint8_t val);
+ void do_adc_nd(uint8_t val);
+ void do_sbc_d(uint8_t val);
+ void do_sbc_nd(uint8_t val);
+ void do_arr_d();
+ void do_arr_nd();
+
+ void do_adc(uint8_t val);
+ void do_cmp(uint8_t val1, uint8_t val2);
+ void do_sbc(uint8_t val);
+ void do_bit(uint8_t val);
+ void do_arr();
+ uint8_t do_asl(uint8_t v);
+ uint8_t do_lsr(uint8_t v);
+ uint8_t do_ror(uint8_t v);
+ uint8_t do_rol(uint8_t v);
+ uint8_t do_asr(uint8_t v);
+
+#define O(o) void o ## _full(); void o ## _partial()
+
+ // NMOS 6502 opcodes
+ // documented opcodes
+ O(adc_aba); O(adc_abx); O(adc_aby); O(adc_idx); O(adc_idy); O(adc_imm); O(adc_zpg); O(adc_zpx);
+ O(and_aba); O(and_abx); O(and_aby); O(and_imm); O(and_idx); O(and_idy); O(and_zpg); O(and_zpx);
+ O(asl_aba); O(asl_abx); O(asl_acc); O(asl_zpg); O(asl_zpx);
+ O(bcc_rel);
+ O(bcs_rel);
+ O(beq_rel);
+ O(bit_aba); O(bit_zpg);
+ O(bmi_rel);
+ O(bne_rel);
+ O(bpl_rel);
+ O(brk_imp);
+ O(bvc_rel);
+ O(bvs_rel);
+ O(clc_imp);
+ O(cld_imp);
+ O(cli_imp);
+ O(clv_imp);
+ O(cmp_aba); O(cmp_abx); O(cmp_aby); O(cmp_idx); O(cmp_idy); O(cmp_imm); O(cmp_zpg); O(cmp_zpx);
+ O(cpx_aba); O(cpx_imm); O(cpx_zpg);
+ O(cpy_aba); O(cpy_imm); O(cpy_zpg);
+ O(dec_aba); O(dec_abx); O(dec_zpg); O(dec_zpx);
+ O(dex_imp);
+ O(dey_imp);
+ O(eor_aba); O(eor_abx); O(eor_aby); O(eor_idx); O(eor_idy); O(eor_imm); O(eor_zpg); O(eor_zpx);
+ O(inc_aba); O(inc_abx); O(inc_zpg); O(inc_zpx);
+ O(inx_imp);
+ O(iny_imp);
+ O(jmp_adr); O(jmp_ind);
+ O(jsr_adr);
+ O(lda_aba); O(lda_abx); O(lda_aby); O(lda_idx); O(lda_idy); O(lda_imm); O(lda_zpg); O(lda_zpx);
+ O(ldx_aba); O(ldx_aby); O(ldx_imm); O(ldx_zpg); O(ldx_zpy);
+ O(ldy_aba); O(ldy_abx); O(ldy_imm); O(ldy_zpg); O(ldy_zpx);
+ O(lsr_aba); O(lsr_abx); O(lsr_acc); O(lsr_zpg); O(lsr_zpx);
+ O(nop_imp);
+ O(ora_aba); O(ora_abx); O(ora_aby); O(ora_imm); O(ora_idx); O(ora_idy); O(ora_zpg); O(ora_zpx);
+ O(pha_imp);
+ O(php_imp);
+ O(pla_imp);
+ O(plp_imp);
+ O(rol_aba); O(rol_abx); O(rol_acc); O(rol_zpg); O(rol_zpx);
+ O(ror_aba); O(ror_abx); O(ror_acc); O(ror_zpg); O(ror_zpx);
+ O(rti_imp);
+ O(rts_imp);
+ O(sbc_aba); O(sbc_abx); O(sbc_aby); O(sbc_idx); O(sbc_idy); O(sbc_imm); O(sbc_zpg); O(sbc_zpx);
+ O(sec_imp);
+ O(sed_imp);
+ O(sei_imp);
+ O(sta_aba); O(sta_abx); O(sta_aby); O(sta_idx); O(sta_idy); O(sta_zpg); O(sta_zpx);
+ O(stx_aba); O(stx_zpg); O(stx_zpy);
+ O(sty_aba); O(sty_zpg); O(sty_zpx);
+ O(tax_imp);
+ O(tay_imp);
+ O(tsx_imp);
+ O(txa_imp);
+ O(txs_imp);
+ O(tya_imp);
+
+ // exceptions
+ O(reset);
+
+ // undocumented reliable instructions
+ O(dcp_aba); O(dcp_abx); O(dcp_aby); O(dcp_idx); O(dcp_idy); O(dcp_zpg); O(dcp_zpx);
+ O(isb_aba); O(isb_abx); O(isb_aby); O(isb_idx); O(isb_idy); O(isb_zpg); O(isb_zpx);
+ O(lax_aba); O(lax_aby); O(lax_idx); O(lax_idy); O(lax_zpg); O(lax_zpy);
+ O(rla_aba); O(rla_abx); O(rla_aby); O(rla_idx); O(rla_idy); O(rla_zpg); O(rla_zpx);
+ O(rra_aba); O(rra_abx); O(rra_aby); O(rra_idx); O(rra_idy); O(rra_zpg); O(rra_zpx);
+ O(sax_aba); O(sax_idx); O(sax_zpg); O(sax_zpy);
+ O(sbx_imm);
+ O(sha_aby); O(sha_idy);
+ O(shs_aby);
+ O(shx_aby);
+ O(shy_abx);
+ O(slo_aba); O(slo_abx); O(slo_aby); O(slo_idx); O(slo_idy); O(slo_zpg); O(slo_zpx);
+ O(sre_aba); O(sre_abx); O(sre_aby); O(sre_idx); O(sre_idy); O(sre_zpg); O(sre_zpx);
+
+ // undocumented unreliable instructions
+ // behaviour differs between visual6502 and online docs, which
+ // is a clear sign reliability is not to be expected
+ // implemented version follows visual6502
+ O(anc_imm);
+ O(ane_imm);
+ O(arr_imm);
+ O(asr_imm);
+ O(las_aby);
+ O(lxa_imm);
+
+ // nop variants
+ O(nop_imm); O(nop_aba); O(nop_abx); O(nop_zpg); O(nop_zpx);
+
+ // system killers
+ O(kil_non);
+
+#undef O
+};
+
+class m6502_mcu_device : public m6502_device {
+protected:
+ m6502_mcu_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
+
+ void internal_update() { internal_update(total_cycles()); }
+ virtual void internal_update(uint64_t current_time) = 0;
+ void recompute_bcount(uint64_t event_time);
+ static void add_event(uint64_t &event_time, uint64_t new_event);
+
+ virtual void execute_run() override;
+};
+
+enum {
+ M6502_PC = 1,
+ M6502_A,
+ M6502_X,
+ M6502_Y,
+ M6502_P,
+ M6502_S,
+ M6502_IR
+};
+
+enum {
+ M6502_IRQ_LINE = m6502_device::IRQ_LINE,
+ M6502_NMI_LINE = m6502_device::NMI_LINE,
+ M6502_SET_OVERFLOW = m6502_device::V_LINE
+};
+
+DECLARE_DEVICE_TYPE(M6502, m6502_device)
+
+#endif // MAME_CPU_M6502_M6502_H
--- /dev/null
+mos metal oxid semiconductor
+bought by cbm
+
+license to produce chips
+ rockwell
+
+transistor, logic gate designs:
+NMOS (M65xx)
+CMOS (M65Cxx)
+HMOS (M75xx) hyper? MOS, used in early c16/plus4 series
+H2MOS (M85xx) hyper2 MOS, used in C128, later c16/plus4, late C64
+?SCMOS (M65SCxx) Super? CMOS
+?CE (M65CExx, M45xx) CMOS Enhanced?, used in not released C65
+
+HMOS, H2MOS CPUs have the same core as the NMOS series
+
+6500 / 6501
+mask programable microcontroller
+32 io ports (2 interruptable)
+timer
+64 byte ram
+8 kbyte rom
+
+6502 (used in many designs)
+b-flag always 1! (only pushed as 0 when break executed!)
+memory changing opcodes accesses memory: read, write data, write modified data
+
+6504
+only 12 address pins a11..a0
+
+6508
+8 io pins (p0 bis p7)
+
+6509
+1 megabyte memory management
+(lda,sta (zeropage),y modified, uses 2nd address extension register)
+
+6510/8500 (used in some designs)
+6 io pins (p0 bis p5)
+
+6510T/8503? (used in commodore C1551 floppy)
+8 io pins
+integrated clock generation?
+
+7501/8501 (c16, c116, c232, c264, plus4, c364)
+7 io pins (no p5)
+no nmi
+
+8502 (c128)
+7 io pins (no p7)
+
+the above series is opcode compatible (including illegal opcodes)
+
+
+n2a03 (some arcades, NES)
+-------------------------
+(nintendo variant)
+NMOS based!
+illegal opcodes
+$6c jump indirect low byte overrun problem as in 6502
+no decimal mode
+integrated sound hardware
+
+
+65c02 (used in some designs)
+----------------------------
+fixed jmp ind opcode
+memory changing opcodes accesses memory: read, read, write
+no illegal opcodes from the above series
+so not full compatible to 6502 series
+b flag always 1 as in NMOS Series is not known?
+additional commands
+
+several other CMOS variants
+
+
+65sc02 (where used?)
+--------------------
+65c02 compatible
+additional commands
+
+atari lynx bastian schicks bll
+integrated m65sc02 cpu core
+no bbr bbs instructions, else m65c02 compatible
+
+watara supervision
+integrated m65c02 cpu core (or m65sc02 or m65ce02?)
+
+
+gte65816 (nintendo snes)
+------------------------
+65802 upgrade cpu (c64 and c128 upgrade cpu)
+16 bit wide registers
+24 bit address space
+65c02? compatible mode
+additional commands
+
+
+spc700
+------
+(snes sound processor)
+same register layout?
+same addressing modes?
+heavily modified opcodes
+YA could be combined for 16 bit operations?
+
+
+huc6280 (nec pcengine)
+----------------------
+65sc02 compatible?
+8 memory registers
+(highest 3 bits select memory register, these build a22..a13)
+(so 2 Megabyte address room!)
+additional commands?
+several additional integrated features
+
+
+65ce02 (c65 prototype)
+----------------------
+(scan of documentation available, also use
+c65 m4510 documentation)
+(cpu core to be used in asics)
+65sc02 compatible
+z register
+(65c02 zeropage indexed addressing is now (zeropage),z)
+b bank register, highbyte of all zerozape addressing
+register for stack high byte
+additional command (some from the 65816)
+
+
+m4510 (Commodore C65 CPU)
+-------------------------
+(scan of documentation (in c65 documentation) available)
+65ce02 compatible
+integrated 20 bit memory management (map)
+(aug opcode changed to map opcode)
+2 cia6526 integrated
+1 uart integrated
+
+
+mitsubishi 740 series
+---------------------
+(data book in electronic form available)
+(M507xx, M509xx, M374xx, M38xxx, M375xx)
+NMOS based
+additional operation mode
+(arithmetic instruction not performing on akku (a=a operation addressing mode)
+but on zeropage ([x]=[x] operation addressing mode))
+additional instructions LDM, MUL, DIV, TST, COM, RRF, CLT, SET, WIT, STP, CLP
+BRK 1 byte only?
+BRA CMOS compatible
+BBC, BBR different opcode as CMOS, and also akku addressing
+different TRB, TSB
+no CMOS STZ, JMP ind,x
+STP not in all variants
+MUL, DIV not in all variants
+
+
+Set Overflow Pin
+----------------
+in 6502 and pin compatibles (65C02 65SC02 65SC802 65CE02), M6509
+no SO pin 6510/7501/8500/8501/8502/65sc816
+6510T ?
--- /dev/null
+// license:BSD-3-Clause
+// copyright-holders:Olivier Galibert
+/***************************************************************************
+
+ m6502d.cpp
+
+ MOS Technology 6502, original NMOS variant, disassembler
+
+***************************************************************************/
+
+#include "emu.h"
+#include "m6502d.h"
+#include "cpu/m6502/m6502d.hxx"
+
+m6502_base_disassembler::m6502_base_disassembler(const disasm_entry *_table) : table(_table)
+{
+}
+
+u32 m6502_base_disassembler::get_instruction_bank() const
+{
+ return 0;
+}
+
+u32 m6502_base_disassembler::opcode_alignment() const
+{
+ return 1;
+}
+
+offs_t m6502_base_disassembler::disassemble(std::ostream &stream, offs_t pc, const data_buffer &opcodes, const data_buffer ¶ms)
+{
+ const disasm_entry &e = table[opcodes.r8(pc) | get_instruction_bank()];
+ uint32_t flags = e.flags | SUPPORTED;
+ util::stream_format(stream, "%s", e.opcode);
+
+ switch(e.mode) {
+ case DASM_non:
+ flags |= 1;
+ break;
+
+ case DASM_aba:
+ util::stream_format(stream, " $%02x%02x", params.r8(pc+2), params.r8(pc+1));
+ flags |= 3;
+ break;
+
+ case DASM_abx:
+ util::stream_format(stream, " $%02x%02x, x", params.r8(pc+2), params.r8(pc+1));
+ flags |= 3;
+ break;
+
+ case DASM_aby:
+ util::stream_format(stream, " $%02x%02x, y", params.r8(pc+2), params.r8(pc+1));
+ flags |= 3;
+ break;
+
+ case DASM_acc:
+ util::stream_format(stream, " a");
+ flags |= 1;
+ break;
+
+ case DASM_adr:
+ util::stream_format(stream, " $%02x%02x", params.r8(pc+2), params.r8(pc+1));
+ flags |= 3;
+ break;
+
+ case DASM_bzp:
+ util::stream_format(stream, "%d $%02x", (opcodes.r8(pc) >> 4) & 7, params.r8(pc+1));
+ flags |= 2;
+ break;
+
+ case DASM_iax:
+ util::stream_format(stream, " ($%02x%02x, x)", params.r8(pc+2), params.r8(pc+1));
+ flags |= 3;
+ break;
+
+ case DASM_idx:
+ util::stream_format(stream, " ($%02x, x)", params.r8(pc+1));
+ flags |= 2;
+ break;
+
+ case DASM_idy:
+ util::stream_format(stream, " ($%02x), y", params.r8(pc+1));
+ flags |= 2;
+ break;
+
+ case DASM_idz:
+ util::stream_format(stream, " ($%02x), z", params.r8(pc+1));
+ flags |= 2;
+ break;
+
+ case DASM_imm:
+ util::stream_format(stream, " #$%02x", params.r8(pc+1));
+ flags |= 2;
+ break;
+
+ case DASM_imp:
+ flags |= 1;
+ break;
+
+ case DASM_ind:
+ util::stream_format(stream, " ($%02x%02x)", params.r8(pc+2), params.r8(pc+1));
+ flags |= 3;
+ break;
+
+ case DASM_isy:
+ util::stream_format(stream, " ($%02x, s), y", params.r8(pc+1));
+ flags |= 2;
+ break;
+
+ case DASM_iw2:
+ util::stream_format(stream, " #$%02x%02x", params.r8(pc+2), params.r8(pc+1));
+ flags |= 3;
+ break;
+
+ case DASM_iw3:
+ util::stream_format(stream, " #$%02x%02x%02x", params.r8(pc+3), params.r8(pc+2), params.r8(pc+1));
+ flags |= 4;
+ break;
+
+ case DASM_rel:
+ util::stream_format(stream, " $%04x", (pc & 0xf0000) | uint16_t(pc + 2 + int8_t(params.r8(pc+1))));
+ flags |= 2;
+ break;
+
+ case DASM_rw2:
+ util::stream_format(stream, " $%04x", (pc & 0xf0000) | uint16_t(pc + 2 + int16_t((params.r8(pc+2) << 8) | params.r8(pc+1))));
+ flags |= 3;
+ break;
+
+ case DASM_zpb:
+ util::stream_format(stream, "%d $%02x, $%04x", (opcodes.r8(pc) >> 4) & 7, params.r8(pc+1), (pc & 0xf0000) | uint16_t(pc + 3 + int8_t(params.r8(pc+2))));
+ flags |= 3;
+ break;
+
+ case DASM_zpg:
+ util::stream_format(stream, " $%02x", params.r8(pc+1));
+ flags |= 2;
+ break;
+
+ case DASM_zpi:
+ util::stream_format(stream, " ($%02x)", params.r8(pc+1));
+ flags |= 2;
+ break;
+
+ case DASM_zpx:
+ util::stream_format(stream, " $%02x, x", params.r8(pc+1));
+ flags |= 2;
+ break;
+
+ case DASM_zpy:
+ util::stream_format(stream, " $%02x, y", params.r8(pc+1));
+ flags |= 2;
+ break;
+
+ case DASM_imz:
+ util::stream_format(stream, " #$%02x, $%02x", params.r8(pc+1), params.r8(pc+2));
+ flags |= 3;
+ break;
+
+ case DASM_spg:
+ util::stream_format(stream, " \\$%02x", params.r8(pc+1));
+ flags |= 2;
+ break;
+
+ case DASM_biz:
+ util::stream_format(stream, " %d, $%02x", (opcodes.r8(pc) >> 5) & 7, params.r8(pc+1));
+ flags |= 2;
+ break;
+
+ case DASM_bzr:
+ util::stream_format(stream, " %d, $%02x, $%04x", (opcodes.r8(pc) >> 5) & 7, params.r8(pc+1), (pc & 0xf0000) | uint16_t(pc + 3 + int8_t(params.r8(pc+2))));
+ flags |= 3;
+ break;
+
+ case DASM_bar:
+ util::stream_format(stream, " %d, a, $%04x", (opcodes.r8(pc) >> 5) & 7, (pc & 0xf0000) | uint16_t(pc + 3 + int8_t(params.r8(pc+1))));
+ flags |= 2;
+ break;
+
+ case DASM_bac:
+ util::stream_format(stream, " %d, a", (opcodes.r8(pc) >> 5) & 7);
+ flags |= 1;
+ break;
+
+ case DASM_xa3:
+ util::stream_format(stream, " #$%02x%02x%02x", params.r8(pc+1), params.r8(pc+3), params.r8(pc+2));
+ flags |= 4;
+ break;
+
+ default:
+ fprintf(stderr, "Unhandled dasm mode %d\n", e.mode);
+ abort();
+ }
+ return flags;
+}
+
+m6502_disassembler::m6502_disassembler() : m6502_base_disassembler(disasm_entries)
+{
+}
--- /dev/null
+// license:BSD-3-Clause
+// copyright-holders:Olivier Galibert
+/***************************************************************************
+
+ m6502d.h
+
+ MOS Technology 6502, original NMOS variant, disassembler
+
+***************************************************************************/
+
+#ifndef MAME_CPU_M6502_M6502D_H
+#define MAME_CPU_M6502_M6502D_H
+
+#pragma once
+
+class m6502_base_disassembler : public util::disasm_interface
+{
+public:
+ struct disasm_entry {
+ const char *opcode;
+ int mode;
+ offs_t flags;
+ };
+
+ m6502_base_disassembler(const disasm_entry *table);
+ virtual ~m6502_base_disassembler() = default;
+
+ virtual u32 opcode_alignment() const override;
+ virtual offs_t disassemble(std::ostream &stream, offs_t pc, const data_buffer &opcodes, const data_buffer ¶ms) override;
+
+protected:
+ enum {
+ DASM_non, /* no additional arguments */
+ DASM_aba, /* absolute */
+ DASM_abx, /* absolute + X */
+ DASM_aby, /* absolute + Y */
+ DASM_acc, /* accumulator */
+ DASM_adr, /* absolute address (jmp,jsr) */
+ DASM_bzp, /* zero page with bit selection */
+ DASM_iax, /* indirect + X (65c02 jmp) */
+ DASM_idx, /* zero page pre indexed */
+ DASM_idy, /* zero page post indexed */
+ DASM_idz, /* zero page post indexed (65ce02) */
+ DASM_imm, /* immediate */
+ DASM_imp, /* implicit */
+ DASM_ind, /* indirect (jmp) */
+ DASM_isy, /* zero page pre indexed sp and post indexed Y (65ce02) */
+ DASM_iw2, /* immediate word (65ce02) */
+ DASM_iw3, /* augment (65ce02) */
+ DASM_rel, /* relative */
+ DASM_rw2, /* relative word (65cs02, 65ce02) */
+ DASM_zpb, /* zero page and branch (65c02 bbr, bbs) */
+ DASM_zpg, /* zero page */
+ DASM_zpi, /* zero page indirect (65c02) */
+ DASM_zpx, /* zero page + X */
+ DASM_zpy, /* zero page + Y */
+ DASM_imz, /* load immediate byte, store to zero page address (M740) */
+ DASM_spg, /* "special page": implied FF00 OR immediate value (M740)*/
+ DASM_biz, /* bit, zero page (M740) */
+ DASM_bzr, /* bit, zero page, relative offset (M740) */
+ DASM_bar, /* bit, accumulator, relative offset (M740) */
+ DASM_bac, /* bit, accumulator (M740) */
+ DASM_xa3 /* unknown XaviX opcode, 24-bit ROM pointer? */
+ };
+
+ virtual u32 get_instruction_bank() const;
+
+private:
+ const disasm_entry *table;
+};
+
+class m6502_disassembler : public m6502_base_disassembler
+{
+public:
+ m6502_disassembler();
+ virtual ~m6502_disassembler() = default;
+
+private:
+ static const disasm_entry disasm_entries[0x100];
+};
+
+#endif
--- /dev/null
+#!/usr/bin/python
+# license:BSD-3-Clause
+# copyright-holders:Olivier Galibert
+
+from __future__ import print_function
+
+USAGE = """
+Usage:
+%s prefix {opc.lst|-} disp.lst device.inc deviced.inc
+"""
+import sys
+import logging
+
+MAX_STATES = 0
+
+def load_opcodes(fname):
+ """Load opcodes from .lst file"""
+ opcodes = []
+ logging.info("load_opcodes: %s", fname)
+ try:
+ f = open(fname, "rU")
+ except Exception:
+ err = sys.exc_info()[1]
+ logging.error("cannot read opcodes file %s [%s]", fname, err)
+ sys.exit(1)
+
+ for line in f:
+ if line.startswith("#"): continue
+ line = line.rstrip()
+ if not line: continue
+ if line.startswith(" ") or line.startswith("\t"):
+ # append instruction to last opcode
+ opcodes[-1][1].append(line)
+ else:
+ # add new opcode
+ opcodes.append((line, []))
+ return opcodes
+
+
+def load_disp(fname):
+ logging.info("load_disp: %s", fname)
+ states = []
+ try:
+ f = open(fname, "rU")
+ except Exception:
+ err = sys.exc_info()[1]
+ logging.error("cannot read display file %s [%s]", fname, err)
+ sys.exit(1)
+ for line in f:
+ if line.startswith("#"): continue
+ line = line.strip()
+ if not line: continue
+ tokens = line.split()
+ states += tokens
+ return states
+
+def emit(f, text):
+ """write string to file"""
+ print(text, file=f)
+
+FULL_PROLOG="""\
+void %(device)s_device::%(opcode)s_full()
+{
+"""
+
+FULL_EPILOG="""\
+}
+"""
+
+FULL_EAT_ALL="""\
+\ticount=0; inst_substate = %(substate)s; return;
+"""
+
+FULL_MEMORY="""\
+\tif(icount == 0) { inst_substate = %(substate)s; return; }
+%(ins)s
+\ticount--;
+"""
+
+FULL_NONE="""\
+%(ins)s
+"""
+
+PARTIAL_PROLOG="""\
+void %(device)s_device::%(opcode)s_partial()
+{
+switch(inst_substate) {
+case 0:
+"""
+
+PARTIAL_EPILOG="""\
+}
+\tinst_substate = 0;
+}
+
+"""
+
+PARTIAL_EAT_ALL="""\
+\ticount=0; inst_substate = %(substate)s; return;
+case %(substate)s:;
+"""
+
+PARTIAL_MEMORY="""\
+\tif(icount == 0) { inst_substate = %(substate)s; return; }
+case %(substate)s:
+%(ins)s
+\ticount--;
+"""
+
+PARTIAL_NONE="""\
+%(ins)s
+"""
+def identify_line_type(ins):
+ if "eat-all-cycles" in ins: return "EAT"
+ for s in ["read", "write", "prefetch(", "prefetch_noirq("]:
+ if s in ins:
+ return "MEMORY"
+ return "NONE"
+
+
+def save_opcodes(f, device, opcodes):
+ for name, instructions in opcodes:
+ d = { "device": device,
+ "opcode": name,
+ }
+
+ emit(f, FULL_PROLOG % d)
+ substate = 1
+ for ins in instructions:
+ d["substate"] = str(substate)
+ d["ins"] = ins
+ line_type = identify_line_type(ins)
+ if line_type == "EAT":
+ emit(f, FULL_EAT_ALL % d)
+ substate += 1
+ elif line_type == "MEMORY":
+ emit(f, FULL_MEMORY % d)
+ substate += 1
+ else:
+ emit(f, FULL_NONE %d)
+ emit(f, FULL_EPILOG % d)
+
+ emit(f, PARTIAL_PROLOG % d)
+ substate = 1
+ for ins in instructions:
+ d["substate"] = str(substate)
+ d["ins"] = ins
+ line_type = identify_line_type(ins)
+ if line_type == "EAT":
+ emit(f, PARTIAL_EAT_ALL % d)
+ substate += 1
+ elif line_type == "MEMORY":
+ emit(f, PARTIAL_MEMORY % d)
+ substate += 1
+ else:
+ emit(f, PARTIAL_NONE %d)
+ emit(f, PARTIAL_EPILOG % d)
+
+
+DO_EXEC_FULL_PROLOG="""\
+void %(device)s_device::do_exec_full()
+{
+\tswitch(inst_state) {
+"""
+
+DO_EXEC_FULL_EPILOG="""\
+\t}
+}
+"""
+
+DO_EXEC_PARTIAL_PROLOG="""\
+void %(device)s_device::do_exec_partial()
+{
+\tswitch(inst_state) {
+"""
+
+DO_EXEC_PARTIAL_EPILOG="""\
+\t}
+}
+"""
+
+DISASM_PROLOG="""\
+const %(device)s_disassembler::disasm_entry %(device)s_disassembler::disasm_entries[0x%(disasm_count)x] = {
+"""
+
+DISASM_EPILOG="""\
+};
+"""
+
+def save_tables(f, device, states):
+ total_states = len(states)
+
+ d = { "device": device,
+ "disasm_count": total_states-1
+ }
+
+ emit(f, DO_EXEC_FULL_PROLOG % d)
+ for n, state in enumerate(states):
+ if state == ".": continue
+ if n < total_states - 1:
+ emit(f, "\tcase 0x%02x: %s_full(); break;" % (n, state))
+ else:
+ emit(f, "\tcase %s: %s_full(); break;" % ("STATE_RESET", state))
+ emit(f, DO_EXEC_FULL_EPILOG % d)
+
+ emit(f, DO_EXEC_PARTIAL_PROLOG % d)
+ for n, state in enumerate(states):
+ if state == ".": continue
+ if n < total_states - 1:
+ emit(f, "\tcase 0x%02x: %s_partial(); break;" % (n, state))
+ else:
+ emit(f, "\tcase %s: %s_partial(); break;" % ("STATE_RESET", state))
+ emit(f, DO_EXEC_PARTIAL_EPILOG % d)
+
+def save_dasm(f, device, states):
+ total_states = len(states)
+
+ d = { "device": device,
+ "disasm_count": total_states-1
+ }
+
+ emit(f, DISASM_PROLOG % d )
+ for n, state in enumerate(states):
+ if state == ".": continue
+ if n == total_states - 1: break
+ tokens = state.split("_")
+ opc = tokens[0]
+ mode = tokens[-1]
+ extra = "0"
+ if opc in ["jsr", "bsr", "callf"]:
+ extra = "STEP_OVER"
+ elif opc in ["rts", "rti", "rtn", "retf"]:
+ extra = "STEP_OUT"
+ emit(f, '\t{ "%s", DASM_%s, %s },' % (opc, mode, extra))
+ emit(f, DISASM_EPILOG % d)
+
+def saves(fname, device, opcodes, states):
+ logging.info("saving: %s", fname)
+ try:
+ f = open(fname, "w")
+ except Exception:
+ err = sys.exc_info()[1]
+ logging.error("cannot write file %s [%s]", fname, err)
+ sys.exit(1)
+ save_opcodes(f, device, opcodes)
+ emit(f, "\n")
+ save_tables(f, device, states)
+ f.close()
+
+
+def saved(fname, device, opcodes, states):
+ logging.info("saving: %s", fname)
+ try:
+ f = open(fname, "w")
+ except Exception:
+ err = sys.exc_info()[1]
+ logging.error("cannot write file %s [%s]", fname, err)
+ sys.exit(1)
+ save_dasm(f, device, states)
+ f.close()
+
+
+def main(argv):
+ debug = False
+ logformat=("%(levelname)s:"
+ "%(module)s:"
+ "%(lineno)d:"
+ "%(threadName)s:"
+ "%(message)s")
+ if debug:
+ logging.basicConfig(level=logging.INFO, format=logformat)
+ else:
+ logging.basicConfig(level=logging.WARNING, format=logformat)
+
+
+ if len(argv) != 6:
+ print(USAGE % argv[0])
+ return 1
+
+ mode = argv[1]
+ device_name = argv[2]
+
+ opcodes = []
+ if argv[3] != "-":
+ opcodes = load_opcodes(argv[3])
+ logging.info("found %d opcodes", len(opcodes))
+ else:
+ logging.info("skipping opcode reading")
+
+
+ states = load_disp(argv[4])
+ logging.info("loaded %s states", len(states))
+
+ assert (len(states) & 0xff) == 1
+ if mode == 's':
+ saves(argv[5], device_name, opcodes, states)
+ else:
+ saved(argv[5], device_name, opcodes, states)
+
+
+# ======================================================================
+if __name__ == "__main__":
+ sys.exit(main(sys.argv))
+
--- /dev/null
+// license:BSD-3-Clause
+// copyright-holders:Olivier Galibert
+/***************************************************************************
+
+ m65c02.c
+
+ MOS Technology 6502, CMOS variant with some additional instructions
+ (but not the bitwise ones)
+
+***************************************************************************/
+
+#include "emu.h"
+#include "m65c02.h"
+#include "m65c02d.h"
+
+DEFINE_DEVICE_TYPE(M65C02, m65c02_device, "m65c02", "MOS Technology M65C02")
+
+m65c02_device::m65c02_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+ m6502_device(mconfig, M65C02, tag, owner, clock)
+{
+}
+
+m65c02_device::m65c02_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock) :
+ m6502_device(mconfig, type, tag, owner, clock)
+{
+}
+
+std::unique_ptr<util::disasm_interface> m65c02_device::create_disassembler()
+{
+ return std::make_unique<m65c02_disassembler>();
+}
+
+#include "cpu/m6502/m65c02.hxx"
--- /dev/null
+// license:BSD-3-Clause
+// copyright-holders:Olivier Galibert
+/***************************************************************************
+
+ m65c02.h
+
+ MOS Technology 6502, CMOS variant with some additional instructions
+ (but not the bitwise ones)
+
+***************************************************************************/
+#ifndef MAME_CPU_M6502_M65C02_H
+#define MAME_CPU_M6502_M65C02_H
+
+#pragma once
+
+#include "m6502.h"
+
+class m65c02_device : public m6502_device {
+public:
+ m65c02_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+ virtual std::unique_ptr<util::disasm_interface> create_disassembler() override;
+ virtual void do_exec_full() override;
+ virtual void do_exec_partial() override;
+
+protected:
+ m65c02_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
+
+#define O(o) void o ## _full(); void o ## _partial()
+
+ // 65c02 opcodes
+ O(adc_c_aba); O(adc_c_abx); O(adc_c_aby); O(adc_c_idx); O(adc_c_idy); O(adc_c_imm); O(adc_c_zpg); O(adc_c_zpi); O(adc_c_zpx);
+ O(and_zpi);
+ O(asl_c_abx);
+ O(bbr_zpb);
+ O(bbs_zpb);
+ O(bit_abx); O(bit_imm); O(bit_zpx);
+ O(bra_rel);
+ O(brk_c_imp);
+ O(cmp_zpi);
+ O(dec_acc);
+ O(eor_zpi);
+ O(inc_acc);
+ O(jmp_c_ind); O(jmp_iax);
+ O(lda_zpi);
+ O(lsr_c_abx);
+ O(nop_c_aba); O(nop_c_abx); O(nop_c_imp);
+ O(ora_zpi);
+ O(phx_imp);
+ O(phy_imp);
+ O(plx_imp);
+ O(ply_imp);
+ O(rmb_bzp);
+ O(rol_c_abx);
+ O(ror_c_abx);
+ O(sbc_c_aba); O(sbc_c_abx); O(sbc_c_aby); O(sbc_c_idx); O(sbc_c_idy); O(sbc_c_imm); O(sbc_c_zpg); O(sbc_c_zpi); O(sbc_c_zpx);
+ O(smb_bzp);
+ O(stp_imp);
+ O(sta_zpi);
+ O(stz_aba); O(stz_abx); O(stz_zpg); O(stz_zpx);
+ O(trb_aba); O(trb_zpg);
+ O(tsb_aba); O(tsb_zpg);
+ O(wai_imp);
+
+#undef O
+};
+
+enum {
+ M65C02_IRQ_LINE = m6502_device::IRQ_LINE,
+ M65C02_NMI_LINE = m6502_device::NMI_LINE,
+ M65C02_SET_OVERFLOW = m6502_device::V_LINE
+};
+
+DECLARE_DEVICE_TYPE(M65C02, m65c02_device)
+
+#endif // MAME_CPU_M6502_M65C02_H
--- /dev/null
+// license:BSD-3-Clause
+// copyright-holders:Olivier Galibert
+/***************************************************************************
+
+ m65c02d.cpp
+
+ MOS Technology 6502, CMOS variant with some additional instructions
+ (but not the bitwise ones), disassembler
+
+***************************************************************************/
+
+#include "emu.h"
+#include "m65c02d.h"
+#include "cpu/m6502/m65c02d.hxx"
+
+m65c02_disassembler::m65c02_disassembler() : m6502_base_disassembler(disasm_entries)
+{
+}
--- /dev/null
+// license:BSD-3-Clause
+// copyright-holders:Olivier Galibert
+/***************************************************************************
+
+ m65c02d.h
+
+ MOS Technology 6502, CMOS variant with some additional instructions
+ (but not the bitwise ones), disassembler
+
+***************************************************************************/
+
+#ifndef MAME_CPU_M6502_M65C02D_H
+#define MAME_CPU_M6502_M65C02D_H
+
+#pragma once
+
+#include "m6502d.h"
+
+class m65c02_disassembler : public m6502_base_disassembler
+{
+public:
+ m65c02_disassembler();
+ virtual ~m65c02_disassembler() = default;
+
+private:
+ static const disasm_entry disasm_entries[0x100];
+};
+
+#endif
--- /dev/null
+# license:BSD-3-Clause
+# copyright-holders:Olivier Galibert
+# NMOS 6502 opcodes
+# Verified with visual6502
+# documented opcodes
+
+adc_aba
+ TMP = read_pc();
+ TMP = set_h(TMP, read_pc());
+ TMP = read(TMP);
+ do_adc(TMP);
+ prefetch();
+
+adc_abx
+ TMP = read_pc();
+ TMP = set_h(TMP, read_pc());
+ if(page_changing(TMP, X)) {
+ read(set_l(TMP, TMP+X));
+ }
+ TMP += X;
+ TMP = read(TMP);
+ do_adc(TMP);
+ prefetch();
+
+adc_aby
+ TMP = read_pc();
+ TMP = set_h(TMP, read_pc());
+ if(page_changing(TMP, Y)) {
+ read(set_l(TMP, TMP+Y));
+ }
+ TMP += Y;
+ TMP = read(TMP);
+ do_adc(TMP);
+ prefetch();
+
+adc_idx
+ TMP2 = read_pc();
+ read(TMP2);
+ TMP2 += X;
+ TMP = read(TMP2 & 0xff);
+ TMP = set_h(TMP, read((TMP2+1) & 0xff));
+ do_adc(read(TMP));
+ prefetch();
+
+adc_idy
+ TMP2 = read_pc();
+ TMP = read(TMP2);
+ TMP = set_h(TMP, read((TMP2+1) & 0xff));
+ if(page_changing(TMP, Y)) {
+ read(set_l(TMP, TMP+Y));
+ }
+ do_adc(read(TMP+Y));
+ prefetch();
+
+adc_imm
+ TMP = read_pc();
+ do_adc(TMP);
+ prefetch();
+
+adc_zpg
+ TMP = read_pc();
+ TMP = read(TMP);
+ do_adc(TMP);
+ prefetch();
+
+adc_zpx
+ TMP = read_pc();
+ read(TMP);
+ TMP = read(uint8_t(TMP+X));
+ do_adc(TMP);
+ prefetch();
+
+and_aba
+ TMP = read_pc();
+ TMP = set_h(TMP, read_pc());
+ A &= read(TMP);
+ set_nz(A);
+ prefetch();
+
+and_abx
+ TMP = read_pc();
+ TMP = set_h(TMP, read_pc());
+ if(page_changing(TMP, X)) {
+ read(set_l(TMP, TMP+X));
+ }
+ TMP += X;
+ A &= read(TMP);
+ set_nz(A);
+ prefetch();
+
+and_aby
+ TMP = read_pc();
+ TMP = set_h(TMP, read_pc());
+ if(page_changing(TMP, Y)) {
+ read(set_l(TMP, TMP+Y));
+ }
+ TMP += Y;
+ A &= read(TMP);
+ set_nz(A);
+ prefetch();
+
+and_imm
+ A &= read_pc();
+ set_nz(A);
+ prefetch();
+
+and_idx
+ TMP2 = read_pc();
+ read(TMP2);
+ TMP2 += X;
+ TMP = read(TMP2 & 0xff);
+ TMP = set_h(TMP, read((TMP2+1) & 0xff));
+ A &= read(TMP);
+ set_nz(A);
+ prefetch();
+
+and_idy
+ TMP2 = read_pc();
+ TMP = read(TMP2);
+ TMP = set_h(TMP, read((TMP2+1) & 0xff));
+ if(page_changing(TMP, Y)) {
+ read(set_l(TMP, TMP+Y));
+ }
+ A &= read(TMP+Y);
+ set_nz(A);
+ prefetch();
+
+and_zpg
+ TMP = read_pc();
+ A &= read(TMP);
+ set_nz(A);
+ prefetch();
+
+and_zpx
+ TMP = read_pc();
+ read(TMP);
+ A &= read(uint8_t(TMP+X));
+ set_nz(A);
+ prefetch();
+
+asl_aba
+ TMP = read_pc();
+ TMP = set_h(TMP, read_pc());
+ TMP2 = read(TMP);
+ write(TMP, TMP2);
+ TMP2 = do_asl(TMP2);
+ write(TMP, TMP2);
+ prefetch();
+
+asl_abx
+ TMP = read_pc();
+ TMP = set_h(TMP, read_pc());
+ read(set_l(TMP, TMP+X));
+ TMP += X;
+ TMP2 = read(TMP);
+ write(TMP, TMP2);
+ TMP2 = do_asl(TMP2);
+ write(TMP, TMP2);
+ prefetch();
+
+asl_acc
+ read_pc_noinc();
+ A = do_asl(A);
+ prefetch();
+
+asl_zpg
+ TMP = read_pc();
+ TMP2 = read(TMP);
+ write(TMP, TMP2);
+ TMP2 = do_asl(TMP2);
+ write(TMP, TMP2);
+ prefetch();
+
+asl_zpx
+ TMP = read_pc();
+ read(TMP);
+ TMP = uint8_t(TMP+X);
+ TMP2 = read(TMP);
+ write(TMP, TMP2);
+ TMP2 = do_asl(TMP2);
+ write(TMP, TMP2);
+ prefetch();
+
+bcc_rel
+ TMP = read_pc();
+ if(!(P & F_C)) {
+ read_pc_noinc();
+ if(page_changing(PC, int8_t(TMP))) {
+ read_arg(set_l(PC, PC+int8_t(TMP)));
+ }
+ PC += int8_t(TMP);
+ }
+ prefetch();
+
+bcs_rel
+ TMP = read_pc();
+ if(P & F_C) {
+ read_pc_noinc();
+ if(page_changing(PC, int8_t(TMP))) {
+ read_arg(set_l(PC, PC+int8_t(TMP)));
+ }
+ PC += int8_t(TMP);
+ }
+ prefetch();
+
+beq_rel
+ TMP = read_pc();
+ if(P & F_Z) {
+ read_pc_noinc();
+ if(page_changing(PC, int8_t(TMP))) {
+ read_arg(set_l(PC, PC+int8_t(TMP)));
+ }
+ PC += int8_t(TMP);
+ }
+ prefetch();
+
+bit_aba
+ TMP = read_pc();
+ TMP = set_h(TMP, read_pc());
+ do_bit(read(TMP));
+ prefetch();
+
+bit_zpg
+ TMP = read_pc();
+ do_bit(read(TMP));
+ prefetch();
+
+bmi_rel
+ TMP = read_pc();
+ if(P & F_N) {
+ read_pc_noinc();
+ if(page_changing(PC, int8_t(TMP))) {
+ read_arg(set_l(PC, PC+int8_t(TMP)));
+ }
+ PC += int8_t(TMP);
+ }
+ prefetch();
+
+bne_rel
+ TMP = read_pc();
+ if(!(P & F_Z)) {
+ read_pc_noinc();
+ if(page_changing(PC, int8_t(TMP))) {
+ read_arg(set_l(PC, PC+int8_t(TMP)));
+ }
+ PC += int8_t(TMP);
+ }
+ prefetch();
+
+bpl_rel
+ TMP = read_pc();
+ if(!(P & F_N)) {
+ read_pc_noinc();
+ if(page_changing(PC, int8_t(TMP))) {
+ read_arg(set_l(PC, PC+int8_t(TMP)));
+ }
+ PC += int8_t(TMP);
+ }
+ prefetch();
+
+brk_imp
+ // The 6502 bug when a nmi occurs in a brk is reproduced (case !irq_taken && nmi_state)
+ if(irq_taken) {
+ read_pc_noinc();
+ } else {
+ read_pc();
+ }
+ write(SP, PC >> 8);
+ dec_SP();
+ write(SP, PC);
+ dec_SP();
+ write(SP, irq_taken ? P & ~F_B : P);
+ dec_SP();
+ if(nmi_state) {
+ PC = read_arg(0xfffa);
+ PC = set_h(PC, read_arg(0xfffb));
+ nmi_state = false;
+ standard_irq_callback(NMI_LINE);
+ } else {
+ PC = read_arg(0xfffe);
+ PC = set_h(PC, read_arg(0xffff));
+ if(irq_taken)
+ standard_irq_callback(IRQ_LINE);
+ }
+ irq_taken = false;
+ P |= F_I; // Do *not* move after the prefetch
+ prefetch();
+ inst_state = -1;
+
+bvc_rel
+ TMP = read_pc();
+ if(!(P & F_V)) {
+ read_pc_noinc();
+ if(page_changing(PC, int8_t(TMP))) {
+ read_arg(set_l(PC, PC+int8_t(TMP)));
+ }
+ PC += int8_t(TMP);
+ }
+ prefetch();
+
+bvs_rel
+ TMP = read_pc();
+ if(P & F_V) {
+ read_pc_noinc();
+ if(page_changing(PC, int8_t(TMP))) {
+ read_arg(set_l(PC, PC+int8_t(TMP)));
+ }
+ PC += int8_t(TMP);
+ }
+ prefetch();
+
+clc_imp
+ read_pc_noinc();
+ P &= ~F_C;
+ prefetch();
+
+cld_imp
+ read_pc_noinc();
+ P &= ~F_D;
+ prefetch();
+
+cli_imp
+ read_pc_noinc();
+ prefetch();
+ P &= ~F_I; // Do *not* move it before the prefetch
+
+clv_imp
+ read_pc_noinc();
+ P &= ~F_V;
+ prefetch();
+
+cmp_aba
+ TMP = read_pc();
+ TMP = set_h(TMP, read_pc());
+ TMP = read(TMP);
+ do_cmp(A, TMP);
+ prefetch();
+
+cmp_abx
+ TMP = read_pc();
+ TMP = set_h(TMP, read_pc());
+ if(page_changing(TMP, X)) {
+ read(set_l(TMP, TMP+X));
+ }
+ TMP += X;
+ TMP = read(TMP);
+ do_cmp(A, TMP);
+ prefetch();
+
+cmp_aby
+ TMP = read_pc();
+ TMP = set_h(TMP, read_pc());
+ if(page_changing(TMP, Y)) {
+ read(set_l(TMP, TMP+Y));
+ }
+ TMP += Y;
+ TMP = read(TMP);
+ do_cmp(A, TMP);
+ prefetch();
+
+cmp_idx
+ TMP2 = read_pc();
+ read(TMP2);
+ TMP2 += X;
+ TMP = read(TMP2 & 0xff);
+ TMP = set_h(TMP, read((TMP2+1) & 0xff));
+ do_cmp(A, read(TMP));
+ prefetch();
+
+cmp_idy
+ TMP2 = read_pc();
+ TMP = read(TMP2);
+ TMP = set_h(TMP, read((TMP2+1) & 0xff));
+ if(page_changing(TMP, Y)) {
+ read(set_l(TMP, TMP+Y));
+ }
+ do_cmp(A, read(TMP+Y));
+ prefetch();
+
+cmp_imm
+ TMP = read_pc();
+ do_cmp(A, TMP);
+ prefetch();
+
+cmp_zpg
+ TMP = read_pc();
+ TMP = read(TMP);
+ do_cmp(A, TMP);
+ prefetch();
+
+cmp_zpx
+ TMP = read_pc();
+ read(TMP);
+ TMP = read(uint8_t(TMP+X));
+ do_cmp(A, TMP);
+ prefetch();
+
+cpx_aba
+ TMP = read_pc();
+ TMP = set_h(TMP, read_pc());
+ TMP = read(TMP);
+ do_cmp(X, TMP);
+ prefetch();
+
+cpx_imm
+ TMP = read_pc();
+ do_cmp(X, TMP);
+ prefetch();
+
+cpx_zpg
+ TMP = read_pc();
+ TMP = read(TMP);
+ do_cmp(X, TMP);
+ prefetch();
+
+cpy_aba
+ TMP = read_pc();
+ TMP = set_h(TMP, read_pc());
+ TMP = read(TMP);
+ do_cmp(Y, TMP);
+ prefetch();
+
+cpy_imm
+ TMP = read_pc();
+ do_cmp(Y, TMP);
+ prefetch();
+
+cpy_zpg
+ TMP = read_pc();
+ TMP = read(TMP);
+ do_cmp(Y, TMP);
+ prefetch();
+
+dec_aba
+ TMP = read_pc();
+ TMP = set_h(TMP, read_pc());
+ TMP2 = read(TMP);
+ write(TMP, TMP2);
+ TMP2--;
+ set_nz(TMP2);
+ write(TMP, TMP2);
+ prefetch();
+
+dec_abx
+ TMP = read_pc();
+ TMP = set_h(TMP, read_pc());
+ read(set_l(TMP, TMP+X));
+ TMP += X;
+ TMP2 = read(TMP);
+ write(TMP, TMP2);
+ TMP2--;
+ set_nz(TMP2);
+ write(TMP, TMP2);
+ prefetch();
+
+dec_zpg
+ TMP = read_pc();
+ TMP2 = read(TMP);
+ write(TMP, TMP2);
+ TMP2--;
+ set_nz(TMP2);
+ write(TMP, TMP2);
+ prefetch();
+
+dec_zpx
+ TMP = read_pc();
+ read(TMP);
+ TMP = uint8_t(TMP+X);
+ TMP2 = read(TMP);
+ write(TMP, TMP2);
+ TMP2--;
+ set_nz(TMP2);
+ write(TMP, TMP2);
+ prefetch();
+
+dex_imp
+ read_pc_noinc();
+ X--;
+ set_nz(X);
+ prefetch();
+
+dey_imp
+ read_pc_noinc();
+ Y--;
+ set_nz(Y);
+ prefetch();
+
+eor_aba
+ TMP = read_pc();
+ TMP = set_h(TMP, read_pc());
+ A ^= read(TMP);
+ set_nz(A);
+ prefetch();
+
+eor_abx
+ TMP = read_pc();
+ TMP = set_h(TMP, read_pc());
+ if(page_changing(TMP, X)) {
+ read(set_l(TMP, TMP+X));
+ }
+ TMP += X;
+ A ^= read(TMP);
+ set_nz(A);
+ prefetch();
+
+eor_aby
+ TMP = read_pc();
+ TMP = set_h(TMP, read_pc());
+ if(page_changing(TMP, Y)) {
+ read(set_l(TMP, TMP+Y));
+ }
+ TMP += Y;
+ A ^= read(TMP);
+ set_nz(A);
+ prefetch();
+
+eor_idx
+ TMP2 = read_pc();
+ read(TMP2);
+ TMP2 += X;
+ TMP = read(TMP2 & 0xff);
+ TMP = set_h(TMP, read((TMP2+1) & 0xff));
+ A ^= read(TMP);
+ set_nz(A);
+ prefetch();
+
+eor_idy
+ TMP2 = read_pc();
+ TMP = read(TMP2);
+ TMP = set_h(TMP, read((TMP2+1) & 0xff));
+ if(page_changing(TMP, Y)) {
+ read(set_l(TMP, TMP+Y));
+ }
+ A ^= read(TMP+Y);
+ set_nz(A);
+ prefetch();
+
+eor_imm
+ A ^= read_pc();
+ set_nz(A);
+ prefetch();
+
+eor_zpg
+ TMP = read_pc();
+ A ^= read(TMP);
+ set_nz(A);
+ prefetch();
+
+eor_zpx
+ TMP = read_pc();
+ read(TMP);
+ A ^= read(uint8_t(TMP+X));
+ set_nz(A);
+ prefetch();
+
+inc_aba
+ TMP = read_pc();
+ TMP = set_h(TMP, read_pc());
+ TMP2 = read(TMP);
+ write(TMP, TMP2);
+ TMP2++;
+ set_nz(TMP2);
+ write(TMP, TMP2);
+ prefetch();
+
+inc_abx
+ TMP = read_pc();
+ TMP = set_h(TMP, read_pc());
+ read(set_l(TMP, TMP+X));
+ TMP += X;
+ TMP2 = read(TMP);
+ write(TMP, TMP2);
+ TMP2++;
+ set_nz(TMP2);
+ write(TMP, TMP2);
+ prefetch();
+
+inc_zpg
+ TMP = read_pc();
+ TMP2 = read(TMP);
+ write(TMP, TMP2);
+ TMP2++;
+ set_nz(TMP2);
+ write(TMP, TMP2);
+ prefetch();
+
+inc_zpx
+ TMP = read_pc();
+ read(TMP);
+ TMP = uint8_t(TMP+X);
+ TMP2 = read(TMP);
+ write(TMP, TMP2);
+ TMP2++;
+ set_nz(TMP2);
+ write(TMP, TMP2);
+ prefetch();
+
+inx_imp
+ read_pc_noinc();
+ X++;
+ set_nz(X);
+ prefetch();
+
+iny_imp
+ read_pc_noinc();
+ Y++;
+ set_nz(Y);
+ prefetch();
+
+jmp_adr
+ TMP = read_pc();
+ TMP = set_h(TMP, read_pc());
+ PC = TMP;
+ prefetch();
+
+jmp_ind
+ TMP = read_pc();
+ TMP = set_h(TMP, read_pc());
+ PC = read(TMP);
+ PC = set_h(PC, read(set_l(TMP, TMP+1)));
+ prefetch();
+
+jsr_adr
+ TMP = read_pc();
+ read(SP);
+ write(SP, PC>>8);
+ dec_SP();
+ write(SP, PC);
+ dec_SP();
+ TMP = set_h(TMP, read_pc());
+ PC = TMP;
+ prefetch();
+
+lda_aba
+ TMP = read_pc();
+ TMP = set_h(TMP, read_pc());
+ A = read(TMP);
+ set_nz(A);
+ prefetch();
+
+lda_abx
+ TMP = read_pc();
+ TMP = set_h(TMP, read_pc());
+ if(page_changing(TMP, X)) {
+ read(set_l(TMP, TMP+X));
+ }
+ A = read(TMP + X);
+ set_nz(A);
+ prefetch();
+
+lda_aby
+ TMP = read_pc();
+ TMP = set_h(TMP, read_pc());
+ if(page_changing(TMP, Y)) {
+ read(set_l(TMP, TMP+Y));
+ }
+ A = read(TMP + Y);
+ set_nz(A);
+ prefetch();
+
+lda_idx
+ TMP2 = read_pc();
+ read(TMP2);
+ TMP2 += X;
+ TMP = read(TMP2 & 0xff);
+ TMP = set_h(TMP, read((TMP2+1) & 0xff));
+ A = read(TMP);
+ set_nz(A);
+ prefetch();
+
+lda_idy
+ TMP2 = read_pc();
+ TMP = read(TMP2);
+ TMP = set_h(TMP, read((TMP2+1) & 0xff));
+ if(page_changing(TMP, Y)) {
+ read(set_l(TMP, TMP+Y));
+ }
+ A = read(TMP+Y);
+ set_nz(A);
+ prefetch();
+
+lda_imm
+ A = read_pc();
+ set_nz(A);
+ prefetch();
+
+lda_zpg
+ TMP = read_pc();
+ A = read(TMP);
+ set_nz(A);
+ prefetch();
+
+lda_zpx
+ TMP = read_pc();
+ read(TMP);
+ A = read(uint8_t(TMP+X));
+ set_nz(A);
+ prefetch();
+
+ldx_aba
+ TMP = read_pc();
+ TMP = set_h(TMP, read_pc());
+ X = read(TMP);
+ set_nz(X);
+ prefetch();
+
+ldx_aby
+ TMP = read_pc();
+ TMP = set_h(TMP, read_pc());
+ if(page_changing(TMP, Y)) {
+ read(set_l(TMP, TMP+Y));
+ }
+ X = read(TMP + Y);
+ set_nz(X);
+ prefetch();
+
+ldx_imm
+ X = read_pc();
+ set_nz(X);
+ prefetch();
+
+ldx_zpg
+ TMP = read_pc();
+ X = read(TMP);
+ set_nz(X);
+ prefetch();
+
+ldx_zpy
+ TMP = read_pc();
+ read(TMP);
+ X = read(uint8_t(TMP+Y));
+ set_nz(X);
+ prefetch();
+
+ldy_aba
+ TMP = read_pc();
+ TMP = set_h(TMP, read_pc());
+ Y = read(TMP);
+ set_nz(Y);
+ prefetch();
+
+ldy_abx
+ TMP = read_pc();
+ TMP = set_h(TMP, read_pc());
+ if(page_changing(TMP, X)) {
+ read(set_l(TMP, TMP+X));
+ }
+ TMP += X;
+ Y = read(TMP);
+ set_nz(Y);
+ prefetch();
+
+ldy_imm
+ Y = read_pc();
+ set_nz(Y);
+ prefetch();
+
+ldy_zpg
+ TMP = read_pc();
+ Y = read(TMP);
+ set_nz(Y);
+ prefetch();
+
+ldy_zpx
+ TMP = read_pc();
+ read(TMP);
+ Y = read(uint8_t(TMP+X));
+ set_nz(Y);
+ prefetch();
+
+lsr_aba
+ TMP = read_pc();
+ TMP = set_h(TMP, read_pc());
+ TMP2 = read(TMP);
+ write(TMP, TMP2);
+ TMP2 = do_lsr(TMP2);
+ write(TMP, TMP2);
+ prefetch();
+
+lsr_abx
+ TMP = read_pc();
+ TMP = set_h(TMP, read_pc());
+ read(set_l(TMP, TMP+X));
+ TMP += X;
+ TMP2 = read(TMP);
+ write(TMP, TMP2);
+ TMP2 = do_lsr(TMP2);
+ write(TMP, TMP2);
+ prefetch();
+
+lsr_acc
+ read_pc_noinc();
+ A = do_lsr(A);
+ prefetch();
+
+lsr_zpg
+ TMP = read_pc();
+ TMP2 = read(TMP);
+ write(TMP, TMP2);
+ TMP2 = do_lsr(TMP2);
+ write(TMP, TMP2);
+ prefetch();
+
+lsr_zpx
+ TMP = read_pc();
+ read(TMP);
+ TMP = uint8_t(TMP+X);
+ TMP2 = read(TMP);
+ write(TMP, TMP2);
+ TMP2 = do_lsr(TMP2);
+ write(TMP, TMP2);
+ prefetch();
+
+nop_imp
+ read_pc_noinc();
+ prefetch();
+
+ora_aba
+ TMP = read_pc();
+ TMP = set_h(TMP, read_pc());
+ A |= read(TMP);
+ set_nz(A);
+ prefetch();
+
+ora_abx
+ TMP = read_pc();
+ TMP = set_h(TMP, read_pc());
+ if(page_changing(TMP, X)) {
+ read(set_l(TMP, TMP+X));
+ }
+ TMP += X;
+ A |= read(TMP);
+ set_nz(A);
+ prefetch();
+
+ora_aby
+ TMP = read_pc();
+ TMP = set_h(TMP, read_pc());
+ if(page_changing(TMP, Y)) {
+ read(set_l(TMP, TMP+Y));
+ }
+ TMP += Y;
+ A |= read(TMP);
+ set_nz(A);
+ prefetch();
+
+ora_imm
+ A |= read_pc();
+ set_nz(A);
+ prefetch();
+
+ora_idx
+ TMP2 = read_pc();
+ read(TMP2);
+ TMP2 += X;
+ TMP = read(TMP2 & 0xff);
+ TMP = set_h(TMP, read((TMP2+1) & 0xff));
+ A |= read(TMP);
+ set_nz(A);
+ prefetch();
+
+ora_idy
+ TMP2 = read_pc();
+ TMP = read(TMP2);
+ TMP = set_h(TMP, read((TMP2+1) & 0xff));
+ if(page_changing(TMP, Y)) {
+ read(set_l(TMP, TMP+Y));
+ }
+ A |= read(TMP+Y);
+ set_nz(A);
+ prefetch();
+
+ora_zpg
+ TMP = read_pc();
+ A |= read(TMP);
+ set_nz(A);
+ prefetch();
+
+ora_zpx
+ TMP = read_pc();
+ read(TMP);
+ A |= read(uint8_t(TMP+X));
+ set_nz(A);
+ prefetch();
+
+pha_imp
+ read_pc_noinc();
+ write(SP, A);
+ dec_SP();
+ prefetch();
+
+php_imp
+ read_pc_noinc();
+ write(SP, P);
+ dec_SP();
+ prefetch();
+
+pla_imp
+ read_pc_noinc();
+ read(SP);
+ inc_SP();
+ A = read(SP);
+ set_nz(A);
+ prefetch();
+
+plp_imp
+ read_pc_noinc();
+ read(SP);
+ inc_SP();
+ TMP = read(SP) | (F_B|F_E);
+ prefetch();
+ P = TMP; // Do *not* move it before the prefetch
+
+rol_aba
+ TMP = read_pc();
+ TMP = set_h(TMP, read_pc());
+ TMP2 = read(TMP);
+ write(TMP, TMP2);
+ TMP2 = do_rol(TMP2);
+ write(TMP, TMP2);
+ prefetch();
+
+rol_abx
+ TMP = read_pc();
+ TMP = set_h(TMP, read_pc());
+ read(set_l(TMP, TMP+X));
+ TMP += X;
+ TMP2 = read(TMP);
+ write(TMP, TMP2);
+ TMP2 = do_rol(TMP2);
+ write(TMP, TMP2);
+ prefetch();
+
+rol_acc
+ read_pc_noinc();
+ A = do_rol(A);
+ prefetch();
+
+rol_zpg
+ TMP = read_pc();
+ TMP2 = read(TMP);
+ write(TMP, TMP2);
+ TMP2 = do_rol(TMP2);
+ write(TMP, TMP2);
+ prefetch();
+
+rol_zpx
+ TMP = read_pc();
+ read(TMP);
+ TMP = uint8_t(TMP+X);
+ TMP2 = read(TMP);
+ write(TMP, TMP2);
+ TMP2 = do_rol(TMP2);
+ write(TMP, TMP2);
+ prefetch();
+
+ror_aba
+ TMP = read_pc();
+ TMP = set_h(TMP, read_pc());
+ TMP2 = read(TMP);
+ write(TMP, TMP2);
+ TMP2 = do_ror(TMP2);
+ write(TMP, TMP2);
+ prefetch();
+
+ror_abx
+ TMP = read_pc();
+ TMP = set_h(TMP, read_pc());
+ read(set_l(TMP, TMP+X));
+ TMP += X;
+ TMP2 = read(TMP);
+ write(TMP, TMP2);
+ TMP2 = do_ror(TMP2);
+ write(TMP, TMP2);
+ prefetch();
+
+ror_acc
+ read_pc_noinc();
+ A = do_ror(A);
+ prefetch();
+
+ror_zpg
+ TMP = read_pc();
+ TMP2 = read(TMP);
+ write(TMP, TMP2);
+ TMP2 = do_ror(TMP2);
+ write(TMP, TMP2);
+ prefetch();
+
+ror_zpx
+ TMP = read_pc();
+ read(TMP);
+ TMP = uint8_t(TMP+X);
+ TMP2 = read(TMP);
+ write(TMP, TMP2);
+ TMP2 = do_ror(TMP2);
+ write(TMP, TMP2);
+ prefetch();
+
+rti_imp
+ read_pc_noinc();
+ read(SP);
+ inc_SP();
+ P = read(SP) | (F_B|F_E);
+ inc_SP();
+ PC = read(SP);
+ inc_SP();
+ PC = set_h(PC, read(SP));
+ prefetch();
+
+rts_imp
+ read_pc_noinc();
+ read(SP);
+ inc_SP();
+ PC = read(SP);
+ inc_SP();
+ PC = set_h(PC, read(SP));
+ read_pc();
+ prefetch();
+
+sbc_aba
+ TMP = read_pc();
+ TMP = set_h(TMP, read_pc());
+ TMP = read(TMP);
+ do_sbc(TMP);
+ prefetch();
+
+sbc_abx
+ TMP = read_pc();
+ TMP = set_h(TMP, read_pc());
+ if(page_changing(TMP, X)) {
+ read(set_l(TMP, TMP+X));
+ }
+ TMP += X;
+ TMP = read(TMP);
+ do_sbc(TMP);
+ prefetch();
+
+sbc_aby
+ TMP = read_pc();
+ TMP = set_h(TMP, read_pc());
+ if(page_changing(TMP, Y)) {
+ read(set_l(TMP, TMP+Y));
+ }
+ TMP += Y;
+ TMP = read(TMP);
+ do_sbc(TMP);
+ prefetch();
+
+sbc_idx
+ TMP2 = read_pc();
+ read(TMP2);
+ TMP2 += X;
+ TMP = read(TMP2 & 0xff);
+ TMP = set_h(TMP, read((TMP2+1) & 0xff));
+ do_sbc(read(TMP));
+ prefetch();
+
+sbc_idy
+ TMP2 = read_pc();
+ TMP = read(TMP2);
+ TMP = set_h(TMP, read((TMP2+1) & 0xff));
+ if(page_changing(TMP, Y)) {
+ read(set_l(TMP, TMP+Y));
+ }
+ do_sbc(read(TMP+Y));
+ prefetch();
+
+sbc_imm
+ TMP = read_pc();
+ do_sbc(TMP);
+ prefetch();
+
+sbc_zpg
+ TMP = read_pc();
+ TMP = read(TMP);
+ do_sbc(TMP);
+ prefetch();
+
+sbc_zpx
+ TMP = read_pc();
+ read(TMP);
+ TMP = read(uint8_t(TMP+X));
+ do_sbc(TMP);
+ prefetch();
+
+sec_imp
+ read_pc_noinc();
+ P |= F_C;
+ prefetch();
+
+sed_imp
+ read_pc_noinc();
+ P |= F_D;
+ prefetch();
+
+sei_imp
+ read_pc_noinc();
+ prefetch();
+ P |= F_I; // Do *not* move it before the prefetch
+
+sta_aba
+ TMP = read_pc();
+ TMP = set_h(TMP, read_pc());
+ write(TMP, A);
+ prefetch();
+
+sta_abx
+ TMP = read_pc();
+ TMP = set_h(TMP, read_pc());
+ read(set_l(TMP, TMP+X));
+ write(TMP+X, A);
+ prefetch();
+
+sta_aby
+ TMP = read_pc();
+ TMP = set_h(TMP, read_pc());
+ read(set_l(TMP, TMP+Y));
+ write(TMP+Y, A);
+ prefetch();
+
+sta_idx
+ TMP2 = read_pc();
+ read(TMP2);
+ TMP2 += X;
+ TMP = read(TMP2 & 0xff);
+ TMP = set_h(TMP, read((TMP2+1) & 0xff));
+ write(TMP, A);
+ prefetch();
+
+sta_idy
+ TMP2 = read_pc();
+ TMP = read(TMP2);
+ TMP = set_h(TMP, read((TMP2+1) & 0xff));
+ read(set_l(TMP, TMP+Y));
+ write(TMP+Y, A);
+ prefetch();
+
+sta_zpg
+ TMP = read_pc();
+ write(TMP, A);
+ prefetch();
+
+sta_zpx
+ TMP = read_pc();
+ read(TMP);
+ write(uint8_t(TMP+X), A);
+ prefetch();
+
+stx_aba
+ TMP = read_pc();
+ TMP = set_h(TMP, read_pc());
+ write(TMP, X);
+ prefetch();
+
+stx_zpg
+ TMP = read_pc();
+ write(TMP, X);
+ prefetch();
+
+stx_zpy
+ TMP = read_pc();
+ read(TMP);
+ write(uint8_t(TMP+Y), X);
+ prefetch();
+
+sty_aba
+ TMP = read_pc();
+ TMP = set_h(TMP, read_pc());
+ write(TMP, Y);
+ prefetch();
+
+sty_zpg
+ TMP = read_pc();
+ write(TMP, Y);
+ prefetch();
+
+sty_zpx
+ TMP = read_pc();
+ read(TMP);
+ write(uint8_t(TMP+X), Y);
+ prefetch();
+
+tax_imp
+ read_pc_noinc();
+ X = A;
+ set_nz(X);
+ prefetch();
+
+tay_imp
+ read_pc_noinc();
+ Y = A;
+ set_nz(Y);
+ prefetch();
+
+tsx_imp
+ read_pc_noinc();
+ X = SP;
+ set_nz(X);
+ prefetch();
+
+txa_imp
+ read_pc_noinc();
+ A = X;
+ set_nz(A);
+ prefetch();
+
+txs_imp
+ read_pc_noinc();
+ SP = set_l(SP, X);
+ prefetch();
+
+tya_imp
+ read_pc_noinc();
+ A = Y;
+ set_nz(A);
+ prefetch();
+
+# exceptions
+reset
+ PC = read_arg(0xfffc);
+ PC = set_h(PC, read_arg(0xfffd));
+ prefetch();
+ inst_state = -1;
+
+
+# undocumented reliable instructions
+dcp_aba
+ TMP = read_pc();
+ TMP = set_h(TMP, read_pc());
+ TMP2 = read(TMP);
+ write(TMP, TMP2);
+ TMP2--;
+ write(TMP, TMP2);
+ do_cmp(A, TMP2);
+ prefetch();
+
+dcp_abx
+ TMP = read_pc();
+ TMP = set_h(TMP, read_pc());
+ read(set_l(TMP, TMP+X));
+ TMP += X;
+ TMP2 = read(TMP);
+ write(TMP, TMP2);
+ TMP2--;
+ write(TMP, TMP2);
+ do_cmp(A, TMP2);
+ prefetch();
+
+dcp_aby
+ TMP = read_pc();
+ TMP = set_h(TMP, read_pc());
+ read(set_l(TMP, TMP+Y));
+ TMP += Y;
+ TMP2 = read(TMP);
+ write(TMP, TMP2);
+ TMP2--;
+ write(TMP, TMP2);
+ do_cmp(A, TMP2);
+ prefetch();
+
+dcp_idx
+ TMP2 = read_pc();
+ read(TMP2);
+ TMP2 += X;
+ TMP = read(TMP2 & 0xff);
+ TMP = set_h(TMP, read((TMP2+1) & 0xff));
+ TMP2 = read(TMP);
+ write(TMP, TMP2);
+ TMP2--;
+ write(TMP, TMP2);
+ do_cmp(A, TMP2);
+ prefetch();
+
+dcp_idy
+ TMP2 = read_pc();
+ TMP = read(TMP2);
+ TMP = set_h(TMP, read((TMP2+1) & 0xff));
+ read(set_l(TMP, TMP+Y));
+ TMP += Y;
+ TMP2 = read(TMP);
+ write(TMP, TMP2);
+ TMP2--;
+ write(TMP, TMP2);
+ do_cmp(A, TMP2);
+ prefetch();
+
+dcp_zpg
+ TMP = read_pc();
+ TMP2 = read(TMP);
+ write(TMP, TMP2);
+ TMP2--;
+ write(TMP, TMP2);
+ do_cmp(A, TMP2);
+ prefetch();
+
+dcp_zpx
+ TMP = read_pc();
+ read(TMP);
+ TMP = uint8_t(TMP+X);
+ TMP2 = read(TMP);
+ write(TMP, TMP2);
+ TMP2--;
+ write(TMP, TMP2);
+ do_cmp(A, TMP2);
+ prefetch();
+
+isb_aba
+ TMP = read_pc();
+ TMP = set_h(TMP, read_pc());
+ TMP2 = read(TMP);
+ write(TMP, TMP2);
+ TMP2++;
+ write(TMP, TMP2);
+ do_sbc(TMP2);
+ prefetch();
+
+isb_abx
+ TMP = read_pc();
+ TMP = set_h(TMP, read_pc());
+ read(set_l(TMP, TMP+X));
+ TMP += X;
+ TMP2 = read(TMP);
+ write(TMP, TMP2);
+ TMP2++;
+ write(TMP, TMP2);
+ do_sbc(TMP2);
+ prefetch();
+
+isb_aby
+ TMP = read_pc();
+ TMP = set_h(TMP, read_pc());
+ read(set_l(TMP, TMP+Y));
+ TMP += Y;
+ TMP2 = read(TMP);
+ write(TMP, TMP2);
+ TMP2++;
+ write(TMP, TMP2);
+ do_sbc(TMP2);
+ prefetch();
+
+isb_idx
+ TMP2 = read_pc();
+ read(TMP2);
+ TMP2 += X;
+ TMP = read(TMP2 & 0xff);
+ TMP = set_h(TMP, read((TMP2+1) & 0xff));
+ TMP2 = read(TMP);
+ write(TMP, TMP2);
+ TMP2++;
+ write(TMP, TMP2);
+ do_sbc(TMP2);
+ prefetch();
+
+isb_idy
+ TMP2 = read_pc();
+ TMP = read(TMP2);
+ TMP = set_h(TMP, read((TMP2+1) & 0xff));
+ read(set_l(TMP, TMP+Y));
+ TMP += Y;
+ TMP2 = read(TMP);
+ write(TMP, TMP2);
+ TMP2++;
+ write(TMP, TMP2);
+ do_sbc(TMP2);
+ prefetch();
+
+isb_zpg
+ TMP = read_pc();
+ TMP2 = read(TMP);
+ write(TMP, TMP2);
+ TMP2++;
+ write(TMP, TMP2);
+ do_sbc(TMP2);
+ prefetch();
+
+isb_zpx
+ TMP = read_pc();
+ read(TMP);
+ TMP = uint8_t(TMP+X);
+ TMP2 = read(TMP);
+ write(TMP, TMP2);
+ TMP2++;
+ write(TMP, TMP2);
+ do_sbc(TMP2);
+ prefetch();
+
+lax_aba
+ TMP = read_pc();
+ TMP = set_h(TMP, read_pc());
+ A = X = read(TMP);
+ set_nz(A);
+ prefetch();
+
+lax_aby
+ TMP = read_pc();
+ TMP = set_h(TMP, read_pc());
+ if(page_changing(TMP, Y)) {
+ read(set_l(TMP, TMP+Y));
+ }
+ A = X = read(TMP+Y);
+ set_nz(A);
+ prefetch();
+
+lax_idx
+ TMP2 = read_pc();
+ read(TMP2);
+ TMP2 += X;
+ TMP = read(TMP2 & 0xff);
+ TMP = set_h(TMP, read((TMP2+1) & 0xff));
+ A = X = read(TMP);
+ set_nz(A);
+ prefetch();
+
+lax_idy
+ TMP2 = read_pc();
+ TMP = read(TMP2);
+ TMP = set_h(TMP, read((TMP2+1) & 0xff));
+ if(page_changing(TMP, Y)) {
+ read(set_l(TMP, TMP+Y));
+ }
+ A = X = read(TMP+Y);
+ set_nz(A);
+ prefetch();
+
+lax_zpg
+ TMP = read_pc();
+ A = X = read(TMP);
+ set_nz(A);
+ prefetch();
+
+lax_zpy
+ TMP = read_pc();
+ read(TMP);
+ TMP = uint8_t(TMP+Y);
+ A = X = read(TMP);
+ set_nz(A);
+ prefetch();
+
+rla_aba
+ TMP = read_pc();
+ TMP = set_h(TMP, read_pc());
+ TMP2 = read(TMP);
+ write(TMP, TMP2);
+ TMP2 = do_rol(TMP2);
+ write(TMP, TMP2);
+ A &= TMP2;
+ set_nz(A);
+ prefetch();
+
+rla_abx
+ TMP = read_pc();
+ TMP = set_h(TMP, read_pc());
+ read(set_l(TMP, TMP+X));
+ TMP += X;
+ TMP2 = read(TMP);
+ write(TMP, TMP2);
+ TMP2 = do_rol(TMP2);
+ write(TMP, TMP2);
+ A &= TMP2;
+ set_nz(A);
+ prefetch();
+
+rla_aby
+ TMP = read_pc();
+ TMP = set_h(TMP, read_pc());
+ read(set_l(TMP, TMP+Y));
+ TMP += Y;
+ TMP2 = read(TMP);
+ write(TMP, TMP2);
+ TMP2 = do_rol(TMP2);
+ write(TMP, TMP2);
+ A &= TMP2;
+ set_nz(A);
+ prefetch();
+
+rla_idx
+ TMP2 = read_pc();
+ read(TMP2);
+ TMP2 += X;
+ TMP = read(TMP2 & 0xff);
+ TMP = set_h(TMP, read((TMP2+1) & 0xff));
+ TMP2 = read(TMP);
+ write(TMP, TMP2);
+ TMP2 = do_rol(TMP2);
+ write(TMP, TMP2);
+ A &= TMP2;
+ set_nz(A);
+ prefetch();
+
+rla_idy
+ TMP2 = read_pc();
+ TMP = read(TMP2);
+ TMP = set_h(TMP, read((TMP2+1) & 0xff));
+ read(set_l(TMP, TMP+Y));
+ TMP += Y;
+ TMP2 = read(TMP);
+ write(TMP, TMP2);
+ TMP2 = do_rol(TMP2);
+ write(TMP, TMP2);
+ A &= TMP2;
+ set_nz(A);
+ prefetch();
+
+rla_zpg
+ TMP = read_pc();
+ TMP2 = read(TMP);
+ write(TMP, TMP2);
+ TMP2 = do_rol(TMP2);
+ write(TMP, TMP2);
+ A &= TMP2;
+ set_nz(A);
+ prefetch();
+
+rla_zpx
+ TMP = read_pc();
+ read(TMP);
+ TMP = uint8_t(TMP+X);
+ TMP2 = read(TMP);
+ write(TMP, TMP2);
+ TMP2 = do_rol(TMP2);
+ write(TMP, TMP2);
+ A &= TMP2;
+ set_nz(A);
+ prefetch();
+
+rra_aba
+ TMP = read_pc();
+ TMP = set_h(TMP, read_pc());
+ TMP2 = read(TMP);
+ write(TMP, TMP2);
+ TMP2 = do_ror(TMP2);
+ write(TMP, TMP2);
+ do_adc(TMP2);
+ prefetch();
+
+rra_abx
+ TMP = read_pc();
+ TMP = set_h(TMP, read_pc());
+ read(set_l(TMP, TMP+X));
+ TMP += X;
+ TMP2 = read(TMP);
+ write(TMP, TMP2);
+ TMP2 = do_ror(TMP2);
+ write(TMP, TMP2);
+ do_adc(TMP2);
+ prefetch();
+
+rra_aby
+ TMP = read_pc();
+ TMP = set_h(TMP, read_pc());
+ read(set_l(TMP, TMP+Y));
+ TMP += Y;
+ TMP2 = read(TMP);
+ write(TMP, TMP2);
+ TMP2 = do_ror(TMP2);
+ write(TMP, TMP2);
+ do_adc(TMP2);
+ prefetch();
+
+rra_idx
+ TMP2 = read_pc();
+ read(TMP2);
+ TMP2 += X;
+ TMP = read(TMP2 & 0xff);
+ TMP = set_h(TMP, read((TMP2+1) & 0xff));
+ TMP2 = read(TMP);
+ write(TMP, TMP2);
+ TMP2 = do_ror(TMP2);
+ write(TMP, TMP2);
+ do_adc(TMP2);
+ prefetch();
+
+rra_idy
+ TMP2 = read_pc();
+ TMP = read(TMP2);
+ TMP = set_h(TMP, read((TMP2+1) & 0xff));
+ read(set_l(TMP, TMP+Y));
+ TMP += Y;
+ TMP2 = read(TMP);
+ write(TMP, TMP2);
+ TMP2 = do_ror(TMP2);
+ write(TMP, TMP2);
+ do_adc(TMP2);
+ prefetch();
+
+rra_zpg
+ TMP = read_pc();
+ TMP2 = read(TMP);
+ write(TMP, TMP2);
+ TMP2 = do_ror(TMP2);
+ write(TMP, TMP2);
+ do_adc(TMP2);
+ prefetch();
+
+rra_zpx
+ TMP = read_pc();
+ read(TMP);
+ TMP = uint8_t(TMP+X);
+ TMP2 = read(TMP);
+ write(TMP, TMP2);
+ TMP2 = do_ror(TMP2);
+ write(TMP, TMP2);
+ do_adc(TMP2);
+ prefetch();
+
+sax_aba
+ TMP = read_pc();
+ TMP = set_h(TMP, read_pc());
+ TMP2 = A & X;
+ write(TMP, TMP2);
+ prefetch();
+
+sax_idx
+ TMP2 = read_pc();
+ read(TMP2);
+ TMP2 += X;
+ TMP = read(TMP2 & 0xff);
+ TMP = set_h(TMP, read((TMP2+1) & 0xff));
+ TMP2 = A & X;
+ write(TMP, TMP2);
+ prefetch();
+
+sax_zpg
+ TMP = read_pc();
+ TMP2 = A & X;
+ write(TMP, TMP2);
+ prefetch();
+
+sax_zpy
+ TMP = read_pc();
+ read(TMP);
+ TMP = uint8_t(TMP+Y);
+ TMP2 = A & X;
+ write(TMP, TMP2);
+ prefetch();
+
+sbx_imm
+ TMP2 = read_pc();
+ X &= A;
+ if(X < TMP2)
+ P &= ~F_C;
+ else
+ P |= F_C;
+ X -= TMP2;
+ set_nz(X);
+ prefetch();
+
+sha_aby
+ TMP = read_pc();
+ TMP = set_h(TMP, read_pc());
+ read(set_l(TMP, TMP+Y));
+ TMP2 = A & X & ((TMP >> 8)+1);
+ if(page_changing(TMP, Y))
+ TMP = set_h(TMP+Y, TMP2);
+ else
+ TMP += Y;
+ write(TMP, TMP2);
+ prefetch();
+
+sha_idy
+ TMP2 = read_pc();
+ TMP = read(TMP2);
+ TMP = set_h(TMP, read((TMP2+1) & 0xff));
+ read(set_l(TMP, TMP+Y));
+ TMP2 = A & X & ((TMP >> 8)+1);
+ if(page_changing(TMP, Y))
+ TMP = set_h(TMP+Y, TMP2);
+ else
+ TMP += Y;
+ write(TMP, TMP2);
+ prefetch();
+
+shs_aby
+ TMP = read_pc();
+ TMP = set_h(TMP, read_pc());
+ read(set_l(TMP, TMP+Y));
+ SP = set_l(SP, A & X);
+ TMP2 = A & X & ((TMP >> 8)+1);
+ if(page_changing(TMP, Y))
+ TMP = set_h(TMP+Y, TMP2);
+ else
+ TMP += Y;
+ write(TMP, TMP2);
+ prefetch();
+
+shx_aby
+ TMP = read_pc();
+ TMP = set_h(TMP, read_pc());
+ read(set_l(TMP, TMP+Y));
+ TMP2 = X & ((TMP >> 8)+1);
+ if(page_changing(TMP, Y))
+ TMP = set_h(TMP+Y, TMP2);
+ else
+ TMP += Y;
+ write(TMP, TMP2);
+ prefetch();
+
+shy_abx
+ TMP = read_pc();
+ TMP = set_h(TMP, read_pc());
+ read(set_l(TMP, TMP+X));
+ TMP2 = Y & ((TMP >> 8)+1);
+ if(page_changing(TMP, X))
+ TMP = set_h(TMP+X, TMP2);
+ else
+ TMP += X;
+ write(TMP, TMP2);
+ prefetch();
+
+slo_aba
+ TMP = read_pc();
+ TMP = set_h(TMP, read_pc());
+ TMP2 = read(TMP);
+ write(TMP, TMP2);
+ TMP2 = do_asl(TMP2);
+ write(TMP, TMP2);
+ A |= TMP2;
+ set_nz(A);
+ prefetch();
+
+slo_abx
+ TMP = read_pc();
+ TMP = set_h(TMP, read_pc());
+ read(set_l(TMP, TMP+X));
+ TMP += X;
+ TMP2 = read(TMP);
+ write(TMP, TMP2);
+ TMP2 = do_asl(TMP2);
+ write(TMP, TMP2);
+ A |= TMP2;
+ set_nz(A);
+ prefetch();
+
+slo_aby
+ TMP = read_pc();
+ TMP = set_h(TMP, read_pc());
+ read(set_l(TMP, TMP+Y));
+ TMP += Y;
+ TMP2 = read(TMP);
+ write(TMP, TMP2);
+ TMP2 = do_asl(TMP2);
+ write(TMP, TMP2);
+ A |= TMP2;
+ set_nz(A);
+ prefetch();
+
+slo_idx
+ TMP2 = read_pc();
+ read(TMP2);
+ TMP2 += X;
+ TMP = read(TMP2 & 0xff);
+ TMP = set_h(TMP, read((TMP2+1) & 0xff));
+ TMP2 = read(TMP);
+ write(TMP, TMP2);
+ TMP2 = do_asl(TMP2);
+ write(TMP, TMP2);
+ A |= TMP2;
+ set_nz(A);
+ prefetch();
+
+slo_idy
+ TMP2 = read_pc();
+ TMP = read(TMP2);
+ TMP = set_h(TMP, read((TMP2+1) & 0xff));
+ read(set_l(TMP, TMP+Y));
+ TMP += Y;
+ TMP2 = read(TMP);
+ write(TMP, TMP2);
+ TMP2 = do_asl(TMP2);
+ write(TMP, TMP2);
+ A |= TMP2;
+ set_nz(A);
+ prefetch();
+
+slo_zpg
+ TMP = read_pc();
+ TMP2 = read(TMP);
+ write(TMP, TMP2);
+ TMP2 = do_asl(TMP2);
+ write(TMP, TMP2);
+ A |= TMP2;
+ set_nz(A);
+ prefetch();
+
+slo_zpx
+ TMP = read_pc();
+ read(TMP);
+ TMP = uint8_t(TMP+X);
+ TMP2 = read(TMP);
+ write(TMP, TMP2);
+ TMP2 = do_asl(TMP2);
+ write(TMP, TMP2);
+ A |= TMP2;
+ set_nz(A);
+ prefetch();
+
+sre_aba
+ TMP = read_pc();
+ TMP = set_h(TMP, read_pc());
+ TMP2 = read(TMP);
+ write(TMP, TMP2);
+ TMP2 = do_lsr(TMP2);
+ write(TMP, TMP2);
+ A ^= TMP2;
+ set_nz(A);
+ prefetch();
+
+sre_abx
+ TMP = read_pc();
+ TMP = set_h(TMP, read_pc());
+ read(set_l(TMP, TMP+X));
+ TMP += X;
+ TMP2 = read(TMP);
+ write(TMP, TMP2);
+ TMP2 = do_lsr(TMP2);
+ write(TMP, TMP2);
+ A ^= TMP2;
+ set_nz(A);
+ prefetch();
+
+sre_aby
+ TMP = read_pc();
+ TMP = set_h(TMP, read_pc());
+ read(set_l(TMP, TMP+Y));
+ TMP += Y;
+ TMP2 = read(TMP);
+ write(TMP, TMP2);
+ TMP2 = do_lsr(TMP2);
+ write(TMP, TMP2);
+ A ^= TMP2;
+ set_nz(A);
+ prefetch();
+
+sre_idx
+ TMP2 = read_pc();
+ read(TMP2);
+ TMP2 += X;
+ TMP = read(TMP2 & 0xff);
+ TMP = set_h(TMP, read((TMP2+1) & 0xff));
+ TMP2 = read(TMP);
+ write(TMP, TMP2);
+ TMP2 = do_lsr(TMP2);
+ write(TMP, TMP2);
+ A ^= TMP2;
+ set_nz(A);
+ prefetch();
+
+sre_idy
+ TMP2 = read_pc();
+ TMP = read(TMP2);
+ TMP = set_h(TMP, read((TMP2+1) & 0xff));
+ read(set_l(TMP, TMP+Y));
+ TMP += Y;
+ TMP2 = read(TMP);
+ write(TMP, TMP2);
+ TMP2 = do_lsr(TMP2);
+ write(TMP, TMP2);
+ A ^= TMP2;
+ set_nz(A);
+ prefetch();
+
+sre_zpg
+ TMP = read_pc();
+ TMP2 = read(TMP);
+ write(TMP, TMP2);
+ TMP2 = do_lsr(TMP2);
+ write(TMP, TMP2);
+ A ^= TMP2;
+ set_nz(A);
+ prefetch();
+
+sre_zpx
+ TMP = read_pc();
+ read(TMP);
+ TMP = uint8_t(TMP+X);
+ TMP2 = read(TMP);
+ write(TMP, TMP2);
+ TMP2 = do_lsr(TMP2);
+ write(TMP, TMP2);
+ A ^= TMP2;
+ set_nz(A);
+ prefetch();
+
+# undocumented unreliable instructions
+anc_imm
+ A &= read_pc();
+ set_nz(A);
+ if(A & 0x80)
+ P |= F_C;
+ else
+ P &= ~F_C;
+ prefetch();
+
+ane_imm
+ TMP2 = read_pc();
+ A &= TMP2 & X;
+ set_nz(A);
+ prefetch();
+
+asr_imm
+ A &= read_pc();
+ A = do_lsr(A);
+ prefetch();
+
+arr_imm
+ A &= read_pc();
+ do_arr();
+ prefetch();
+
+las_aby
+ TMP = read_pc();
+ TMP = set_h(TMP, read_pc());
+ if(page_changing(TMP, Y)) {
+ read(set_l(TMP, TMP+Y));
+ }
+ TMP2 = read(TMP+Y);
+ A = TMP2 | 0x51;
+ X = 0xff;
+ set_nz(TMP2);
+ prefetch();
+
+lxa_imm
+ A = X = read_pc();
+ set_nz(A);
+ prefetch();
+
+# nop variants
+nop_aba
+ TMP = read_pc();
+ TMP = set_h(TMP, read_pc());
+ read(TMP);
+ prefetch();
+
+nop_abx
+ TMP = read_pc();
+ TMP = set_h(TMP, read_pc());
+ if(page_changing(TMP, X)) {
+ read(set_l(TMP, TMP+X));
+ }
+ read(TMP + X);
+ prefetch();
+
+nop_imm
+ read_pc();
+ prefetch();
+
+nop_zpg
+ TMP = read_pc();
+ read(TMP);
+ prefetch();
+
+nop_zpx
+ TMP = read_pc();
+ read(TMP);
+ read(uint8_t(TMP+X));
+ prefetch();
+
+# system killers
+kil_non
+ read_pc();
+ read(0xffff);
+ read(0xfffe);
+ read(0xfffe);
+ for(;;) {
+ read(0xffff);
+ }
--- /dev/null
+# license:BSD-3-Clause
+# copyright-holders:Olivier Galibert
+# m65c02 opcodes
+
+adc_c_aba
+ TMP = read_pc();
+ TMP = set_h(TMP, read_pc());
+ TMP = read(TMP);
+ do_adc(TMP);
+ if(P & F_D) {
+ read_pc_noinc();
+ set_nz(A);
+ }
+ prefetch();
+
+adc_c_abx
+ TMP = read_pc();
+ TMP = set_h(TMP, read_pc());
+ if(page_changing(TMP, X)) {
+ read(set_l(TMP, TMP+X));
+ }
+ TMP += X;
+ TMP = read(TMP);
+ do_adc(TMP);
+ if(P & F_D) {
+ read_pc_noinc();
+ set_nz(A);
+ }
+ prefetch();
+
+adc_c_aby
+ TMP = read_pc();
+ TMP = set_h(TMP, read_pc());
+ if(page_changing(TMP, Y)) {
+ read(set_l(TMP, TMP+Y));
+ }
+ TMP += Y;
+ TMP = read(TMP);
+ do_adc(TMP);
+ if(P & F_D) {
+ read_pc_noinc();
+ set_nz(A);
+ }
+ prefetch();
+
+adc_c_idx
+ TMP2 = read_pc();
+ read(TMP2);
+ TMP2 += X;
+ TMP = read(TMP2 & 0xff);
+ TMP = set_h(TMP, read((TMP2+1) & 0xff));
+ do_adc(read(TMP));
+ if(P & F_D) {
+ read_pc_noinc();
+ set_nz(A);
+ }
+ prefetch();
+
+adc_c_idy
+ TMP2 = read_pc();
+ TMP = read(TMP2);
+ TMP = set_h(TMP, read((TMP2+1) & 0xff));
+ if(page_changing(TMP, Y)) {
+ read(set_l(TMP, TMP+Y));
+ }
+ do_adc(read(TMP+Y));
+ if(P & F_D) {
+ read_pc_noinc();
+ set_nz(A);
+ }
+ prefetch();
+
+adc_c_imm
+ TMP = read_pc();
+ do_adc(TMP);
+ if(P & F_D) {
+ read_pc_noinc();
+ set_nz(A);
+ }
+ prefetch();
+
+adc_c_zpg
+ TMP = read_pc();
+ TMP = read(TMP);
+ do_adc(TMP);
+ if(P & F_D) {
+ read_pc_noinc();
+ set_nz(A);
+ }
+ prefetch();
+
+adc_c_zpi
+ TMP2 = read_pc();
+ TMP = read(TMP2 & 0xff);
+ TMP = set_h(TMP, read((TMP2+1) & 0xff));
+ do_adc(read(TMP));
+ if(P & F_D) {
+ read_pc_noinc();
+ set_nz(A);
+ }
+ prefetch();
+
+adc_c_zpx
+ TMP = read_pc();
+ read(TMP);
+ TMP = read(uint8_t(TMP+X));
+ do_adc(TMP);
+ if(P & F_D) {
+ read_pc_noinc();
+ set_nz(A);
+ }
+ prefetch();
+
+and_zpi
+ TMP2 = read_pc();
+ TMP = read(TMP2 & 0xff);
+ TMP = set_h(TMP, read((TMP2+1) & 0xff));
+ A &= read(TMP);
+ set_nz(A);
+ prefetch();
+
+asl_c_abx
+ TMP = read_pc();
+ TMP = set_h(TMP, read_pc());
+ if(page_changing(TMP, X)) {
+ read(set_l(TMP, TMP+X));
+ }
+ TMP += X;
+ TMP2 = read(TMP);
+ write(TMP, TMP2);
+ TMP2 = do_asl(TMP2);
+ write(TMP, TMP2);
+ prefetch();
+
+bbr_zpb
+ // Access pattern uncertain
+ TMP = read_pc();
+ TMP2 = read(TMP);
+ TMP = read_pc();
+ read_pc_noinc();
+ if(!(TMP2 & (1 << ((inst_state >> 4) & 7)))) {
+ PC += int8_t(TMP);
+ }
+ prefetch();
+
+bbs_zpb
+ // Access pattern uncertain
+ TMP = read_pc();
+ TMP2 = read(TMP);
+ TMP = read_pc();
+ read_pc_noinc();
+ if(TMP2 & (1 << ((inst_state >> 4) & 7))) {
+ PC += int8_t(TMP);
+ }
+ prefetch();
+
+bit_abx
+ TMP = read_pc();
+ TMP = set_h(TMP, read_pc());
+ if(page_changing(TMP, X)) {
+ read(set_l(TMP, TMP+X));
+ }
+ TMP += X;
+ do_bit(read(TMP));
+ prefetch();
+
+bit_imm
+ TMP = read_pc();
+ if(A & TMP)
+ P &= ~F_Z;
+ else
+ P |= F_Z;
+ prefetch();
+
+bit_zpx
+ TMP = read_pc();
+ read(TMP);
+ TMP = read(uint8_t(TMP+X));
+ do_bit(TMP);
+ prefetch();
+
+bra_rel
+ TMP = read_pc();
+ read_pc_noinc();
+ if(page_changing(PC, int8_t(TMP))) {
+ read_arg(set_l(PC, PC+int8_t(TMP)));
+ }
+ PC += int8_t(TMP);
+ prefetch();
+
+brk_c_imp
+ if(irq_taken || nmi_state) {
+ read_pc_noinc();
+ } else {
+ read_pc();
+ }
+ write(SP, PC >> 8);
+ dec_SP();
+ write(SP, PC);
+ dec_SP();
+ write(SP, irq_taken || nmi_state ? P & ~F_B : P);
+ dec_SP();
+ if(irq_taken && nmi_state) {
+ PC = read_arg(0xfffa);
+ PC = set_h(PC, read_arg(0xfffb));
+ nmi_state = false;
+ standard_irq_callback(NMI_LINE);
+ } else {
+ PC = read_arg(0xfffe);
+ PC = set_h(PC, read_arg(0xffff));
+ if(irq_taken)
+ standard_irq_callback(IRQ_LINE);
+ }
+ irq_taken = false;
+ P = (P | F_I) & ~F_D; // Do *not* move after the prefetch
+ prefetch();
+ inst_state = -1;
+
+cmp_zpi
+ TMP2 = read_pc();
+ TMP = read(TMP2 & 0xff);
+ TMP = set_h(TMP, read((TMP2+1) & 0xff));
+ do_cmp(A, read(TMP));
+ prefetch();
+
+dec_acc
+ read_pc_noinc();
+ A--;
+ set_nz(A);
+ prefetch();
+
+eor_zpi
+ TMP2 = read_pc();
+ TMP = read(TMP2 & 0xff);
+ TMP = set_h(TMP, read((TMP2+1) & 0xff));
+ A ^= read(TMP);
+ set_nz(A);
+ prefetch();
+
+inc_acc
+ read_pc_noinc();
+ A++;
+ set_nz(A);
+ prefetch();
+
+jmp_iax
+ TMP = read_pc();
+ TMP = set_h(TMP, read_pc());
+ read(set_l(TMP, TMP+X));
+ TMP += X;
+ PC = read(TMP);
+ PC = set_h(PC, read(TMP+1));
+ prefetch();
+
+jmp_c_ind
+ TMP = read_pc();
+ TMP = set_h(TMP, read_pc());
+ PC = read(TMP);
+ read(set_l(TMP, TMP+1));
+ PC = set_h(PC, read(TMP+1));
+ prefetch();
+
+lda_zpi
+ TMP2 = read_pc();
+ TMP = read(TMP2 & 0xff);
+ TMP = set_h(TMP, read((TMP2+1) & 0xff));
+ A = read(TMP);
+ set_nz(A);
+ prefetch();
+
+
+lsr_c_abx
+ TMP = read_pc();
+ TMP = set_h(TMP, read_pc());
+ if(page_changing(TMP, X)) {
+ read(set_l(TMP, TMP+X));
+ }
+ TMP += X;
+ TMP2 = read(TMP);
+ write(TMP, TMP2);
+ TMP2 = do_lsr(TMP2);
+ write(TMP, TMP2);
+ prefetch();
+
+nop_c_imp
+ prefetch();
+
+nop_c_aba
+ read_pc();
+ read_pc();
+ read_pc_noinc();
+ read_pc_noinc();
+ read_pc_noinc();
+ read_pc_noinc();
+ read_pc_noinc();
+ prefetch();
+
+nop_c_abx
+ TMP = read_pc();
+ TMP = set_h(TMP, read_pc());
+ read(set_l(TMP, TMP+X));
+ prefetch();
+
+ora_zpi
+ TMP2 = read_pc();
+ TMP = read(TMP2 & 0xff);
+ TMP = set_h(TMP, read((TMP2+1) & 0xff));
+ A |= read(TMP);
+ set_nz(A);
+ prefetch();
+
+phx_imp
+ read_pc_noinc();
+ write(SP, X);
+ dec_SP();
+ prefetch();
+
+phy_imp
+ read_pc_noinc();
+ write(SP, Y);
+ dec_SP();
+ prefetch();
+
+plx_imp
+ read_pc_noinc();
+ read(SP);
+ inc_SP();
+ X = read(SP);
+ set_nz(X);
+ prefetch();
+
+ply_imp
+ read_pc_noinc();
+ read(SP);
+ inc_SP();
+ Y = read(SP);
+ set_nz(Y);
+ prefetch();
+
+rmb_bzp
+ // Access pattern unknown but probable (built upon inc_zpg)
+ TMP = read_pc();
+ TMP2 = read(TMP);
+ write(TMP, TMP2);
+ TMP2 &= ~(1 << ((inst_state >> 4) & 7));
+ write(TMP, TMP2);
+ prefetch();
+
+rol_c_abx
+ TMP = read_pc();
+ TMP = set_h(TMP, read_pc());
+ if(page_changing(TMP, X)) {
+ read(set_l(TMP, TMP+X));
+ }
+ TMP += X;
+ TMP2 = read(TMP);
+ write(TMP, TMP2);
+ TMP2 = do_rol(TMP2);
+ write(TMP, TMP2);
+ prefetch();
+
+
+ror_c_abx
+ TMP = read_pc();
+ TMP = set_h(TMP, read_pc());
+ if(page_changing(TMP, X)) {
+ read(set_l(TMP, TMP+X));
+ }
+ TMP += X;
+ TMP2 = read(TMP);
+ write(TMP, TMP2);
+ TMP2 = do_ror(TMP2);
+ write(TMP, TMP2);
+ prefetch();
+
+sbc_c_aba
+ TMP = read_pc();
+ TMP = set_h(TMP, read_pc());
+ TMP = read(TMP);
+ do_sbc(TMP);
+ if(P & F_D) {
+ read_pc_noinc();
+ set_nz(A);
+ }
+ prefetch();
+
+sbc_c_abx
+ TMP = read_pc();
+ TMP = set_h(TMP, read_pc());
+ if(page_changing(TMP, X)) {
+ read(set_l(TMP, TMP+X));
+ }
+ TMP += X;
+ TMP = read(TMP);
+ do_sbc(TMP);
+ if(P & F_D) {
+ read_pc_noinc();
+ set_nz(A);
+ }
+ prefetch();
+
+sbc_c_aby
+ TMP = read_pc();
+ TMP = set_h(TMP, read_pc());
+ if(page_changing(TMP, Y)) {
+ read(set_l(TMP, TMP+Y));
+ }
+ TMP += Y;
+ TMP = read(TMP);
+ do_sbc(TMP);
+ if(P & F_D) {
+ read_pc_noinc();
+ set_nz(A);
+ }
+ prefetch();
+
+sbc_c_idx
+ TMP2 = read_pc();
+ read(TMP2);
+ TMP2 += X;
+ TMP = read(TMP2 & 0xff);
+ TMP = set_h(TMP, read((TMP2+1) & 0xff));
+ do_sbc(read(TMP));
+ if(P & F_D) {
+ read_pc_noinc();
+ set_nz(A);
+ }
+ prefetch();
+
+sbc_c_idy
+ TMP2 = read_pc();
+ TMP = read(TMP2);
+ TMP = set_h(TMP, read((TMP2+1) & 0xff));
+ if(page_changing(TMP, Y)) {
+ read(set_l(TMP, TMP+Y));
+ }
+ do_sbc(read(TMP+Y));
+ if(P & F_D) {
+ read_pc_noinc();
+ set_nz(A);
+ }
+ prefetch();
+
+sbc_c_imm
+ TMP = read_pc();
+ do_sbc(TMP);
+ if(P & F_D) {
+ read_pc_noinc();
+ set_nz(A);
+ }
+ prefetch();
+
+sbc_c_zpg
+ TMP = read_pc();
+ TMP = read(TMP);
+ do_sbc(TMP);
+ if(P & F_D) {
+ read_pc_noinc();
+ set_nz(A);
+ }
+ prefetch();
+
+sbc_c_zpi
+ TMP2 = read_pc();
+ TMP = read(TMP2 & 0xff);
+ TMP = set_h(TMP, read((TMP2+1) & 0xff));
+ do_sbc(read(TMP));
+ if(P & F_D) {
+ read_pc_noinc();
+ set_nz(A);
+ }
+ prefetch();
+
+sbc_c_zpx
+ TMP = read_pc();
+ read(TMP);
+ TMP = read(uint8_t(TMP+X));
+ do_sbc(TMP);
+ if(P & F_D) {
+ read_pc_noinc();
+ set_nz(A);
+ }
+ prefetch();
+
+smb_bzp
+ // Access pattern unknown but probable (built upon inc_zpg)
+ TMP = read_pc();
+ TMP2 = read(TMP);
+ write(TMP, TMP2);
+ TMP2 |= 1 << ((inst_state >> 4) & 7);
+ write(TMP, TMP2);
+ prefetch();
+
+sta_zpi
+ TMP2 = read_pc();
+ TMP = read(TMP2 & 0xff);
+ TMP = set_h(TMP, read((TMP2+1) & 0xff));
+ write(TMP, A);
+ prefetch();
+
+stp_imp
+ for(;;) {
+ eat-all-cycles;
+ }
+
+stz_aba
+ TMP = read_pc();
+ TMP = set_h(TMP, read_pc());
+ write(TMP, 0x00);
+ prefetch();
+
+stz_abx
+ TMP = read_pc();
+ TMP = set_h(TMP, read_pc());
+ read(set_l(TMP, TMP+X));
+ write(TMP+X, 0x00);
+ prefetch();
+
+stz_zpg
+ TMP = read_pc();
+ write(TMP, 0x00);
+ prefetch();
+
+stz_zpx
+ TMP = read_pc();
+ read(TMP);
+ write(uint8_t(TMP+X), 0x00);
+ prefetch();
+
+trb_aba
+ TMP = read_pc();
+ TMP = set_h(TMP, read_pc());
+ TMP2 = read(TMP);
+ write(TMP, TMP2);
+ if(A & TMP2)
+ P &= ~F_Z;
+ else
+ P |= F_Z;
+ TMP2 &= ~A;
+ write(TMP, TMP2);
+ prefetch();
+
+trb_zpg
+ TMP = read_pc();
+ TMP2 = read(TMP);
+ write(TMP, TMP2);
+ if(A & TMP2)
+ P &= ~F_Z;
+ else
+ P |= F_Z;
+ TMP2 &= ~A;
+ write(TMP, TMP2);
+ prefetch();
+
+tsb_aba
+ TMP = read_pc();
+ TMP = set_h(TMP, read_pc());
+ TMP2 = read(TMP);
+ write(TMP, TMP2);
+ if(A & TMP2)
+ P &= ~F_Z;
+ else
+ P |= F_Z;
+ TMP2 |= A;
+ write(TMP, TMP2);
+ prefetch();
+
+tsb_zpg
+ TMP = read_pc();
+ TMP2 = read(TMP);
+ write(TMP, TMP2);
+ if(A & TMP2)
+ P &= ~F_Z;
+ else
+ P |= F_Z;
+ TMP2 |= A;
+ write(TMP, TMP2);
+ prefetch();
+
+wai_imp
+ read_pc_noinc();
+ read_pc_noinc();
+ while(!nmi_state && !irq_state) {
+ eat-all-cycles;
+ }
+ prefetch();