mirror of
https://github.com/mamedev/mame.git
synced 2024-11-16 07:48:32 +01:00
hmcs40: add hmcs46/hmcs47
This commit is contained in:
parent
2b906b6f90
commit
9ca21b386b
4 changed files with 191 additions and 30 deletions
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 ¶ms) override;
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue