summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/cpu/z180
diff options
context:
space:
mode:
author AJR <ajrhacker@users.noreply.github.com>2019-09-30 21:26:08 -0400
committer AJR <ajrhacker@users.noreply.github.com>2019-09-30 21:30:10 -0400
commit12c08b06c8b89d2de51fb9ddfcb626de9b491a84 (patch)
tree86755393785998e1a78b46076c3da92cb0f3f245 /src/devices/cpu/z180
parent04732f12816067e1ea9ba0d807845835a39ed945 (diff)
Split generic Z180 device into several subtypes. HD647180X now has specific device emulation for the internal PROM, RAM and parallel ports.
Diffstat (limited to 'src/devices/cpu/z180')
-rw-r--r--src/devices/cpu/z180/hd647180x.cpp330
-rw-r--r--src/devices/cpu/z180/hd647180x.h87
-rw-r--r--src/devices/cpu/z180/z180.cpp122
-rw-r--r--src/devices/cpu/z180/z180.h55
-rw-r--r--src/devices/cpu/z180/z180dasm.cpp4
-rw-r--r--src/devices/cpu/z180/z180ops.h4
6 files changed, 551 insertions, 51 deletions
diff --git a/src/devices/cpu/z180/hd647180x.cpp b/src/devices/cpu/z180/hd647180x.cpp
new file mode 100644
index 00000000000..15bf3961d23
--- /dev/null
+++ b/src/devices/cpu/z180/hd647180x.cpp
@@ -0,0 +1,330 @@
+// license:BSD-3-Clause
+// copyright-holders:AJR
+/**********************************************************************
+
+ Hitachi HD647180X MCU (Micro Controller Unit)
+
+ This expandable 8-bit microcontroller architecturally extends the
+ on-chip I/O capabilities of the Hitachi HD64180/Zilog Z80180 CPU
+ with parallel ports and more. It also contains a 16-kilobyte
+ internal programmable ROM (which can be disabled by strapping) and
+ 512 bytes of internal RAM, the latter being software-remappable to
+ the end of any 64K block. The MP pins configure the MCU for either
+ single-chip mode, one of two expanded modes or PROM writing/
+ verification. (Hitachi also had the HD643180X, which uses a 16 KB
+ mask ROM instead of the PROM, and HD641180X, which offers neither
+ ROM nor PROM and therefore must be used in ROMless mode.)
+
+ TODO: the current emulation is incomplete, implementing mostly
+ the internal memory and parallel ports. Timer 2 (which is very
+ similar to the additional timer of the HD6301) is not emulated at
+ all. Programs trying to execute from internal RAM will also fail,
+ though this likely capability is merely theoretical so far.
+
+**********************************************************************/
+
+#include "emu.h"
+#include "hd647180x.h"
+
+#define VERBOSE 0
+#include "logmacro.h"
+
+// device type definition
+DEFINE_DEVICE_TYPE(HD647180X, hd647180x_device, "hd647180x", "Hitachi HD647180X MCU")
+
+hd647180x_device::hd647180x_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : z180_device(mconfig, HD647180X, tag, owner, clock, true, address_map_constructor(FUNC(hd647180x_device::prom_map), this))
+ , m_port_input_cb{{*this}, {*this}, {*this}, {*this}, {*this}, {*this}, {*this}}
+ , m_port_output_cb{{*this}, {*this}, {*this}, {*this}, {*this}, {*this}}
+ , m_data_config("data", ENDIANNESS_LITTLE, 8, 9, 0, address_map_constructor(FUNC(hd647180x_device::ram_map), this))
+{
+ // arbitrary initial states
+ m_ccsr = 0;
+ std::fill(std::begin(m_odr), std::end(m_odr), 0);
+}
+
+void hd647180x_device::prom_map(address_map &map)
+{
+ map(0x00000, 0x03fff).rom().region(DEVICE_SELF, 0); // 16 KB internal PROM (not used in mode 1)
+}
+
+void hd647180x_device::ram_map(address_map &map)
+{
+ map(0x000, 0x1ff).ram(); // 512 bytes remappable internal RAM (available in all modes)
+}
+
+device_memory_interface::space_config_vector hd647180x_device::memory_space_config() const
+{
+ auto spaces = z180_device::memory_space_config();
+ spaces.emplace_back(AS_DATA, &m_data_config);
+ return spaces;
+}
+
+uint8_t hd647180x_device::z180_read_memory(offs_t addr)
+{
+ if ((addr & 0xffe00) == (offs_t(m_rmcr) << 12 | 0x0fe00))
+ return m_data->read_byte(addr & 0x1ff);
+ else
+ return z180_device::z180_read_memory(addr);
+}
+
+void hd647180x_device::z180_write_memory(offs_t addr, uint8_t data)
+{
+ if ((addr & 0xffe00) == (offs_t(m_rmcr) << 12 | 0x0fe00))
+ m_data->write_byte(addr & 0x1ff, data);
+ else
+ z180_device::z180_write_memory(addr, data);
+}
+
+uint8_t hd647180x_device::z180_internal_port_read(uint8_t port)
+{
+ uint8_t data = 0xff;
+
+ switch (port)
+ {
+ case 0x40:
+ data = m_t2frc.b.l;
+ LOG("HD647180X T2FRCL rd $%02x\n", data);
+ break;
+
+ case 0x41:
+ data = m_t2frc.b.h;
+ LOG("HD647180X T2FRCH rd $%02x\n", data);
+ break;
+
+ case 0x42:
+ data = m_t2ocr[0].b.l;
+ LOG("HD647180X T2OCR1L rd $%02x\n", data);
+ break;
+
+ case 0x43:
+ data = m_t2ocr[0].b.h;
+ LOG("HD647180X T2OCR1H rd $%02x\n", data);
+ break;
+
+ case 0x44:
+ data = m_t2ocr[1].b.l;
+ LOG("HD647180X T2OCR2L rd $%02x\n", data);
+ break;
+
+ case 0x45:
+ data = m_t2ocr[1].b.h;
+ LOG("HD647180X T2OCR2H rd $%02x\n", data);
+ break;
+
+ case 0x46:
+ data = m_t2icr.b.l;
+ LOG("HD647180X T2ICRL rd $%02x\n", data);
+ break;
+
+ case 0x47:
+ data = m_t2icr.b.h;
+ LOG("HD647180X T2ICRH rd $%02x\n", data);
+ break;
+
+ case 0x48:
+ data = m_t2csr[0];
+ LOG("HD647180X T2CSR1 rd $%02x\n", data);
+ break;
+
+ case 0x49:
+ data = m_t2csr[1] | 0x10;
+ LOG("HD647180X T2CSR2 rd $%02x\n", data);
+ break;
+
+ case 0x50:
+ data = m_ccsr | 0x40;
+ LOG("HD647180X CCSR rd $%02x\n", data);
+ break;
+
+ case 0x51:
+ data = m_rmcr | 0x0f;
+ LOG("HD647180X RMCR rd $%02x\n", data);
+ break;
+
+ case 0x53:
+ data = m_dera;
+ LOG("HD647180X DERA rd $%02x\n", data);
+ break;
+
+ case 0x60:
+ case 0x61:
+ case 0x62:
+ case 0x65:
+ data = m_odr[port - 0x60] & m_ddr[port - 0x60];
+ if (m_ddr[port - 0x60] != 0xff)
+ data |= m_port_input_cb[port - 0x60](0, ~m_ddr[port - 0x60]) & ~m_ddr[port - 0x60];
+ LOG("HD647180X IDR%c rd $%02x\n", port - 0x60 + 'A', data);
+ break;
+
+ case 0x63: // ODRD is write-only
+ data = m_ddr[3];
+ if (m_ddr[3] != 0xff)
+ data |= m_port_input_cb[3](0, ~m_ddr[3]) & ~m_ddr[3];
+ LOG("HD647180X IDRD rd $%02x\n", data);
+ break;
+
+ case 0x64: // lower half of ODRE is write-only
+ data = (m_odr[port - 0x60] | 0x0f) & m_ddr[3];
+ if (m_ddr[3] != 0xff)
+ data |= m_port_input_cb[3](0, ~m_ddr[3]) & ~m_ddr[3];
+ LOG("HD647180X IDRE rd $%02x\n", data);
+ break;
+
+ case 0x66: // Port G is read-only and only has 6 bits
+ data = m_port_input_cb[6](0, 0x3f) | 0xc0;
+ LOG("HD647180X IDRG rd $%02x\n", data);
+ break;
+
+ default:
+ data = z180_device::z180_internal_port_read(port);
+ break;
+ }
+
+ return data;
+}
+
+void hd647180x_device::z180_internal_port_write(uint8_t port, uint8_t data)
+{
+ switch (port)
+ {
+ case 0x40:
+ LOG("HD647180X T2FRCL wr $%02x\n", data);
+ m_t2frc.b.l = data;
+ break;
+
+ case 0x41:
+ LOG("HD647180X T2FRCH wr $%02x\n", data);
+ m_t2frc.b.h = data;
+ break;
+
+ case 0x42:
+ LOG("HD647180X T2OCR1L wr $%02x\n", data);
+ m_t2ocr[0].b.l = data;
+ break;
+
+ case 0x43:
+ LOG("HD647180X T2OCR1H wr $%02x\n", data);
+ m_t2ocr[0].b.h = data;
+ break;
+
+ case 0x44:
+ LOG("HD647180X T2OCR2L wr $%02x\n", data);
+ m_t2ocr[1].b.l = data;
+ break;
+
+ case 0x45:
+ LOG("HD647180X T2OCR2H wr $%02x\n", data);
+ m_t2ocr[1].b.h = data;
+ break;
+
+ case 0x48:
+ LOG("HD647180X T2CSR1 wr $%02x\n", data);
+ m_t2csr[0] = data;
+ break;
+
+ case 0x49:
+ LOG("HD647180X T2CSR2 wr $%02x\n", data);
+ m_t2csr[1] = data & 0xef;
+ break;
+
+ case 0x50:
+ LOG("HD647180X CCSR wr $%02x\n", data);
+ m_ccsr = (m_ccsr & 0x80) | (data & 0x3f);
+ break;
+
+ case 0x51:
+ LOG("HD647180X RMCR wr $%02x\n", data);
+ m_rmcr = data & 0xf0;
+ break;
+
+ case 0x53:
+ LOG("HD647180X DERA wr $%02x\n", data);
+ m_dera = data;
+ break;
+
+ case 0x60:
+ case 0x61:
+ case 0x62:
+ case 0x63:
+ case 0x64:
+ case 0x65:
+ LOG("HD647180X ODR%c wr $%02x\n", port - 0x60 + 'A', data);
+ if ((data & m_ddr[port - 0x60]) != (m_odr[port - 0x60] & m_ddr[port - 0x60]))
+ m_port_output_cb[port - 0x60](0, data | ~m_ddr[port - 0x60], m_ddr[port - 0x60]);
+ m_odr[port - 0x60] = data;
+ break;
+
+ case 0x70:
+ case 0x71:
+ case 0x72:
+ case 0x73:
+ case 0x74:
+ case 0x75:
+ LOG("HD647180X DDR%c wr $%02x\n", port - 0x70 + 'A', data);
+ if ((data & ~m_ddr[port - 0x70]) != 0)
+ m_port_output_cb[port - 0x70](0, m_odr[port - 0x70] | ~data, data);
+ m_ddr[port - 0x70] = data;
+ break;
+
+ default:
+ z180_device::z180_internal_port_write(port, data);
+ break;
+ }
+}
+
+void hd647180x_device::device_resolve_objects()
+{
+ for (auto &cb : m_port_input_cb)
+ cb.resolve_safe(0xff);
+ for (auto &cb : m_port_output_cb)
+ cb.resolve_safe();
+}
+
+void hd647180x_device::device_start()
+{
+ z180_device::device_start();
+
+ m_data = &space(AS_DATA);
+
+ state_add(HD647180X_T2FRC, "T2FRC", m_t2frc.w);
+ state_add(HD647180X_T2OCR1, "T2OCR1", m_t2ocr[0].w);
+ state_add(HD647180X_T2OCR2, "T2OCR2", m_t2ocr[1].w);
+ state_add(HD647180X_T2ICR, "T2ICR", m_t2icr.w);
+ state_add(HD647180X_T2CSR1, "T2CSR1", m_t2csr[0]);
+ state_add(HD647180X_T2CSR2, "T2CSR2", m_t2csr[1]).mask(0xef);
+ state_add(HD647180X_CCSR, "CCSR", m_ccsr).mask(0xbf);
+ state_add(HD647180X_RMCR, "RMCR", m_rmcr).mask(0xf0);
+ state_add(HD647180X_DERA, "DERA", m_dera);
+ for (int i = 0; i < 6; i++)
+ {
+ state_add(HD647180X_ODRA + i, string_format("ODR%c", i + 'A').c_str(), m_odr[i]);
+ state_add(HD647180X_DDRA + i, string_format("DDR%c", i + 'A').c_str(), m_ddr[i]);
+ }
+
+ save_item(NAME(m_t2frc.w));
+ save_item(NAME(m_t2ocr[0].w));
+ save_item(NAME(m_t2ocr[1].w));
+ save_item(NAME(m_t2icr.w));
+ save_item(NAME(m_t2csr));
+ save_item(NAME(m_ccsr));
+ save_item(NAME(m_rmcr));
+ save_item(NAME(m_dera));
+ save_item(NAME(m_odr));
+ save_item(NAME(m_ddr));
+}
+
+void hd647180x_device::device_reset()
+{
+ z180_device::device_reset();
+
+ m_t2frc.w = 0;
+ m_t2ocr[0].w = m_t2ocr[1].w = 0xffff;
+ m_t2icr.w = 0;
+ m_t2csr[0] = 0x00;
+ m_t2csr[1] = 0x00;
+ m_ccsr = (m_ccsr & 0x80) | 0x2c;
+ m_rmcr = 0;
+ m_dera = 0;
+ std::fill(std::begin(m_ddr), std::end(m_ddr), 0);
+}
diff --git a/src/devices/cpu/z180/hd647180x.h b/src/devices/cpu/z180/hd647180x.h
new file mode 100644
index 00000000000..0221a614794
--- /dev/null
+++ b/src/devices/cpu/z180/hd647180x.h
@@ -0,0 +1,87 @@
+// license:BSD-3-Clause
+// copyright-holders:AJR
+
+#ifndef MAME_CPU_Z180_HD647180X_H
+#define MAME_CPU_Z180_HD647180X_H
+
+#pragma once
+
+#include "z180.h"
+
+class hd647180x_device : public z180_device
+{
+public:
+ enum
+ {
+ HD647180X_T2FRC = Z180_IOLINES + 1,
+ HD647180X_T2OCR1, HD647180X_T2OCR2,
+ HD647180X_T2ICR,
+ HD647180X_T2CSR1, HD647180X_T2CSR2,
+ HD647180X_CCSR,
+ HD647180X_RMCR,
+ HD647180X_DERA,
+ HD647180X_ODRA, HD647180X_ODRB, HD647180X_ODRC, HD647180X_ODRD, HD647180X_ODRE, HD647180X_ODRF,
+ HD647180X_DDRA, HD647180X_DDRB, HD647180X_DDRC, HD647180X_DDRD, HD647180X_DDRE, HD647180X_DDRF
+ };
+
+ // construction/destruction
+ hd647180x_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+ auto in_pa_callback() { return m_port_input_cb[0].bind(); }
+ auto in_pb_callback() { return m_port_input_cb[1].bind(); }
+ auto in_pc_callback() { return m_port_input_cb[2].bind(); }
+ auto in_pd_callback() { return m_port_input_cb[3].bind(); }
+ auto in_pe_callback() { return m_port_input_cb[4].bind(); }
+ auto in_pf_callback() { return m_port_input_cb[5].bind(); }
+ auto in_pg_callback() { return m_port_input_cb[6].bind(); }
+ auto out_pa_callback() { return m_port_output_cb[0].bind(); }
+ auto out_pb_callback() { return m_port_output_cb[1].bind(); }
+ auto out_pc_callback() { return m_port_output_cb[2].bind(); }
+ auto out_pd_callback() { return m_port_output_cb[3].bind(); }
+ auto out_pe_callback() { return m_port_output_cb[4].bind(); }
+ auto out_pf_callback() { return m_port_output_cb[5].bind(); }
+
+protected:
+ // device-specific overrides
+ virtual void device_resolve_objects() override;
+ virtual void device_start() override;
+ virtual void device_reset() override;
+
+ // device_memory_interface overrides
+ virtual space_config_vector memory_space_config() const override;
+
+ // z180_device overrides
+ virtual uint8_t z180_read_memory(offs_t addr) override;
+ virtual void z180_write_memory(offs_t addr, uint8_t data) override;
+ virtual uint8_t z180_internal_port_read(uint8_t port) override;
+ virtual void z180_internal_port_write(uint8_t port, uint8_t data) override;
+
+private:
+ // internal memory maps
+ void prom_map(address_map &map);
+ void ram_map(address_map &map);
+
+ // port callbacks
+ devcb_read8 m_port_input_cb[7];
+ devcb_write8 m_port_output_cb[6];
+
+ // internal RAM space
+ address_space_config m_data_config;
+ address_space *m_data;
+
+ // internal registers
+ PAIR16 m_t2frc;
+ PAIR16 m_t2ocr[2];
+ PAIR16 m_t2icr;
+ uint8_t m_t2csr[2];
+ uint8_t m_ccsr;
+ uint8_t m_rmcr;
+ uint8_t m_dera;
+ uint8_t m_odr[6];
+ uint8_t m_ddr[6];
+};
+
+// device type declaration
+DECLARE_DEVICE_TYPE(HD647180X, hd647180x_device)
+
+#endif // MAME_CPU_Z180_HD647180X_H
diff --git a/src/devices/cpu/z180/z180.cpp b/src/devices/cpu/z180/z180.cpp
index aede5f08a28..510075b041d 100644
--- a/src/devices/cpu/z180/z180.cpp
+++ b/src/devices/cpu/z180/z180.cpp
@@ -78,15 +78,19 @@ Hitachi HD647180 series:
/* register is calculated as follows: refresh=(Regs.R&127)|(Regs.R2&128) */
/****************************************************************************/
-DEFINE_DEVICE_TYPE(Z180, z180_device, "z180", "Zilog Z180")
+DEFINE_DEVICE_TYPE(Z80180, z80180_device, "z80180", "Zilog Z80180") // equivalent to Hitachi HD64180
+DEFINE_DEVICE_TYPE(HD64180RP, hd64180rp_device, "hd64180rp", "Hitachi HD64180RP") // DIP version identical to Zilog Z80180xxPSC
+DEFINE_DEVICE_TYPE(Z8S180, z8s180_device, "z8s180", "Zilog Z8S180")
+DEFINE_DEVICE_TYPE(Z80182, z80182_device, "z80182", "Zilog Z80182")
-z180_device::z180_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : cpu_device(mconfig, Z180, tag, owner, clock)
+z180_device::z180_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock, bool extended_io, address_map_constructor internal_map)
+ : cpu_device(mconfig, type, tag, owner, clock)
, z80_daisy_chain_interface(mconfig, *this)
- , m_program_config("program", ENDIANNESS_LITTLE, 8, 20, 0)
+ , m_program_config("program", ENDIANNESS_LITTLE, 8, 20, 0, internal_map)
, m_io_config("io", ENDIANNESS_LITTLE, 8, 16, 0)
- , m_decrypted_opcodes_config("program", ENDIANNESS_LITTLE, 8, 20, 0)
+ , m_decrypted_opcodes_config("opcodes", ENDIANNESS_LITTLE, 8, 20, 0)
+ , m_extended_io(extended_io)
{
// some arbitrary initial values
m_asci_cntla[0] = m_asci_cntla[1] = 0;
@@ -110,6 +114,28 @@ std::unique_ptr<util::disasm_interface> z180_device::create_disassembler()
return std::make_unique<z180_disassembler>();
}
+z80180_device::z80180_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : z180_device(mconfig, Z80180, tag, owner, clock, false, address_map_constructor())
+{
+}
+
+hd64180rp_device::hd64180rp_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : z180_device(mconfig, HD64180RP, tag, owner, clock, false, address_map_constructor())
+{
+ // 64-pin DIP versions omit A19
+ set_data_width(19);
+}
+
+z8s180_device::z8s180_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : z180_device(mconfig, Z8S180, tag, owner, clock, false, address_map_constructor())
+{
+}
+
+z80182_device::z80182_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : z180_device(mconfig, Z80182, tag, owner, clock, false, address_map_constructor())
+{
+}
+
#define CF 0x01
#define NF 0x02
#define PF 0x04
@@ -388,8 +414,6 @@ bool z180_device::get_tend1()
/* 3f I/O control register */
#define Z180_IOCR_IOSTP 0x20
-#define Z180_IOCR_MASK 0xe0
-
/***************************************************************************
CPU PREFIXES
@@ -427,6 +451,12 @@ static std::unique_ptr<uint8_t[]> SZHVC_sub;
#include "z180op.hxx"
+void z180_device::set_data_width(int bits)
+{
+ m_program_config.m_data_width = bits;
+ m_decrypted_opcodes_config.m_data_width = bits;
+}
+
device_memory_interface::space_config_vector z180_device::memory_space_config() const
{
if(has_configured_map(AS_OPCODES))
@@ -442,16 +472,29 @@ device_memory_interface::space_config_vector z180_device::memory_space_config()
};
}
+uint8_t z180_device::z180_read_memory(offs_t addr)
+{
+ return m_program->read_byte(addr);
+}
+
+void z180_device::z180_write_memory(offs_t addr, uint8_t data)
+{
+ m_program->write_byte(addr, data);
+}
+
uint8_t z180_device::z180_readcontrol(offs_t port)
{
- /* normal external readport */
- uint8_t data = m_iospace->read_byte(port);
+ // normal external readport (ignore the data)
+ (void)m_iospace->read_byte(port);
+
+ // read the internal register
+ return z180_internal_port_read(port & (m_extended_io ? 0x7f : 0x3f));
+}
- /* remap internal I/O registers */
- if((port & (m_iocr & 0xc0)) == (m_iocr & 0xc0))
- port = port - (m_iocr & 0xc0);
+uint8_t z180_device::z180_internal_port_read(uint8_t port)
+{
+ uint8_t data = 0xff;
- /* but ignore the data and read the internal register */
switch (port)
{
case 0x00:
@@ -512,7 +555,7 @@ uint8_t z180_device::z180_readcontrol(offs_t port)
case 0x0b:
data = m_csio_trdr;
- logerror("Z180 TRDR rd $%02x\n", data);
+ LOG("Z180 TRDR rd $%02x\n", data);
break;
case 0x0c:
@@ -862,7 +905,7 @@ uint8_t z180_device::z180_readcontrol(offs_t port)
break;
case 0x3f:
- data = m_iocr | ~Z180_IOCR_MASK;
+ data = m_iocr | ~(m_extended_io ? 0xa0 : 0xe0);
LOG("Z180 IOCR rd $%02x ($%02x)\n", data, m_iocr);
break;
}
@@ -872,14 +915,15 @@ uint8_t z180_device::z180_readcontrol(offs_t port)
void z180_device::z180_writecontrol(offs_t port, uint8_t data)
{
- /* normal external write port */
+ // normal external write port
m_iospace->write_byte(port, data);
- /* remap internal I/O registers */
- if((port & (m_iocr & 0xc0)) == (m_iocr & 0xc0))
- port = port - (m_iocr & 0xc0);
+ // store the data in the internal register
+ z180_internal_port_write(port & (m_extended_io ? 0x7f : 0x3f), data);
+}
- /* store the data in the internal register */
+void z180_device::z180_internal_port_write(uint8_t port, uint8_t data)
+{
switch (port)
{
case 0x00:
@@ -1223,8 +1267,8 @@ void z180_device::z180_writecontrol(offs_t port, uint8_t data)
break;
case 0x3f:
- LOG("Z180 IOCR wr $%02x ($%02x)\n", data, data & Z180_IOCR_MASK);
- m_iocr = data & Z180_IOCR_MASK;
+ LOG("Z180 IOCR wr $%02x ($%02x)\n", data, data & (m_extended_io ? 0xa0 : 0xe0));
+ m_iocr = data & (m_extended_io ? 0xa0 : 0xe0);
break;
}
}
@@ -1259,24 +1303,24 @@ int z180_device::z180_dma0(int max_cycles)
switch( m_dmode & (Z180_DMODE_SM | Z180_DMODE_DM) )
{
case 0x00: /* memory SAR0+1 to memory DAR0+1 */
- m_program->write_byte(dar0++, m_program->read_byte(sar0++));
+ z180_write_memory(dar0++, z180_read_memory(sar0++));
cycles += memory_wait_states() * 2;
bcr0--;
break;
case 0x04: /* memory SAR0-1 to memory DAR0+1 */
- m_program->write_byte(dar0++, m_program->read_byte(sar0--));
+ z180_write_memory(dar0++, z180_read_memory(sar0--));
cycles += memory_wait_states() * 2;
bcr0--;
break;
case 0x08: /* memory SAR0 fixed to memory DAR0+1 */
- m_program->write_byte(dar0++, m_program->read_byte(sar0));
+ z180_write_memory(dar0++, z180_read_memory(sar0));
cycles += memory_wait_states() * 2;
bcr0--;
break;
case 0x0c: /* I/O SAR0 fixed to memory DAR0+1 */
if (m_iol & Z180_DREQ0)
{
- m_program->write_byte(dar0++, IN(sar0));
+ z180_write_memory(dar0++, IN(sar0));
cycles += memory_wait_states();
bcr0--;
/* edge sensitive DREQ0 ? */
@@ -1288,24 +1332,24 @@ int z180_device::z180_dma0(int max_cycles)
}
break;
case 0x10: /* memory SAR0+1 to memory DAR0-1 */
- m_program->write_byte(dar0--, m_program->read_byte(sar0++));
+ z180_write_memory(dar0--, z180_read_memory(sar0++));
cycles += memory_wait_states() * 2;
bcr0--;
break;
case 0x14: /* memory SAR0-1 to memory DAR0-1 */
- m_program->write_byte(dar0--, m_program->read_byte(sar0--));
+ z180_write_memory(dar0--, z180_read_memory(sar0--));
cycles += memory_wait_states() * 2;
bcr0--;
break;
case 0x18: /* memory SAR0 fixed to memory DAR0-1 */
- m_program->write_byte(dar0--, m_program->read_byte(sar0));
+ z180_write_memory(dar0--, z180_read_memory(sar0));
cycles += memory_wait_states() * 2;
bcr0--;
break;
case 0x1c: /* I/O SAR0 fixed to memory DAR0-1 */
if (m_iol & Z180_DREQ0)
{
- m_program->write_byte(dar0--, IN(sar0));
+ z180_write_memory(dar0--, IN(sar0));
cycles += memory_wait_states();
bcr0--;
/* edge sensitive DREQ0 ? */
@@ -1317,12 +1361,12 @@ int z180_device::z180_dma0(int max_cycles)
}
break;
case 0x20: /* memory SAR0+1 to memory DAR0 fixed */
- m_program->write_byte(dar0, m_program->read_byte(sar0++));
+ z180_write_memory(dar0, z180_read_memory(sar0++));
cycles += memory_wait_states() * 2;
bcr0--;
break;
case 0x24: /* memory SAR0-1 to memory DAR0 fixed */
- m_program->write_byte(dar0, m_program->read_byte(sar0--));
+ z180_write_memory(dar0, z180_read_memory(sar0--));
cycles += memory_wait_states() * 2;
bcr0--;
break;
@@ -1333,7 +1377,7 @@ int z180_device::z180_dma0(int max_cycles)
case 0x30: /* memory SAR0+1 to I/O DAR0 fixed */
if (m_iol & Z180_DREQ0)
{
- OUT(dar0, m_program->read_byte(sar0++));
+ OUT(dar0, z180_read_memory(sar0++));
cycles += memory_wait_states();
bcr0--;
/* edge sensitive DREQ0 ? */
@@ -1347,7 +1391,7 @@ int z180_device::z180_dma0(int max_cycles)
case 0x34: /* memory SAR0-1 to I/O DAR0 fixed */
if (m_iol & Z180_DREQ0)
{
- OUT(dar0, m_program->read_byte(sar0--));
+ OUT(dar0, z180_read_memory(sar0--));
cycles += memory_wait_states();
bcr0--;
/* edge sensitive DREQ0 ? */
@@ -1417,16 +1461,16 @@ int z180_device::z180_dma1()
switch (m_dcntl & (Z180_DCNTL_DIM1 | Z180_DCNTL_DIM0))
{
case 0x00: /* memory MAR1+1 to I/O IAR1 fixed */
- m_iospace->write_byte(iar1, m_program->read_byte(mar1++));
+ m_iospace->write_byte(iar1, z180_read_memory(mar1++));
break;
case 0x01: /* memory MAR1-1 to I/O IAR1 fixed */
- m_iospace->write_byte(iar1, m_program->read_byte(mar1--));
+ m_iospace->write_byte(iar1, z180_read_memory(mar1--));
break;
case 0x02: /* I/O IAR1 fixed to memory MAR1+1 */
- m_program->write_byte(mar1++, m_iospace->read_byte(iar1));
+ z180_write_memory(mar1++, m_iospace->read_byte(iar1));
break;
case 0x03: /* I/O IAR1 fixed to memory MAR1-1 */
- m_program->write_byte(mar1--, m_iospace->read_byte(iar1));
+ z180_write_memory(mar1--, m_iospace->read_byte(iar1));
break;
}
@@ -1742,7 +1786,7 @@ void z180_device::device_start()
state_add(Z180_BBR, "BBR", m_mmu_bbr).callimport();
state_add(Z180_CBAR, "CBAR", m_mmu_cbar).callimport();
state_add(Z180_OMCR, "OMCR", m_omcr).mask(Z180_OMCR_MASK);
- state_add(Z180_IOCR, "IOCR", m_iocr).mask(Z180_IOCR_MASK);
+ state_add(Z180_IOCR, "IOCR", m_iocr).mask(m_extended_io ? 0xa0 : 0xe0);
}
save_item(NAME(m_AF.w.l));
diff --git a/src/devices/cpu/z180/z180.h b/src/devices/cpu/z180/z180.h
index d5a1bc6ef94..25b93f8a07e 100644
--- a/src/devices/cpu/z180/z180.h
+++ b/src/devices/cpu/z180/z180.h
@@ -105,13 +105,13 @@ enum {
class z180_device : public cpu_device, public z80_daisy_chain_interface
{
public:
- // construction/destruction
- z180_device(const machine_config &mconfig, const char *_tag, device_t *_owner, uint32_t _clock);
-
bool get_tend0();
bool get_tend1();
protected:
+ // construction/destruction
+ z180_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock, bool extended_io, address_map_constructor internal_map);
+
// device-level overrides
virtual void device_start() override;
virtual void device_reset() override;
@@ -138,15 +138,24 @@ protected:
// device_disasm_interface overrides
virtual std::unique_ptr<util::disasm_interface> create_disassembler() override;
-private:
- int memory_wait_states() const { return (m_dcntl & 0xc0) >> 6; }
- int io_wait_states() const { return (m_dcntl & 0x30) == 0 ? 0 : ((m_dcntl & 0x30) >> 4) + 1; }
- bool is_internal_io_address(uint16_t port) const { return ((port ^ m_iocr) & 0xffc0) == 0; }
+ virtual uint8_t z180_read_memory(offs_t addr);
+ virtual void z180_write_memory(offs_t addr, uint8_t data);
+ virtual uint8_t z180_internal_port_read(uint8_t port);
+ virtual void z180_internal_port_write(uint8_t port, uint8_t data);
address_space_config m_program_config;
address_space_config m_io_config;
address_space_config m_decrypted_opcodes_config;
+ void set_data_width(int bits);
+
+private:
+ int memory_wait_states() const { return (m_dcntl & 0xc0) >> 6; }
+ int io_wait_states() const { return (m_dcntl & 0x30) == 0 ? 0 : ((m_dcntl & 0x30) >> 4) + 1; }
+ bool is_internal_io_address(uint16_t port) const { return ((port ^ m_iocr) & (m_extended_io ? 0xff80 : 0xffc0)) == 0; }
+
+ const bool m_extended_io;
+
PAIR m_PREPC,m_PC,m_SP,m_AF,m_BC,m_DE,m_HL,m_IX,m_IY;
PAIR m_AF2,m_BC2,m_DE2,m_HL2;
uint8_t m_R,m_R2,m_IFF1,m_IFF2,m_HALT,m_IM,m_I;
@@ -1787,7 +1796,37 @@ private:
void xycb_ff();
};
+class z80180_device : public z180_device
+{
+public:
+ // construction/destruction
+ z80180_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+};
+
+class hd64180rp_device : public z180_device
+{
+public:
+ // construction/destruction
+ hd64180rp_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+};
+
+class z8s180_device : public z180_device
+{
+public:
+ // construction/destruction
+ z8s180_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+};
+
+class z80182_device : public z180_device
+{
+public:
+ // construction/destruction
+ z80182_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+};
-DECLARE_DEVICE_TYPE(Z180, z180_device)
+DECLARE_DEVICE_TYPE(Z80180, z80180_device)
+DECLARE_DEVICE_TYPE(HD64180RP, hd64180rp_device)
+DECLARE_DEVICE_TYPE(Z8S180, z8s180_device)
+DECLARE_DEVICE_TYPE(Z80182, z80182_device)
#endif // MAME_CPU_Z180_Z180_H
diff --git a/src/devices/cpu/z180/z180dasm.cpp b/src/devices/cpu/z180/z180dasm.cpp
index 521ec1bfe41..f8d332eca15 100644
--- a/src/devices/cpu/z180/z180dasm.cpp
+++ b/src/devices/cpu/z180/z180dasm.cpp
@@ -450,7 +450,7 @@ offs_t z180_disassembler::disassemble(std::ostream &stream, offs_t pc, const dat
break;
case 'O': /* Offset relative to PC */
offset = (int8_t) params.r8(pos++);
- util::stream_format(stream, "$%05X", pc + offset + 2);
+ util::stream_format(stream, "$%04X", (pc + offset + 2) & 0xffff);
break;
case 'P': /* Port number */
ea = params.r8(pos++);
@@ -463,7 +463,7 @@ offs_t z180_disassembler::disassemble(std::ostream &stream, offs_t pc, const dat
case 'W': /* Memory address word */
ea = params.r16(pos);
pos += 2;
- util::stream_format(stream, "$%05X", ea);
+ util::stream_format(stream, "$%04X", ea);
break;
case 'X':
offset = (int8_t) params.r8(pos++);
diff --git a/src/devices/cpu/z180/z180ops.h b/src/devices/cpu/z180/z180ops.h
index 2bc68e3b5e3..7b4d0f159f2 100644
--- a/src/devices/cpu/z180/z180ops.h
+++ b/src/devices/cpu/z180/z180ops.h
@@ -81,13 +81,13 @@ void z180_device::z180_mmu()
inline u8 z180_device::RM(offs_t addr)
{
m_extra_cycles += memory_wait_states();
- return m_program->read_byte(MMU_REMAP_ADDR(addr));
+ return z180_read_memory(MMU_REMAP_ADDR(addr));
}
/***************************************************************
* Write a byte to given memory location
***************************************************************/
-#define WM(addr,value) m_extra_cycles += memory_wait_states(); m_program->write_byte(MMU_REMAP_ADDR(addr),value)
+#define WM(addr,value) m_extra_cycles += memory_wait_states(); z180_write_memory(MMU_REMAP_ADDR(addr),value)
/***************************************************************
* Read a word from given memory location