diff options
Diffstat (limited to 'src/devices/cpu/m6502/m6500_1.cpp')
-rw-r--r-- | src/devices/cpu/m6502/m6500_1.cpp | 98 |
1 files changed, 50 insertions, 48 deletions
diff --git a/src/devices/cpu/m6502/m6500_1.cpp b/src/devices/cpu/m6502/m6500_1.cpp index cb3630e6668..8aa30f08c89 100644 --- a/src/devices/cpu/m6502/m6500_1.cpp +++ b/src/devices/cpu/m6502/m6500_1.cpp @@ -2,7 +2,7 @@ // copyright-holders:Vas Crabb /*************************************************************************** - m6500_1.h + m6500_1.cpp MOS Technology 6500/1, original NMOS variant with onboard peripherals: * 6502 CPU @@ -12,10 +12,10 @@ * Sixteen-bit programmable counter/latch The onboad clock generator has mask options for an external crystal - (2MHz to 6MHz) an external TTL-compatible clock with a 300Ω pull-up + (2MHz to 6MHz), an external TTL-compatible clock with a 300Ω pull-up resistor (2MHz to 6MHz), or an RC oscillator with an external 47kΩ resistor and internal capacitor (nominally 2MHz). The clock is - divided by two to generate the two-phase CPU code clock. + divided by two to generate the two-phase CPU core clock. There is no on-board power-on reset generator. The /RES pin must be held low (asserted) for at least eight phase 2 clock cycles after @@ -45,7 +45,7 @@ on the CNTR pin in event counter mode is half the phase 2 clock rate. This suggests that an internal flag is set when a rasing edge is detected on CNTR and reset when the counter is synchronously - decremented. This is not emulated - for simplicity the counter is + decremented. This is not emulated - for simplicity, the counter is asynchronously decremented on detecting a rising edge on CNTR. The CNTR pin has an active low driver and internal passive pull-up. @@ -58,11 +58,23 @@ appear to include the addition of an onboard power-on reset. It is unknown what other differences these devices have. + TODO: + - For some reason most if not all Amiga MCU programs access + arbitrary zero page 0x90-0xff with a back-to-back cmp($00, x) + opcode at PC=c06-c08 with the actual result discarded. X can be + any value in the 0x90-0xff range, depending on the last user + keypress row source e.g. 0xdf-0xe0 for 'A', 0xef-0xf0 for 'Q', + 0xfb-0xfc for function keys. + This can be extremely verbose in the logging facility so we nop it + out for the time being. + ***************************************************************************/ #include "emu.h" #include "m6500_1.h" +#include "m6502mcu.ipp" + namespace { @@ -78,13 +90,13 @@ constexpr u8 CR_CTRO = 0x80U; } // anonymous namespace -DEFINE_DEVICE_TYPE(M6500_1, m6500_1_device, "m6500_1", "MOS M6500/1"); +DEFINE_DEVICE_TYPE(M6500_1, m6500_1_device, "m6500_1", "MOS Technology 6500/1"); m6500_1_device::m6500_1_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock) - : m6502_mcu_device(mconfig, M6500_1, tag, owner, clock) - , m_port_in_cb{ { *this }, { *this }, { *this }, { *this } } - , m_port_out_cb{ { *this }, { *this }, { *this }, { *this } } + : m6502_mcu_device_base<m6502_device>(mconfig, M6500_1, tag, owner, clock) + , m_port_in_cb{ *this, 0xffU } + , m_port_out_cb{ *this } , m_cntr_out_cb{ *this } , m_cr{ 0x00U } , m_port_in{ 0xffU, 0xffU, 0xffU, 0xffU } @@ -103,49 +115,36 @@ m6500_1_device::m6500_1_device(machine_config const &mconfig, char const *tag, d } -WRITE8_MEMBER(m6500_1_device::pa_w) +void m6500_1_device::pa_w(uint8_t data) { machine().scheduler().synchronize(timer_expired_delegate(FUNC(m6500_1_device::set_port_in<0>), this), unsigned(data)); } -WRITE8_MEMBER(m6500_1_device::pb_w) +void m6500_1_device::pb_w(u8 data) { machine().scheduler().synchronize(timer_expired_delegate(FUNC(m6500_1_device::set_port_in<1>), this), unsigned(data)); } -WRITE8_MEMBER(m6500_1_device::pc_w) +void m6500_1_device::pc_w(u8 data) { machine().scheduler().synchronize(timer_expired_delegate(FUNC(m6500_1_device::set_port_in<2>), this), unsigned(data)); } -WRITE8_MEMBER(m6500_1_device::pd_w) +void m6500_1_device::pd_w(u8 data) { machine().scheduler().synchronize(timer_expired_delegate(FUNC(m6500_1_device::set_port_in<3>), this), unsigned(data)); } -WRITE_LINE_MEMBER(m6500_1_device::cntr_w) +void m6500_1_device::cntr_w(int state) { machine().scheduler().synchronize(timer_expired_delegate(FUNC(m6500_1_device::set_cntr_in), this), state); } -void m6500_1_device::device_resolve_objects() -{ - m6502_mcu_device::device_resolve_objects(); - - for (devcb_read8 &cb : m_port_in_cb) - cb.resolve(); - - for (devcb_write8 &cb : m_port_out_cb) - cb.resolve_safe(); - - m_cntr_out_cb.resolve_safe(); -} - void m6500_1_device::device_start() { - m6502_mcu_device::device_start(); + m6502_mcu_device_base<m6502_device>::device_start(); m_counter_base = 0U; @@ -167,7 +166,7 @@ void m6500_1_device::device_start() void m6500_1_device::device_reset() { - m6502_mcu_device::device_reset(); + m6502_mcu_device_base<m6502_device>::device_reset(); SP = 0x003fU; @@ -175,7 +174,7 @@ void m6500_1_device::device_reset() m_cr = 0x00U; - for (unsigned i = 0; ARRAY_LENGTH(m_port_buf) > i; ++i) + for (unsigned i = 0; std::size(m_port_buf) > i; ++i) { if (0xffU != m_port_buf[i]) m_port_out_cb[i](m_port_buf[i] = 0xffU); @@ -189,12 +188,12 @@ void m6500_1_device::device_reset() } -u64 m6500_1_device::execute_clocks_to_cycles(u64 clocks) const +u64 m6500_1_device::execute_clocks_to_cycles(u64 clocks) const noexcept { return (clocks + 1) / 2; } -u64 m6500_1_device::execute_cycles_to_clocks(u64 cycles) const +u64 m6500_1_device::execute_cycles_to_clocks(u64 cycles) const noexcept { return cycles * 2; } @@ -232,7 +231,7 @@ void m6500_1_device::state_import(device_state_entry const &entry) break; default: - m6502_mcu_device::state_import(entry); + m6502_mcu_device_base<m6502_device>::state_import(entry); } } @@ -263,7 +262,7 @@ void m6500_1_device::state_export(device_state_entry const &entry) break; default: - m6502_mcu_device::state_export(entry); + m6502_mcu_device_base<m6502_device>::state_export(entry); } } @@ -276,13 +275,13 @@ void m6500_1_device::internal_update(u64 current_time) } -READ8_MEMBER(m6500_1_device::read_control_register) +u8 m6500_1_device::read_control_register() { internal_update(); return m_cr; } -WRITE8_MEMBER(m6500_1_device::write_control_register) +void m6500_1_device::write_control_register(u8 data) { internal_update(); m_cr = (m_cr & (CR_A1ED | CR_A0ED | CR_CTRO)) | (data & (CR_CMC0 | CR_CMC1 | CR_A1IE | CR_A0IE | CR_CIE)); @@ -298,12 +297,12 @@ void m6500_1_device::update_irq() } -READ8_MEMBER(m6500_1_device::read_port) +u8 m6500_1_device::read_port(offs_t offset) { - if (!machine().side_effects_disabled() && m_port_in_cb[offset]) + if (!machine().side_effects_disabled() && !m_port_in_cb[offset].isunset()) { u8 const prev(m_port_in[offset]); - m_port_in[offset] = m_port_in_cb[offset](space); + m_port_in[offset] = m_port_in_cb[offset](); if (!offset) { u8 const diff((prev ^ m_port_in[0]) & m_port_buf[0]); @@ -318,16 +317,16 @@ READ8_MEMBER(m6500_1_device::read_port) return m_port_in[offset] & m_port_buf[offset]; } -WRITE8_MEMBER(m6500_1_device::write_port) +void m6500_1_device::write_port(offs_t offset, u8 data) { u8 const prev(m_port_in[offset] & m_port_buf[offset]); if (m_port_buf[offset] != data) - m_port_out_cb[offset](space, m_port_buf[offset] = data); + m_port_out_cb[offset](m_port_buf[offset] = data); if (!offset) { - if (!machine().side_effects_disabled() && m_port_in_cb[0]) - m_port_in[0] = m_port_in_cb[0](space); + if (!machine().side_effects_disabled() && !m_port_in_cb[0].isunset()) + m_port_in[0] = m_port_in_cb[0](); u8 const effective(m_port_in[0] & data); u8 const diff(prev ^ effective); if (BIT(diff, 0) && BIT(effective, 0)) @@ -338,7 +337,7 @@ WRITE8_MEMBER(m6500_1_device::write_port) } } -WRITE8_MEMBER(m6500_1_device::clear_edge) +void m6500_1_device::clear_edge(offs_t offset, u8 data) { m_cr &= BIT(offset, 0) ? ~CR_A1ED : ~CR_A0ED; update_irq(); @@ -347,7 +346,7 @@ WRITE8_MEMBER(m6500_1_device::clear_edge) template <unsigned Port> TIMER_CALLBACK_MEMBER(m6500_1_device::set_port_in) { u8 const prev(m_port_in[Port]); - m_port_in[Port] = m_port_in_cb[Port] ? m_port_in_cb[Port]() : u8(u32(param)); + m_port_in[Port] = !m_port_in_cb[Port].isunset() ? m_port_in_cb[Port]() : u8(u32(param)); if (!Port) { @@ -361,13 +360,13 @@ template <unsigned Port> TIMER_CALLBACK_MEMBER(m6500_1_device::set_port_in) } -READ8_MEMBER(m6500_1_device::read_upper_count) +u8 m6500_1_device::read_upper_count() { internal_update(); return u8(m_counter >> 8); } -READ8_MEMBER(m6500_1_device::read_lower_count) +u8 m6500_1_device::read_lower_count() { internal_update(); if (!machine().side_effects_disabled()) @@ -379,7 +378,7 @@ READ8_MEMBER(m6500_1_device::read_lower_count) return u8(m_counter); } -template <bool Transfer> WRITE8_MEMBER(m6500_1_device::write_upper_latch) +template <bool Transfer> void m6500_1_device::write_upper_latch(u8 data) { m_latch = (m_latch & 0x00ffU) | u16(data << 8); if (Transfer) @@ -393,7 +392,7 @@ template <bool Transfer> WRITE8_MEMBER(m6500_1_device::write_upper_latch) } } -WRITE8_MEMBER(m6500_1_device::write_lower_latch) +void m6500_1_device::write_lower_latch(u8 data) { m_latch = (m_latch & 0xff00U) | u16(data); } @@ -508,5 +507,8 @@ void m6500_1_device::memory_map(address_map &map) map(0x008f, 0x008f).rw(FUNC(m6500_1_device::read_control_register), FUNC(m6500_1_device::write_control_register)); + // TODO: mirror or actually unmapped? + map(0x0090, 0x00ff).nopr(); + map(0x0800, 0x0fff).rom().region(DEVICE_SELF, 0); } |