hmcs400: add cpu skeleton device

This commit is contained in:
hap 2024-09-15 23:42:57 +02:00
parent 343655b39d
commit dbd8fd2b2c
13 changed files with 709 additions and 120 deletions

View File

@ -855,6 +855,24 @@ if opt_tool(CPUS, "HMCS40") then
table.insert(disasm_files , MAME_DIR .. "src/devices/cpu/hmcs40/hmcs40d.h")
end
--------------------------------------------------
-- Hitachi HMCS400 series
--@src/devices/cpu/hmcs400/hmcs400.h,CPUS["HMCS400"] = true
--------------------------------------------------
if CPUS["HMCS400"] then
files {
MAME_DIR .. "src/devices/cpu/hmcs400/hmcs400.cpp",
MAME_DIR .. "src/devices/cpu/hmcs400/hmcs400.h",
MAME_DIR .. "src/devices/cpu/hmcs400/hmcs400op.cpp",
}
end
if opt_tool(CPUS, "HMCS400") then
table.insert(disasm_files , MAME_DIR .. "src/devices/cpu/hmcs400/hmcs400d.cpp")
table.insert(disasm_files , MAME_DIR .. "src/devices/cpu/hmcs400/hmcs400d.h")
end
--------------------------------------------------
-- Hitachi SuperH series (SH1/SH2/SH3/SH4)
--@src/devices/cpu/sh/sh2.h,CPUS["SH"] = true

View File

@ -25,74 +25,47 @@ TODO:
#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
// 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
// internal memory maps
//-------------------------------------------------
// constructor
//-------------------------------------------------
// On HMCS42/3/4/5, 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. This data can still be accessed with the P opcode.
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);
}
// 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),
@ -109,8 +82,11 @@ hmcs40_cpu_device::hmcs40_cpu_device(const machine_config &mconfig, device_type
m_write_d(*this)
{ }
hmcs40_cpu_device::~hmcs40_cpu_device() { }
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))
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) :
@ -128,7 +104,7 @@ hd44758_device::hd44758_device(const machine_config &mconfig, const char *tag, d
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))
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) :
@ -146,7 +122,7 @@ hd44808_device::hd44808_device(const machine_config &mconfig, const char *tag, d
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))
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) :
@ -162,38 +138,9 @@ hd44828_device::hd44828_device(const machine_config &mconfig, const char *tag, d
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;
default: break;
}
}
std::unique_ptr<util::disasm_interface> hmcs40_cpu_device::create_disassembler()
{
return std::make_unique<hmcs40_disassembler>();
}
//-------------------------------------------------
// device_start - device-specific startup
// initialization
//-------------------------------------------------
void hmcs40_cpu_device::device_start()
@ -282,12 +229,6 @@ void hmcs40_cpu_device::device_start()
set_icountptr(m_icount);
}
//-------------------------------------------------
// device_reset - device-specific reset
//-------------------------------------------------
void hmcs40_cpu_device::device_reset()
{
m_pc = m_pcmask;
@ -309,6 +250,72 @@ void hmcs40_cpu_device::device_reset()
}
//-------------------------------------------------
// 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/3/4/5, 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. This data can still be accessed with the P opcode.
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);
}
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
@ -435,7 +442,6 @@ void hmcs45_cpu_device::write_r(int index, u8 data)
}
//-------------------------------------------------
// interrupt/timer handling
//-------------------------------------------------
@ -518,7 +524,6 @@ void hmcs40_cpu_device::increment_tc()
}
//-------------------------------------------------
// execute
//-------------------------------------------------

View File

@ -81,6 +81,8 @@ enum
class hmcs40_cpu_device : public cpu_device
{
public:
virtual ~hmcs40_cpu_device();
// max 8 4-bit R ports
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(); }
@ -92,38 +94,38 @@ 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
// device_t implementation
virtual void device_start() override;
virtual void device_reset() override;
// device_execute_interface overrides
// 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 u32 execute_input_lines() const noexcept override { return 2+1; } // 3rd one is internal
virtual u32 execute_input_lines() const noexcept override { return 3; }
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
// memory maps
void program_1k(address_map &map);
void program_2k(address_map &map);
void data_160x4(address_map &map);
@ -137,12 +139,12 @@ protected:
int m_icount;
int m_state_count;
int const m_pcwidth; // Program Counter bit-width
int const m_prgwidth;
int const m_datawidth;
int const m_family; // MCU family (42-47)
u16 const m_polarity; // i/o polarity (pmos vs cmos)
int const m_stack_levels; // number of callstack levels
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;

