diff options
author | AJR <ajrhacker@users.noreply.github.com> | 2019-11-03 11:30:14 -0500 |
---|---|---|
committer | AJR <ajrhacker@users.noreply.github.com> | 2019-11-03 11:32:32 -0500 |
commit | 27ddae4ecfaef153a184341cd5432f370d20c697 (patch) | |
tree | 62de06d2a1986db84f4ef672f0a7e72bb26409b1 /src/devices/cpu | |
parent | 7791be49e4819855d52c5037cdf976ee37c40b14 (diff) |
Preliminary SoC emulation for Sitronix ST2204 and ST2205U
Diffstat (limited to 'src/devices/cpu')
-rw-r--r-- | src/devices/cpu/m6502/dst2xxx.lst | 20 | ||||
-rw-r--r-- | src/devices/cpu/m6502/ost2xxx.lst | 58 | ||||
-rw-r--r-- | src/devices/cpu/m6502/st2204.cpp | 276 | ||||
-rw-r--r-- | src/devices/cpu/m6502/st2204.h | 72 | ||||
-rw-r--r-- | src/devices/cpu/m6502/st2205u.cpp | 400 | ||||
-rw-r--r-- | src/devices/cpu/m6502/st2205u.h | 97 | ||||
-rw-r--r-- | src/devices/cpu/m6502/st2xxx.cpp | 252 | ||||
-rw-r--r-- | src/devices/cpu/m6502/st2xxx.h | 134 |
8 files changed, 1309 insertions, 0 deletions
diff --git a/src/devices/cpu/m6502/dst2xxx.lst b/src/devices/cpu/m6502/dst2xxx.lst new file mode 100644 index 00000000000..e9687ba68f9 --- /dev/null +++ b/src/devices/cpu/m6502/dst2xxx.lst @@ -0,0 +1,20 @@ +# license:BSD-3-Clause +# copyright-holders:Olivier Galibert +# almost identical to r65c02 +brk_st_imp ora_idx nop_imm nop_c_imp tsb_zpg ora_zpg asl_c_zpg rmb_bzp php_imp ora_imm asl_acc nop_c_imp tsb_aba ora_aba asl_c_aba bbr_zpb +bpl_rel ora_idy ora_zpi nop_c_imp trb_zpg ora_zpx asl_c_zpx rmb_bzp clc_imp ora_aby inc_acc nop_c_imp trb_aba ora_abx asl_c_abx bbr_zpb +jsr_adr and_idx nop_imm nop_c_imp bit_zpg and_zpg rol_c_zpg rmb_bzp plp_imp and_imm rol_acc nop_c_imp bit_aba and_aba rol_c_aba bbr_zpb +bmi_rel and_idy and_zpi nop_c_imp bit_zpx and_zpx rol_c_zpx rmb_bzp sec_imp and_aby dec_acc nop_c_imp bit_abx and_abx rol_c_abx bbr_zpb +rti_st_imp eor_idx nop_imm nop_c_imp nop_zpg eor_zpg lsr_c_zpg rmb_bzp pha_imp eor_imm lsr_acc nop_c_imp jmp_adr eor_aba lsr_c_aba bbr_zpb +bvc_rel eor_idy eor_zpi nop_c_imp nop_zpx eor_zpx lsr_c_zpx rmb_bzp cli_imp eor_aby phy_imp nop_c_imp nop_c_aba eor_abx lsr_c_abx bbr_zpb +rts_imp adc_c_idx nop_imm nop_c_imp stz_zpg adc_c_zpg ror_c_zpg rmb_bzp pla_imp adc_c_imm ror_acc nop_c_imp jmp_c_ind adc_c_aba ror_c_aba bbr_zpb +bvs_rel adc_c_idy adc_c_zpi nop_c_imp stz_zpx adc_c_zpx ror_c_zpx rmb_bzp sei_imp adc_c_aby ply_imp nop_c_imp jmp_iax adc_c_abx ror_c_abx bbr_zpb +bra_rel sta_idx nop_imm nop_c_imp sty_zpg sta_zpg stx_zpg smb_bzp dey_imp bit_imm txa_imp nop_c_imp sty_aba sta_aba stx_aba bbs_zpb +bcc_rel sta_idy sta_zpi nop_c_imp sty_zpx sta_zpx stx_zpy smb_bzp tya_imp sta_aby txs_imp nop_c_imp stz_aba sta_abx stz_abx bbs_zpb +ldy_imm lda_idx ldx_imm nop_c_imp ldy_zpg lda_zpg ldx_zpg smb_bzp tay_imp lda_imm tax_imp nop_c_imp ldy_aba lda_aba ldx_aba bbs_zpb +bcs_rel lda_idy lda_zpi nop_c_imp ldy_zpx lda_zpx ldx_zpy smb_bzp clv_imp lda_aby tsx_imp nop_c_imp ldy_abx lda_abx ldx_aby bbs_zpb +cpy_imm cmp_idx nop_imm nop_c_imp cpy_zpg cmp_zpg dec_c_zpg smb_bzp iny_imp cmp_imm dex_imp wai_imp cpy_aba cmp_aba dec_c_aba bbs_zpb +bne_rel cmp_idy cmp_zpi nop_c_imp nop_zpx cmp_zpx dec_c_zpx smb_bzp cld_imp cmp_aby phx_imp stp_imp nop_c_abx cmp_abx dec_c_abx bbs_zpb +cpx_imm sbc_c_idx nop_imm nop_c_imp cpx_zpg sbc_c_zpg inc_c_zpg smb_bzp inx_imp sbc_c_imm nop_imp nop_c_imp cpx_aba sbc_c_aba inc_c_aba bbs_zpb +beq_rel sbc_c_idy sbc_c_zpi nop_c_imp nop_zpx sbc_c_zpx inc_c_zpx smb_bzp sed_imp sbc_c_aby plx_imp nop_c_imp nop_c_abx sbc_c_abx inc_c_abx bbs_zpb +reset_st diff --git a/src/devices/cpu/m6502/ost2xxx.lst b/src/devices/cpu/m6502/ost2xxx.lst new file mode 100644 index 00000000000..9b30c2e9b05 --- /dev/null +++ b/src/devices/cpu/m6502/ost2xxx.lst @@ -0,0 +1,58 @@ +# license:BSD-3-Clause +# copyright-holders:Olivier Galibert +# m65c02 opcodes, with a twist + +brk_st_imp + if(irq_taken || nmi_state) { + read_pc_noinc(); + } else { + read_pc(); + } + write(SP, PC >> 8); + dec_SP(); + write(SP, PC); + dec_SP(); + write(SP, irq_taken || nmi_state ? P & ~F_B : P); + dec_SP(); + set_irq_service(true); + if(irq_taken && nmi_state) { // NMI is not present on actual parts + PC = read_vector(0x7ffa); + PC = set_h(PC, read_vector(0x7ffb)); + nmi_state = false; + } else if(irq_taken) { + TMP = acknowledge_irq(); + PC = read_vector(0x7ff8 - (TMP << 1)); + PC = set_h(PC, read_vector(0x7ff9 - (TMP << 1))); + } else { + PC = read_vector(0x7ffe); + PC = set_h(PC, read_vector(0x7fff)); + } + irq_taken = false; + P = (P | F_I) & ~F_D; // Do *not* move after the prefetch + prefetch(); + inst_state = -1; + +rti_st_imp + read_pc_noinc(); + read(SP); + inc_SP(); + P = read(SP) | (F_B|F_E); + inc_SP(); + PC = read(SP); + inc_SP(); + PC = set_h(PC, read(SP)); + set_irq_service(false); + prefetch(); + +reset_st + read_arg(0xffff); + read_pc_noinc(); + read(SP); dec_SP(); + read(SP); dec_SP(); + read(SP); dec_SP(); + P = (P | F_I) & ~F_D; + set_irq_service(false); + PC = read_vector(0x7ffc); + PC = set_h(PC, read_vector(0x7ffd)); + prefetch(); + inst_state = -1; diff --git a/src/devices/cpu/m6502/st2204.cpp b/src/devices/cpu/m6502/st2204.cpp new file mode 100644 index 00000000000..7f70fd70b89 --- /dev/null +++ b/src/devices/cpu/m6502/st2204.cpp @@ -0,0 +1,276 @@ +// license:BSD-3-Clause +// copyright-holders:AJR +/********************************************************************** + + Sitronix ST2204 8-Bit Integrated Microcontroller + + Functional blocks: + * Interrupt controller (11 levels excluding BRK and RESET) + * GPIO (6 ports, 8 bits each) + * External bus (up to 7 CS outputs, 48M maximum addressable) + * Timers/event counters with clocking outputs (2 plus base timer) + * Programmable sound generator (2 channels plus DAC) + * LCD controller (320x240 B/W or 240x160 4-gray) + * Serial peripheral interface + * UART (built-in BRG; RS-232 and IrDA modes) + * Direct memory access + * Power down modes (WAI-0, WAI-1, STP) + * Watchdog timer + * Low voltage detector + * 512K ROM (may be disabled) + * 10K RAM + + Emulation is largely based on documentation for the ST2202, which + has similar though somewhat lesser capabilities. + +**********************************************************************/ + +#include "emu.h" +#include "st2204.h" + +DEFINE_DEVICE_TYPE(ST2204, st2204_device, "st2204", "Sitronix ST2204 Integrated Microcontroller") + +st2204_device::st2204_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) + : st2xxx_device(mconfig, ST2204, tag, owner, clock, + address_map_constructor(FUNC(st2204_device::int_map), this), + 26, // logical; only 23 address lines are brought out + 0x0f7f) +{ +} + +void st2204_device::device_start() +{ + std::unique_ptr<mi_st2204> intf = std::make_unique<mi_st2204>(); + intf->data = &space(AS_DATA); + intf->dcache = space(AS_DATA).cache<0, 0, ENDIANNESS_LITTLE>(); + intf->irr_enable = false; + intf->irr = 0; + intf->prr = 0; + intf->drr = 0; + intf->irq_service = false; + + save_item(NAME(m_pdata)); + save_item(NAME(m_pctrl)); + save_item(NAME(m_psel)); + save_item(NAME(m_pfun)); + save_item(NAME(m_sys)); + save_item(NAME(m_pmcr)); + save_item(NAME(m_ireq)); + save_item(NAME(m_iena)); + save_item(NAME(intf->irr_enable)); + save_item(NAME(intf->irr)); + save_item(NAME(intf->prr)); + save_item(NAME(intf->drr)); + save_item(NAME(intf->irq_service)); + + mintf = std::move(intf); + init(); + + state_add(ST_IRR, "IRR", downcast<mi_st2204 &>(*mintf).irr).mask(0xff); + state_add(ST_PRR, "PRR", downcast<mi_st2204 &>(*mintf).prr).mask(0xfff); + state_add(ST_DRR, "DRR", downcast<mi_st2204 &>(*mintf).drr).mask(0x7ff); + state_add<u8>(ST_IREQ, "IREQ", [this]() { return m_ireq; }, [this](u16 data) { m_ireq = data; update_irq_state(); }).mask(m_ireq_mask); + state_add<u8>(ST_IENA, "IENA", [this]() { return m_iena; }, [this](u16 data) { m_iena = data; update_irq_state(); }).mask(m_ireq_mask); + for (int i = 0; i < 5; i++) + { + state_add(ST_PDA + i, string_format("PD%c", 'A' + i).c_str(), m_pdata[i]); + state_add(ST_PCA + i, string_format("PC%c", 'A' + i).c_str(), m_pctrl[i]); + if (i == 2) + state_add(ST_PSA + i, string_format("PS%c", 'A' + i).c_str(), m_psel[i]); + if (i == 2 || i == 3) + state_add(ST_PFC + i - 2, string_format("PF%c", 'A' + i).c_str(), m_pfun[i - 2]); + } + state_add(ST_PDL, "PDL", m_pdata[6]); + state_add(ST_PCL, "PCL", m_pctrl[6]); + state_add(ST_PMCR, "PMCR", m_pmcr); + state_add<u8>(ST_SYS, "SYS", [this]() { return m_sys; }, [this](u8 data) { sys_w(data); }); +} + +void st2204_device::device_reset() +{ + st2xxx_device::device_reset(); + + mi_st2204 &m = downcast<mi_st2204 &>(*mintf); + m.irr_enable = false; + m.irr = 0; + m.prr = 0; + m.drr = 0; +} + +u8 st2204_device::mi_st2204::pread(u16 adr) +{ + u16 bank = irq_service && irr_enable ? irr : prr; + return data->read_byte(u32(bank ^ 1) << 14 | (adr & 0x3fff)); +} + +u8 st2204_device::mi_st2204::preadc(u16 adr) +{ + u16 bank = irq_service && irr_enable ? irr : prr; + return dcache->read_byte(u32(bank ^ 1) << 14 | (adr & 0x3fff)); +} + +void st2204_device::mi_st2204::pwrite(u16 adr, u8 val) +{ + u16 bank = irq_service && irr_enable ? irr : prr; + data->write_byte(u32(bank ^ 1) << 14 | (adr & 0x3fff), val); +} + +u8 st2204_device::mi_st2204::dread(u16 adr) +{ + return data->read_byte(u32(drr) << 15 | (adr & 0x7fff)); +} + +u8 st2204_device::mi_st2204::dreadc(u16 adr) +{ + return dcache->read_byte(u32(drr) << 15 | (adr & 0x7fff)); +} + +void st2204_device::mi_st2204::dwrite(u16 adr, u8 val) +{ + data->write_byte(u32(drr) << 15 | (adr & 0x7fff), val); +} + +u8 st2204_device::mi_st2204::read(u16 adr) +{ + return program->read_byte(adr); +} + +u8 st2204_device::mi_st2204::read_sync(u16 adr) +{ + return BIT(adr, 15) ? dreadc(adr) : BIT(adr, 14) ? preadc(adr) : cache->read_byte(adr); +} + +u8 st2204_device::mi_st2204::read_arg(u16 adr) +{ + return BIT(adr, 15) ? dreadc(adr) : BIT(adr, 14) ? preadc(adr) : cache->read_byte(adr); +} + +u8 st2204_device::mi_st2204::read_vector(u16 adr) +{ + return pread(adr); +} + +void st2204_device::mi_st2204::write(u16 adr, u8 val) +{ + program->write_byte(adr, val); +} + +u8 st2204_device::pmcr_r() +{ + return m_pmcr; +} + +void st2204_device::pmcr_w(u8 data) +{ + m_pmcr = data; +} + +u8 st2204_device::sys_r() +{ + return m_sys | 0x01; +} + +void st2204_device::sys_w(u8 data) +{ + m_sys = data; + downcast<mi_st2204 &>(*mintf).irr_enable = BIT(data, 2); +} + +u8 st2204_device::irr_r() +{ + return downcast<mi_st2204 &>(*mintf).irr; +} + +void st2204_device::irr_w(u8 data) +{ + downcast<mi_st2204 &>(*mintf).irr = data; +} + +u8 st2204_device::prrl_r() +{ + return downcast<mi_st2204 &>(*mintf).prr & 0xff; +} + +void st2204_device::prrl_w(u8 data) +{ + u16 &prr = downcast<mi_st2204 &>(*mintf).prr; + prr = data | (prr & 0x0f00); +} + +u8 st2204_device::prrh_r() +{ + return downcast<mi_st2204 &>(*mintf).prr >> 8; +} + +void st2204_device::prrh_w(u8 data) +{ + u16 &prr = downcast<mi_st2204 &>(*mintf).prr; + prr = (data & 0x0f) << 16 | (prr & 0x00ff); +} + +u8 st2204_device::drrl_r() +{ + return downcast<mi_st2204 &>(*mintf).drr & 0xff; +} + +void st2204_device::drrl_w(u8 data) +{ + u16 &drr = downcast<mi_st2204 &>(*mintf).drr; + drr = data | (drr & 0x0700); +} + +u8 st2204_device::drrh_r() +{ + return downcast<mi_st2204 &>(*mintf).drr >> 8; +} + +void st2204_device::drrh_w(u8 data) +{ + u16 &drr = downcast<mi_st2204 &>(*mintf).drr; + drr = (data & 0x07) << 16 | (drr & 0x00ff); +} + +u8 st2204_device::pmem_r(offs_t offset) +{ + return downcast<mi_st2204 &>(*mintf).pread(offset); +} + +void st2204_device::pmem_w(offs_t offset, u8 data) +{ + downcast<mi_st2204 &>(*mintf).pwrite(offset, data); +} + +u8 st2204_device::dmem_r(offs_t offset) +{ + return downcast<mi_st2204 &>(*mintf).dread(offset); +} + +void st2204_device::dmem_w(offs_t offset, u8 data) +{ + downcast<mi_st2204 &>(*mintf).dwrite(offset, data); +} + +void st2204_device::int_map(address_map &map) +{ + map(0x0000, 0x0004).rw(FUNC(st2204_device::pdata_r), FUNC(st2204_device::pdata_w)); + map(0x0005, 0x0005).rw(FUNC(st2204_device::psc_r), FUNC(st2204_device::psc_w)); + map(0x0008, 0x000c).rw(FUNC(st2204_device::pdata_r), FUNC(st2204_device::pdata_w)); + map(0x000d, 0x000d).rw(FUNC(st2204_device::pfc_r), FUNC(st2204_device::pfc_w)); + map(0x000e, 0x000e).rw(FUNC(st2204_device::pfd_r), FUNC(st2204_device::pfd_w)); + map(0x000f, 0x000f).rw(FUNC(st2204_device::pmcr_r), FUNC(st2204_device::pmcr_w)); + map(0x0030, 0x0030).rw(FUNC(st2204_device::sys_r), FUNC(st2204_device::sys_w)); + map(0x0031, 0x0031).rw(FUNC(st2204_device::irr_r), FUNC(st2204_device::irr_w)); + map(0x0032, 0x0032).rw(FUNC(st2204_device::prrl_r), FUNC(st2204_device::prrl_w)); + map(0x0033, 0x0033).rw(FUNC(st2204_device::prrh_r), FUNC(st2204_device::prrh_w)); + map(0x0034, 0x0034).rw(FUNC(st2204_device::drrl_r), FUNC(st2204_device::drrl_w)); + map(0x0035, 0x0035).rw(FUNC(st2204_device::drrh_r), FUNC(st2204_device::drrh_w)); + map(0x003c, 0x003c).rw(FUNC(st2204_device::ireql_r), FUNC(st2204_device::ireql_w)); + map(0x003d, 0x003d).rw(FUNC(st2204_device::ireqh_r), FUNC(st2204_device::ireqh_w)); + map(0x003e, 0x003e).rw(FUNC(st2204_device::ienal_r), FUNC(st2204_device::ienal_w)); + map(0x003f, 0x003f).rw(FUNC(st2204_device::ienah_r), FUNC(st2204_device::ienah_w)); + map(0x004c, 0x004c).rw(FUNC(st2204_device::pl_r), FUNC(st2204_device::pl_w)); + map(0x004e, 0x004e).w(FUNC(st2204_device::pcl_w)); + map(0x0080, 0x27ff).ram(); // 10K internal SRAM; extent of mapping guessed + map(0x4000, 0x7fff).rw(FUNC(st2204_device::pmem_r), FUNC(st2204_device::pmem_w)); + map(0x8000, 0xffff).rw(FUNC(st2204_device::dmem_r), FUNC(st2204_device::dmem_w)); +} diff --git a/src/devices/cpu/m6502/st2204.h b/src/devices/cpu/m6502/st2204.h new file mode 100644 index 00000000000..4ec61636d65 --- /dev/null +++ b/src/devices/cpu/m6502/st2204.h @@ -0,0 +1,72 @@ +// license:BSD-3-Clause +// copyright-holders:AJR +/********************************************************************** + + Sitronix ST2204 8-Bit Integrated Microcontroller + +**********************************************************************/ + +#ifndef MAME_CPU_M6502_ST2204_H +#define MAME_CPU_M6502_ST2204_H + +#pragma once + +#include "st2xxx.h" + +class st2204_device : public st2xxx_device +{ +public: + st2204_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock); + +protected: + virtual void device_start() override; + virtual void device_reset() override; + +private: + class mi_st2204 : public mi_st2xxx { + public: + virtual u8 read(u16 adr) override; + virtual u8 read_sync(u16 adr) override; + virtual u8 read_arg(u16 adr) override; + virtual u8 read_vector(u16 adr) override; + virtual void write(u16 adr, u8 val) override; + + u8 pread(u16 adr); + u8 preadc(u16 adr); + void pwrite(u16 adr, u8 val); + u8 dread(u16 adr); + u8 dreadc(u16 adr); + void dwrite(u16 adr, u8 val); + + bool irr_enable; + u8 irr; + u16 prr; + u16 drr; + }; + + u8 sys_r(); + void sys_w(u8 data); + u8 irr_r(); + void irr_w(u8 data); + u8 prrl_r(); + void prrl_w(u8 data); + u8 prrh_r(); + void prrh_w(u8 data); + u8 drrl_r(); + void drrl_w(u8 data); + u8 drrh_r(); + void drrh_w(u8 data); + u8 pmcr_r(); + void pmcr_w(u8 data); + + u8 pmem_r(offs_t offset); + void pmem_w(offs_t offset, u8 data); + u8 dmem_r(offs_t offset); + void dmem_w(offs_t offset, u8 data); + + void int_map(address_map &map); +}; + +DECLARE_DEVICE_TYPE(ST2204, st2204_device) + +#endif // MAME_MACHINE_M6502_ST2204_H diff --git a/src/devices/cpu/m6502/st2205u.cpp b/src/devices/cpu/m6502/st2205u.cpp new file mode 100644 index 00000000000..7084eb632c4 --- /dev/null +++ b/src/devices/cpu/m6502/st2205u.cpp @@ -0,0 +1,400 @@ +// license:BSD-3-Clause +// copyright-holders:AJR +/********************************************************************** + + Sitronix ST2205U 8-Bit Integrated Microcontroller + + Functional blocks: + * Interrupt controller (15 levels excluding BRK and RESET) + * GPIO (7 ports, 8 bits each) + * External bus (up to 7 CS outputs, 48M maximum addressable) + * Timers/event counters with clocking outputs (4 plus base timer) + * Programmable sound generator (4 channels with FIFOs, plus PWM + or ADPCM DAC and 16x8 signed multiplicator) + * LCD controller (640x400 B/W, 400x320 4-gray, 160xRGBx120 16-gray) + * Serial peripheral interface + * UART (built-in BRG; RS-232 and IrDA modes) + * USB 1.1 (separate control and bulk transfer endpoint buffers) + * Direct memory access + * NAND/AND Flash memory interface (includes ECC generator) + * Power down modes (WAI-0, WAI-1, STP) + * Watchdog timer + * Real time clock (seconds, minutes, hours with alarm interrupts) + * Low voltage detector with reset + * 512K ROM (may be disabled) + * 32K SRAM + +**********************************************************************/ + +#include "emu.h" +#include "st2205u.h" + +DEFINE_DEVICE_TYPE(ST2205U, st2205u_device, "st2205", "Sitronix ST2205U Integrated Microcontroller") + +st2205u_device::st2205u_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) + : st2xxx_device(mconfig, ST2205U, tag, owner, clock, + address_map_constructor(FUNC(st2205u_device::int_map), this), + 26, // logical; only 23 address lines are brought out + 0xdfff) + , m_lvctr(0) +{ +} + +void st2205u_device::device_start() +{ + std::unique_ptr<mi_st2205u> intf = std::make_unique<mi_st2205u>(); + intf->data = &space(AS_DATA); + intf->dcache = space(AS_DATA).cache<0, 0, ENDIANNESS_LITTLE>(); + intf->irr_enable = false; + intf->irr = 0; + intf->prr = 0; + intf->drr = 0; + intf->brr = 0; + intf->irq_service = false; + + intf->ram = make_unique_clear<u8[]>(0x8000); + + save_item(NAME(m_pdata)); + save_item(NAME(m_pctrl)); + save_item(NAME(m_psel)); + save_item(NAME(m_pfun)); + save_item(NAME(m_sys)); + save_item(NAME(m_pmcr)); + save_item(NAME(m_ireq)); + save_item(NAME(m_iena)); + save_item(NAME(m_lvctr)); + save_item(NAME(intf->irr_enable)); + save_item(NAME(intf->irr)); + save_item(NAME(intf->prr)); + save_item(NAME(intf->drr)); + save_item(NAME(intf->brr)); + save_item(NAME(intf->irq_service)); + save_pointer(NAME(intf->ram), 0x8000); + + mintf = std::move(intf); + init(); + + state_add(ST_IRR, "IRR", downcast<mi_st2205u &>(*mintf).irr).mask(0x87ff); + state_add(ST_PRR, "PRR", downcast<mi_st2205u &>(*mintf).prr).mask(0x87ff); + state_add(ST_DRR, "DRR", downcast<mi_st2205u &>(*mintf).drr).mask(0x8fff); + state_add(ST_BRR, "BRR", downcast<mi_st2205u &>(*mintf).brr).mask(0x9fff); + state_add<u8>(ST_IREQ, "IREQ", [this]() { return m_ireq; }, [this](u16 data) { m_ireq = data; update_irq_state(); }).mask(m_ireq_mask); + state_add<u8>(ST_IENA, "IENA", [this]() { return m_iena; }, [this](u16 data) { m_iena = data; update_irq_state(); }).mask(m_ireq_mask); + for (int i = 0; i < 6; i++) + { + state_add(ST_PDA + i, string_format("PD%c", 'A' + i).c_str(), m_pdata[i]); + state_add(ST_PCA + i, string_format("PC%c", 'A' + i).c_str(), m_pctrl[i]); + if (i == 2 || i == 4) + state_add(ST_PSA + i, string_format("PS%c", 'A' + i).c_str(), m_psel[i]); + if (i == 2 || i == 3) + state_add(ST_PFC + i - 2, string_format("PF%c", 'A' + i).c_str(), m_pfun[i - 2]).mask(i == 2 ? 0xfe : 0xff); + } + state_add(ST_PDL, "PDL", m_pdata[6]); + state_add(ST_PCL, "PCL", m_pctrl[6]); + state_add(ST_PMCR, "PMCR", m_pmcr); + state_add<u8>(ST_SYS, "SYS", [this]() { return m_sys; }, [this](u8 data) { sys_w(data); }).mask(0xfe); + state_add(ST_LVCTR, "LVCTR", m_lvctr).mask(0x0f); +} + +void st2205u_device::device_reset() +{ + st2xxx_device::device_reset(); + + mi_st2205u &m = downcast<mi_st2205u &>(*mintf); + m.irr_enable = false; + m.irr = 0; + m.prr = 0; + m.drr = 0; + + m_lvctr = 0; +} + +u8 st2205u_device::mi_st2205u::pread(u16 adr) +{ + u16 bank = irq_service ? irr : prr; + if (BIT(bank, 15)) + return ram[0x4000 | (adr & 0x3fff)]; + else + return data->read_byte(u32(bank) << 14 | (adr & 0x3fff)); +} + +u8 st2205u_device::mi_st2205u::preadc(u16 adr) +{ + u16 bank = irq_service ? irr : prr; + if (BIT(bank, 15)) + return ram[0x4000 | (adr & 0x3fff)]; + else + return dcache->read_byte(u32(bank) << 14 | (adr & 0x3fff)); +} + +void st2205u_device::mi_st2205u::pwrite(u16 adr, u8 val) +{ + u16 bank = irq_service ? irr : prr; + if (BIT(bank, 15)) + ram[0x4000 | (adr & 0x3fff)] = val; + else + data->write_byte(u32(bank) << 14 | (adr & 0x3fff), val); +} + +u8 st2205u_device::mi_st2205u::dread(u16 adr) +{ + if (BIT(drr, 15)) + return ram[adr & 0x7fff]; + else + return data->read_byte(u32(drr) << 15 | (adr & 0x7fff)); +} + +u8 st2205u_device::mi_st2205u::dreadc(u16 adr) +{ + if (BIT(drr, 15)) + return ram[adr & 0x7fff]; + else + return dcache->read_byte(u32(drr) << 15 | (adr & 0x7fff)); +} + +void st2205u_device::mi_st2205u::dwrite(u16 adr, u8 val) +{ + if (BIT(drr, 15)) + ram[adr & 0x7fff] = val; + else + data->write_byte(u32(drr) << 15 | (adr & 0x7fff), val); +} + +u8 st2205u_device::mi_st2205u::bread(u16 adr) +{ + if (BIT(brr, 15)) + return ram[0x2000 | (adr & 0x1fff)]; + else + return data->read_byte(u32(brr) << 13 | (adr & 0x1fff)); +} + +u8 st2205u_device::mi_st2205u::breadc(u16 adr) +{ + if (BIT(brr, 15)) + return ram[0x2000 | (adr & 0x1fff)]; + else + return dcache->read_byte(u32(brr) << 13 | (adr & 0x1fff)); +} + +void st2205u_device::mi_st2205u::bwrite(u16 adr, u8 val) +{ + if (BIT(brr, 15)) + ram[0x2000 | (adr & 0x1fff)] = val; + else + data->write_byte(u32(brr) << 13 | (adr & 0x1fff), val); +} + +u8 st2205u_device::mi_st2205u::read(u16 adr) +{ + return program->read_byte(adr); +} + +u8 st2205u_device::mi_st2205u::read_sync(u16 adr) +{ + return BIT(adr, 15) ? dreadc(adr) : BIT(adr, 14) ? preadc(adr) : BIT(adr, 13) ? breadc(adr) : cache->read_byte(adr); +} + +u8 st2205u_device::mi_st2205u::read_arg(u16 adr) +{ + return BIT(adr, 15) ? dreadc(adr) : BIT(adr, 14) ? preadc(adr) : BIT(adr, 13) ? breadc(adr) : cache->read_byte(adr); +} + +u8 st2205u_device::mi_st2205u::read_vector(u16 adr) +{ + return pread(adr); +} + +void st2205u_device::mi_st2205u::write(u16 adr, u8 val) +{ + program->write_byte(adr, val); +} + +u8 st2205u_device::irrl_r() +{ + return downcast<mi_st2205u &>(*mintf).irr & 0xff; +} + +void st2205u_device::irrl_w(u8 data) +{ + u16 &irr = downcast<mi_st2205u &>(*mintf).irr; + irr = data | (irr & 0x8f00); +} + +u8 st2205u_device::irrh_r() +{ + return downcast<mi_st2205u &>(*mintf).irr >> 8; +} + +void st2205u_device::irrh_w(u8 data) +{ + u16 &irr = downcast<mi_st2205u &>(*mintf).irr; + irr = (data & 0x8f) << 16 | (irr & 0x00ff); +} + +u8 st2205u_device::prrl_r() +{ + return downcast<mi_st2205u &>(*mintf).prr & 0xff; +} + +void st2205u_device::prrl_w(u8 data) +{ + u16 &prr = downcast<mi_st2205u &>(*mintf).prr; + prr = data | (prr & 0x8f00); +} + +u8 st2205u_device::prrh_r() +{ + return downcast<mi_st2205u &>(*mintf).prr >> 8; +} + +void st2205u_device::prrh_w(u8 data) +{ + u16 &prr = downcast<mi_st2205u &>(*mintf).prr; + prr = (data & 0x8f) << 16 | (prr & 0x00ff); +} + +u8 st2205u_device::drrl_r() +{ + return downcast<mi_st2205u &>(*mintf).drr & 0xff; +} + +void st2205u_device::drrl_w(u8 data) +{ + u16 &drr = downcast<mi_st2205u &>(*mintf).drr; + drr = data | (drr & 0x8700); +} + +u8 st2205u_device::drrh_r() +{ + return downcast<mi_st2205u &>(*mintf).drr >> 8; +} + +void st2205u_device::drrh_w(u8 data) +{ + u16 &drr = downcast<mi_st2205u &>(*mintf).drr; + drr = (data & 0x87) << 16 | (drr & 0x00ff); +} + +u8 st2205u_device::brrl_r() +{ + return downcast<mi_st2205u &>(*mintf).brr & 0xff; +} + +void st2205u_device::brrl_w(u8 data) +{ + u16 &brr = downcast<mi_st2205u &>(*mintf).brr; + brr = data | (brr & 0x9f00); +} + +u8 st2205u_device::brrh_r() +{ + return downcast<mi_st2205u &>(*mintf).brr >> 8; +} + +void st2205u_device::brrh_w(u8 data) +{ + u16 &brr = downcast<mi_st2205u &>(*mintf).brr; + brr = (data & 0x9f) << 16 | (brr & 0x00ff); +} + +u8 st2205u_device::pmcr_r() +{ + return m_pmcr; +} + +void st2205u_device::pmcr_w(u8 data) +{ + m_pmcr = data; +} + +u8 st2205u_device::sys_r() +{ + return m_sys; +} + +void st2205u_device::sys_w(u8 data) +{ + m_sys = data & 0xfe; + downcast<mi_st2205u &>(*mintf).irr_enable = BIT(data, 2); +} + +u8 st2205u_device::lvctr_r() +{ + return m_lvctr | 0x01; +} + +void st2205u_device::lvctr_w(u8 data) +{ + m_lvctr = data & 0x0f; +} + +u8 st2205u_device::ram_r(offs_t offset) +{ + return downcast<mi_st2205u &>(*mintf).ram[0x0080 + offset]; +} + +void st2205u_device::ram_w(offs_t offset, u8 data) +{ + downcast<mi_st2205u &>(*mintf).ram[0x0080 + offset] = data; +} + +u8 st2205u_device::pmem_r(offs_t offset) +{ + return downcast<mi_st2205u &>(*mintf).pread(offset); +} + +void st2205u_device::pmem_w(offs_t offset, u8 data) +{ + downcast<mi_st2205u &>(*mintf).pwrite(offset, data); +} + +u8 st2205u_device::dmem_r(offs_t offset) +{ + return downcast<mi_st2205u &>(*mintf).dread(offset); +} + +void st2205u_device::dmem_w(offs_t offset, u8 data) +{ + downcast<mi_st2205u &>(*mintf).dwrite(offset, data); +} + +u8 st2205u_device::bmem_r(offs_t offset) +{ + return downcast<mi_st2205u &>(*mintf).bread(offset); +} + +void st2205u_device::bmem_w(offs_t offset, u8 data) +{ + downcast<mi_st2205u &>(*mintf).bwrite(offset, data); +} + +void st2205u_device::int_map(address_map &map) +{ + map(0x0000, 0x0005).rw(FUNC(st2205u_device::pdata_r), FUNC(st2205u_device::pdata_w)); + map(0x0006, 0x0006).rw(FUNC(st2205u_device::psc_r), FUNC(st2205u_device::psc_w)); + map(0x0007, 0x0007).rw(FUNC(st2205u_device::pse_r), FUNC(st2205u_device::pse_w)); + map(0x0008, 0x000d).rw(FUNC(st2205u_device::pctrl_r), FUNC(st2205u_device::pctrl_w)); + map(0x000e, 0x000e).rw(FUNC(st2205u_device::pfc_r), FUNC(st2205u_device::pfc_w)); + map(0x000f, 0x000f).rw(FUNC(st2205u_device::pfd_r), FUNC(st2205u_device::pfd_w)); + map(0x0030, 0x0030).rw(FUNC(st2205u_device::irrl_r), FUNC(st2205u_device::irrl_w)); + map(0x0031, 0x0031).rw(FUNC(st2205u_device::irrh_r), FUNC(st2205u_device::irrh_w)); + map(0x0032, 0x0032).rw(FUNC(st2205u_device::prrl_r), FUNC(st2205u_device::prrl_w)); + map(0x0033, 0x0033).rw(FUNC(st2205u_device::prrh_r), FUNC(st2205u_device::prrh_w)); + map(0x0034, 0x0034).rw(FUNC(st2205u_device::drrl_r), FUNC(st2205u_device::drrl_w)); + map(0x0035, 0x0035).rw(FUNC(st2205u_device::drrh_r), FUNC(st2205u_device::drrh_w)); + map(0x0036, 0x0036).rw(FUNC(st2205u_device::brrl_r), FUNC(st2205u_device::brrl_w)); + map(0x0037, 0x0037).rw(FUNC(st2205u_device::brrh_r), FUNC(st2205u_device::brrh_w)); + map(0x0039, 0x0039).rw(FUNC(st2205u_device::sys_r), FUNC(st2205u_device::sys_w)); + map(0x003a, 0x003a).rw(FUNC(st2205u_device::pmcr_r), FUNC(st2205u_device::pmcr_w)); + map(0x003c, 0x003c).rw(FUNC(st2205u_device::ireql_r), FUNC(st2205u_device::ireql_w)); + map(0x003d, 0x003d).rw(FUNC(st2205u_device::ireqh_r), FUNC(st2205u_device::ireqh_w)); + map(0x003e, 0x003e).rw(FUNC(st2205u_device::ienal_r), FUNC(st2205u_device::ienal_w)); + map(0x003f, 0x003f).rw(FUNC(st2205u_device::ienah_r), FUNC(st2205u_device::ienah_w)); + map(0x004e, 0x004e).rw(FUNC(st2205u_device::pl_r), FUNC(st2205u_device::pl_w)); + map(0x004f, 0x004f).rw(FUNC(st2205u_device::pcl_r), FUNC(st2205u_device::pcl_w)); + map(0x0057, 0x0057).rw(FUNC(st2205u_device::lvctr_r), FUNC(st2205u_device::lvctr_w)); + map(0x0080, 0x1fff).rw(FUNC(st2205u_device::ram_r), FUNC(st2205u_device::ram_w)); // assumed to be shared with banked RAM + map(0x2000, 0x3fff).rw(FUNC(st2205u_device::bmem_r), FUNC(st2205u_device::bmem_w)); + map(0x4000, 0x7fff).rw(FUNC(st2205u_device::pmem_r), FUNC(st2205u_device::pmem_w)); + map(0x8000, 0xffff).rw(FUNC(st2205u_device::dmem_r), FUNC(st2205u_device::dmem_w)); +} diff --git a/src/devices/cpu/m6502/st2205u.h b/src/devices/cpu/m6502/st2205u.h new file mode 100644 index 00000000000..15ab962b8f3 --- /dev/null +++ b/src/devices/cpu/m6502/st2205u.h @@ -0,0 +1,97 @@ +// license:BSD-3-Clause +// copyright-holders:AJR +/********************************************************************** + + Sitronix ST2205U 8-Bit Integrated Microcontroller + +**********************************************************************/ + +#ifndef MAME_CPU_M6502_ST2205U_H +#define MAME_CPU_M6502_ST2205U_H + +#pragma once + +#include "st2xxx.h" + +class st2205u_device : public st2xxx_device +{ +public: + enum { + ST_BRR = ST_IENA + 1, + ST_LVCTR + }; + + st2205u_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock); + +protected: + virtual void device_start() override; + virtual void device_reset() override; + +private: + class mi_st2205u : public mi_st2xxx { + public: + virtual u8 read(u16 adr) override; + virtual u8 read_sync(u16 adr) override; + virtual u8 read_arg(u16 adr) override; + virtual u8 read_vector(u16 adr) override; + virtual void write(u16 adr, u8 val) override; + + u8 pread(u16 adr); + u8 preadc(u16 adr); + void pwrite(u16 adr, u8 val); + u8 dread(u16 adr); + u8 dreadc(u16 adr); + void dwrite(u16 adr, u8 val); + u8 bread(u16 adr); + u8 breadc(u16 adr); + void bwrite(u16 adr, u8 val); + + bool irr_enable; + u16 irr; + u16 prr; + u16 drr; + u16 brr; + + std::unique_ptr<u8[]> ram; + }; + + u8 irrl_r(); + void irrl_w(u8 data); + u8 irrh_r(); + void irrh_w(u8 data); + u8 prrl_r(); + void prrl_w(u8 data); + u8 prrh_r(); + void prrh_w(u8 data); + u8 drrl_r(); + void drrl_w(u8 data); + u8 drrh_r(); + void drrh_w(u8 data); + u8 brrl_r(); + void brrl_w(u8 data); + u8 brrh_r(); + void brrh_w(u8 data); + u8 sys_r(); + void sys_w(u8 data); + u8 pmcr_r(); + void pmcr_w(u8 data); + u8 lvctr_r(); + void lvctr_w(u8 data); + + u8 ram_r(offs_t offset); + void ram_w(offs_t offset, u8 data); + u8 pmem_r(offs_t offset); + void pmem_w(offs_t offset, u8 data); + u8 dmem_r(offs_t offset); + void dmem_w(offs_t offset, u8 data); + u8 bmem_r(offs_t offset); + void bmem_w(offs_t offset, u8 data); + + void int_map(address_map &map); + + u8 m_lvctr; +}; + +DECLARE_DEVICE_TYPE(ST2205U, st2205u_device) + +#endif // MAME_MACHINE_M6502_ST2205_H diff --git a/src/devices/cpu/m6502/st2xxx.cpp b/src/devices/cpu/m6502/st2xxx.cpp new file mode 100644 index 00000000000..711360b355f --- /dev/null +++ b/src/devices/cpu/m6502/st2xxx.cpp @@ -0,0 +1,252 @@ +// license:BSD-3-Clause +// copyright-holders:AJR +/********************************************************************** + + Sitronix ST2XXX LCD MCUs + + This extended SoC family combines a 65C02 CPU core (including the + Rockwell bit opcodes) with a wide variety of on-chip peripherals. + Features common to all besides internal RAM and ROM are parallel + ports, internal timers, a multi-level interrupt controller, LCD + controllers (of varying degrees of sophistication), R/C/slow XTAL + clock generators, power management and PSG channels for speaker + output. Each MCU also has numerous pins dedicated to LCD segment + drivers, an external bus addressing several MB of off-chip + memory using multiple chip select signals, or both. Program ROM, + whether internal or external, is banked to a greater or lesser + extent except on the smallest single-chip ST20XX models. + +**********************************************************************/ + +#include "emu.h" +#include "st2xxx.h" +#include "r65c02d.h" + +st2xxx_device::st2xxx_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock, address_map_constructor internal_map, int data_bits, u16 ireq_mask) + : r65c02_device(mconfig, type, tag, owner, clock) + , m_data_config("data", ENDIANNESS_LITTLE, 8, data_bits, 0) + , m_in_port_cb{{*this}, {*this}, {*this}, {*this}, {*this}, {*this}, {*this}} + , m_out_port_cb{{*this}, {*this}, {*this}, {*this}, {*this}, {*this}, {*this}} + , m_pdata{0} + , m_pctrl{0} + , m_psel{0} + , m_pfun{0} + , m_pmcr(0) + , m_ireq(0) + , m_iena(0) + , m_ireq_mask(ireq_mask) + , m_sys(0) +{ + program_config.m_internal_map = std::move(internal_map); +} + +device_memory_interface::space_config_vector st2xxx_device::memory_space_config() const +{ + return space_config_vector { + std::make_pair(AS_PROGRAM, &program_config), + std::make_pair(AS_DATA, &m_data_config) + }; +} + +void st2xxx_device::device_resolve_objects() +{ + for (auto &cb : m_in_port_cb) + cb.resolve_safe(0xff); + for (auto &cb : m_out_port_cb) + cb.resolve_safe(); +} + +void st2xxx_device::device_reset() +{ + m6502_device::device_reset(); + + // reset port registers + std::fill(std::begin(m_pdata), std::end(m_pdata), 0xff); + std::fill(std::begin(m_pctrl), std::end(m_pctrl), 0); + std::fill(std::begin(m_psel), std::end(m_psel), 0xff); + std::fill(std::begin(m_pfun), std::end(m_pfun), 0); + for (auto &cb : m_out_port_cb) + cb(0xff); + m_pmcr = 0x80; + + // reset interrupt registers + m_ireq = 0; + m_iena = 0; + update_irq_state(); + + // reset miscellaneous registers + m_sys = 0; +} + +std::unique_ptr<util::disasm_interface> st2xxx_device::create_disassembler() +{ + return std::make_unique<r65c02_disassembler>(); +} + +u8 st2xxx_device::acknowledge_irq() +{ + // IREQH interrupts have priority over IREQL interrupts + for (int level = 8; level < 16; level++) + { + if (BIT(m_ireq & m_iena, level)) + { + m_ireq &= ~(1 << level); + update_irq_state(); + return level; + } + } + for (int level = 0; level < 8; level++) + { + if (BIT(m_ireq & m_iena, level)) + { + m_ireq &= ~(1 << level); + update_irq_state(); + return level; + } + } + throw emu_fatalerror("ST2XXX: no IRQ to acknowledge!\n"); +} + +u8 st2xxx_device::pdata_r(offs_t offset) +{ + u8 pdata = m_pdata[offset]; + u8 pinmask = ~m_pctrl[offset] | (pdata & ~m_psel[offset]); + if (pinmask != 0) + pdata = (pdata & ~pinmask) | (m_in_port_cb[offset](0, pinmask) & pinmask); + return pdata; +} + +void st2xxx_device::pdata_w(offs_t offset, u8 data) +{ + if (data != m_pdata[offset]) + { + m_pdata[offset] = data; + m_out_port_cb[offset](0, data, m_pctrl[offset]); + } +} + +u8 st2xxx_device::pctrl_r(offs_t offset) +{ + return m_pctrl[offset]; +} + +void st2xxx_device::pctrl_w(offs_t offset, u8 data) +{ + if (data != m_pctrl[offset]) + { + m_pctrl[offset] = data; + m_out_port_cb[offset](0, m_pdata[offset], data); + } +} + +u8 st2xxx_device::pfc_r() +{ + return m_pfun[0]; +} + +void st2xxx_device::pfc_w(u8 data) +{ + m_pfun[0] = data; +} + +u8 st2xxx_device::pfd_r() +{ + return m_pfun[1]; +} + +void st2xxx_device::pfd_w(u8 data) +{ + m_pfun[1] = data; +} + +u8 st2xxx_device::pl_r() +{ + return pdata_r(6); +} + +void st2xxx_device::pl_w(u8 data) +{ + pdata_w(6, data); +} + +u8 st2xxx_device::psc_r() +{ + return m_psel[2]; +} + +void st2xxx_device::psc_w(u8 data) +{ + m_psel[2] = data; +} + +u8 st2xxx_device::pse_r() +{ + return m_psel[4]; +} + +void st2xxx_device::pse_w(u8 data) +{ + m_psel[4] = data; +} + +u8 st2xxx_device::pcl_r() +{ + return pctrl_r(6); +} + +void st2xxx_device::pcl_w(u8 data) +{ + pctrl_w(6, data); +} + +u8 st2xxx_device::ireql_r() +{ + return m_ireq & 0x00ff; +} + +void st2xxx_device::ireql_w(u8 data) +{ + if ((m_ireq & ~data & 0x00ff) != 0) + { + m_ireq &= data | 0xff00; + update_irq_state(); + } +} + +u8 st2xxx_device::ireqh_r() +{ + return m_ireq >> 8; +} + +void st2xxx_device::ireqh_w(u8 data) +{ + if ((m_ireq & ~(u16(data) << 8) & 0xff00) != 0) + { + m_ireq &= u16(data) << 8 | 0x00ff; + update_irq_state(); + } +} + +u8 st2xxx_device::ienal_r() +{ + return m_iena & 0x00ff; +} + +void st2xxx_device::ienal_w(u8 data) +{ + m_iena = (m_iena & 0xff00) | (data & m_ireq_mask); + update_irq_state(); +} + +u8 st2xxx_device::ienah_r() +{ + return m_iena >> 8; +} + +void st2xxx_device::ienah_w(u8 data) +{ + m_iena = (m_iena & 0x00ff) | ((u16(data) << 8) & m_ireq_mask); + update_irq_state(); +} + +#include "cpu/m6502/st2xxx.hxx" diff --git a/src/devices/cpu/m6502/st2xxx.h b/src/devices/cpu/m6502/st2xxx.h new file mode 100644 index 00000000000..2d328be54f0 --- /dev/null +++ b/src/devices/cpu/m6502/st2xxx.h @@ -0,0 +1,134 @@ +#ifndef MAME_CPU_M6502_ST2XXX_H +#define MAME_CPU_M6502_ST2XXX_H + +#pragma once + +#include "r65c02.h" + +class st2xxx_device : public r65c02_device { +public: + enum { + ST_PDA = M6502_IR + 1, + ST_PDB, + ST_PDC, + ST_PDD, + ST_PDE, + ST_PDF, + ST_PDL, + ST_PCA, + ST_PCB, + ST_PCC, + ST_PCD, + ST_PCE, + ST_PCF, + ST_PCL, + ST_PSA, + ST_PSB, + ST_PSC, + ST_PSD, + ST_PSE, + ST_PSF, + ST_PSL, + ST_PFC, + ST_PFD, + ST_PMCR, + ST_SYS, + ST_IRR, + ST_PRR, + ST_DRR, + ST_IREQ, + ST_IENA + }; + + auto in_pa_callback() { return m_in_port_cb[0].bind(); } + auto out_pa_callback() { return m_out_port_cb[0].bind(); } + auto in_pb_callback() { return m_in_port_cb[1].bind(); } + auto out_pb_callback() { return m_out_port_cb[1].bind(); } + auto in_pc_callback() { return m_in_port_cb[2].bind(); } + auto out_pc_callback() { return m_out_port_cb[2].bind(); } + auto in_pd_callback() { return m_in_port_cb[3].bind(); } + auto out_pd_callback() { return m_out_port_cb[3].bind(); } + auto in_pe_callback() { return m_in_port_cb[4].bind(); } + auto out_pe_callback() { return m_out_port_cb[4].bind(); } + auto in_pf_callback() { return m_in_port_cb[5].bind(); } + auto out_pf_callback() { return m_out_port_cb[5].bind(); } + auto in_pl_callback() { return m_in_port_cb[6].bind(); } + auto out_pl_callback() { return m_out_port_cb[6].bind(); } + +protected: + st2xxx_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock, address_map_constructor internal_map, int data_bits, u16 ireq_mask); + + virtual space_config_vector memory_space_config() const override; + virtual void device_resolve_objects() override; + virtual void device_reset() override; + + virtual std::unique_ptr<util::disasm_interface> create_disassembler() override; + virtual void do_exec_full() override; + virtual void do_exec_partial() override; + + class mi_st2xxx : public memory_interface { + public: + virtual u8 read_vector(u16 adr) = 0; + + address_space *data; + memory_access_cache<0, 0, ENDIANNESS_LITTLE> *dcache; + bool irq_service; + }; + + u8 read_vector(u16 adr) { return downcast<mi_st2xxx &>(*mintf).read_vector(adr); } + void set_irq_service(bool state) { downcast<mi_st2xxx &>(*mintf).irq_service = state; } + + void update_irq_state() { irq_state = (m_ireq & m_iena) != 0; } + u8 acknowledge_irq(); + + u8 pdata_r(offs_t offset); + void pdata_w(offs_t offset, u8 data); + u8 pctrl_r(offs_t offset); + void pctrl_w(offs_t offset, u8 data); + u8 pl_r(); + void pl_w(u8 data); + u8 pcl_r(); + void pcl_w(u8 data); + u8 psc_r(); + void psc_w(u8 data); + u8 pse_r(); + void pse_w(u8 data); + u8 pfc_r(); + void pfc_w(u8 data); + u8 pfd_r(); + void pfd_w(u8 data); + + u8 ireql_r(); + void ireql_w(u8 data); + u8 ireqh_r(); + void ireqh_w(u8 data); + u8 ienal_r(); + void ienal_w(u8 data); + u8 ienah_r(); + void ienah_w(u8 data); + +#define O(o) void o ## _full(); void o ## _partial() + + O(brk_st_imp); + O(rti_st_imp); + O(reset_st); + +#undef O + + address_space_config m_data_config; + + devcb_read8 m_in_port_cb[7]; + devcb_write8 m_out_port_cb[7]; + + u8 m_pdata[7]; + u8 m_pctrl[7]; + u8 m_psel[7]; + u8 m_pfun[2]; + u8 m_pmcr; + u16 m_ireq; + u16 m_iena; + const u16 m_ireq_mask; + u8 m_sys; +}; + +#endif // MAME_CPU_M6502_ST2XXX_H |