summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/cpu/sh/sh7014.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/devices/cpu/sh/sh7014.cpp')
-rw-r--r--src/devices/cpu/sh/sh7014.cpp201
1 files changed, 201 insertions, 0 deletions
diff --git a/src/devices/cpu/sh/sh7014.cpp b/src/devices/cpu/sh/sh7014.cpp
new file mode 100644
index 00000000000..a8cf17f98f8
--- /dev/null
+++ b/src/devices/cpu/sh/sh7014.cpp
@@ -0,0 +1,201 @@
+// license:BSD-3-Clause
+// copyright-holders:windyfairy
+/***************************************************************************
+
+ SH-2 SH7014
+
+***************************************************************************/
+
+#include "emu.h"
+
+#include "sh7014.h"
+
+
+DEFINE_DEVICE_TYPE(SH7014, sh7014_device, "sh7014", "Hitachi SH-2 (SH7014)")
+
+sh7014_device::sh7014_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : sh2_device(mconfig, SH7014, tag, owner, clock, CPU_TYPE_SH2, address_map_constructor(FUNC(sh7014_device::sh7014_map), this), 32, 0xffffffff)
+ , m_sci(*this, "sci%u", 0u)
+ , m_bsc(*this, "bsc")
+ , m_dmac(*this, "dmac")
+ , m_intc(*this, "intc")
+ , m_mtu(*this, "mtu")
+ , m_port(*this, "io_port")
+ , m_sci_tx_cb(*this)
+{
+}
+
+void sh7014_device::device_start()
+{
+ sh2_device::device_start();
+
+ save_item(NAME(m_ccr));
+}
+
+void sh7014_device::device_reset()
+{
+ sh2_device::device_reset();
+
+ // CAC
+ m_ccr = 0;
+}
+
+void sh7014_device::device_add_mconfig(machine_config &config)
+{
+ SH7014_SCI(config, m_sci[0], DERIVED_CLOCK(1, 1), m_intc,
+ 0, // id
+ sh7014_intc_device::INT_VECTOR_SCI_ERI0,
+ sh7014_intc_device::INT_VECTOR_SCI_RXI0,
+ sh7014_intc_device::INT_VECTOR_SCI_TXI0,
+ sh7014_intc_device::INT_VECTOR_SCI_TEI0
+ );
+
+ SH7014_SCI(config, m_sci[1], DERIVED_CLOCK(1, 1), m_intc,
+ 1, // id
+ sh7014_intc_device::INT_VECTOR_SCI_ERI1,
+ sh7014_intc_device::INT_VECTOR_SCI_RXI1,
+ sh7014_intc_device::INT_VECTOR_SCI_TXI1,
+ sh7014_intc_device::INT_VECTOR_SCI_TEI1
+ );
+
+ SH7014_BSC(config, m_bsc);
+
+ SH7014_DMAC(config, m_dmac, DERIVED_CLOCK(1, 1), *this, m_intc);
+ m_dmac->set_notify_dma_source_callback(FUNC(sh7014_device::notify_dma_source));
+
+ SH7014_INTC(config, m_intc);
+ m_intc->set_irq_callback(FUNC(sh7014_device::set_irq));
+
+ SH7014_MTU(config, m_mtu, DERIVED_CLOCK(1, 1), m_intc);
+
+ SH7014_PORT(config, m_port);
+}
+
+void sh7014_device::sh7014_map(address_map &map)
+{
+ // SCI - Serial Communication Interface
+ map(0xffff81a0, 0xffff81af).m(m_sci[0], FUNC(sh7014_sci_device::map));
+ map(0xffff81b0, 0xffff81bf).m(m_sci[1], FUNC(sh7014_sci_device::map));
+
+ // MTU - Multifunction Timer Pulse Unit
+ map(0xffff8240, 0xffff82af).m(m_mtu, FUNC(sh7014_mtu_device::map));
+
+ // INTC - Interrupt Controller
+ map(0xffff8348, 0xffff835b).m(m_intc, FUNC(sh7014_intc_device::map));
+
+ // I/O - I/O Ports (DR registers)
+ // PFC - Pin Function Controller (IOR, CR registers)
+ // TODO: SH7016/SH7017 support additionally C and D ports in addition to the A, B, E, F that the SH7014 supports
+ map(0xffff8382, 0xffff8383).rw(m_port, FUNC(sh7014_port_device::padrl_r), FUNC(sh7014_port_device::padrl_w));
+ map(0xffff8386, 0xffff8387).rw(m_port, FUNC(sh7014_port_device::paiorl_r), FUNC(sh7014_port_device::paiorl_w));
+ map(0xffff838c, 0xffff838d).rw(m_port, FUNC(sh7014_port_device::pacrl1_r), FUNC(sh7014_port_device::pacrl1_w));
+ map(0xffff838e, 0xffff838f).rw(m_port, FUNC(sh7014_port_device::pacrl2_r), FUNC(sh7014_port_device::pacrl2_w));
+
+ map(0xffff8390, 0xffff8391).rw(m_port, FUNC(sh7014_port_device::pbdr_r), FUNC(sh7014_port_device::pbdr_w));
+ map(0xffff8394, 0xffff8395).rw(m_port, FUNC(sh7014_port_device::pbior_r), FUNC(sh7014_port_device::pbior_w));
+ map(0xffff8398, 0xffff8399).rw(m_port, FUNC(sh7014_port_device::pbcr1_r), FUNC(sh7014_port_device::pbcr1_w));
+ map(0xffff839a, 0xffff839b).rw(m_port, FUNC(sh7014_port_device::pbcr2_r), FUNC(sh7014_port_device::pbcr2_w));
+
+ map(0xffff83b0, 0xffff83b1).rw(m_port, FUNC(sh7014_port_device::pedr_r), FUNC(sh7014_port_device::pedr_w));
+ map(0xffff83b4, 0xffff83b5).rw(m_port, FUNC(sh7014_port_device::peior_r), FUNC(sh7014_port_device::peior_w));
+ map(0xffff83b8, 0xffff83b9).rw(m_port, FUNC(sh7014_port_device::pecr1_r), FUNC(sh7014_port_device::pecr1_w));
+ map(0xffff83ba, 0xffff83bb).rw(m_port, FUNC(sh7014_port_device::pecr2_r), FUNC(sh7014_port_device::pecr2_w));
+
+ map(0xffff83b3, 0xffff83b3).r(m_port, FUNC(sh7014_port_device::pfdr_r));
+
+ // TODO: CMT - Compare Match Timer
+ // 0xffff83d0 - 0xffff83df
+
+ // TODO: A/D - A/D Converter (High Speed, for SH7014)
+ // 0xffff83e0 - 0xffff83ff
+
+ // TODO: A/D - A/D Converter (Mid Speed, for SH7016/SH7017)
+ // 0xffff8420 - 0xffff8429
+
+ // TODO: WDT - Watchdog Timer
+ // 0xffff8610 - 0xffff8613
+
+ // TODO: Power-down state
+ // 0xffff8614
+
+ // BSC - Bus State Controller
+ map(0xffff8620, 0xffff8633).m(m_bsc, FUNC(sh7014_bsc_device::map));
+
+ // DMAC - Direct Memory Access Controller
+ map(0xffff86b0, 0xffff86df).m(m_dmac, FUNC(sh7014_dmac_device::map));
+
+ // CAC - Cache Memory
+ map(0xffff8740, 0xffff8741).rw(FUNC(sh7014_device::ccr_r), FUNC(sh7014_device::ccr_w));
+
+ // Cache space
+ map(0xfffff000, 0xffffffff).ram();
+}
+
+void sh7014_device::sh2_exception_internal(const char *message, int irqline, int vector)
+{
+ // IRQ was taken so clear it in the interrupt controller and pass it down
+ m_intc->set_interrupt(vector, CLEAR_LINE);
+ sh2_device::sh2_exception_internal(message, irqline, vector);
+}
+
+void sh7014_device::execute_set_input(int irqline, int state)
+{
+ /*
+ Flow for SH7014 IRQs:
+ sh7014_device::execute_set_input (for externally triggered IRQs)
+ -> sh7014_intc_device::set_input
+ -> sh7014_device::set_irq
+ -> sh2_device::execute_set_input (if not internal peripheral IRQ) OR DMA interception OR set sh2_device's internal IRQ flags
+ */
+ m_intc->set_input(irqline, state);
+}
+
+void sh7014_device::set_irq(int vector, int level, bool is_internal)
+{
+ if (!is_internal) {
+ sh2_device::execute_set_input(vector, ASSERT_LINE);
+ return;
+ }
+
+ // SH7014's DMA controller can be configured to trigger based on various
+ // on-board peripheral IRQs, so on-board peripheral IRQs must go through here
+ if (m_dmac->is_dma_activated(vector)) {
+ m_intc->set_interrupt(vector, CLEAR_LINE);
+ return;
+ }
+
+ m_sh2_state->internal_irq_level = level;
+ m_internal_irq_vector = vector;
+ m_test_irq = 1;
+}
+
+void sh7014_device::notify_dma_source(uint32_t source)
+{
+ if (source == sh7014_dmac_channel_device::RS_SCI_TXI0)
+ m_sci[0]->set_dma_source_tx(true);
+ else if (source == sh7014_dmac_channel_device::RS_SCI_TXI1)
+ m_sci[1]->set_dma_source_tx(true);
+ else if (source == sh7014_dmac_channel_device::RS_SCI_RXI0)
+ m_sci[0]->set_dma_source_rx(true);
+ else if (source == sh7014_dmac_channel_device::RS_SCI_RXI1)
+ m_sci[1]->set_dma_source_rx(true);
+}
+
+///////
+// CAC
+
+uint16_t sh7014_device::ccr_r()
+{
+ // bits 15-5 are undefined
+ return m_ccr & 0x1f;
+}
+
+void sh7014_device::ccr_w(offs_t offset, uint16_t data, uint16_t mem_mask)
+{
+ // bit 0 - CECS0 CS0 Space Cache Enable
+ // bit 1 - CECS1 CS1 Space Cache Enable
+ // bit 2 - CECS2 CS2 Space Cache Enable
+ // bit 3 - CECS3 CS3 Space Cache Enable
+ // bit 4 - CEDRAM DRAM Space Cache Enable
+ COMBINE_DATA(&m_ccr);
+}