summaryrefslogtreecommitdiffstatshomepage
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/devices/cpu/hmcs40/hmcs40.cpp63
-rw-r--r--src/devices/cpu/hmcs40/hmcs40.h25
-rw-r--r--src/devices/cpu/hmcs40/hmcs40op.cpp18
-rw-r--r--src/devices/cpu/hmcs400/hmcs400.cpp88
-rw-r--r--src/devices/cpu/hmcs400/hmcs400.h26
-rw-r--r--src/devices/cpu/hmcs400/hmcs400op.cpp30
6 files changed, 194 insertions, 56 deletions
diff --git a/src/devices/cpu/hmcs40/hmcs40.cpp b/src/devices/cpu/hmcs40/hmcs40.cpp
index 723934604ac..a10d31fca36 100644
--- a/src/devices/cpu/hmcs40/hmcs40.cpp
+++ b/src/devices/cpu/hmcs40/hmcs40.cpp
@@ -247,13 +247,8 @@ void hmcs40_cpu_device::device_reset()
m_iri = m_irt = 0;
m_if[0] = m_if[1] = m_tf = 1;
- // clear i/o
- m_d = m_polarity;
- for (int i = 0; i < 16; i++)
- hmcs40_cpu_device::write_d(i, m_polarity);
-
- for (int i = 0; i < 8; i++)
- hmcs40_cpu_device::write_r(i, m_polarity & 0xf);
+ // all I/O ports set to input
+ reset_io();
}
@@ -325,13 +320,22 @@ device_memory_interface::space_config_vector hmcs40_cpu_device::memory_space_con
//-------------------------------------------------
-// i/o handling
+// i/o ports
//-------------------------------------------------
-u8 hmcs40_cpu_device::read_r(int index)
+void hmcs40_cpu_device::reset_io()
+{
+ m_d = m_polarity;
+ m_write_d(m_polarity);
+
+ for (int i = 0; i < 8; i++)
+ hmcs40_cpu_device::write_r(i, m_polarity);
+}
+
+u8 hmcs40_cpu_device::read_r(u8 index)
{
index &= 7;
- u8 inp = m_read_r[index](index, 0xff);
+ u8 inp = m_read_r[index](index);
if (m_polarity)
return (inp & m_r[index]) & 0xf;
@@ -339,38 +343,39 @@ u8 hmcs40_cpu_device::read_r(int index)
return (inp | m_r[index]) & 0xf;
}
-void hmcs40_cpu_device::write_r(int index, u8 data)
+void hmcs40_cpu_device::write_r(u8 index, u8 data)
{
index &= 7;
data &= 0xf;
m_r[index] = data;
- m_write_r[index](index, data, 0xff);
+ m_write_r[index](index, data);
}
-int hmcs40_cpu_device::read_d(int index)
+int hmcs40_cpu_device::read_d(u8 index)
{
- index &= 15;
+ index &= 0xf;
+ u16 inp = m_read_d(0, 1 << index);
if (m_polarity)
- return (m_read_d(index, 0xffff) & m_d) >> index & 1;
+ return BIT(inp & m_d, index);
else
- return (m_read_d(index, 0xffff) | m_d) >> index & 1;
+ return BIT(inp | m_d, index);
}
-void hmcs40_cpu_device::write_d(int index, int state)
+void hmcs40_cpu_device::write_d(u8 index, int state)
{
- index &= 15;
- state = (state) ? 1 : 0;
+ index &= 0xf;
+ u16 mask = 1 << index;
- m_d = (m_d & ~(1 << index)) | state << index;
- m_write_d(index, m_d, 0xffff);
+ m_d = (m_d & ~mask) | (state ? mask : 0);
+ m_write_d(0, m_d, mask);
}
// HMCS43:
// R0 is input-only, R1 is i/o, R2,R3 are output-only, no R4-R7
// D0-D3 are i/o, D4-D15 are output-only
-u8 hmcs43_cpu_device::read_r(int index)
+u8 hmcs43_cpu_device::read_r(u8 index)
{
index &= 7;
@@ -380,7 +385,7 @@ u8 hmcs43_cpu_device::read_r(int index)
return hmcs40_cpu_device::read_r(index);
}
-void hmcs43_cpu_device::write_r(int index, u8 data)
+void hmcs43_cpu_device::write_r(u8 index, u8 data)
{
index &= 7;
@@ -390,7 +395,7 @@ void hmcs43_cpu_device::write_r(int index, u8 data)
logerror("ineffective write to port R%d = $%X at $%04X\n", index, data & 0xf, m_prev_pc);
}
-int hmcs43_cpu_device::read_d(int index)
+int hmcs43_cpu_device::read_d(u8 index)
{
index &= 15;
@@ -404,7 +409,7 @@ int hmcs43_cpu_device::read_d(int index)
// R0-R3 are i/o, R4,R5 are extra registers, no R6,R7
// D0-D15 are i/o
-u8 hmcs44_cpu_device::read_r(int index)
+u8 hmcs44_cpu_device::read_r(u8 index)
{
index &= 7;
@@ -414,7 +419,7 @@ u8 hmcs44_cpu_device::read_r(int index)
return hmcs40_cpu_device::read_r(index);
}
-void hmcs44_cpu_device::write_r(int index, u8 data)
+void hmcs44_cpu_device::write_r(u8 index, u8 data)
{
index &= 7;
@@ -428,7 +433,7 @@ void hmcs44_cpu_device::write_r(int index, u8 data)
// R0-R5 are i/o, R6 is output-only, no R7
// D0-D15 are i/o
-u8 hmcs45_cpu_device::read_r(int index)
+u8 hmcs45_cpu_device::read_r(u8 index)
{
index &= 7;
@@ -438,7 +443,7 @@ u8 hmcs45_cpu_device::read_r(int index)
return hmcs40_cpu_device::read_r(index);
}
-void hmcs45_cpu_device::write_r(int index, u8 data)
+void hmcs45_cpu_device::write_r(u8 index, u8 data)
{
index &= 7;
@@ -450,7 +455,7 @@ void hmcs45_cpu_device::write_r(int index, u8 data)
//-------------------------------------------------
-// interrupt/timer handling
+// interrupt/timer
//-------------------------------------------------
void hmcs40_cpu_device::do_interrupt()
diff --git a/src/devices/cpu/hmcs40/hmcs40.h b/src/devices/cpu/hmcs40/hmcs40.h
index c9316bbe69a..833b5891cd2 100644
--- a/src/devices/cpu/hmcs40/hmcs40.h
+++ b/src/devices/cpu/hmcs40/hmcs40.h
@@ -12,7 +12,7 @@
#pragma once
-// I/O ports setup
+// input lines
enum
{
@@ -195,10 +195,11 @@ protected:
void pop_stack();
void push_stack();
- virtual u8 read_r(int index);
- virtual void write_r(int index, u8 data);
- virtual int read_d(int index);
- virtual void write_d(int index, int state);
+ virtual void reset_io();
+ virtual u8 read_r(u8 index);
+ virtual void write_r(u8 index, u8 data);
+ virtual int read_d(u8 index);
+ virtual void write_d(u8 index, int state);
void cycle();
void increment_tc();
@@ -309,9 +310,9 @@ protected:
hmcs43_cpu_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock, u16 polarity);
// overrides
- virtual u8 read_r(int index) override;
- virtual void write_r(int index, u8 data) override;
- virtual int read_d(int index) override;
+ virtual u8 read_r(u8 index) override;
+ virtual void write_r(u8 index, u8 data) override;
+ virtual int read_d(u8 index) override;
};
class hd38750_device : public hmcs43_cpu_device
@@ -345,8 +346,8 @@ protected:
hmcs44_cpu_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock, u16 polarity);
// overrides
- virtual u8 read_r(int index) override;
- virtual void write_r(int index, u8 data) override;
+ virtual u8 read_r(u8 index) override;
+ virtual void write_r(u8 index, u8 data) override;
};
class hd38800_device : public hmcs44_cpu_device
@@ -380,8 +381,8 @@ protected:
hmcs45_cpu_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock, u16 polarity);
// overrides
- virtual u8 read_r(int index) override;
- virtual void write_r(int index, u8 data) override;
+ virtual u8 read_r(u8 index) override;
+ virtual void write_r(u8 index, u8 data) override;
};
class hd38820_device : public hmcs45_cpu_device
diff --git a/src/devices/cpu/hmcs40/hmcs40op.cpp b/src/devices/cpu/hmcs40/hmcs40op.cpp
index a2c201946cb..262e82f1d48 100644
--- a/src/devices/cpu/hmcs40/hmcs40op.cpp
+++ b/src/devices/cpu/hmcs40/hmcs40op.cpp
@@ -663,24 +663,24 @@ void hmcs40_cpu_device::op_lrb()
void hmcs40_cpu_device::op_p()
{
+ // P p: Pattern Generation
cycle();
- // P p: Pattern Generation
u16 address = m_a | m_b << 4 | m_c << 8 | (m_op & 7) << 9 | (m_pc & ~0x3f);
- u16 o = m_program->read_word(address & m_prgmask);
+ u16 data = m_program->read_word(address & m_prgmask);
// destination is determined by the 2 highest bits
- if (o & 0x100)
+ if (data & 0x100)
{
// B3 B2 B1 B0 A0 A1 A2 A3
- m_a = bitswap<4>(o,0,1,2,3);
- m_b = o >> 4 & 0xf;
+ m_a = bitswap<4>(data,0,1,2,3);
+ m_b = data >> 4 & 0xf;
}
- if (o & 0x200)
+ if (data & 0x200)
{
// R20 R21 R22 R23 R30 R31 R32 R33
- o = bitswap<8>(o,0,1,2,3,4,5,6,7);
- write_r(2, o & 0xf);
- write_r(3, o >> 4 & 0xf);
+ data = bitswap<8>(data,0,1,2,3,4,5,6,7);
+ write_r(2, data & 0xf);
+ write_r(3, data >> 4 & 0xf);
}
}
diff --git a/src/devices/cpu/hmcs400/hmcs400.cpp b/src/devices/cpu/hmcs400/hmcs400.cpp
index 261e482ac8c..0c8cc8d4a9c 100644
--- a/src/devices/cpu/hmcs400/hmcs400.cpp
+++ b/src/devices/cpu/hmcs400/hmcs400.cpp
@@ -18,6 +18,8 @@ TODO:
way to save this register when using interrupts
- what happens when accessing ROM/RAM out of address range? Hitachi documentation
says 'unused', but maybe it's mirrored?
+- current I/O ports are hardcoded for HMS402/4/8, which will need to be changed
+ when other MCU types are added
*/
@@ -73,7 +75,11 @@ hmcs400_cpu_device::hmcs400_cpu_device(const machine_config &mconfig, device_typ
m_rom_size(rom_size),
m_ram_size(ram_size),
m_has_div(false),
- m_divider(8)
+ m_divider(8),
+ m_read_r(*this, 0),
+ m_write_r(*this),
+ m_read_d(*this, 0),
+ m_write_d(*this)
{ }
hmcs400_cpu_device::~hmcs400_cpu_device() { }
@@ -185,8 +191,6 @@ void hmcs400_cpu_device::device_start()
save_item(NAME(m_prev_pc));
save_item(NAME(m_sp));
save_item(NAME(m_op));
- save_item(NAME(m_param));
- save_item(NAME(m_i));
save_item(NAME(m_a));
save_item(NAME(m_b));
@@ -198,6 +202,9 @@ void hmcs400_cpu_device::device_start()
save_item(NAME(m_st));
save_item(NAME(m_ca));
+ save_item(NAME(m_r));
+ save_item(NAME(m_d));
+
// register state for debugger
state_add(STATE_GENPC, "GENPC", m_pc).formatstr("%04X").noshow();
state_add(STATE_GENPCBASE, "CURPC", m_pc).formatstr("%04X").noshow();
@@ -225,6 +232,9 @@ void hmcs400_cpu_device::device_reset()
m_pc = 0;
m_sp = 0x3ff;
m_st = 1;
+
+ // all I/O ports set to input
+ reset_io();
}
@@ -279,6 +289,78 @@ device_memory_interface::space_config_vector hmcs400_cpu_device::memory_space_co
//-------------------------------------------------
+// i/o ports
+//-------------------------------------------------
+
+void hmcs400_cpu_device::reset_io()
+{
+ // D4-D15 are high-voltage
+ m_d_mask = m_d = 0x000f;
+ m_write_d(m_d_mask);
+
+ for (int i = 0; i < 10; i++)
+ {
+ // R0-R2 and RA are high-voltage
+ u8 mask = (i >= 3 && i <= 9) ? 0xf : 0;
+
+ m_r_mask[i] = m_r[i] = mask;
+ m_write_r[i](i, mask);
+ }
+}
+
+u8 hmcs400_cpu_device::read_r(u8 index)
+{
+ // reads from write-only or non-existent ports are invalid
+ bool write_only = index == 0 || (index >= 6 && index <= 8);
+ if (write_only || index > 10)
+ {
+ logerror("read from %s port R%X at $%04X\n", write_only ? "output" : "unknown", index, m_prev_pc);
+ return 0xf;
+ }
+
+ u8 inp = m_read_r[index].isunset() ? m_r_mask[index] : m_read_r[index](index);
+ u8 mask = (index == 10) ? 3 : 0xf; // port A is 2-bit
+
+ if (m_r_mask[index])
+ return (inp & m_r[index]) & mask;
+ else
+ return (inp | m_r[index]) & mask;
+}
+
+void hmcs400_cpu_device::write_r(u8 index, u8 data)
+{
+ // ignore writes to read-only or non-existent ports
+ if (index > 8)
+ return;
+
+ data &= 0xf;
+ m_r[index] = data;
+ m_write_r[index](index, data);
+}
+
+int hmcs400_cpu_device::read_d(u8 index)
+{
+ index &= 0xf;
+ u16 mask = 1 << index;
+ u16 inp = m_read_d.isunset() ? m_d_mask : m_read_d(0, mask);
+
+ if (m_d_mask & mask)
+ return BIT(inp & m_d, index);
+ else
+ return BIT(inp | m_d, index);
+}
+
+void hmcs400_cpu_device::write_d(u8 index, int state)
+{
+ index &= 0xf;
+ u16 mask = 1 << index;
+
+ m_d = (m_d & ~mask) | (state ? mask : 0);
+ m_write_d(0, m_d, mask);
+}
+
+
+//-------------------------------------------------
// execute
//-------------------------------------------------
diff --git a/src/devices/cpu/hmcs400/hmcs400.h b/src/devices/cpu/hmcs400/hmcs400.h
index 965131df530..c8572fe0192 100644
--- a/src/devices/cpu/hmcs400/hmcs400.h
+++ b/src/devices/cpu/hmcs400/hmcs400.h
@@ -19,6 +19,14 @@ public:
// configuration helpers
+ // 10 4-bit R ports (port A is 2-bit)
+ 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(); }
+
+ // 16-bit discrete
+ auto read_d() { return m_read_d.bind(); }
+ auto write_d() { return m_write_d.bind(); }
+
// 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; }
@@ -81,7 +89,16 @@ protected:
u8 m_st; // status flag
u8 m_ca; // carry flag
- u16 fetch();
+ u8 m_r[10]; // R outputs state
+ u8 m_r_mask[10];
+ u16 m_d; // D pins state
+ u16 m_d_mask;
+
+ // I/O handlers
+ devcb_read8::array<8> m_read_r;
+ devcb_write8::array<8> m_write_r;
+ devcb_read16 m_read_d;
+ devcb_write16 m_write_d;
// misc internal helpers
u8 ram_r(u8 mem_mask = 0xf);
@@ -89,7 +106,14 @@ protected:
void pop_stack();
void push_stack();
+ void reset_io();
+ u8 read_r(u8 index);
+ void write_r(u8 index, u8 data);
+ int read_d(u8 index);
+ void write_d(u8 index, int state);
+
void cycle();
+ u16 fetch();
// opcode handlers
void op_illegal();
diff --git a/src/devices/cpu/hmcs400/hmcs400op.cpp b/src/devices/cpu/hmcs400/hmcs400op.cpp
index b9656db83b5..0fb1ea015c5 100644
--- a/src/devices/cpu/hmcs400/hmcs400op.cpp
+++ b/src/devices/cpu/hmcs400/hmcs400op.cpp
@@ -534,9 +534,9 @@ void hmcs400_cpu_device::op_cal()
// CAL a: Subroutine Jump on Status 1
if (m_st)
{
+ cycle();
push_stack();
m_pc = m_op & 0x3f;
- cycle();
}
else
m_st = 1;
@@ -563,9 +563,9 @@ void hmcs400_cpu_device::op_tbr()
void hmcs400_cpu_device::op_rtn()
{
// RTN: Return from Subroutine
- pop_stack();
cycle();
cycle();
+ pop_stack();
}
void hmcs400_cpu_device::op_rtni()
@@ -580,56 +580,82 @@ void hmcs400_cpu_device::op_rtni()
void hmcs400_cpu_device::op_sed()
{
// SED: Set Discrete I/O Latch
+ write_d(m_y, 1);
}
void hmcs400_cpu_device::op_sedd()
{
// SEDD m: Set Discrete I/O Latch Direct
+ write_d(m_i, 1);
}
void hmcs400_cpu_device::op_red()
{
// RED: Reset Discrete I/O Latch
+ write_d(m_y, 0);
}
void hmcs400_cpu_device::op_redd()
{
// REDD m: Reset Discrete I/O Latch Direct
+ write_d(m_i, 0);
}
void hmcs400_cpu_device::op_td()
{
// TD: Test Discrete I/O Latch
+ m_st = read_d(m_y);
}
void hmcs400_cpu_device::op_tdd()
{
// TDD m: Test Discrete I/O Latch Direct
+ m_st = read_d(m_i);
}
void hmcs400_cpu_device::op_lar()
{
// LAR m: Load A from R Port Register
+ m_a = read_r(m_i);
}
void hmcs400_cpu_device::op_lbr()
{
// LBR m: Load B from R Port Register
+ m_b = read_r(m_i);
}
void hmcs400_cpu_device::op_lra()
{
// LRA m: Load R Port Register from A
+ write_r(m_i, m_a);
}
void hmcs400_cpu_device::op_lrb()
{
// LRB m: Load R Port Register from B
+ write_r(m_i, m_b);
}
void hmcs400_cpu_device::op_p()
{
// P p: Pattern Generation
+ cycle();
+ u16 data = m_program->read_word(m_i << 8 | m_b << 4 | m_a);
+
+ // destination is determined by the 2 highest bits
+ if (data & 0x100)
+ {
+ // to A/B registers
+ m_a = data & 0xf;
+ m_b = data >> 4 & 0xf;
+ }
+ if (data & 0x200)
+ {
+ // to R1/R2 ports
+ write_r(1, data & 0xf);
+ write_r(2, data >> 4 & 0xf);
+ }
}