View File

@ -35,6 +35,10 @@ hmcs40_disassembler::hmcs40_disassembler()
}
}
hmcs40_disassembler::~hmcs40_disassembler()
{
}
// common lookup tables

View File

@ -15,7 +15,7 @@ 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; }

View File

@ -86,7 +86,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

View File

@ -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();
}
}

View File

@ -0,0 +1,162 @@
// license:BSD-3-Clause
// copyright-holders:hap
/*
Hitachi HMCS400 MCU family cores
*/
#ifndef MAME_CPU_HMCS400_HMCS400_H
#define MAME_CPU_HMCS400_HMCS400_H
#pragma once
class hmcs400_cpu_device : public cpu_device
{
public:
virtual ~hmcs400_cpu_device();
// configuration helpers
// system clock divider mask option (only for HMCS408, HMCS414, HMCS424)
// valid options: 4, 8, 16, default to 8
auto &set_divider(u8 div) { assert(m_has_div); m_divider = div; return *this; }
protected:
// construction
hmcs400_cpu_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock, u32 rom_size, u32 ram_size);
// device_t implementation
virtual void device_start() override;
virtual void device_reset() override;
// device_execute_interface implementation
virtual u64 execute_clocks_to_cycles(u64 clocks) const noexcept override { return (clocks + m_divider - 1) / m_divider; }
virtual u64 execute_cycles_to_clocks(u64 cycles) const noexcept override { return (cycles * m_divider); }
virtual u32 execute_min_cycles() const noexcept override { return 1; }
virtual u32 execute_max_cycles() const noexcept override { return 2+2; } // max 2 + interrupt
virtual u32 execute_input_lines() const noexcept override { return 2; }
//virtual void execute_set_input(int line, int state) override;
virtual void execute_run() override;
// device_memory_interface implementation
virtual space_config_vector memory_space_config() const override;
// device_disasm_interface implementation
virtual std::unique_ptr<util::disasm_interface> create_disassembler() override;
// memory maps
void program_map(address_map &map);
void data_map(address_map &map);
address_space_config m_program_config;
address_space_config m_data_config;
address_space *m_program;
address_space *m_data;
const u32 m_rom_size; // ROM size in 16-bit words
const u32 m_ram_size; // RAM size minus the 64-byte stack
bool m_has_div; // MCU supports divider mask option
bool m_has_law; // MCU supports LAW/LWA opcodes
u8 m_divider; // system clock divider
u16 m_pc;
u16 m_prev_pc;
u16 m_op;
int m_icount;
// opcode handlers
void op_illegal();
};
class hmcs402_cpu_device : public hmcs400_cpu_device
{
protected:
hmcs402_cpu_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock);
};
class hd614022_device : public hmcs402_cpu_device
{
public:
hd614022_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
};
class hd614025_device : public hmcs402_cpu_device
{
public:
hd614025_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
};
class hd614028_device : public hmcs402_cpu_device
{
public:
hd614028_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
};
class hmcs404_cpu_device : public hmcs400_cpu_device
{
protected:
hmcs404_cpu_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock);
};
class hd614042_device : public hmcs404_cpu_device
{
public:
hd614042_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
};
class hd614045_device : public hmcs404_cpu_device
{
public:
hd614045_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
};
class hd614048_device : public hmcs404_cpu_device
{
public:
hd614048_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
};
class hmcs408_cpu_device : public hmcs400_cpu_device
{
protected:
hmcs408_cpu_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock);
};
class hd614080_device : public hmcs408_cpu_device
{
public:
hd614080_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
};
class hd614085_device : public hmcs408_cpu_device
{
public:
hd614085_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
};
class hd614088_device : public hmcs408_cpu_device
{
public:
hd614088_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
};
DECLARE_DEVICE_TYPE(HD614022, hd614022_device)
DECLARE_DEVICE_TYPE(HD614025, hd614025_device)
DECLARE_DEVICE_TYPE(HD614028, hd614028_device)
DECLARE_DEVICE_TYPE(HD614042, hd614042_device)
DECLARE_DEVICE_TYPE(HD614045, hd614045_device)
DECLARE_DEVICE_TYPE(HD614048, hd614048_device)
DECLARE_DEVICE_TYPE(HD614080, hd614080_device)
DECLARE_DEVICE_TYPE(HD614085, hd614085_device)
DECLARE_DEVICE_TYPE(HD614088, hd614088_device)
#endif // MAME_CPU_HMCS400_HMCS400_H

