hmcs40: add hmcs46/hmcs47

This commit is contained in:
hap 2024-09-25 16:11:06 +02:00
parent 2b906b6f90
commit 9ca21b386b
4 changed files with 191 additions and 30 deletions

View File

@ -53,13 +53,20 @@ DEFINE_DEVICE_TYPE(HD44820, hd44820_device, "hd44820", "Hitachi HD44820") // CMO
DEFINE_DEVICE_TYPE(HD44828, hd44828_device, "hd44828", "Hitachi HD44828") // CMOS, low-power DEFINE_DEVICE_TYPE(HD44828, hd44828_device, "hd44828", "Hitachi HD44828") // CMOS, low-power
// HMCS46C/CL, 42 pins, 32 I/O lines, 4096x10 ROM, 256x4 RAM (no PMOS version exists) // 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(HD44840, hd44840_device, "hd44840", "Hitachi HD44840") // CMOS
//DEFINE_DEVICE_TYPE(HD44848, hd44848_device, "hd44848", "Hitachi HD44848") // CMOS, low-power DEFINE_DEVICE_TYPE(HD44848, hd44848_device, "hd44848", "Hitachi HD44848") // CMOS, low-power
// HMCS47A/C/CL, 54 pins(QFP) or 64 pins(DIP), 44 I/O lines, 4096x10 ROM, 256x4 RAM // 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(HD38870, hd38870_device, "hd38870", "Hitachi HD38870") // PMOS
//DEFINE_DEVICE_TYPE(HD44860, hd44860_device, "hd44860", "Hitachi HD44860") // CMOS DEFINE_DEVICE_TYPE(HD44860, hd44860_device, "hd44860", "Hitachi HD44860") // CMOS
//DEFINE_DEVICE_TYPE(HD44868, hd44868_device, "hd44868", "Hitachi HD44868") // CMOS, low-power 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
// LCD-IV, 64 pins, HMCS46C core, LCDC with 4 commons and 32 segments
//DEFINE_DEVICE_TYPE(HD613901, hd613901_device, "hd613901", "Hitachi HD613901") // CMOS
//------------------------------------------------- //-------------------------------------------------
@ -139,6 +146,33 @@ hd44828_device::hd44828_device(const machine_config &mconfig, const char *tag, d
{ } { }
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))
{ }
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)
{ }
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)
{ }
//------------------------------------------------- //-------------------------------------------------
// initialization // initialization
//------------------------------------------------- //-------------------------------------------------
@ -163,7 +197,7 @@ void hmcs40_cpu_device::device_start()
m_pc = 0; m_pc = 0;
m_prev_pc = 0; m_prev_pc = 0;
m_page = 0; m_pc_upper = 0;
m_a = 0; m_a = 0;
m_b = 0; m_b = 0;
m_x = 0; m_x = 0;
@ -195,7 +229,7 @@ void hmcs40_cpu_device::device_start()
save_item(NAME(m_pc)); save_item(NAME(m_pc));
save_item(NAME(m_prev_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_a));
save_item(NAME(m_b)); save_item(NAME(m_b));
save_item(NAME(m_x)); save_item(NAME(m_x));
@ -249,6 +283,10 @@ void hmcs40_cpu_device::device_reset()
// all I/O ports set to input // all I/O ports set to input
reset_io(); reset_io();
// 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;
} }
@ -281,10 +319,19 @@ std::unique_ptr<util::disasm_interface> hmcs40_cpu_device::create_disassembler()
// internal memory maps // 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 On HMCS42/43/44/45, only half of the ROM address range contains user-executable
// mode is enabled externally. This data can still be accessed with the P opcode. 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) void hmcs40_cpu_device::program_1k(address_map &map)
{ {
@ -310,6 +357,11 @@ void hmcs40_cpu_device::data_160x4(address_map &map)
map(0xc0, 0xcf).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 device_memory_interface::space_config_vector hmcs40_cpu_device::memory_space_config() const
{ {
return space_config_vector { return space_config_vector {
@ -453,6 +505,44 @@ void hmcs45_cpu_device::write_r(u8 index, u8 data)
logerror("ineffective write to port R%d = $%X @ $%04X\n", 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 // interrupt/timer
@ -506,23 +596,13 @@ void hmcs40_cpu_device::execute_set_input(int line, int state)
// clock tc if it is in counter mode // clock tc if it is in counter mode
if (m_cf && line == 1) if (m_cf && line == 1)
increment_tc(); clock_timer();
} }
m_int[line] = state; m_int[line] = state;
} }
void hmcs40_cpu_device::cycle() void hmcs40_cpu_device::clock_timer()
{
m_icount--;
m_prescaler = (m_prescaler + 1) & 0x3f;
// timer prescaler overflow
if (m_prescaler == 0 && !m_cf)
increment_tc();
}
void hmcs40_cpu_device::increment_tc()
{ {
// increment timer/counter // increment timer/counter
m_tc = (m_tc + 1) & 0xf; m_tc = (m_tc + 1) & 0xf;
@ -535,6 +615,15 @@ 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();
}
//------------------------------------------------- //-------------------------------------------------
// execute // execute
@ -555,6 +644,12 @@ inline void hmcs40_cpu_device::increment_pc()
m_pc = (m_pc & ~mask) | ((m_pc << 1 | fb) & mask); 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() void hmcs40_cpu_device::execute_run()
{ {
// in HLT state, the internal clock is not running // in HLT state, the internal clock is not running
@ -568,7 +663,7 @@ void hmcs40_cpu_device::execute_run()
{ {
// LPU is handled 1 cycle later // LPU is handled 1 cycle later
if ((m_prev_op & 0x7e0) == 0x340) 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 // remember previous state
m_prev_op = m_op; m_prev_op = m_op;

View File

@ -127,8 +127,9 @@ protected:
// memory maps // memory maps
void program_1k(address_map &map); void program_1k(address_map &map);
void program_2k(address_map &map); void program_2k(address_map &map);
void data_160x4(address_map &map);
void data_80x4(address_map &map); void data_80x4(address_map &map);
void data_160x4(address_map &map);
void data_256x4(address_map &map);
address_space_config m_program_config; address_space_config m_program_config;
address_space_config m_data_config; address_space_config m_data_config;
@ -159,7 +160,7 @@ protected:
u16 m_pc; // program counter u16 m_pc; // program counter
u16 m_prev_pc; u16 m_prev_pc;
u8 m_page; // LPU prepared page u8 m_pc_upper; // LPU prepared upper bits of PC
u8 m_a; // 4-bit accumulator u8 m_a; // 4-bit accumulator
u8 m_b; // 4-bit B register u8 m_b; // 4-bit B register
u8 m_x; // 1/3/4-bit X register u8 m_x; // 1/3/4-bit X register
@ -188,6 +189,7 @@ protected:
// misc internal helpers // misc internal helpers
void increment_pc(); void increment_pc();
void cycle();
u8 ram_r(); u8 ram_r();
void ram_w(u8 data); void ram_w(u8 data);
@ -200,9 +202,9 @@ protected:
virtual int read_d(u8 index); virtual int read_d(u8 index);
virtual void write_d(u8 index, int state); virtual void write_d(u8 index, int state);
void cycle();
void increment_tc();
void take_interrupt(); void take_interrupt();
void clock_timer();
void clock_prescaler();
// opcode handlers // opcode handlers
void op_illegal(); void op_illegal();
@ -409,6 +411,57 @@ 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(HD38750, hd38750_device)
DECLARE_DEVICE_TYPE(HD38755, hd38755_device) DECLARE_DEVICE_TYPE(HD38755, hd38755_device)
DECLARE_DEVICE_TYPE(HD44750, hd44750_device) DECLARE_DEVICE_TYPE(HD44750, hd44750_device)
@ -424,4 +477,12 @@ DECLARE_DEVICE_TYPE(HD38825, hd38825_device)
DECLARE_DEVICE_TYPE(HD44820, hd44820_device) DECLARE_DEVICE_TYPE(HD44820, hd44820_device)
DECLARE_DEVICE_TYPE(HD44828, hd44828_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 #endif // MAME_CPU_HMCS40_HMCS40_H

View File

@ -18,8 +18,9 @@ public:
virtual ~hmcs40_disassembler(); virtual ~hmcs40_disassembler();
virtual u32 opcode_alignment() const override { return 1; } 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 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_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 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; virtual offs_t disassemble(std::ostream &stream, offs_t pc, const data_buffer &opcodes, const data_buffer &params) override;

View File

@ -465,7 +465,11 @@ void hmcs40_cpu_device::op_lpu()
if (m_s) if (m_s)
{ {
m_block_int = true; m_block_int = true;
m_page = m_op & 0x1f; 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 else
m_op |= 0x400; // indicate unhandled LPU m_op |= 0x400; // indicate unhandled LPU