summaryrefslogtreecommitdiffstatshomepage
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/devices/cpu/hmcs40/hmcs40.cpp143
-rw-r--r--src/devices/cpu/hmcs40/hmcs40.h69
-rw-r--r--src/devices/cpu/hmcs40/hmcs40d.h3
-rw-r--r--src/devices/cpu/hmcs40/hmcs40op.cpp6
4 files changed, 191 insertions, 30 deletions
diff --git a/src/devices/cpu/hmcs40/hmcs40.cpp b/src/devices/cpu/hmcs40/hmcs40.cpp
index 38e150b9575..a28c40904ca 100644
--- a/src/devices/cpu/hmcs40/hmcs40.cpp
+++ b/src/devices/cpu/hmcs40/hmcs40.cpp
@@ -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
// 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
+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, 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
+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
+
+// 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
//-------------------------------------------------
@@ -163,7 +197,7 @@ void hmcs40_cpu_device::device_start()
m_pc = 0;
m_prev_pc = 0;
- m_page = 0;
+ m_pc_upper = 0;
m_a = 0;
m_b = 0;
m_x = 0;
@@ -195,7 +229,7 @@ void hmcs40_cpu_device::device_start()
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));
@@ -249,6 +283,10 @@ void hmcs40_cpu_device::device_reset()
// all I/O ports set to input
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
//-------------------------------------------------
-// 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.
+/*
+
+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)
{
@@ -310,6 +357,11 @@ void hmcs40_cpu_device::data_160x4(address_map &map)
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 {
@@ -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);
}
+// 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
@@ -506,23 +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::cycle()
-{
- 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()
+void hmcs40_cpu_device::clock_timer()
{
// increment timer/counter
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
@@ -555,6 +644,12 @@ 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
@@ -568,7 +663,7 @@ 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;
diff --git a/src/devices/cpu/hmcs40/hmcs40.h b/src/devices/cpu/hmcs40/hmcs40.h
index c1c24d81b0d..e17bd020aa7 100644
--- a/src/devices/cpu/hmcs40/hmcs40.h
+++ b/src/devices/cpu/hmcs40/hmcs40.h
@@ -127,8 +127,9 @@ protected:
// memory maps
void program_1k(address_map &map);
void program_2k(address_map &map);
- void data_160x4(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_data_config;
@@ -159,7 +160,7 @@ protected:
u16 m_pc; // program counter
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_b; // 4-bit B register
u8 m_x; // 1/3/4-bit X register
@@ -188,6 +189,7 @@ protected:
// misc internal helpers
void increment_pc();
+ void cycle();
u8 ram_r();
void ram_w(u8 data);
@@ -200,9 +202,9 @@ protected:
virtual int read_d(u8 index);
virtual void write_d(u8 index, int state);
- void cycle();
- void increment_tc();
void take_interrupt();
+ void clock_timer();
+ void clock_prescaler();
// opcode handlers
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(HD38755, hd38755_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(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.h b/src/devices/cpu/hmcs40/hmcs40d.h
index a02d7e87a1b..f67ba8f3b9f 100644
--- a/src/devices/cpu/hmcs40/hmcs40d.h
+++ b/src/devices/cpu/hmcs40/hmcs40d.h
@@ -18,8 +18,9 @@ public:
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;
diff --git a/src/devices/cpu/hmcs40/hmcs40op.cpp b/src/devices/cpu/hmcs40/hmcs40op.cpp
index 17e307ca6fa..713dd111777 100644
--- a/src/devices/cpu/hmcs40/hmcs40op.cpp
+++ b/src/devices/cpu/hmcs40/hmcs40op.cpp
@@ -465,7 +465,11 @@ void hmcs40_cpu_device::op_lpu()
if (m_s)
{
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
m_op |= 0x400; // indicate unhandled LPU