summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/cpu/hmcs400/hmcs400.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/devices/cpu/hmcs400/hmcs400.cpp')
-rw-r--r--src/devices/cpu/hmcs400/hmcs400.cpp194
1 files changed, 194 insertions, 0 deletions
diff --git a/src/devices/cpu/hmcs400/hmcs400.cpp b/src/devices/cpu/hmcs400/hmcs400.cpp
new file mode 100644
index 00000000000..40f32275166
--- /dev/null
+++ b/src/devices/cpu/hmcs400/hmcs400.cpp
@@ -0,0 +1,194 @@
+// license:BSD-3-Clause
+// copyright-holders:hap
+/*
+
+Hitachi HMCS400 MCU family cores
+
+TODO:
+- what happens when accessing ROM/RAM out of address range? Hitachi documentation
+ says 'unused', but maybe it's mirrored?
+
+*/
+
+#include "emu.h"
+#include "hmcs400.h"
+#include "hmcs400d.h"
+
+
+//-------------------------------------------------
+// device types
+//-------------------------------------------------
+
+// C = standard
+// CL = low-power
+// AC = high-speed
+
+// HMCS408, HMCS414, HMCS424 have a mask option for the system clock divider
+// HMCS408 and newer MCUs add 2 opcodes: LAW and LWA
+
+// HMCS402C/CL/AC, 64 pins DP-64S or FP-64, 2Kx10 ROM, 160x4 RAM
+DEFINE_DEVICE_TYPE(HD614022, hd614022_device, "hd614022", "Hitachi HD614022") // C
+DEFINE_DEVICE_TYPE(HD614025, hd614025_device, "hd614025", "Hitachi HD614025") // CL
+DEFINE_DEVICE_TYPE(HD614028, hd614028_device, "hd614028", "Hitachi HD614028") // AC
+
+// HMCS404C/CL/AC, 64 pins DP-64S or FP-64, 4Kx10 ROM, 256x4 RAM
+DEFINE_DEVICE_TYPE(HD614042, hd614042_device, "hd614042", "Hitachi HD614042") // C
+DEFINE_DEVICE_TYPE(HD614045, hd614045_device, "hd614045", "Hitachi HD614045") // CL
+DEFINE_DEVICE_TYPE(HD614048, hd614048_device, "hd614048", "Hitachi HD614048") // AC
+
+// HMCS408C/CL/AC, 64 pins DP-64S or FP-64, 8Kx10 ROM, 512x4 RAM
+DEFINE_DEVICE_TYPE(HD614080, hd614080_device, "hd614080", "Hitachi HD614080") // C
+DEFINE_DEVICE_TYPE(HD614085, hd614085_device, "hd614085", "Hitachi HD614085") // CL
+DEFINE_DEVICE_TYPE(HD614088, hd614088_device, "hd614088", "Hitachi HD614088") // AC
+
+
+//-------------------------------------------------
+// constructor
+//-------------------------------------------------
+
+hmcs400_cpu_device::hmcs400_cpu_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock, u32 rom_size, u32 ram_size) :
+ cpu_device(mconfig, type, tag, owner, clock),
+ m_program_config("program", ENDIANNESS_LITTLE, 16, 14, -1, address_map_constructor(FUNC(hmcs400_cpu_device::program_map), this)),
+ m_data_config("data", ENDIANNESS_LITTLE, 8, 10, 0, address_map_constructor(FUNC(hmcs400_cpu_device::data_map), this)),
+ m_rom_size(rom_size),
+ m_ram_size(ram_size),
+ m_has_div(false),
+ m_has_law(false),
+ m_divider(8)
+{ }
+
+hmcs400_cpu_device::~hmcs400_cpu_device() { }
+
+
+hmcs402_cpu_device::hmcs402_cpu_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock) :
+ hmcs400_cpu_device(mconfig, type, tag, owner, clock, 0x800, 96)
+{ }
+
+hd614022_device::hd614022_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) :
+ hmcs402_cpu_device(mconfig, HD614022, tag, owner, clock)
+{ }
+hd614025_device::hd614025_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) :
+ hmcs402_cpu_device(mconfig, HD614025, tag, owner, clock)
+{ }
+hd614028_device::hd614028_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) :
+ hmcs402_cpu_device(mconfig, HD614028, tag, owner, clock)
+{ }
+
+
+hmcs404_cpu_device::hmcs404_cpu_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock) :
+ hmcs400_cpu_device(mconfig, type, tag, owner, clock, 0x1000, 192)
+{ }
+
+hd614042_device::hd614042_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) :
+ hmcs404_cpu_device(mconfig, HD614042, tag, owner, clock)
+{ }
+hd614045_device::hd614045_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) :
+ hmcs404_cpu_device(mconfig, HD614045, tag, owner, clock)
+{ }
+hd614048_device::hd614048_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) :
+ hmcs404_cpu_device(mconfig, HD614048, tag, owner, clock)
+{ }
+
+
+hmcs408_cpu_device::hmcs408_cpu_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock) :
+ hmcs400_cpu_device(mconfig, type, tag, owner, clock, 0x2000, 448)
+{
+ m_has_div = true;
+ m_has_law = true;
+}
+
+hd614080_device::hd614080_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) :
+ hmcs408_cpu_device(mconfig, HD614080, tag, owner, clock)
+{ }
+hd614085_device::hd614085_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) :
+ hmcs408_cpu_device(mconfig, HD614085, tag, owner, clock)
+{ }
+hd614088_device::hd614088_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) :
+ hmcs408_cpu_device(mconfig, HD614088, tag, owner, clock)
+{ }
+
+
+//-------------------------------------------------
+// initialization
+//-------------------------------------------------
+
+void hmcs400_cpu_device::device_start()
+{
+ m_program = &space(AS_PROGRAM);
+ m_data = &space(AS_DATA);
+
+ // zerofill
+ m_pc = 0;
+ m_prev_pc = 0;
+ m_op = 0;
+
+ // register for savestates
+ save_item(NAME(m_pc));
+ save_item(NAME(m_prev_pc));
+ save_item(NAME(m_op));
+
+ // register state for debugger
+ state_add(STATE_GENPC, "GENPC", m_pc).formatstr("%04X").noshow();
+ state_add(STATE_GENPCBASE, "CURPC", m_pc).formatstr("%04X").noshow();
+
+ int state_count = 0;
+ state_add(++state_count, "PC", m_pc).formatstr("%04X"); // 1
+
+ set_icountptr(m_icount);
+}
+
+void hmcs400_cpu_device::device_reset()
+{
+ m_pc = 0;
+}
+
+std::unique_ptr<util::disasm_interface> hmcs400_cpu_device::create_disassembler()
+{
+ return std::make_unique<hmcs400_disassembler>();
+}
+
+
+//-------------------------------------------------
+// internal memory maps
+//-------------------------------------------------
+
+void hmcs400_cpu_device::program_map(address_map &map)
+{
+ map.unmap_value_high();
+ map(0, m_rom_size - 1).rom();
+}
+
+void hmcs400_cpu_device::data_map(address_map &map)
+{
+ map(0x020, 0x020 + m_ram_size - 1).ram();
+ map(0x3c0, 0x3ff).ram();
+}
+
+device_memory_interface::space_config_vector hmcs400_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)
+ };
+}
+
+
+//-------------------------------------------------
+// execute
+//-------------------------------------------------
+
+void hmcs400_cpu_device::execute_run()
+{
+ while (m_icount > 0)
+ {
+ // fetch next opcode
+ m_prev_pc = m_pc;
+ debugger_instruction_hook(m_pc);
+ m_op = m_program->read_word(m_pc) & 0x3ff;
+ m_pc = (m_pc + 1) & 0x3fff;
+
+ m_icount--;
+
+ op_illegal();
+ }
+}