summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/cpu/m6502/m6500_1.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/devices/cpu/m6502/m6500_1.cpp')
-rw-r--r--src/devices/cpu/m6502/m6500_1.cpp98
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);
}