diff options
Diffstat (limited to 'src/devices/cpu/m6502/m6502.cpp')
-rw-r--r-- | src/devices/cpu/m6502/m6502.cpp | 192 |
1 files changed, 68 insertions, 124 deletions
diff --git a/src/devices/cpu/m6502/m6502.cpp b/src/devices/cpu/m6502/m6502.cpp index 013e4f19ef4..e72fd74459a 100644 --- a/src/devices/cpu/m6502/m6502.cpp +++ b/src/devices/cpu/m6502/m6502.cpp @@ -2,59 +2,62 @@ // copyright-holders:Olivier Galibert /*************************************************************************** - m6502.c + m6502.cpp 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") +DEFINE_DEVICE_TYPE(M6502, m6502_device, "m6502", "MOS Technology 6502") +DEFINE_DEVICE_TYPE(M6512, m6512_device, "m6512", "MOS Technology 6512") m6502_device::m6502_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : m6502_device(mconfig, M6502, tag, owner, clock) { } +m6512_device::m6512_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : + m6502_device(mconfig, M6512, 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) + sprogram_config("decrypted_opcodes", ENDIANNESS_LITTLE, 8, 16), + mintf(nullptr), + uses_custom_memory_interface(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>(); + if(!uses_custom_memory_interface) + mintf = space(AS_PROGRAM).addr_width() > 14 ? std::make_unique<mi_default>() : std::make_unique<mi_default14>(); init(); } void m6502_device::init() { - mintf->program = &space(AS_PROGRAM); - mintf->sprogram = has_space(AS_OPCODES) ? &space(AS_OPCODES) : mintf->program; + if(mintf) { + space(AS_PROGRAM).cache(mintf->cprogram); + space(has_space(AS_OPCODES) ? AS_OPCODES : AS_PROGRAM).cache(mintf->csprogram); - mintf->cache = mintf->program->cache<0, 0, ENDIANNESS_LITTLE>(); - mintf->scache = mintf->sprogram->cache<0, 0, ENDIANNESS_LITTLE>(); - - sync_w.resolve_safe(); - - XPC = 0; + // specific group 1-14 or 15-31 + if(space(AS_PROGRAM).addr_width() > 14) + space(AS_PROGRAM).specific(mintf->program); + else + space(AS_PROGRAM).specific(mintf->program14); + } 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); @@ -79,14 +82,17 @@ void m6502_device::init() save_item(NAME(irq_state)); save_item(NAME(apu_irq_state)); save_item(NAME(v_state)); + save_item(NAME(nmi_pending)); + save_item(NAME(irq_taken)); 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); + XPC = 0x0000; + PPC = 0x0000; PC = 0x0000; NPC = 0x0000; A = 0x00; @@ -100,8 +106,9 @@ void m6502_device::init() nmi_state = false; irq_state = false; apu_irq_state = false; - irq_taken = false; v_state = false; + nmi_pending = false; + irq_taken = false; inst_state = STATE_RESET; inst_substate = 0; inst_state_base = 0; @@ -115,35 +122,27 @@ 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; + nmi_pending = false; irq_taken = false; - v_state = false; sync = false; sync_w(CLEAR_LINE); inhibit_interrupts = false; } -uint32_t m6502_device::execute_min_cycles() const +uint32_t m6502_device::execute_min_cycles() const noexcept { return 1; } -uint32_t m6502_device::execute_max_cycles() const +uint32_t m6502_device::execute_max_cycles() const noexcept { return 10; } -uint32_t m6502_device::execute_input_lines() const +bool m6502_device::execute_input_edge_triggered(int inputnum) const noexcept { - return NMI_LINE+1; -} - -bool m6502_device::execute_input_edge_triggered(int inputnum) const -{ - return inputnum == NMI_LINE; + return inputnum == NMI_LINE || inputnum == V_LINE; } void m6502_device::do_adc_d(uint8_t val) @@ -395,7 +394,7 @@ void m6502_device::execute_run() if(inst_state < 0xff00) { PPC = NPC; inst_state = IR | inst_state_base; - if(machine().debug_flags & DEBUG_FLAG_ENABLED) + if(debugger_enabled()) debugger_instruction_hook(pc_to_external(NPC)); } do_exec_full(); @@ -407,9 +406,13 @@ 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 NMI_LINE: + if(machine().time() > attotime::zero && !nmi_state && state == ASSERT_LINE) + nmi_pending = true; + nmi_state = state == ASSERT_LINE; + break; case V_LINE: - if(!v_state && state == ASSERT_LINE) + if(machine().time() > attotime::zero && !v_state && state == ASSERT_LINE) P |= F_V; v_state = state == ASSERT_LINE; break; @@ -441,7 +444,9 @@ void m6502_device::state_import(const device_state_entry &entry) case M6502_PC: PC = NPC; irq_taken = false; - prefetch(); + prefetch_start(); + IR = mintf->read_sync(PC); + prefetch_end(); PPC = NPC; inst_state = IR | inst_state_base; break; @@ -472,30 +477,32 @@ void m6502_device::state_string_export(const device_state_entry &entry, std::str } } -void m6502_device::prefetch() +void m6502_device::prefetch_start() { sync = true; - sync_w(ASSERT_LINE); + if(!sync_w.isunset()) + sync_w(ASSERT_LINE); NPC = PC; - IR = mintf->read_sync(PC); +} + +void m6502_device::prefetch_end() +{ sync = false; - sync_w(CLEAR_LINE); + if(!sync_w.isunset()) + sync_w(CLEAR_LINE); - if((nmi_state || ((irq_state || apu_irq_state) && !(P & F_I))) && !inhibit_interrupts) { + if((nmi_pending || ((irq_state || apu_irq_state) && !(P & F_I))) && !inhibit_interrupts) { irq_taken = true; IR = 0x00; } else PC++; } -void m6502_device::prefetch_noirq() +void m6502_device::prefetch_end_noirq() { - sync = true; - sync_w(ASSERT_LINE); - NPC = PC; - IR = mintf->read_sync(PC); sync = false; - sync_w(CLEAR_LINE); + if(!sync_w.isunset()) + sync_w(CLEAR_LINE); PC++; } @@ -524,97 +531,34 @@ void m6502_device::memory_interface::write_9(uint16_t adr, uint8_t val) } -uint8_t m6502_device::mi_default_normal::read(uint16_t adr) +uint8_t m6502_device::mi_default::read(uint16_t adr) { - return program->read_byte(adr); + return program.read_byte(adr); } -uint8_t m6502_device::mi_default_normal::read_sync(uint16_t adr) +uint8_t m6502_device::mi_default::read_sync(uint16_t adr) { - return scache->read_byte(adr); + return csprogram.read_byte(adr); } -uint8_t m6502_device::mi_default_normal::read_arg(uint16_t adr) +uint8_t m6502_device::mi_default::read_arg(uint16_t adr) { - return cache->read_byte(adr); + return cprogram.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) +void m6502_device::mi_default::write(uint16_t adr, uint8_t val) { - return program->read_byte(adr); + program.write_byte(adr, val); } -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) +uint8_t m6502_device::mi_default14::read(uint16_t adr) { + return program14.read_byte(adr); } - -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) +void m6502_device::mi_default14::write(uint16_t adr, uint8_t val) { - if(!new_event) - return; - if(!event_time || event_time > new_event) - event_time = new_event; + program14.write_byte(adr, val); } |