summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/cpu/hmcs40
diff options
context:
space:
mode:
Diffstat (limited to 'src/devices/cpu/hmcs40')
-rw-r--r--src/devices/cpu/hmcs40/hmcs40.cpp893
-rw-r--r--src/devices/cpu/hmcs40/hmcs40.h223
-rw-r--r--src/devices/cpu/hmcs40/hmcs40d.cpp75
-rw-r--r--src/devices/cpu/hmcs40/hmcs40d.h24
-rw-r--r--src/devices/cpu/hmcs40/hmcs40op.cpp92
5 files changed, 676 insertions, 631 deletions
diff --git a/src/devices/cpu/hmcs40/hmcs40.cpp b/src/devices/cpu/hmcs40/hmcs40.cpp
index 42e1ca45ef8..0e36b65b11b 100644
--- a/src/devices/cpu/hmcs40/hmcs40.cpp
+++ b/src/devices/cpu/hmcs40/hmcs40.cpp
@@ -2,198 +2,181 @@
// copyright-holders:hap
/*
- Hitachi HMCS40 MCU family cores
+Hitachi HMCS40 MCU family cores
- References:
- - 1985 #AP1 Hitachi 4-bit Single-Chip Microcomputer Data Book
- - 1988 HMCS400 Series Handbook (note: *400 is a newer MCU series, with similarities)
- - opcode decoding by Tatsuyuki Satoh, Olivier Galibert, Kevin Horton, Lord Nightmare - and verified
+References:
+- 1985 #AP1 Hitachi 4-bit Single-Chip Microcomputer Data Book
+- 1988 HMCS400 Series Handbook (note: *400 is a newer MCU series, with similarities)
+- opcode decoding by Tatsuyuki Satoh, Olivier Galibert, Kevin Horton, Lord Nightmare
+ (verified a while later after new documentation was found)
+
+TODO:
+- Which opcodes block interrupt on next cycle? LPU is obvious, and Gakken Crazy Kong
+ (VFD tabletop game) locks up if CAL doesn't do it. Maybe BR? But that's a
+ dangerous assumption since tight infinite loops wouldn't work right anymore.
*/
#include "emu.h"
#include "hmcs40.h"
-#include "debugger.h"
#include "hmcs40d.h"
#define IS_PMOS 0
#define IS_CMOS ~0
-// MCU types
+//-------------------------------------------------
+// device types
+//-------------------------------------------------
-// HMCS42/C/CL
-//DEFINE_DEVICE_TYPE(HD38702, hd38702_device, "hd38702", "Hitachi HD38702") // PMOS, 28 pins, 22 I/O lines, (512+32)x10 ROM, 32x4 RAM, no B or SPY register
-//DEFINE_DEVICE_TYPE(HD44700, hd44700_device, "hd44700", "Hitachi HD44700") // CMOS version
-//DEFINE_DEVICE_TYPE(HD44708, hd44708_device, "hd44708", "Hitachi HD44708") // CMOS version, low-power
+// HMCS42/C/CL, 28 pins, 22 I/O lines, (512+32)x10 ROM, 32x4 RAM, no B or SPY register
+//DEFINE_DEVICE_TYPE(HD38702, hd38702_device, "hd38702", "Hitachi HD38702") // PMOS
+//DEFINE_DEVICE_TYPE(HD44700, hd44700_device, "hd44700", "Hitachi HD44700") // CMOS
+//DEFINE_DEVICE_TYPE(HD44708, hd44708_device, "hd44708", "Hitachi HD44708") // CMOS, low-power
-// HMCS43/C/CL
-DEFINE_DEVICE_TYPE(HD38750, hd38750_device, "hd38750", "Hitachi HD38750") // PMOS, 42 pins, 32 I/O lines, (1024+64)x10 ROM, 80x4 RAM
+// HMCS43/C/CL, 42 pins, 32 I/O lines, (1024+64)x10 ROM, 80x4 RAM
+DEFINE_DEVICE_TYPE(HD38750, hd38750_device, "hd38750", "Hitachi HD38750") // PMOS
DEFINE_DEVICE_TYPE(HD38755, hd38755_device, "hd38755", "Hitachi HD38755") // ceramic filter oscillator type
-DEFINE_DEVICE_TYPE(HD44750, hd44750_device, "hd44750", "Hitachi HD44750") // CMOS version
-DEFINE_DEVICE_TYPE(HD44758, hd44758_device, "hd44758", "Hitachi HD44758") // CMOS version, low-power
+DEFINE_DEVICE_TYPE(HD44750, hd44750_device, "hd44750", "Hitachi HD44750") // CMOS
+DEFINE_DEVICE_TYPE(HD44758, hd44758_device, "hd44758", "Hitachi HD44758") // CMOS, low-power
-// HMCS44A/C/CL
-DEFINE_DEVICE_TYPE(HD38800, hd38800_device, "hd38800", "Hitachi HD38800") // PMOS, 42 pins, 32 I/O lines, (2048+128)x10 ROM, 160x4 RAM
+// HMCS44A/C/CL, 42 pins, 32 I/O lines, (2048+128)x10 ROM, 160x4 RAM
+DEFINE_DEVICE_TYPE(HD38800, hd38800_device, "hd38800", "Hitachi HD38800") // PMOS
DEFINE_DEVICE_TYPE(HD38805, hd38805_device, "hd38805", "Hitachi HD38805") // ceramic filter oscillator type
-DEFINE_DEVICE_TYPE(HD44801, hd44801_device, "hd44801", "Hitachi HD44801") // CMOS version
-DEFINE_DEVICE_TYPE(HD44808, hd44808_device, "hd44808", "Hitachi HD44808") // CMOS version, low-power
+DEFINE_DEVICE_TYPE(HD44801, hd44801_device, "hd44801", "Hitachi HD44801") // CMOS
+DEFINE_DEVICE_TYPE(HD44808, hd44808_device, "hd44808", "Hitachi HD44808") // CMOS, low-power
-// HMCS45A/C/CL
-DEFINE_DEVICE_TYPE(HD38820, hd38820_device, "hd38820", "Hitachi HD38820") // PMOS, 54 pins(QFP) or 64 pins(DIP), 44 I/O lines, (2048+128)x10 ROM, 160x4 RAM
+// HMCS45A/C/CL, 54 pins(QFP) or 64 pins(DIP), 44 I/O lines, (2048+128)x10 ROM, 160x4 RAM
+DEFINE_DEVICE_TYPE(HD38820, hd38820_device, "hd38820", "Hitachi HD38820") // PMOS
DEFINE_DEVICE_TYPE(HD38825, hd38825_device, "hd38825", "Hitachi HD38825") // ceramic filter oscillator type
-DEFINE_DEVICE_TYPE(HD44820, hd44820_device, "hd44820", "Hitachi HD44820") // CMOS version
-DEFINE_DEVICE_TYPE(HD44828, hd44828_device, "hd44828", "Hitachi HD44828") // CMOS version, low-power
+DEFINE_DEVICE_TYPE(HD44820, hd44820_device, "hd44820", "Hitachi HD44820") // CMOS
+DEFINE_DEVICE_TYPE(HD44828, hd44828_device, "hd44828", "Hitachi HD44828") // CMOS, low-power
-// HMCS46C/CL (no PMOS version exists)
-//DEFINE_DEVICE_TYPE(HD44840, hd44840_device, "hd44840", "Hitachi HD44840") // CMOS, 42 pins, 32 I/O lines, 4096x10 ROM, 256x4 RAM
-//DEFINE_DEVICE_TYPE(HD44848, hd44848_device, "hd44848", "Hitachi HD44848") // CMOS, low-power
+// HMCS46C/CL, 42 pins, 32 I/O lines, 4096x10 ROM, 256x4 RAM (no PMOS version exists)
+DEFINE_DEVICE_TYPE(HD44840, hd44840_device, "hd44840", "Hitachi HD44840") // CMOS
+DEFINE_DEVICE_TYPE(HD44848, hd44848_device, "hd44848", "Hitachi HD44848") // CMOS, low-power
-// HMCS47A/C/CL
-//DEFINE_DEVICE_TYPE(HD38870, hd38870_device, "hd38870", "Hitachi HD38870") // PMOS, 54 pins(QFP) or 64 pins(DIP), 44 I/O lines, 4096x10 ROM, 256x4 RAM
-//DEFINE_DEVICE_TYPE(HD44860, hd44860_device, "hd44860", "Hitachi HD44860") // CMOS version
-//DEFINE_DEVICE_TYPE(HD44868, hd44868_device, "hd44868", "Hitachi HD44868") // CMOS version, low-power
+// HMCS47A/C/CL, 54 pins(QFP) or 64 pins(DIP), 44 I/O lines, 4096x10 ROM, 256x4 RAM
+DEFINE_DEVICE_TYPE(HD38870, hd38870_device, "hd38870", "Hitachi HD38870") // PMOS
+DEFINE_DEVICE_TYPE(HD44860, hd44860_device, "hd44860", "Hitachi HD44860") // CMOS
+DEFINE_DEVICE_TYPE(HD44868, hd44868_device, "hd44868", "Hitachi HD44868") // CMOS, low-power
+// LCD-III, 64 pins, HMCS44C core, LCDC with 4 commons and 32 segments
+//DEFINE_DEVICE_TYPE(HD44790, hd44790_device, "hd44790", "Hitachi HD44790") // CMOS
+//DEFINE_DEVICE_TYPE(HD44795, hd44795_device, "hd44795", "Hitachi HD44795") // CMOS, low-power
-// internal memory maps
-void hmcs40_cpu_device::program_1k(address_map &map)
-{
- map(0x0000, 0x03ff).rom();
- map(0x0780, 0x07bf).rom(); // patterns on page 30
-}
+// LCD-IV, 64 pins, HMCS46C core, LCDC with 4 commons and 32 segments
+//DEFINE_DEVICE_TYPE(HD613901, hd613901_device, "hd613901", "Hitachi HD613901") // CMOS
-void hmcs40_cpu_device::program_2k(address_map &map)
-{
- map(0x0000, 0x07ff).rom();
- map(0x0f40, 0x0fbf).rom(); // patterns on page 61,62
-}
+//-------------------------------------------------
+// constructor
+//-------------------------------------------------
-void hmcs40_cpu_device::data_80x4(address_map &map)
-{
- map(0x00, 0x3f).ram();
- map(0x40, 0x4f).ram().mirror(0x30);
-}
-
-void hmcs40_cpu_device::data_160x4(address_map &map)
-{
- map(0x00, 0x7f).ram();
- map(0x80, 0x8f).ram().mirror(0x30);
- map(0xc0, 0xcf).ram().mirror(0x30);
-}
+hmcs40_cpu_device::hmcs40_cpu_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock, int family, u16 polarity, int stack_levels, int pcwidth, int prgwidth, address_map_constructor program, int datawidth, address_map_constructor data) :
+ cpu_device(mconfig, type, tag, owner, clock),
+ m_program_config("program", ENDIANNESS_LITTLE, 16, prgwidth, -1, program),
+ m_data_config("data", ENDIANNESS_LITTLE, 8, datawidth, 0, data),
+ m_pcwidth(pcwidth),
+ m_prgwidth(prgwidth),
+ m_datawidth(datawidth),
+ m_family(family),
+ m_polarity(polarity),
+ m_stack_levels(stack_levels),
+ m_read_r(*this, polarity & 0xf),
+ m_write_r(*this),
+ m_read_d(*this, polarity),
+ m_write_d(*this)
+{ }
+hmcs40_cpu_device::~hmcs40_cpu_device() { }
-// device definitions
-hmcs40_cpu_device::hmcs40_cpu_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock, int family, u16 polarity, int stack_levels, int pcwidth, int prgwidth, address_map_constructor program, int datawidth, address_map_constructor data)
- : cpu_device(mconfig, type, tag, owner, clock)
- , m_program_config("program", ENDIANNESS_LITTLE, 16, prgwidth, -1, program)
- , m_data_config("data", ENDIANNESS_LITTLE, 8, datawidth, 0, data)
- , m_pcwidth(pcwidth)
- , m_prgwidth(prgwidth)
- , m_datawidth(datawidth)
- , m_family(family)
- , m_polarity(polarity)
- , m_stack_levels(stack_levels)
- , m_read_r{{*this}, {*this}, {*this}, {*this}, {*this}, {*this}, {*this}, {*this}}
- , m_write_r{{*this}, {*this}, {*this}, {*this}, {*this}, {*this}, {*this}, {*this}}
- , m_read_d(*this)
- , m_write_d(*this)
-{
-}
-hmcs43_cpu_device::hmcs43_cpu_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock, u16 polarity)
- : hmcs40_cpu_device(mconfig, type, tag, owner, clock, HMCS40_FAMILY_HMCS43, polarity, 3 /* stack levels */, 10 /* pc width */, 11 /* prg width */, address_map_constructor(FUNC(hmcs43_cpu_device::program_1k), this), 7 /* data width */, address_map_constructor(FUNC(hmcs43_cpu_device::data_80x4), this))
+hmcs43_cpu_device::hmcs43_cpu_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock, u16 polarity) :
+ hmcs40_cpu_device(mconfig, type, tag, owner, clock, HMCS43_FAMILY, polarity, 3 /* stack levels */, 10 /* pc width */, 11 /* prg width */, address_map_constructor(FUNC(hmcs43_cpu_device::program_1k), this), 7 /* data width */, address_map_constructor(FUNC(hmcs43_cpu_device::data_80x4), this))
{ }
-hd38750_device::hd38750_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
- : hmcs43_cpu_device(mconfig, HD38750, tag, owner, clock, IS_PMOS)
+hd38750_device::hd38750_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) :
+ hmcs43_cpu_device(mconfig, HD38750, tag, owner, clock, IS_PMOS)
{ }
-hd38755_device::hd38755_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
- : hmcs43_cpu_device(mconfig, HD38755, tag, owner, clock, IS_PMOS)
+hd38755_device::hd38755_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) :
+ hmcs43_cpu_device(mconfig, HD38755, tag, owner, clock, IS_PMOS)
{ }
-hd44750_device::hd44750_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
- : hmcs43_cpu_device(mconfig, HD44750, tag, owner, clock, IS_CMOS)
+hd44750_device::hd44750_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) :
+ hmcs43_cpu_device(mconfig, HD44750, tag, owner, clock, IS_CMOS)
{ }
-hd44758_device::hd44758_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
- : hmcs43_cpu_device(mconfig, HD44758, tag, owner, clock, IS_CMOS)
+hd44758_device::hd44758_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) :
+ hmcs43_cpu_device(mconfig, HD44758, tag, owner, clock, IS_CMOS)
{ }
-hmcs44_cpu_device::hmcs44_cpu_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock, u16 polarity)
- : hmcs40_cpu_device(mconfig, type, tag, owner, clock, HMCS40_FAMILY_HMCS44, polarity, 4, 11, 12, address_map_constructor(FUNC(hmcs44_cpu_device::program_2k), this), 8, address_map_constructor(FUNC(hmcs44_cpu_device::data_160x4), this))
+hmcs44_cpu_device::hmcs44_cpu_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock, u16 polarity) :
+ hmcs40_cpu_device(mconfig, type, tag, owner, clock, HMCS44_FAMILY, polarity, 4, 11, 12, address_map_constructor(FUNC(hmcs44_cpu_device::program_2k), this), 8, address_map_constructor(FUNC(hmcs44_cpu_device::data_160x4), this))
{ }
-hd38800_device::hd38800_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
- : hmcs44_cpu_device(mconfig, HD38800, tag, owner, clock, IS_PMOS)
+hd38800_device::hd38800_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) :
+ hmcs44_cpu_device(mconfig, HD38800, tag, owner, clock, IS_PMOS)
{ }
-hd38805_device::hd38805_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
- : hmcs44_cpu_device(mconfig, HD38805, tag, owner, clock, IS_PMOS)
+hd38805_device::hd38805_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) :
+ hmcs44_cpu_device(mconfig, HD38805, tag, owner, clock, IS_PMOS)
{ }
-hd44801_device::hd44801_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
- : hmcs44_cpu_device(mconfig, HD44801, tag, owner, clock, IS_CMOS)
+hd44801_device::hd44801_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) :
+ hmcs44_cpu_device(mconfig, HD44801, tag, owner, clock, IS_CMOS)
{ }
-hd44808_device::hd44808_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
- : hmcs44_cpu_device(mconfig, HD44808, tag, owner, clock, IS_CMOS)
+hd44808_device::hd44808_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) :
+ hmcs44_cpu_device(mconfig, HD44808, tag, owner, clock, IS_CMOS)
{ }
-hmcs45_cpu_device::hmcs45_cpu_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock, u16 polarity)
- : hmcs40_cpu_device(mconfig, type, tag, owner, clock, HMCS40_FAMILY_HMCS45, polarity, 4, 11, 12, address_map_constructor(FUNC(hmcs45_cpu_device::program_2k), this), 8, address_map_constructor(FUNC(hmcs45_cpu_device::data_160x4), this))
+hmcs45_cpu_device::hmcs45_cpu_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock, u16 polarity) :
+ hmcs40_cpu_device(mconfig, type, tag, owner, clock, HMCS45_FAMILY, polarity, 4, 11, 12, address_map_constructor(FUNC(hmcs45_cpu_device::program_2k), this), 8, address_map_constructor(FUNC(hmcs45_cpu_device::data_160x4), this))
{ }
-hd38820_device::hd38820_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
- : hmcs45_cpu_device(mconfig, HD38820, tag, owner, clock, IS_PMOS)
+hd38820_device::hd38820_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) :
+ hmcs45_cpu_device(mconfig, HD38820, tag, owner, clock, IS_PMOS)
{ }
-hd38825_device::hd38825_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
- : hmcs45_cpu_device(mconfig, HD38825, tag, owner, clock, IS_PMOS)
+hd38825_device::hd38825_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) :
+ hmcs45_cpu_device(mconfig, HD38825, tag, owner, clock, IS_PMOS)
{ }
-hd44820_device::hd44820_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
- : hmcs45_cpu_device(mconfig, HD44820, tag, owner, clock, IS_CMOS)
+hd44820_device::hd44820_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) :
+ hmcs45_cpu_device(mconfig, HD44820, tag, owner, clock, IS_CMOS)
{ }
-hd44828_device::hd44828_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
- : hmcs45_cpu_device(mconfig, HD44828, tag, owner, clock, IS_CMOS)
+hd44828_device::hd44828_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) :
+ hmcs45_cpu_device(mconfig, HD44828, tag, owner, clock, IS_CMOS)
{ }
-device_memory_interface::space_config_vector hmcs40_cpu_device::memory_space_config() const
-{
- return space_config_vector {
- std::make_pair(AS_PROGRAM, &m_program_config),
- std::make_pair(AS_DATA, &m_data_config)
- };
-}
-// disasm
-void hmcs40_cpu_device::state_string_export(const device_state_entry &entry, std::string &str) const
-{
- switch (entry.index())
- {
- case STATE_GENFLAGS:
- str = string_format("%c%c",
- m_c ? 'C':'c',
- m_s ? 'S':'s'
- );
- break;
+hmcs46_cpu_device::hmcs46_cpu_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock, u16 polarity) :
+ hmcs40_cpu_device(mconfig, type, tag, owner, clock, HMCS46_FAMILY, polarity, 4, 12, 12, address_map_constructor(FUNC(hmcs46_cpu_device::program_2k), this), 8, address_map_constructor(FUNC(hmcs46_cpu_device::data_256x4), this))
+{ }
- default: break;
- }
-}
+hd44840_device::hd44840_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) :
+ hmcs46_cpu_device(mconfig, HD44840, tag, owner, clock, IS_CMOS)
+{ }
+hd44848_device::hd44848_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) :
+ hmcs46_cpu_device(mconfig, HD44848, tag, owner, clock, IS_CMOS)
+{ }
-std::unique_ptr<util::disasm_interface> hmcs40_cpu_device::create_disassembler()
-{
- return std::make_unique<hmcs40_disassembler>();
-}
+
+hmcs47_cpu_device::hmcs47_cpu_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock, u16 polarity) :
+ hmcs40_cpu_device(mconfig, type, tag, owner, clock, HMCS47_FAMILY, polarity, 4, 12, 12, address_map_constructor(FUNC(hmcs47_cpu_device::program_2k), this), 8, address_map_constructor(FUNC(hmcs47_cpu_device::data_256x4), this))
+{ }
+
+hd38870_device::hd38870_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) :
+ hmcs47_cpu_device(mconfig, HD38870, tag, owner, clock, IS_PMOS)
+{ }
+hd44860_device::hd44860_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) :
+ hmcs47_cpu_device(mconfig, HD44860, tag, owner, clock, IS_CMOS)
+{ }
+hd44868_device::hd44868_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) :
+ hmcs47_cpu_device(mconfig, HD44868, tag, owner, clock, IS_CMOS)
+{ }
//-------------------------------------------------
-// device_start - device-specific startup
+// initialization
//-------------------------------------------------
-enum
-{
- HMCS40_PC=1, HMCS40_A, HMCS40_B,
- HMCS40_X, HMCS40_SPX, HMCS40_Y, HMCS40_SPY
-};
-
void hmcs40_cpu_device::device_start()
{
m_program = &space(AS_PROGRAM);
@@ -202,19 +185,6 @@ void hmcs40_cpu_device::device_start()
m_datamask = (1 << m_datawidth) - 1;
m_pcmask = (1 << m_pcwidth) - 1;
- m_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(hmcs40_cpu_device::simple_timer_cb), this));
- reset_prescaler();
-
- // resolve callbacks
- for (int i = 0; i < 8; i++)
- {
- m_read_r[i].resolve_safe(m_polarity & 0xf);
- m_write_r[i].resolve_safe();
- }
-
- m_read_d.resolve_safe(m_polarity);
- m_write_d.resolve_safe();
-
// zerofill
memset(m_stack, 0, sizeof(m_stack));
m_op = 0;
@@ -222,9 +192,12 @@ void hmcs40_cpu_device::device_start()
m_i = 0;
m_eint_line = 0;
m_halt = 0;
+ m_prescaler = 0;
+ m_block_int = false;
+
m_pc = 0;
m_prev_pc = 0;
- m_page = 0;
+ m_pc_upper = 0;
m_a = 0;
m_b = 0;
m_x = 0;
@@ -233,6 +206,7 @@ void hmcs40_cpu_device::device_start()
m_spy = 0;
m_s = 1;
m_c = 0;
+
m_tc = 0;
m_cf = 0;
m_ie = 0;
@@ -250,10 +224,12 @@ void hmcs40_cpu_device::device_start()
save_item(NAME(m_i));
save_item(NAME(m_eint_line));
save_item(NAME(m_halt));
- save_item(NAME(m_timer_halted_remain));
+ save_item(NAME(m_prescaler));
+ save_item(NAME(m_block_int));
+
save_item(NAME(m_pc));
save_item(NAME(m_prev_pc));
- save_item(NAME(m_page));
+ save_item(NAME(m_pc_upper));
save_item(NAME(m_a));
save_item(NAME(m_b));
save_item(NAME(m_x));
@@ -262,6 +238,7 @@ void hmcs40_cpu_device::device_start()
save_item(NAME(m_spy));
save_item(NAME(m_s));
save_item(NAME(m_c));
+
save_item(NAME(m_tc));
save_item(NAME(m_cf));
save_item(NAME(m_ie));
@@ -270,31 +247,28 @@ void hmcs40_cpu_device::device_start()
save_item(NAME(m_if));
save_item(NAME(m_tf));
save_item(NAME(m_int));
-
save_item(NAME(m_r));
save_item(NAME(m_d));
// register state for debugger
- state_add(HMCS40_PC, "PC", m_pc).formatstr("%04X");
- state_add(HMCS40_A, "A", m_a).formatstr("%01X");
- state_add(HMCS40_B, "B", m_b).formatstr("%01X");
- state_add(HMCS40_X, "X", m_x).formatstr("%01X");
- state_add(HMCS40_SPX, "SPX", m_spx).formatstr("%01X");
- state_add(HMCS40_Y, "Y", m_y).formatstr("%01X");
- state_add(HMCS40_SPY, "SPY", m_spy).formatstr("%01X");
-
state_add(STATE_GENPC, "GENPC", m_pc).formatstr("%04X").noshow();
state_add(STATE_GENPCBASE, "CURPC", m_pc).formatstr("%04X").noshow();
state_add(STATE_GENFLAGS, "GENFLAGS", m_s).formatstr("%2s").noshow();
- set_icountptr(m_icount);
-}
-
+ m_state_count = 0;
+ state_add(++m_state_count, "PC", m_pc).formatstr("%04X"); // 1
+ state_add(++m_state_count, "A", m_a).formatstr("%01X"); // 2
+ state_add(++m_state_count, "B", m_b).formatstr("%01X"); // 3
+ state_add(++m_state_count, "X", m_x).formatstr("%01X"); // 4
+ state_add(++m_state_count, "SPX", m_spx).formatstr("%01X"); // 5
+ state_add(++m_state_count, "Y", m_y).formatstr("%01X"); // 6
+ state_add(++m_state_count, "SPY", m_spy).formatstr("%01X"); // 7
+ state_add(++m_state_count, "S", m_s).formatstr("%01X").noshow(); // 8
+ state_add(++m_state_count, "C", m_c).formatstr("%01X").noshow(); // 9
-//-------------------------------------------------
-// device_reset - device-specific reset
-//-------------------------------------------------
+ set_icountptr(m_icount);
+}
void hmcs40_cpu_device::device_reset()
{
@@ -307,25 +281,113 @@ void hmcs40_cpu_device::device_reset()
m_iri = m_irt = 0;
m_if[0] = m_if[1] = m_tf = 1;
- // clear i/o
- m_d = m_polarity;
- for (int i = 0; i < 16; i++)
- hmcs40_cpu_device::write_d(i, m_polarity);
+ // all I/O ports set to input
+ reset_io();
- for (int i = 0; i < 8; i++)
- hmcs40_cpu_device::write_r(i, m_polarity & 0xf);
+ // HMCS46/47 R70 set to 1 (already the default on CMOS devices)
+ if (m_family == HMCS46_FAMILY || m_family == HMCS47_FAMILY)
+ m_r[7] |= 1;
+}
+
+
+//-------------------------------------------------
+// disasm
+//-------------------------------------------------
+
+void hmcs40_cpu_device::state_string_export(const device_state_entry &entry, std::string &str) const
+{
+ switch (entry.index())
+ {
+ case STATE_GENFLAGS:
+ str = string_format("%c%c",
+ m_c ? 'C':'c',
+ m_s ? 'S':'s'
+ );
+ break;
+
+ default: break;
+ }
+}
+
+std::unique_ptr<util::disasm_interface> hmcs40_cpu_device::create_disassembler()
+{
+ return std::make_unique<hmcs40_disassembler>();
+}
+
+
+//-------------------------------------------------
+// internal memory maps
+//-------------------------------------------------
+
+/*
+
+On HMCS42/43/44/45, only half of the ROM address range contains user-executable
+code, there is up to 128 bytes of pattern data in the 2nd half. The 2nd half
+also includes a couple of pages with factory test code by Hitachi, only executable
+when MCU test mode is enabled externally (TEST pin). This data can still be accessed
+with the P opcode.
+
+On HMCS46/47, the 2nd half can be jumped to with a bank bit from R70. These MCUs
+have 2 more banks with factory test code, but that part of the ROM is only accessible
+under MCU test mode.
+
+*/
+
+void hmcs40_cpu_device::program_1k(address_map &map)
+{
+ map(0x0000, 0x07ff).rom();
+}
+
+void hmcs40_cpu_device::program_2k(address_map &map)
+{
+ map(0x0000, 0x0fff).rom();
+}
+
+
+void hmcs40_cpu_device::data_80x4(address_map &map)
+{
+ map(0x00, 0x3f).ram();
+ map(0x40, 0x4f).ram().mirror(0x30);
+}
+
+void hmcs40_cpu_device::data_160x4(address_map &map)
+{
+ map(0x00, 0x7f).ram();
+ map(0x80, 0x8f).ram().mirror(0x30);
+ map(0xc0, 0xcf).ram().mirror(0x30);
+}
+
+void hmcs40_cpu_device::data_256x4(address_map &map)
+{
+ map(0x00, 0xff).ram();
}
+device_memory_interface::space_config_vector hmcs40_cpu_device::memory_space_config() const
+{
+ return space_config_vector {
+ std::make_pair(AS_PROGRAM, &m_program_config),
+ std::make_pair(AS_DATA, &m_data_config)
+ };
+}
//-------------------------------------------------
-// i/o handling
+// i/o ports
//-------------------------------------------------
-u8 hmcs40_cpu_device::read_r(int index)
+void hmcs40_cpu_device::reset_io()
+{
+ m_d = m_polarity;
+ m_write_d(m_polarity);
+
+ for (int i = 0; i < 8; i++)
+ hmcs40_cpu_device::write_r(i, m_polarity);
+}
+
+u8 hmcs40_cpu_device::read_r(u8 index)
{
index &= 7;
- u8 inp = m_read_r[index](index, 0xff);
+ u8 inp = m_read_r[index](index);
if (m_polarity)
return (inp & m_r[index]) & 0xf;
@@ -333,63 +395,64 @@ u8 hmcs40_cpu_device::read_r(int index)
return (inp | m_r[index]) & 0xf;
}
-void hmcs40_cpu_device::write_r(int index, u8 data)
+void hmcs40_cpu_device::write_r(u8 index, u8 data)
{
index &= 7;
data &= 0xf;
m_r[index] = data;
- m_write_r[index](index, data, 0xff);
+ m_write_r[index](index, data);
}
-int hmcs40_cpu_device::read_d(int index)
+int hmcs40_cpu_device::read_d(u8 index)
{
- index &= 15;
+ index &= 0xf;
+ u16 inp = m_read_d(0, 1 << index);
if (m_polarity)
- return (m_read_d(index, 0xffff) & m_d) >> index & 1;
+ return BIT(inp & m_d, index);
else
- return (m_read_d(index, 0xffff) | m_d) >> index & 1;
+ return BIT(inp | m_d, index);
}
-void hmcs40_cpu_device::write_d(int index, int state)
+void hmcs40_cpu_device::write_d(u8 index, int state)
{
- index &= 15;
- state = (state) ? 1 : 0;
+ index &= 0xf;
+ u16 mask = 1 << index;
- m_d = (m_d & ~(1 << index)) | state << index;
- m_write_d(index, m_d, 0xffff);
+ m_d = (m_d & ~mask) | (state ? mask : 0);
+ m_write_d(0, m_d, mask);
}
// HMCS43:
// R0 is input-only, R1 is i/o, R2,R3 are output-only, no R4-R7
// D0-D3 are i/o, D4-D15 are output-only
-u8 hmcs43_cpu_device::read_r(int index)
+u8 hmcs43_cpu_device::read_r(u8 index)
{
index &= 7;
if (index >= 2)
- logerror("%s read from %s port R%d at $%04X\n", tag(), (index >= 4) ? "unknown" : "output", index, m_prev_pc);
+ logerror("read from %s port R%d @ $%04X\n", (index >= 4) ? "unknown" : "output", index, m_prev_pc);
return hmcs40_cpu_device::read_r(index);
}
-void hmcs43_cpu_device::write_r(int index, u8 data)
+void hmcs43_cpu_device::write_r(u8 index, u8 data)
{
index &= 7;
if (index != 0 && index < 4)
hmcs40_cpu_device::write_r(index, data);
else
- logerror("%s ineffective write to port R%d = $%X at $%04X\n", tag(), index, data & 0xf, m_prev_pc);
+ logerror("ineffective write to port R%d = $%X @ $%04X\n", index, data & 0xf, m_prev_pc);
}
-int hmcs43_cpu_device::read_d(int index)
+int hmcs43_cpu_device::read_d(u8 index)
{
index &= 15;
if (index >= 4)
- logerror("%s read from output pin D%d at $%04X\n", tag(), index, m_prev_pc);
+ logerror("read from output pin D%d @ $%04X\n", index, m_prev_pc);
return hmcs40_cpu_device::read_d(index);
}
@@ -398,64 +461,101 @@ int hmcs43_cpu_device::read_d(int index)
// R0-R3 are i/o, R4,R5 are extra registers, no R6,R7
// D0-D15 are i/o
-u8 hmcs44_cpu_device::read_r(int index)
+u8 hmcs44_cpu_device::read_r(u8 index)
{
index &= 7;
if (index >= 6)
- logerror("%s read from unknown port R%d at $%04X\n", tag(), index, m_prev_pc);
+ logerror("read from unknown port R%d @ $%04X\n", index, m_prev_pc);
return hmcs40_cpu_device::read_r(index);
}
-void hmcs44_cpu_device::write_r(int index, u8 data)
+void hmcs44_cpu_device::write_r(u8 index, u8 data)
{
index &= 7;
if (index < 6)
hmcs40_cpu_device::write_r(index, data);
else
- logerror("%s ineffective write to port R%d = $%X at $%04X\n", tag(), index, data & 0xf, m_prev_pc);
+ logerror("ineffective write to port R%d = $%X @ $%04X\n", index, data & 0xf, m_prev_pc);
}
// HMCS45:
// R0-R5 are i/o, R6 is output-only, no R7
// D0-D15 are i/o
-u8 hmcs45_cpu_device::read_r(int index)
+u8 hmcs45_cpu_device::read_r(u8 index)
{
index &= 7;
if (index >= 6)
- logerror("%s read from %s port R%d at $%04X\n", tag(), (index == 7) ? "unknown" : "output", index, m_prev_pc);
+ logerror("read from %s port R%d @ $%04X\n", (index == 7) ? "unknown" : "output", index, m_prev_pc);
return hmcs40_cpu_device::read_r(index);
}
-void hmcs45_cpu_device::write_r(int index, u8 data)
+void hmcs45_cpu_device::write_r(u8 index, u8 data)
{
index &= 7;
if (index != 7)
hmcs40_cpu_device::write_r(index, data);
else
- logerror("%s ineffective write to port R%d = $%X at $%04X\n", tag(), index, data & 0xf, m_prev_pc);
+ logerror("ineffective write to port R%d = $%X @ $%04X\n", index, data & 0xf, m_prev_pc);
+}
+
+// HMCS46:
+// R0-R3 are i/o, R4,R5,R7 are extra registers, no R6
+// D0-D15 are i/o
+
+u8 hmcs46_cpu_device::read_r(u8 index)
+{
+ index &= 7;
+
+ if (index == 6)
+ logerror("read from unknown port R%d @ $%04X\n", index, m_prev_pc);
+
+ return hmcs40_cpu_device::read_r(index);
+}
+
+void hmcs46_cpu_device::write_r(u8 index, u8 data)
+{
+ index &= 7;
+
+ if (index != 6)
+ hmcs40_cpu_device::write_r(index, data);
+ else
+ logerror("ineffective write to port R%d = $%X @ $%04X\n", index, data & 0xf, m_prev_pc);
}
+// HMCS47:
+// R0-R5 are i/o, R6 is output-only, R7 is an extra register
+// D0-D15 are i/o
+
+u8 hmcs47_cpu_device::read_r(u8 index)
+{
+ index &= 7;
+
+ if (index == 6)
+ logerror("read from output port R%d @ $%04X\n", index, m_prev_pc);
+
+ return hmcs40_cpu_device::read_r(index);
+}
//-------------------------------------------------
-// interrupt/timer handling
+// interrupt/timer
//-------------------------------------------------
-void hmcs40_cpu_device::do_interrupt()
+void hmcs40_cpu_device::take_interrupt()
{
- m_icount--;
push_stack();
m_ie = 0;
// line 0/1 for external interrupt, let's use 2 for t/c interrupt
int line = (m_iri) ? m_eint_line : 2;
+ standard_irq_callback(line, m_pc);
// vector $3f, on page 0(timer/counter), or page 1(external)
// external interrupt has priority over t/c interrupt
@@ -465,25 +565,18 @@ void hmcs40_cpu_device::do_interrupt()
else
m_irt = 0;
- standard_irq_callback(line);
m_prev_pc = m_pc;
+
+ cycle();
}
void hmcs40_cpu_device::execute_set_input(int line, int state)
{
- state = (state) ? 1 : 0;
+ state = state ? 1 : 0;
// halt/unhalt mcu
if (line == HMCS40_INPUT_LINE_HLT && state != m_halt)
{
- if (state)
- {
- m_timer_halted_remain = m_timer->remaining();
- m_timer->reset();
- }
- else
- m_timer->adjust(m_timer_halted_remain);
-
m_halt = state;
return;
}
@@ -503,29 +596,13 @@ void hmcs40_cpu_device::execute_set_input(int line, int state)
// clock tc if it is in counter mode
if (m_cf && line == 1)
- increment_tc();
+ clock_timer();
}
m_int[line] = state;
}
-void hmcs40_cpu_device::reset_prescaler()
-{
- // reset 6-bit timer prescaler
- attotime base = attotime::from_ticks(4 * 64, unscaled_clock());
- m_timer->adjust(base);
-}
-
-TIMER_CALLBACK_MEMBER( hmcs40_cpu_device::simple_timer_cb )
-{
- // timer prescaler overflow
- if (!m_cf)
- increment_tc();
-
- reset_prescaler();
-}
-
-void hmcs40_cpu_device::increment_tc()
+void hmcs40_cpu_device::clock_timer()
{
// increment timer/counter
m_tc = (m_tc + 1) & 0xf;
@@ -538,6 +615,14 @@ void hmcs40_cpu_device::increment_tc()
}
}
+void hmcs40_cpu_device::clock_prescaler()
+{
+ m_prescaler = (m_prescaler + 1) & 0x3f;
+
+ // timer prescaler overflow
+ if (m_prescaler == 0 && !m_cf)
+ clock_timer();
+}
//-------------------------------------------------
@@ -559,11 +644,18 @@ inline void hmcs40_cpu_device::increment_pc()
m_pc = (m_pc & ~mask) | ((m_pc << 1 | fb) & mask);
}
+void hmcs40_cpu_device::cycle()
+{
+ m_icount--;
+ clock_prescaler();
+}
+
void hmcs40_cpu_device::execute_run()
{
// in HLT state, the internal clock is not running
if (m_halt)
{
+ debugger_wait_hook();
m_icount = 0;
return;
}
@@ -572,255 +664,132 @@ void hmcs40_cpu_device::execute_run()
{
// LPU is handled 1 cycle later
if ((m_prev_op & 0x7e0) == 0x340)
- m_pc = ((m_page << 6) | (m_pc & 0x3f)) & m_pcmask;
+ m_pc = ((m_pc_upper << 6) | (m_pc & 0x3f)) & m_pcmask;
// remember previous state
m_prev_op = m_op;
m_prev_pc = m_pc;
- // check/handle interrupt, but not in the middle of a long jump
- if (m_ie && (m_iri || m_irt) && (m_prev_op & 0x3e0) != 0x340)
- {
- do_interrupt();
- if (m_icount <= 0)
- break;
- }
+ // check/handle interrupt
+ if (m_ie && (m_iri || m_irt) && !m_block_int)
+ take_interrupt();
+ m_block_int = false;
// fetch next opcode
debugger_instruction_hook(m_pc);
- m_icount--;
m_op = m_program->read_word(m_pc) & 0x3ff;
- m_i = bitswap<8>(m_op,7,6,5,4,0,1,2,3) & 0xf; // reversed bit-order for 4-bit immediate param (except for XAMR)
+ m_i = bitswap<4>(m_op,0,1,2,3); // reversed bit-order for 4-bit immediate param (except for XAMR)
increment_pc();
+ cycle();
// handle opcode
- switch (m_op)
+ switch (m_op & 0x3f0)
{
- /* 0x000 */
-
- case 0x000: case 0x001: case 0x002: case 0x003:
- op_xsp(); break;
- case 0x004: case 0x005: case 0x006: case 0x007:
- op_sem(); break;
- case 0x008: case 0x009: case 0x00a: case 0x00b:
- op_lam(); break;
- case 0x010: case 0x011: case 0x012: case 0x013: case 0x014: case 0x015: case 0x016: case 0x017:
- case 0x018: case 0x019: case 0x01a: case 0x01b: case 0x01c: case 0x01d: case 0x01e: case 0x01f:
- op_lmiiy(); break;
- case 0x020: case 0x021: case 0x022: case 0x023:
- op_lbm(); break;
- case 0x024:
- op_blem(); break;
- case 0x030:
- op_amc(); break;
- case 0x034:
- op_am(); break;
- case 0x03c:
- op_lta(); break;
-
- case 0x040:
- op_lxa(); break;
- case 0x045:
- op_das(); break;
- case 0x046:
- op_daa(); break;
- case 0x04c:
- op_rec(); break;
- case 0x04f:
- op_sec(); break;
- case 0x050:
- op_lya(); break;
- case 0x054:
- op_iy(); break;
- case 0x058:
- op_ayy(); break;
- case 0x060:
- op_lba(); break;
- case 0x064:
- op_ib(); break;
- case 0x070: case 0x071: case 0x072: case 0x073: case 0x074: case 0x075: case 0x076: case 0x077:
- case 0x078: case 0x079: case 0x07a: case 0x07b: case 0x07c: case 0x07d: case 0x07e: case 0x07f:
- op_lai(); break;
-
- case 0x080: case 0x081: case 0x082: case 0x083: case 0x084: case 0x085: case 0x086: case 0x087:
- case 0x088: case 0x089: case 0x08a: case 0x08b: case 0x08c: case 0x08d: case 0x08e: case 0x08f:
- op_ai(); break;
- case 0x090:
- op_sed(); break;
- case 0x094:
- op_td(); break;
- case 0x0a0:
- op_seif1(); break;
- case 0x0a1:
- op_secf(); break;
- case 0x0a2:
- op_seif0(); break;
- case 0x0a4:
- op_seie(); break;
- case 0x0a5:
- op_setf(); break;
-
- case 0x0c0: case 0x0c1: case 0x0c2: case 0x0c3: case 0x0c4: case 0x0c5: case 0x0c6: case 0x0c7:
- op_lar(); break;
- case 0x0d0: case 0x0d1: case 0x0d2: case 0x0d3:
- op_sedd(); break;
- case 0x0e0: case 0x0e1: case 0x0e2: case 0x0e3: case 0x0e4: case 0x0e5: case 0x0e6: case 0x0e7:
- op_lbr(); break;
- case 0x0f0: case 0x0f1: case 0x0f2: case 0x0f3: case 0x0f4: case 0x0f5: case 0x0f6: case 0x0f7:
- case 0x0f8: case 0x0f9: case 0x0fa: case 0x0fb: case 0x0fc: case 0x0fd: case 0x0fe: case 0x0ff:
- op_xamr(); break;
-
-
- /* 0x100 */
-
- case 0x110: case 0x111:
- op_lmaiy(); break;
- case 0x114: case 0x115:
- op_lmady(); break;
- case 0x118:
- op_lay(); break;
- case 0x120:
- op_or(); break;
- case 0x124:
- op_anem(); break;
-
- case 0x140: case 0x141: case 0x142: case 0x143: case 0x144: case 0x145: case 0x146: case 0x147:
- case 0x148: case 0x149: case 0x14a: case 0x14b: case 0x14c: case 0x14d: case 0x14e: case 0x14f:
- op_lxi(); break;
- case 0x150: case 0x151: case 0x152: case 0x153: case 0x154: case 0x155: case 0x156: case 0x157:
- case 0x158: case 0x159: case 0x15a: case 0x15b: case 0x15c: case 0x15d: case 0x15e: case 0x15f:
- op_lyi(); break;
- case 0x160: case 0x161: case 0x162: case 0x163: case 0x164: case 0x165: case 0x166: case 0x167:
- case 0x168: case 0x169: case 0x16a: case 0x16b: case 0x16c: case 0x16d: case 0x16e: case 0x16f:
- op_lbi(); break;
- case 0x170: case 0x171: case 0x172: case 0x173: case 0x174: case 0x175: case 0x176: case 0x177:
- case 0x178: case 0x179: case 0x17a: case 0x17b: case 0x17c: case 0x17d: case 0x17e: case 0x17f:
- op_lti(); break;
-
- case 0x1a0:
- op_tif1(); break;
- case 0x1a1:
- op_ti1(); break;
- case 0x1a2:
- op_tif0(); break;
- case 0x1a3:
- op_ti0(); break;
- case 0x1a5:
- op_ttf(); break;
-
- case 0x1c0: case 0x1c1: case 0x1c2: case 0x1c3: case 0x1c4: case 0x1c5: case 0x1c6: case 0x1c7:
- case 0x1c8: case 0x1c9: case 0x1ca: case 0x1cb: case 0x1cc: case 0x1cd: case 0x1ce: case 0x1cf:
- case 0x1d0: case 0x1d1: case 0x1d2: case 0x1d3: case 0x1d4: case 0x1d5: case 0x1d6: case 0x1d7:
- case 0x1d8: case 0x1d9: case 0x1da: case 0x1db: case 0x1dc: case 0x1dd: case 0x1de: case 0x1df:
- case 0x1e0: case 0x1e1: case 0x1e2: case 0x1e3: case 0x1e4: case 0x1e5: case 0x1e6: case 0x1e7:
- case 0x1e8: case 0x1e9: case 0x1ea: case 0x1eb: case 0x1ec: case 0x1ed: case 0x1ee: case 0x1ef:
- case 0x1f0: case 0x1f1: case 0x1f2: case 0x1f3: case 0x1f4: case 0x1f5: case 0x1f6: case 0x1f7:
- case 0x1f8: case 0x1f9: case 0x1fa: case 0x1fb: case 0x1fc: case 0x1fd: case 0x1fe: case 0x1ff:
- op_br(); break;
-
-
- /* 0x200 */
-
- case 0x200: case 0x201: case 0x202: case 0x203:
- op_tm(); break;
- case 0x204: case 0x205: case 0x206: case 0x207:
- op_rem(); break;
- case 0x208: case 0x209: case 0x20a: case 0x20b:
- op_xma(); break;
- case 0x210: case 0x211: case 0x212: case 0x213: case 0x214: case 0x215: case 0x216: case 0x217:
- case 0x218: case 0x219: case 0x21a: case 0x21b: case 0x21c: case 0x21d: case 0x21e: case 0x21f:
- op_mnei(); break;
- case 0x220: case 0x221: case 0x222: case 0x223:
- op_xmb(); break;
- case 0x224:
- op_rotr(); break;
- case 0x225:
- op_rotl(); break;
- case 0x230:
- op_smc(); break;
- case 0x234:
- op_alem(); break;
- case 0x23c:
- op_lat(); break;
-
- case 0x240:
- op_laspx(); break;
- case 0x244:
- op_nega(); break;
- case 0x24f:
- op_tc(); break;
- case 0x250:
- op_laspy(); break;
- case 0x254:
- op_dy(); break;
- case 0x258:
- op_syy(); break;
- case 0x260:
- op_lab(); break;
- case 0x267:
- op_db(); break;
- case 0x270: case 0x271: case 0x272: case 0x273: case 0x274: case 0x275: case 0x276: case 0x277:
- case 0x278: case 0x279: case 0x27a: case 0x27b: case 0x27c: case 0x27d: case 0x27e: case 0x27f:
- op_alei(); break;
-
- case 0x280: case 0x281: case 0x282: case 0x283: case 0x284: case 0x285: case 0x286: case 0x287:
- case 0x288: case 0x289: case 0x28a: case 0x28b: case 0x28c: case 0x28d: case 0x28e: case 0x28f:
- op_ynei(); break;
- case 0x290:
- op_red(); break;
- case 0x2a0:
- op_reif1(); break;
- case 0x2a1:
- op_recf(); break;
- case 0x2a2:
- op_reif0(); break;
- case 0x2a4:
- op_reie(); break;
- case 0x2a5:
- op_retf(); break;
-
- case 0x2c0: case 0x2c1: case 0x2c2: case 0x2c3: case 0x2c4: case 0x2c5: case 0x2c6: case 0x2c7:
- op_lra(); break;
- case 0x2d0: case 0x2d1: case 0x2d2: case 0x2d3:
- op_redd(); break;
- case 0x2e0: case 0x2e1: case 0x2e2: case 0x2e3: case 0x2e4: case 0x2e5: case 0x2e6: case 0x2e7:
- op_lrb(); break;
-
-
- /* 0x300 */
- case 0x320:
- op_comb(); break;
- case 0x324:
- op_bnem(); break;
-
- case 0x340: case 0x341: case 0x342: case 0x343: case 0x344: case 0x345: case 0x346: case 0x347:
- case 0x348: case 0x349: case 0x34a: case 0x34b: case 0x34c: case 0x34d: case 0x34e: case 0x34f:
- case 0x350: case 0x351: case 0x352: case 0x353: case 0x354: case 0x355: case 0x356: case 0x357:
- case 0x358: case 0x359: case 0x35a: case 0x35b: case 0x35c: case 0x35d: case 0x35e: case 0x35f:
- op_lpu(); break;
- case 0x360: case 0x361: case 0x362: case 0x363: case 0x364: case 0x365: case 0x366: case 0x367:
- op_tbr(); break;
- case 0x368: case 0x369: case 0x36a: case 0x36b: case 0x36c: case 0x36d: case 0x36e: case 0x36f:
- op_p(); break;
-
- case 0x3a4:
- op_rtni(); break;
- case 0x3a7:
- op_rtn(); break;
-
- case 0x3c0: case 0x3c1: case 0x3c2: case 0x3c3: case 0x3c4: case 0x3c5: case 0x3c6: case 0x3c7:
- case 0x3c8: case 0x3c9: case 0x3ca: case 0x3cb: case 0x3cc: case 0x3cd: case 0x3ce: case 0x3cf:
- case 0x3d0: case 0x3d1: case 0x3d2: case 0x3d3: case 0x3d4: case 0x3d5: case 0x3d6: case 0x3d7:
- case 0x3d8: case 0x3d9: case 0x3da: case 0x3db: case 0x3dc: case 0x3dd: case 0x3de: case 0x3df:
- case 0x3e0: case 0x3e1: case 0x3e2: case 0x3e3: case 0x3e4: case 0x3e5: case 0x3e6: case 0x3e7:
- case 0x3e8: case 0x3e9: case 0x3ea: case 0x3eb: case 0x3ec: case 0x3ed: case 0x3ee: case 0x3ef:
- case 0x3f0: case 0x3f1: case 0x3f2: case 0x3f3: case 0x3f4: case 0x3f5: case 0x3f6: case 0x3f7:
- case 0x3f8: case 0x3f9: case 0x3fa: case 0x3fb: case 0x3fc: case 0x3fd: case 0x3fe: case 0x3ff:
- op_cal(); break;
+ case 0x1c0: case 0x1d0: case 0x1e0: case 0x1f0: op_br(); break;
+ case 0x3c0: case 0x3d0: case 0x3e0: case 0x3f0: op_cal(); break;
+ case 0x340: case 0x350: op_lpu(); break;
+
+ case 0x010: op_lmiiy(); break;
+ case 0x070: op_lai(); break;
+ case 0x080: op_ai(); break;
+ case 0x0f0: op_xamr(); break;
+ case 0x140: op_lxi(); break;
+ case 0x150: op_lyi(); break;
+ case 0x160: op_lbi(); break;
+ case 0x170: op_lti(); break;
+ case 0x210: op_mnei(); break;
+ case 0x270: op_alei(); break;
+ case 0x280: op_ynei(); break;
+ default:
+ switch (m_op & 0x3fc)
+ {
+ case 0x0c0: case 0x0c4: op_lar(); break;
+ case 0x0e0: case 0x0e4: op_lbr(); break;
+ case 0x2c0: case 0x2c4: op_lra(); break;
+ case 0x2e0: case 0x2e4: op_lrb(); break;
+ case 0x360: case 0x364: op_tbr(); break;
+ case 0x368: case 0x36c: op_p(); break;
+
+ case 0x000: op_xsp(); break;
+ case 0x004: op_sem(); break;
+ case 0x008: op_lam(); break;
+ case 0x020: op_lbm(); break;
+ case 0x0d0: op_sedd(); break;
+ case 0x200: op_tm(); break;
+ case 0x204: op_rem(); break;
+ case 0x208: op_xma(); break;
+ case 0x220: op_xmb(); break;
+ case 0x2d0: op_redd(); break;
default:
- op_illegal(); break;
- } /* big switch */
+ switch (m_op)
+ {
+ case 0x024: op_blem(); break;
+ case 0x030: op_amc(); break;
+ case 0x034: op_am(); break;
+ case 0x03c: op_lta(); break;
+ case 0x040: op_lxa(); break;
+ case 0x045: op_das(); break;
+ case 0x046: op_daa(); break;
+ case 0x04c: op_rec(); break;
+ case 0x04f: op_sec(); break;
+ case 0x050: op_lya(); break;
+ case 0x054: op_iy(); break;
+ case 0x058: op_ayy(); break;
+ case 0x060: op_lba(); break;
+ case 0x064: op_ib(); break;
+ case 0x090: op_sed(); break;
+ case 0x094: op_td(); break;
+ case 0x0a0: op_seif1(); break;
+ case 0x0a1: op_secf(); break;
+ case 0x0a2: op_seif0(); break;
+ case 0x0a4: op_seie(); break;
+ case 0x0a5: op_setf(); break;
+
+ case 0x110: case 0x111: op_lmaiy(); break;
+ case 0x114: case 0x115: op_lmady(); break;
+ case 0x118: op_lay(); break;
+ case 0x120: op_or(); break;
+ case 0x124: op_anem(); break;
+ case 0x1a0: op_tif1(); break;
+ case 0x1a1: op_ti1(); break;
+ case 0x1a2: op_tif0(); break;
+ case 0x1a3: op_ti0(); break;
+ case 0x1a5: op_ttf(); break;
+
+ case 0x224: op_rotr(); break;
+ case 0x225: op_rotl(); break;
+ case 0x230: op_smc(); break;
+ case 0x234: op_alem(); break;
+ case 0x23c: op_lat(); break;
+ case 0x240: op_laspx(); break;
+ case 0x244: op_nega(); break;
+ case 0x24f: op_tc(); break;
+ case 0x250: op_laspy(); break;
+ case 0x254: op_dy(); break;
+ case 0x258: op_syy(); break;
+ case 0x260: op_lab(); break;
+ case 0x267: op_db(); break;
+ case 0x290: op_red(); break;
+ case 0x2a0: op_reif1(); break;
+ case 0x2a1: op_recf(); break;
+ case 0x2a2: op_reif0(); break;
+ case 0x2a4: op_reie(); break;
+ case 0x2a5: op_retf(); break;
+
+ case 0x320: op_comb(); break;
+ case 0x324: op_bnem(); break;
+ case 0x3a4: op_rtni(); break;
+ case 0x3a7: op_rtn(); break;
+
+ default: op_illegal(); break;
+ }
+ break; // 0x3ff
+
+ }
+ break; // 0x3fc
+
+ } // 0x3f0
}
}
diff --git a/src/devices/cpu/hmcs40/hmcs40.h b/src/devices/cpu/hmcs40/hmcs40.h
index a19161f5dcf..c81ac756829 100644
--- a/src/devices/cpu/hmcs40/hmcs40.h
+++ b/src/devices/cpu/hmcs40/hmcs40.h
@@ -12,7 +12,7 @@
#pragma once
-// I/O ports setup
+// input lines
enum
{
@@ -81,9 +81,11 @@ enum
class hmcs40_cpu_device : public cpu_device
{
public:
+ virtual ~hmcs40_cpu_device();
+
// max 8 4-bit R ports
- template <std::size_t Bit> auto read_r() { return m_read_r[Bit].bind(); }
- template <std::size_t Bit> auto write_r() { return m_write_r[Bit].bind(); }
+ template <std::size_t N> auto read_r() { return m_read_r[N].bind(); }
+ template <std::size_t N> auto write_r() { return m_write_r[N].bind(); }
// 16-bit discrete
auto read_d() { return m_read_d.bind(); }
@@ -92,112 +94,117 @@ public:
protected:
enum
{
- HMCS40_FAMILY_HMCS42 = 0,
- HMCS40_FAMILY_HMCS43,
- HMCS40_FAMILY_HMCS44,
- HMCS40_FAMILY_HMCS45,
- HMCS40_FAMILY_HMCS46,
- HMCS40_FAMILY_HMCS47
+ HMCS42_FAMILY = 0,
+ HMCS43_FAMILY,
+ HMCS44_FAMILY,
+ HMCS45_FAMILY,
+ HMCS46_FAMILY,
+ HMCS47_FAMILY
};
- // construction/destruction
+ // construction
hmcs40_cpu_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock, int family, u16 polarity, int stack_levels, int pcwidth, int prgwidth, address_map_constructor program, int datawidth, address_map_constructor data);
- // device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ // device_t implementation
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
- // device_execute_interface overrides
- virtual u64 execute_clocks_to_cycles(u64 clocks) const override { return (clocks + 4 - 1) / 4; } // 4 cycles per machine cycle
- virtual u64 execute_cycles_to_clocks(u64 cycles) const override { return (cycles * 4); } // "
- virtual u32 execute_min_cycles() const override { return 1; }
- virtual u32 execute_max_cycles() const override { return 2; }
- virtual u32 execute_input_lines() const override { return 2+1; } // 3rd one is internal
+ // device_execute_interface implementation
+ virtual u64 execute_clocks_to_cycles(u64 clocks) const noexcept override { return (clocks + 4 - 1) / 4; } // 4 cycles per machine cycle
+ virtual u64 execute_cycles_to_clocks(u64 cycles) const noexcept override { return (cycles * 4); } // "
+ virtual u32 execute_min_cycles() const noexcept override { return 1; }
+ virtual u32 execute_max_cycles() const noexcept override { return 2+1; } // max 2 + interrupt
virtual void execute_set_input(int line, int state) override;
virtual void execute_run() override;
- // device_memory_interface overrides
+ // device_memory_interface implementation
virtual space_config_vector memory_space_config() const override;
- // device_disasm_interface overrides
+ // device_disasm_interface implementation
virtual std::unique_ptr<util::disasm_interface> create_disassembler() override;
virtual void state_string_export(const device_state_entry &entry, std::string &str) const override;
- // memorymaps
- void program_1k(address_map &map);
- void program_2k(address_map &map);
- void data_160x4(address_map &map);
- void data_80x4(address_map &map);
+ // memory maps
+ void program_1k(address_map &map) ATTR_COLD;
+ void program_2k(address_map &map) ATTR_COLD;
+ void data_80x4(address_map &map) ATTR_COLD;
+ void data_160x4(address_map &map) ATTR_COLD;
+ void data_256x4(address_map &map) ATTR_COLD;
address_space_config m_program_config;
address_space_config m_data_config;
address_space *m_program;
address_space *m_data;
- int m_pcwidth; // Program Counter bit-width
- int m_prgwidth;
- int m_datawidth;
+ int m_icount;
+ int m_state_count;
+
+ const int m_pcwidth; // program counter bit-width
+ const int m_prgwidth;
+ const int m_datawidth;
+ const int m_family; // MCU family (42-47)
+ const u16 m_polarity; // i/o polarity (pmos vs cmos)
+ const int m_stack_levels; // number of callstack levels
int m_pcmask;
int m_prgmask;
int m_datamask;
- int m_family; // MCU family (42-47)
- u16 m_polarity; // i/o polarity (pmos vs cmos)
- int m_stack_levels; // number of callstack levels
- u16 m_stack[4]; // max 4
- u16 m_op; // current opcode
+
+ u16 m_stack[4]; // max 4
+ u16 m_op; // current opcode
u16 m_prev_op;
- u8 m_i; // 4-bit immediate opcode param
- int m_eint_line; // which input_line caused an interrupt
- emu_timer *m_timer;
- int m_halt; // internal HLT state
- attotime m_timer_halted_remain;
- int m_icount;
+ u8 m_i; // 4-bit immediate opcode param
+ int m_eint_line; // which input_line caused an interrupt
+ int m_halt; // internal HLT state
+ u8 m_prescaler; // internal timer prescaler
+ bool m_block_int; // block interrupt on next cycle
- u16 m_pc; // Program Counter
+ u16 m_pc; // program counter
u16 m_prev_pc;
- u8 m_page; // LPU prepared page
- u8 m_a; // 4-bit Accumulator
- u8 m_b; // 4-bit B register
- u8 m_x; // 1/3/4-bit X register
- u8 m_spx; // 1/3/4-bit SPX register
- u8 m_y; // 4-bit Y register
- u8 m_spy; // 4-bit SPY register
- u8 m_s; // Status F/F (F/F = flip-flop)
- u8 m_c; // Carry F/F
- u8 m_tc; // Timer/Counter
- u8 m_cf; // CF F/F (timer mode or counter mode)
- u8 m_ie; // I/E(Interrupt Enable) F/F
- u8 m_iri; // external interrupt pending I/RI F/F
- u8 m_irt; // timer interrupt pending I/RT F/F
- u8 m_if[2]; // external interrupt mask IF0,1 F/F
- u8 m_tf; // timer interrupt mask TF F/F
- u8 m_int[2]; // INT0/1 pins state
- u8 m_r[8]; // R outputs state
- u16 m_d; // D pins state
-
- // i/o handlers
- devcb_read8 m_read_r[8];
- devcb_write8 m_write_r[8];
+ u8 m_pc_upper; // LPU prepared upper bits of PC
+ u8 m_a; // 4-bit accumulator
+ u8 m_b; // 4-bit B register
+ u8 m_x; // 1/3/4-bit X register
+ u8 m_spx; // 1/3/4-bit SPX register
+ u8 m_y; // 4-bit Y register
+ u8 m_spy; // 4-bit SPY register
+ u8 m_s; // status F/F (F/F = flip-flop)
+ u8 m_c; // carry F/F
+
+ u8 m_tc; // timer/counter
+ u8 m_cf; // CF F/F (timer mode or counter mode)
+ u8 m_ie; // I/E (interrupt enable) F/F
+ u8 m_iri; // external interrupt pending I/RI F/F
+ u8 m_irt; // timer interrupt pending I/RT F/F
+ u8 m_if[2]; // external interrupt mask IF0,1 F/F
+ u8 m_tf; // timer interrupt mask TF F/F
+ u8 m_int[2]; // INT0/1 pins state
+ u8 m_r[8]; // R outputs state
+ u16 m_d; // D pins state
+
+ // I/O handlers
+ devcb_read8::array<8> m_read_r;
+ devcb_write8::array<8> m_write_r;
devcb_read16 m_read_d;
devcb_write16 m_write_d;
// misc internal helpers
void increment_pc();
+ void cycle();
u8 ram_r();
void ram_w(u8 data);
void pop_stack();
void push_stack();
- virtual u8 read_r(int index);
- virtual void write_r(int index, u8 data);
- virtual int read_d(int index);
- virtual void write_d(int index, int state);
+ virtual void reset_io();
+ virtual u8 read_r(u8 index);
+ virtual void write_r(u8 index, u8 data);
+ virtual int read_d(u8 index);
+ virtual void write_d(u8 index, int state);
- void reset_prescaler();
- TIMER_CALLBACK_MEMBER( simple_timer_cb );
- void increment_tc();
- void do_interrupt();
+ void take_interrupt();
+ void clock_timer();
+ void clock_prescaler();
// opcode handlers
void op_illegal();
@@ -304,9 +311,9 @@ protected:
hmcs43_cpu_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock, u16 polarity);
// overrides
- virtual u8 read_r(int index) override;
- virtual void write_r(int index, u8 data) override;
- virtual int read_d(int index) override;
+ virtual u8 read_r(u8 index) override;
+ virtual void write_r(u8 index, u8 data) override;
+ virtual int read_d(u8 index) override;
};
class hd38750_device : public hmcs43_cpu_device
@@ -340,8 +347,8 @@ protected:
hmcs44_cpu_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock, u16 polarity);
// overrides
- virtual u8 read_r(int index) override;
- virtual void write_r(int index, u8 data) override;
+ virtual u8 read_r(u8 index) override;
+ virtual void write_r(u8 index, u8 data) override;
};
class hd38800_device : public hmcs44_cpu_device
@@ -375,8 +382,8 @@ protected:
hmcs45_cpu_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock, u16 polarity);
// overrides
- virtual u8 read_r(int index) override;
- virtual void write_r(int index, u8 data) override;
+ virtual u8 read_r(u8 index) override;
+ virtual void write_r(u8 index, u8 data) override;
};
class hd38820_device : public hmcs45_cpu_device
@@ -404,6 +411,56 @@ public:
};
+class hmcs46_cpu_device : public hmcs40_cpu_device
+{
+protected:
+ hmcs46_cpu_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock, u16 polarity);
+
+ // overrides
+ virtual u8 read_r(u8 index) override;
+ virtual void write_r(u8 index, u8 data) override;
+};
+
+class hd44840_device : public hmcs46_cpu_device
+{
+public:
+ hd44840_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+};
+
+class hd44848_device : public hmcs46_cpu_device
+{
+public:
+ hd44848_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+};
+
+
+class hmcs47_cpu_device : public hmcs40_cpu_device
+{
+protected:
+ hmcs47_cpu_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock, u16 polarity);
+
+ // overrides
+ virtual u8 read_r(u8 index) override;
+};
+
+class hd38870_device : public hmcs47_cpu_device
+{
+public:
+ hd38870_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+};
+
+class hd44860_device : public hmcs47_cpu_device
+{
+public:
+ hd44860_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+};
+
+class hd44868_device : public hmcs47_cpu_device
+{
+public:
+ hd44868_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+};
+
DECLARE_DEVICE_TYPE(HD38750, hd38750_device)
DECLARE_DEVICE_TYPE(HD38755, hd38755_device)
@@ -420,4 +477,12 @@ DECLARE_DEVICE_TYPE(HD38825, hd38825_device)
DECLARE_DEVICE_TYPE(HD44820, hd44820_device)
DECLARE_DEVICE_TYPE(HD44828, hd44828_device)
+DECLARE_DEVICE_TYPE(HD44840, hd44840_device)
+DECLARE_DEVICE_TYPE(HD44848, hd44848_device)
+
+DECLARE_DEVICE_TYPE(HD38870, hd38870_device)
+DECLARE_DEVICE_TYPE(HD44860, hd44860_device)
+DECLARE_DEVICE_TYPE(HD44868, hd44868_device)
+
+
#endif // MAME_CPU_HMCS40_HMCS40_H
diff --git a/src/devices/cpu/hmcs40/hmcs40d.cpp b/src/devices/cpu/hmcs40/hmcs40d.cpp
index d845b7545ae..251a31cdfa5 100644
--- a/src/devices/cpu/hmcs40/hmcs40d.cpp
+++ b/src/devices/cpu/hmcs40/hmcs40d.cpp
@@ -4,7 +4,8 @@
Hitachi HMCS40 MCU family disassembler
- NOTE: start offset(basepc) is $3F, not 0
+ NOTE: start offset(basepc) is $3F, not 0. In other words, if you want a full
+ disasm from MAME's debugger: dasm x.asm,3f,1000
*/
@@ -16,7 +17,7 @@
hmcs40_disassembler::hmcs40_disassembler()
{
// init lfsr pc lut
- for (u32 i = 0, pc = 0; i < 0x40; i++)
+ for (u32 i = 0, pc = 0x3f; i < 0x40; i++)
{
m_l2r[i] = pc;
m_r2l[pc] = i;
@@ -35,9 +36,29 @@ hmcs40_disassembler::hmcs40_disassembler()
}
}
+hmcs40_disassembler::~hmcs40_disassembler()
+{
+}
+
// common lookup tables
+enum hmcs40_disassembler::e_mnemonics : unsigned
+{
+ mILL,
+ mLAB, mLBA, mLAY, mLASPX, mLASPY, mXAMR,
+ mLXA, mLYA, mLXI, mLYI, mIY, mDY, mAYY, mSYY, mXSP,
+ mLAM, mLBM, mXMA, mXMB, mLMAIY, mLMADY,
+ mLMIIY, mLAI, mLBI,
+ mAI, mIB, mDB, mAMC, mSMC, mAM, mDAA, mDAS, mNEGA, mCOMB, mSEC, mREC, mTC, mROTL, mROTR, mOR,
+ mMNEI, mYNEI, mANEM, mBNEM, mALEI, mALEM, mBLEM,
+ mSEM, mREM, mTM,
+ mBR, mCAL, mLPU, mTBR, mRTN,
+ mSEIE, mSEIF0, mSEIF1, mSETF, mSECF, mREIE, mREIF0, mREIF1, mRETF, mRECF, mTI0, mTI1, mTIF0, mTIF1, mTTF, mLTI, mLTA, mLAT, mRTNI,
+ mSED, mRED, mTD, mSEDD, mREDD, mLAR, mLBR, mLRA, mLRB, mP,
+ mNOP
+};
+
const char *const hmcs40_disassembler::s_mnemonics[] =
{
"?",
@@ -81,7 +102,7 @@ const u32 hmcs40_disassembler::s_flags[] =
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0,
0, 0, 0,
- 0, STEP_OVER, 0, 0, STEP_OUT,
+ STEP_COND, STEP_OVER | STEP_COND, 0, 0, STEP_OUT,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, STEP_OUT,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0
@@ -89,89 +110,89 @@ const u32 hmcs40_disassembler::s_flags[] =
const u8 hmcs40_disassembler::hmcs40_mnemonic[0x400] =
{
-/* 0 1 2 3 4 5 6 7 8 9 A B C D E F */
- /* 0x000 */
+// 0 1 2 3 4 5 6 7 8 9 A B C D E F
+ // 0x000
mNOP, mXSP, mXSP, mXSP, mSEM, mSEM, mSEM, mSEM, mLAM, mLAM, mLAM, mLAM, 0, 0, 0, 0,
mLMIIY,mLMIIY,mLMIIY,mLMIIY,mLMIIY,mLMIIY,mLMIIY,mLMIIY,mLMIIY,mLMIIY,mLMIIY,mLMIIY,mLMIIY,mLMIIY,mLMIIY,mLMIIY,
mLBM, mLBM, mLBM, mLBM, mBLEM, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
mAMC, 0, 0, 0, mAM, 0, 0, 0, 0, 0, 0, 0, mLTA, 0, 0, 0,
- /* 0x040 */
+ // 0x040
mLXA, 0, 0, 0, 0, mDAS, mDAA, 0, 0, 0, 0, 0, mREC, 0, 0, mSEC,
mLYA, 0, 0, 0, mIY, 0, 0, 0, mAYY, 0, 0, 0, 0, 0, 0, 0,
mLBA, 0, 0, 0, mIB, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
mLAI, mLAI, mLAI, mLAI, mLAI, mLAI, mLAI, mLAI, mLAI, mLAI, mLAI, mLAI, mLAI, mLAI, mLAI, mLAI,
- /* 0x080 */
+ // 0x080
mAI, mAI, mAI, mAI, mAI, mAI, mAI, mAI, mAI, mAI, mAI, mAI, mAI, mAI, mAI, mAI,
mSED, 0, 0, 0, mTD, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
mSEIF1,mSECF, mSEIF0,0, mSEIE, mSETF, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- /* 0x0c0 */
+ // 0x0c0
mLAR, mLAR, mLAR, mLAR, mLAR, mLAR, mLAR, mLAR, 0, 0, 0, 0, 0, 0, 0, 0,
mSEDD, mSEDD, mSEDD, mSEDD, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
mLBR, mLBR, mLBR, mLBR, mLBR, mLBR, mLBR, mLBR, 0, 0, 0, 0, 0, 0, 0, 0,
mXAMR, mXAMR, mXAMR, mXAMR, mXAMR, mXAMR, mXAMR, mXAMR, mXAMR, mXAMR, mXAMR, mXAMR, mXAMR, mXAMR, mXAMR, mXAMR,
-/* 0 1 2 3 4 5 6 7 8 9 A B C D E F */
- /* 0x100 */
+// 0 1 2 3 4 5 6 7 8 9 A B C D E F
+ // 0x100
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
mLMAIY,mLMAIY,0, 0, mLMADY,mLMADY,0, 0, mLAY, 0, 0, 0, 0, 0, 0, 0,
mOR, 0, 0, 0, mANEM, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- /* 0x140 */
+ // 0x140
mLXI, mLXI, mLXI, mLXI, mLXI, mLXI, mLXI, mLXI, mLXI, mLXI, mLXI, mLXI, mLXI, mLXI, mLXI, mLXI,
mLYI, mLYI, mLYI, mLYI, mLYI, mLYI, mLYI, mLYI, mLYI, mLYI, mLYI, mLYI, mLYI, mLYI, mLYI, mLYI,
mLBI, mLBI, mLBI, mLBI, mLBI, mLBI, mLBI, mLBI, mLBI, mLBI, mLBI, mLBI, mLBI, mLBI, mLBI, mLBI,
mLTI, mLTI, mLTI, mLTI, mLTI, mLTI, mLTI, mLTI, mLTI, mLTI, mLTI, mLTI, mLTI, mLTI, mLTI, mLTI,
- /* 0x180 */
+ // 0x180
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
mTIF1, mTI1, mTIF0, mTI0, 0, mTTF, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- /* 0x1c0 */
+ // 0x1c0
mBR, mBR, mBR, mBR, mBR, mBR, mBR, mBR, mBR, mBR, mBR, mBR, mBR, mBR, mBR, mBR,
mBR, mBR, mBR, mBR, mBR, mBR, mBR, mBR, mBR, mBR, mBR, mBR, mBR, mBR, mBR, mBR,
mBR, mBR, mBR, mBR, mBR, mBR, mBR, mBR, mBR, mBR, mBR, mBR, mBR, mBR, mBR, mBR,
mBR, mBR, mBR, mBR, mBR, mBR, mBR, mBR, mBR, mBR, mBR, mBR, mBR, mBR, mBR, mBR,
-/* 0 1 2 3 4 5 6 7 8 9 A B C D E F */
- /* 0x200 */
+// 0 1 2 3 4 5 6 7 8 9 A B C D E F
+ // 0x200
mTM, mTM, mTM, mTM, mREM, mREM, mREM, mREM, mXMA, mXMA, mXMA, mXMA, 0, 0, 0, 0,
mMNEI, mMNEI, mMNEI, mMNEI, mMNEI, mMNEI, mMNEI, mMNEI, mMNEI, mMNEI, mMNEI, mMNEI, mMNEI, mMNEI, mMNEI, mMNEI,
mXMB, mXMB, mXMB, mXMB, mROTR, mROTL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
mSMC, 0, 0, 0, mALEM, 0, 0, 0, 0, 0, 0, 0, mLAT, 0, 0, 0,
- /* 0x240 */
+ // 0x240
mLASPX,0, 0, 0, mNEGA, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, mTC,
mLASPY,0, 0, 0, mDY, 0, 0, 0, mSYY, 0, 0, 0, 0, 0, 0, 0,
mLAB, 0, 0, 0, 0, 0, 0, mDB, 0, 0, 0, 0, 0, 0, 0, 0,
mALEI, mALEI, mALEI, mALEI, mALEI, mALEI, mALEI, mALEI, mALEI, mALEI, mALEI, mALEI, mALEI, mALEI, mALEI, mALEI,
- /* 0x280 */
+ // 0x280
mYNEI, mYNEI, mYNEI, mYNEI, mYNEI, mYNEI, mYNEI, mYNEI, mYNEI, mYNEI, mYNEI, mYNEI, mYNEI, mYNEI, mYNEI, mYNEI,
mRED, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
mREIF1,mRECF, mREIF0,0, mREIE, mRETF, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- /* 0x2c0 */
+ // 0x2c0
mLRA, mLRA, mLRA, mLRA, mLRA, mLRA, mLRA, mLRA, 0, 0, 0, 0, 0, 0, 0, 0,
mREDD, mREDD, mREDD, mREDD, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
mLRB, mLRB, mLRB, mLRB, mLRB, mLRB, mLRB, mLRB, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-/* 0 1 2 3 4 5 6 7 8 9 A B C D E F */
- /* 0x300 */
+// 0 1 2 3 4 5 6 7 8 9 A B C D E F
+ // 0x300
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
mCOMB, 0, 0, 0, mBNEM, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- /* 0x340 */
+ // 0x340
mLPU, mLPU, mLPU, mLPU, mLPU, mLPU, mLPU, mLPU, mLPU, mLPU, mLPU, mLPU, mLPU, mLPU, mLPU, mLPU,
mLPU, mLPU, mLPU, mLPU, mLPU, mLPU, mLPU, mLPU, mLPU, mLPU, mLPU, mLPU, mLPU, mLPU, mLPU, mLPU,
mTBR, mTBR, mTBR, mTBR, mTBR, mTBR, mTBR, mTBR, mP, mP, mP, mP, mP, mP, mP, mP,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- /* 0x380 */
+ // 0x380
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, mRTNI, 0, 0, mRTN, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- /* 0x3c0 */
+ // 0x3c0
mCAL, mCAL, mCAL, mCAL, mCAL, mCAL, mCAL, mCAL, mCAL, mCAL, mCAL, mCAL, mCAL, mCAL, mCAL, mCAL,
mCAL, mCAL, mCAL, mCAL, mCAL, mCAL, mCAL, mCAL, mCAL, mCAL, mCAL, mCAL, mCAL, mCAL, mCAL, mCAL,
mCAL, mCAL, mCAL, mCAL, mCAL, mCAL, mCAL, mCAL, mCAL, mCAL, mCAL, mCAL, mCAL, mCAL, mCAL, mCAL,
@@ -199,7 +220,7 @@ offs_t hmcs40_disassembler::disassemble(std::ostream &stream, offs_t pc, const d
}
else
{
- util::stream_format(stream, "%-6s ", s_mnemonics[instr]);
+ util::stream_format(stream, "%-8s", s_mnemonics[instr]);
// opcode parameter
if (bits != 0)
@@ -215,11 +236,7 @@ offs_t hmcs40_disassembler::disassemble(std::ostream &stream, offs_t pc, const d
}
param &= ((1 << bits) - 1);
-
- if (bits > 5)
- util::stream_format(stream, "$%02X", param);
- else
- util::stream_format(stream, "%d", param);
+ util::stream_format(stream, (bits > 4) ? "$%02X" : (param < 10) ? "%d" : "$%X", param);
}
}
diff --git a/src/devices/cpu/hmcs40/hmcs40d.h b/src/devices/cpu/hmcs40/hmcs40d.h
index 0da5f51d3d9..f67ba8f3b9f 100644
--- a/src/devices/cpu/hmcs40/hmcs40d.h
+++ b/src/devices/cpu/hmcs40/hmcs40d.h
@@ -15,32 +15,18 @@ class hmcs40_disassembler : public util::disasm_interface
{
public:
hmcs40_disassembler();
- virtual ~hmcs40_disassembler() = default;
+ virtual ~hmcs40_disassembler();
virtual u32 opcode_alignment() const override { return 1; }
- virtual u32 interface_flags() const override { return NONLINEAR_PC | PAGED; }
+ virtual u32 interface_flags() const override { return NONLINEAR_PC | PAGED2LEVEL; }
virtual u32 page_address_bits() const override { return 6; }
+ virtual u32 page2_address_bits() const override { return 5; }
virtual offs_t pc_linear_to_real(offs_t pc) const override { return (pc & ~0x3f) | m_l2r[pc & 0x3f]; }
virtual offs_t pc_real_to_linear(offs_t pc) const override { return (pc & ~0x3f) | m_r2l[pc & 0x3f]; }
virtual offs_t disassemble(std::ostream &stream, offs_t pc, const data_buffer &opcodes, const data_buffer &params) override;
private:
- enum e_mnemonics
- {
- mILL,
- mLAB, mLBA, mLAY, mLASPX, mLASPY, mXAMR,
- mLXA, mLYA, mLXI, mLYI, mIY, mDY, mAYY, mSYY, mXSP,
- mLAM, mLBM, mXMA, mXMB, mLMAIY, mLMADY,
- mLMIIY, mLAI, mLBI,
- mAI, mIB, mDB, mAMC, mSMC, mAM, mDAA, mDAS, mNEGA, mCOMB, mSEC, mREC, mTC, mROTL, mROTR, mOR,
- mMNEI, mYNEI, mANEM, mBNEM, mALEI, mALEM, mBLEM,
- mSEM, mREM, mTM,
- mBR, mCAL, mLPU, mTBR, mRTN,
- mSEIE, mSEIF0, mSEIF1, mSETF, mSECF, mREIE, mREIF0, mREIF1, mRETF, mRECF, mTI0, mTI1, mTIF0, mTIF1, mTTF, mLTI, mLTA, mLAT, mRTNI,
- mSED, mRED, mTD, mSEDD, mREDD, mLAR, mLBR, mLRA, mLRB, mP,
- mNOP
- };
-
+ enum e_mnemonics : unsigned;
static const char *const s_mnemonics[];
static const s8 s_bits[];
static const u32 s_flags[];
@@ -50,4 +36,4 @@ private:
u8 m_r2l[0x40];
};
-#endif
+#endif // MAME_CPU_HMCS40_HMCS40D_H
diff --git a/src/devices/cpu/hmcs40/hmcs40op.cpp b/src/devices/cpu/hmcs40/hmcs40op.cpp
index 1886768bc8d..713dd111777 100644
--- a/src/devices/cpu/hmcs40/hmcs40op.cpp
+++ b/src/devices/cpu/hmcs40/hmcs40op.cpp
@@ -36,16 +36,15 @@ void hmcs40_cpu_device::push_stack()
}
-
// instruction set
void hmcs40_cpu_device::op_illegal()
{
- logerror("%s unknown opcode $%03X at $%04X\n", tag(), m_op, m_prev_pc);
+ logerror("unknown opcode $%03X @ $%04X\n", m_op, m_prev_pc);
}
-// Register-to-Register Instruction
+// register-to-register instructions
void hmcs40_cpu_device::op_lab()
{
@@ -86,7 +85,7 @@ void hmcs40_cpu_device::op_xamr()
// HMCS42: MR0 on file 0, MR4-MR15 on file 4 (there is no file 1-3)
// HMCS43: MR0-MR3 on file 0-3, MR4-MR15 on file 4
- if (m_family == HMCS40_FAMILY_HMCS42 || m_family == HMCS40_FAMILY_HMCS43)
+ if (m_family == HMCS42_FAMILY || m_family == HMCS43_FAMILY)
address |= (address < 4) ? (address << 4) : 0x40;
// HMCS44/45/46/47: all on last file
@@ -100,7 +99,7 @@ void hmcs40_cpu_device::op_xamr()
}
-// RAM Address Instruction
+// RAM address instructions
void hmcs40_cpu_device::op_lxa()
{
@@ -144,7 +143,7 @@ void hmcs40_cpu_device::op_ayy()
{
// AYY: Add A to Y
m_y += m_a;
- m_s = m_y >> 4 & 1;
+ m_s = BIT(m_y, 4);
m_y &= 0xf;
}
@@ -152,13 +151,13 @@ void hmcs40_cpu_device::op_syy()
{
// SYY: Subtract A from Y
m_y -= m_a;
- m_s = ~m_y >> 4 & 1;
+ m_s = BIT(~m_y, 4);
m_y &= 0xf;
}
void hmcs40_cpu_device::op_xsp()
{
- // XSP (XY): Exchange X and SPX, Y and SPY, or NOP if 0
+ // XSP(XY): Exchange X and SPX, Y and SPY, or NOP if 0
if (m_op & 1)
{
u8 old_x = m_x;
@@ -174,25 +173,25 @@ void hmcs40_cpu_device::op_xsp()
}
-// Ram Register Instruction
+// RAM register instructions
void hmcs40_cpu_device::op_lam()
{
- // LAM (XY): Load A from Memory
+ // LAM(XY): Load A from Memory
m_a = ram_r();
op_xsp();
}
void hmcs40_cpu_device::op_lbm()
{
- // LBM (XY): Load B from Memory
+ // LBM(XY): Load B from Memory
m_b = ram_r();
op_xsp();
}
void hmcs40_cpu_device::op_xma()
{
- // XMA (XY): Exchange Memory and A
+ // XMA(XY): Exchange Memory and A
u8 old_a = m_a;
m_a = ram_r();
ram_w(old_a);
@@ -201,7 +200,7 @@ void hmcs40_cpu_device::op_xma()
void hmcs40_cpu_device::op_xmb()
{
- // XMB (XY): Exchange Memory and B
+ // XMB(XY): Exchange Memory and B
u8 old_b = m_b;
m_b = ram_r();
ram_w(old_b);
@@ -210,7 +209,7 @@ void hmcs40_cpu_device::op_xmb()
void hmcs40_cpu_device::op_lmaiy()
{
- // LMAIY (X): Load Memory from A, Increment Y
+ // LMAIY(X): Load Memory from A, Increment Y
ram_w(m_a);
op_iy();
op_xsp();
@@ -218,14 +217,14 @@ void hmcs40_cpu_device::op_lmaiy()
void hmcs40_cpu_device::op_lmady()
{
- // LMADY (X): Load Memory from A, Decrement Y
+ // LMADY(X): Load Memory from A, Decrement Y
ram_w(m_a);
op_dy();
op_xsp();
}
-// Immediate Instruction
+// immediate instructions
void hmcs40_cpu_device::op_lmiiy()
{
@@ -247,13 +246,13 @@ void hmcs40_cpu_device::op_lbi()
}
-// Arithmetic Instruction
+// arithmetic instructions
void hmcs40_cpu_device::op_ai()
{
// AI i: Add Immediate to A
m_a += m_i;
- m_s = m_a >> 4 & 1;
+ m_s = BIT(m_a, 4);
m_a &= 0xf;
}
@@ -275,7 +274,7 @@ void hmcs40_cpu_device::op_amc()
{
// AMC: Add A to Memory with Carry
m_a += ram_r() + m_c;
- m_c = m_a >> 4 & 1;
+ m_c = BIT(m_a, 4);
m_s = m_c;
m_a &= 0xf;
}
@@ -284,7 +283,7 @@ void hmcs40_cpu_device::op_smc()
{
// SMC: Subtract A from Memory with Carry
m_a = ram_r() - m_a - (m_c ^ 1);
- m_c = ~m_a >> 4 & 1;
+ m_c = BIT(~m_a, 4);
m_s = m_c;
m_a &= 0xf;
}
@@ -293,7 +292,7 @@ void hmcs40_cpu_device::op_am()
{
// AM: Add A to Memory
m_a += ram_r();
- m_s = m_a >> 4 & 1;
+ m_s = BIT(m_a, 4);
m_a &= 0xf;
}
@@ -351,7 +350,7 @@ void hmcs40_cpu_device::op_rotl()
{
// ROTL: Rotate Left A with Carry
m_a = m_a << 1 | m_c;
- m_c = m_a >> 4 & 1;
+ m_c = BIT(m_a, 4);
m_a &= 0xf;
}
@@ -365,17 +364,17 @@ void hmcs40_cpu_device::op_rotr()
void hmcs40_cpu_device::op_or()
{
- // OR: OR A with B
+ // OR: Or A with B
m_a |= m_b;
}
-// Compare Instruction
+// compare instructions
void hmcs40_cpu_device::op_mnei()
{
// MNEI i: Memory Not Equal to Immediate
- m_s = (ram_r() != m_i);
+ m_s = (m_i != ram_r());
}
void hmcs40_cpu_device::op_ynei()
@@ -415,7 +414,7 @@ void hmcs40_cpu_device::op_blem()
}
-// RAM Bit Manipulation Instruction
+// RAM bit manipulation instructions
void hmcs40_cpu_device::op_sem()
{
@@ -432,11 +431,11 @@ void hmcs40_cpu_device::op_rem()
void hmcs40_cpu_device::op_tm()
{
// TM n: Test Memory Bit
- m_s = ram_r() >> (m_op & 3) & 1;
+ m_s = BIT(ram_r(), m_op & 3);
}
-// ROM Address Instruction
+// ROM address instructions
void hmcs40_cpu_device::op_br()
{
@@ -452,6 +451,7 @@ void hmcs40_cpu_device::op_cal()
// CAL a: Subroutine Jump on Status 1
if (m_s)
{
+ m_block_int = true;
push_stack();
m_pc = m_op & 0x3f; // short calls default to page 0
}
@@ -463,7 +463,14 @@ void hmcs40_cpu_device::op_lpu()
{
// LPU u: Load Program Counter Upper on Status 1
if (m_s)
- m_page = m_op & 0x1f;
+ {
+ m_block_int = true;
+ m_pc_upper = m_op & 0x1f;
+
+ // on HMCS46/47, also latches bank from R70
+ if (m_family == HMCS46_FAMILY || m_family == HMCS47_FAMILY)
+ m_pc_upper |= ~m_r[7] << 5 & 0x20;
+ }
else
m_op |= 0x400; // indicate unhandled LPU
}
@@ -482,7 +489,7 @@ void hmcs40_cpu_device::op_rtn()
}
-// Interrupt Instruction
+// interrupt instructions
void hmcs40_cpu_device::op_seie()
{
@@ -578,14 +585,14 @@ void hmcs40_cpu_device::op_lti()
{
// LTI i: Load Timer/Counter from Immediate
m_tc = m_i;
- reset_prescaler();
+ m_prescaler = 0;
}
void hmcs40_cpu_device::op_lta()
{
// LTA: Load Timer/Counter from A
m_tc = m_a;
- reset_prescaler();
+ m_prescaler = 0;
}
void hmcs40_cpu_device::op_lat()
@@ -602,7 +609,7 @@ void hmcs40_cpu_device::op_rtni()
}
-// Input/Output Instruction
+// input/output instructions
void hmcs40_cpu_device::op_sed()
{
@@ -661,22 +668,23 @@ void hmcs40_cpu_device::op_lrb()
void hmcs40_cpu_device::op_p()
{
// P p: Pattern Generation
- m_icount--;
+ cycle();
+
u16 address = m_a | m_b << 4 | m_c << 8 | (m_op & 7) << 9 | (m_pc & ~0x3f);
- u16 o = m_program->read_word(address & m_prgmask);
+ u16 data = m_program->read_word(address & m_prgmask);
// destination is determined by the 2 highest bits
- if (o & 0x100)
+ if (data & 0x100)
{
// B3 B2 B1 B0 A0 A1 A2 A3
- m_a = bitswap<8>(o,7,6,5,4,0,1,2,3) & 0xf;
- m_b = o >> 4 & 0xf;
+ m_a = bitswap<4>(data,0,1,2,3);
+ m_b = data >> 4 & 0xf;
}
- if (o & 0x200)
+ if (data & 0x200)
{
// R20 R21 R22 R23 R30 R31 R32 R33
- o = bitswap<8>(o,0,1,2,3,4,5,6,7);
- write_r(2, o & 0xf);
- write_r(3, o >> 4 & 0xf);
+ data = bitswap<8>(data,0,1,2,3,4,5,6,7);
+ write_r(2, data & 0xf);
+ write_r(3, data >> 4 & 0xf);
}
}