diff options
author | 2019-09-30 21:26:08 -0400 | |
---|---|---|
committer | 2019-09-30 21:30:10 -0400 | |
commit | 12c08b06c8b89d2de51fb9ddfcb626de9b491a84 (patch) | |
tree | 86755393785998e1a78b46076c3da92cb0f3f245 /src/devices/cpu/z180 | |
parent | 04732f12816067e1ea9ba0d807845835a39ed945 (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.cpp | 330 | ||||
-rw-r--r-- | src/devices/cpu/z180/hd647180x.h | 87 | ||||
-rw-r--r-- | src/devices/cpu/z180/z180.cpp | 122 | ||||
-rw-r--r-- | src/devices/cpu/z180/z180.h | 55 | ||||
-rw-r--r-- | src/devices/cpu/z180/z180dasm.cpp | 4 | ||||
-rw-r--r-- | src/devices/cpu/z180/z180ops.h | 4 |
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 |