View File

@ -0,0 +1,154 @@
// license:BSD-3-Clause
// copyright-holders:hap
/*
Hitachi HMCS400 MCU family disassembler
*/
#include "emu.h"
#include "hmcs400d.h"
// constructor
hmcs400_disassembler::hmcs400_disassembler()
{
}
hmcs400_disassembler::~hmcs400_disassembler()
{
}
// common lookup tables
enum hmcs400_disassembler::e_mnemonics : unsigned
{
mILL1
};
const char *const hmcs400_disassembler::s_mnemonics[] =
{
"?"
};
// number of bits per opcode parameter, 99 means (XY) parameter, negative means reversed bit-order
const s8 hmcs400_disassembler::s_bits[] =
{
0
};
const u32 hmcs400_disassembler::s_flags[] =
{
0
};
const u8 hmcs400_disassembler::hmcs400_mnemonic[0x400] =
{
// 0 1 2 3 4 5 6 7 8 9 A B C D E F
// 0x000
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, 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,
// 0x040
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, 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,
// 0x080
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, 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,
// 0x0c0
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, 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 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,
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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
// 0x140
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, 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,
// 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,
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,
// 0x1c0
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, 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 1 2 3 4 5 6 7 8 9 A B C D E F
// 0x200
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, 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,
// 0x240
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, 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,
// 0x280
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, 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,
// 0x2c0
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, 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 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,
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,
// 0x340
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, 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,
// 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, 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,
// 0x3c0
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, 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
};
// disasm
offs_t hmcs400_disassembler::disassemble(std::ostream &stream, offs_t pc, const data_buffer &opcodes, const data_buffer &params)
{
u16 op = opcodes.r16(pc) & 0x3ff;
u8 instr = hmcs400_mnemonic[op];
s8 bits = s_bits[instr];
util::stream_format(stream, "%-8s", s_mnemonics[instr]);
// opcode parameter
if (bits != 0)
{
}
return 1 | s_flags[instr] | SUPPORTED;
}

View File

@ -0,0 +1,31 @@
// license:BSD-3-Clause
// copyright-holders:hap
/*
Hitachi HMCS400 MCU family disassembler
*/
#ifndef MAME_CPU_HMCS400_HMCS400D_H
#define MAME_CPU_HMCS400_HMCS400D_H
#pragma once
class hmcs400_disassembler : public util::disasm_interface
{
public:
hmcs400_disassembler();
virtual ~hmcs400_disassembler();
virtual u32 opcode_alignment() const override { return 1; }
virtual offs_t disassemble(std::ostream &stream, offs_t pc, const data_buffer &opcodes, const data_buffer &params) override;
private:
enum e_mnemonics : unsigned;
static const char *const s_mnemonics[];
static const s8 s_bits[];
static const u32 s_flags[];
static const u8 hmcs400_mnemonic[0x400];
};
#endif // MAME_CPU_HMCS400_HMCS400D_H

View File

@ -0,0 +1,19 @@
// license:BSD-3-Clause
// copyright-holders:hap
// HMCS400 opcode handlers
#include "emu.h"
#include "hmcs400.h"
// internal helpers
// instruction set
void hmcs400_cpu_device::op_illegal()
{
logerror("unknown opcode $%03X at $%04X\n", m_op, m_prev_pc);
}

View File

@ -25,7 +25,7 @@
// DEVICE DEFINITIONS
//**************************************************************************
DEFINE_DEVICE_TYPE(DAVE, dave_device, "dave", "Inteligent Designs DAVE")
DEFINE_DEVICE_TYPE(DAVE, dave_device, "dave", "Intelligent Designs DAVE")
void dave_device::z80_program_map(address_map &map)

View File

@ -405,14 +405,14 @@ void alpha_8201_device::bus_dir_w(int state)
// set RAM bus direction to 0: external, 1: MCU side
// selects one of two 74LS245 (octal bus transceiver) for databus, address bus via
// a couple of 74LS157 (2-input multiplexer)
m_bus = (state) ? 1 : 0;
m_bus = state ? 1 : 0;
mcu_writeram();
}
void alpha_8201_device::mcu_start_w(int state)
{
// connected to MCU INT0
m_mcu->set_input_line(0, (state) ? ASSERT_LINE : CLEAR_LINE);
m_mcu->set_input_line(0, state ? ASSERT_LINE : CLEAR_LINE);
}
u8 alpha_8201_device::ext_ram_r(offs_t offset)