summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
-rw-r--r--scripts/src/cpu.lua8
-rw-r--r--src/devices/bus/plg1x0/plg1x0.cpp4
-rw-r--r--src/devices/cpu/h8/h8_adc.h6
-rw-r--r--src/devices/cpu/sh/sh7042.cpp264
-rw-r--r--src/devices/cpu/sh/sh7042.h91
-rw-r--r--src/devices/cpu/sh/sh_adc.cpp315
-rw-r--r--src/devices/cpu/sh/sh_adc.h100
-rw-r--r--src/devices/cpu/sh/sh_cmt.cpp197
-rw-r--r--src/devices/cpu/sh/sh_cmt.h75
-rw-r--r--src/devices/cpu/sh/sh_intc.cpp75
-rw-r--r--src/devices/cpu/sh/sh_intc.h47
-rw-r--r--src/devices/cpu/sh/sh_port.cpp109
-rw-r--r--src/devices/cpu/sh/sh_port.h75
-rw-r--r--src/mame/tvgames/xavix_a.cpp1
-rw-r--r--src/mame/yamaha/ymmu128.cpp59
15 files changed, 1372 insertions, 54 deletions
diff --git a/scripts/src/cpu.lua b/scripts/src/cpu.lua
index 23f66cd7d5c..8fee43f4ab1 100644
--- a/scripts/src/cpu.lua
+++ b/scripts/src/cpu.lua
@@ -899,6 +899,14 @@ if CPUS["SH"] then
MAME_DIR .. "src/devices/cpu/sh/sh7032.h",
MAME_DIR .. "src/devices/cpu/sh/sh7042.cpp",
MAME_DIR .. "src/devices/cpu/sh/sh7042.h",
+ MAME_DIR .. "src/devices/cpu/sh/sh_adc.cpp",
+ MAME_DIR .. "src/devices/cpu/sh/sh_adc.h",
+ MAME_DIR .. "src/devices/cpu/sh/sh_cmt.cpp",
+ MAME_DIR .. "src/devices/cpu/sh/sh_cmt.h",
+ MAME_DIR .. "src/devices/cpu/sh/sh_intc.cpp",
+ MAME_DIR .. "src/devices/cpu/sh/sh_intc.h",
+ MAME_DIR .. "src/devices/cpu/sh/sh_port.cpp",
+ MAME_DIR .. "src/devices/cpu/sh/sh_port.h",
MAME_DIR .. "src/devices/cpu/sh/sh7604_bus.cpp",
MAME_DIR .. "src/devices/cpu/sh/sh7604_bus.h",
MAME_DIR .. "src/devices/cpu/sh/sh7604_sci.cpp",
diff --git a/src/devices/bus/plg1x0/plg1x0.cpp b/src/devices/bus/plg1x0/plg1x0.cpp
index 11f065b17c4..6abd5100209 100644
--- a/src/devices/bus/plg1x0/plg1x0.cpp
+++ b/src/devices/bus/plg1x0/plg1x0.cpp
@@ -31,8 +31,8 @@ void plg1x0_connector::midi_rx(int state)
void plg1x0_intf(device_slot_interface &device)
{
- device.option_add("plg100-vl", PLG100_VL);
- device.option_add("plg150-ap", PLG150_AP);
+ device.option_add("plg100vl", PLG100_VL);
+ device.option_add("plg150ap", PLG150_AP);
}
device_plg1x0_interface::device_plg1x0_interface(const machine_config &mconfig, device_t &device) :
diff --git a/src/devices/cpu/h8/h8_adc.h b/src/devices/cpu/h8/h8_adc.h
index bb180703c64..8155f5bcd1d 100644
--- a/src/devices/cpu/h8/h8_adc.h
+++ b/src/devices/cpu/h8/h8_adc.h
@@ -19,7 +19,11 @@
class h8_adc_device : public device_t {
public:
- template<typename T, typename U> void set_info(T &&cpu, U &&intc, int vect) { m_cpu.set_tag(std::forward<T>(cpu)), m_intc.set_tag(std::forward<U>(intc)); m_intc_vector = vect; }
+ template<typename T, typename U> void set_info(T &&cpu, U &&intc, int vect) {
+ m_cpu.set_tag(std::forward<T>(cpu));
+ m_intc.set_tag(std::forward<U>(intc));
+ m_intc_vector = vect;
+ }
u8 addr8_r(offs_t offset);
u16 addr16_r(offs_t offset);
diff --git a/src/devices/cpu/sh/sh7042.cpp b/src/devices/cpu/sh/sh7042.cpp
index 35f559b47ce..7ef10f19ce1 100644
--- a/src/devices/cpu/sh/sh7042.cpp
+++ b/src/devices/cpu/sh/sh7042.cpp
@@ -21,13 +21,61 @@ sh7043_device::sh7043_device(const machine_config &mconfig, const char *tag, dev
sh7042_device::sh7042_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock) :
sh2_device(mconfig, type, tag, owner, clock, CPU_TYPE_SH2, address_map_constructor(FUNC(sh7042_device::map), this), 32, 0xffffffff),
+ m_intc(*this, "intc"),
+ m_adc(*this, "adc"),
+ m_cmt(*this, "cmt"),
+ m_porta(*this, "porta"),
+ m_portb(*this, "portb"),
+ m_portc(*this, "portc"),
+ m_portd(*this, "portd"),
+ m_porte(*this, "porte"),
+ m_portf(*this, "portf"),
m_read_adc(*this, 0),
- m_sci_tx(*this)
+ m_sci_tx(*this),
+ m_read_port16(*this, 0xffff),
+ m_write_port16(*this),
+ m_read_port32(*this, 0xffffffff),
+ m_write_port32(*this)
{
+ m_port16_names = "bcef";
+ m_port32_names = "ad";
for(unsigned int i=0; i != m_read_adc.size(); i++)
m_read_adc[i].bind().set([this, i]() { return adc_default(i); });
+ for(unsigned int i=0; i != m_read_port16.size(); i++) {
+ m_read_port16[i].bind().set([this, i]() { return port16_default_r(i); });
+ m_write_port16[i].bind().set([this, i](u16 data) { port16_default_w(i, data); });
+ }
+ for(unsigned int i=0; i != m_read_port32.size(); i++) {
+ m_read_port32[i].bind().set([this, i]() { return port32_default_r(i); });
+ m_write_port32[i].bind().set([this, i](u32 data) { port32_default_w(i, data); });
+ }
}
+u16 sh7042_device::port16_default_r(int port)
+{
+ if(!machine().side_effects_disabled())
+ logerror("read of un-hooked port %c\n", m_port16_names[port]);
+ return 0xffff;
+}
+
+void sh7042_device::port16_default_w(int port, u16 data)
+{
+ logerror("write of un-hooked port %c %04x\n", m_port16_names[port], data);
+}
+
+u32 sh7042_device::port32_default_r(int port)
+{
+ if(!machine().side_effects_disabled())
+ logerror("read of un-hooked port %c\n", m_port32_names[port]);
+ return 0xffff;
+}
+
+void sh7042_device::port32_default_w(int port, u32 data)
+{
+ logerror("write of un-hooked port %c %04x\n", m_port32_names[port], data);
+}
+
+
u16 sh7042_device::adc_default(int adc)
{
logerror("read of un-hooked adc %d\n", adc);
@@ -38,70 +86,214 @@ void sh7042_device::device_start()
{
sh2_device::device_start();
- save_item(NAME(m_addr));
- save_item(NAME(m_adcsr));
- save_item(NAME(m_adcr));
+ m_event_timer = timer_alloc(FUNC(sh7042_device::event_timer_tick), this);
+
+ save_item(NAME(m_pcf_ah));
+ save_item(NAME(m_pcf_al));
+ save_item(NAME(m_pcf_b));
+ save_item(NAME(m_pcf_c));
+ save_item(NAME(m_pcf_dh));
+ save_item(NAME(m_pcf_dl));
+ save_item(NAME(m_pcf_e));
+ save_item(NAME(m_pcf_if));
+
+ m_pcf_ah = 0;
+ m_pcf_al = 0;
+ m_pcf_b = 0;
+ m_pcf_c = 0;
+ m_pcf_dh = 0;
+ m_pcf_dl = 0;
+ m_pcf_e = 0;
+ m_pcf_if = 0;
}
void sh7042_device::device_reset()
{
sh2_device::device_reset();
-
- memset(m_addr, 0, sizeof(m_addr));
- m_adcsr = m_adcr = 0;
}
+
void sh7042_device::map(address_map &map)
{
- map(0xffff83e0, 0xffff83e0).rw(FUNC(sh7042_device::adcsr_r), FUNC(sh7042_device::adcsr_w));
- map(0xffff83e1, 0xffff83e1).rw(FUNC(sh7042_device::adcr_r), FUNC(sh7042_device::adcr_w));
- map(0xffff83f0, 0xffff83ff).r(FUNC(sh7042_device::addr_r));
+ map(0xffff8348, 0xffff8357).rw(m_intc, FUNC(sh_intc_device::ipr_r), FUNC(sh_intc_device::ipr_w));
+ map(0xffff8358, 0xffff8359).rw(m_intc, FUNC(sh_intc_device::icr_r), FUNC(sh_intc_device::icr_w));
+ map(0xffff835a, 0xffff835b).rw(m_intc, FUNC(sh_intc_device::isr_r), FUNC(sh_intc_device::isr_w));
+
+ map(0xffff8380, 0xffff8383).rw(m_porta, FUNC(sh_port32_device::dr_r), FUNC(sh_port32_device::dr_w));
+ map(0xffff8384, 0xffff8387).rw(m_porta, FUNC(sh_port32_device::io_r), FUNC(sh_port32_device::io_w));
+ map(0xffff8388, 0xffff8389).rw(FUNC(sh7042_device::pcf_ah_r), FUNC(sh7042_device::pcf_ah_w));
+ map(0xffff838c, 0xffff838f).rw(FUNC(sh7042_device::pcf_al_r), FUNC(sh7042_device::pcf_al_w));
+ map(0xffff8390, 0xffff8391).rw(m_portb, FUNC(sh_port16_device::dr_r), FUNC(sh_port16_device::dr_w));
+ map(0xffff8392, 0xffff8393).rw(m_portc, FUNC(sh_port16_device::dr_r), FUNC(sh_port16_device::dr_w));
+ map(0xffff8394, 0xffff8395).rw(m_portb, FUNC(sh_port16_device::io_r), FUNC(sh_port16_device::io_w));
+ map(0xffff8396, 0xffff8397).rw(m_portc, FUNC(sh_port16_device::io_r), FUNC(sh_port16_device::io_w));
+ map(0xffff8398, 0xffff839b).rw(FUNC(sh7042_device::pcf_b_r), FUNC(sh7042_device::pcf_b_w));
+ map(0xffff839c, 0xffff839d).rw(FUNC(sh7042_device::pcf_c_r), FUNC(sh7042_device::pcf_c_w));
+ map(0xffff83a0, 0xffff83a3).rw(m_portd, FUNC(sh_port32_device::dr_r), FUNC(sh_port32_device::dr_w));
+ map(0xffff83a4, 0xffff83a7).rw(m_portd, FUNC(sh_port32_device::io_r), FUNC(sh_port32_device::io_w));
+ map(0xffff83a8, 0xffff83ab).rw(FUNC(sh7042_device::pcf_dh_r), FUNC(sh7042_device::pcf_dh_w));
+ map(0xffff83ac, 0xffff83ad).rw(FUNC(sh7042_device::pcf_dl_r), FUNC(sh7042_device::pcf_dl_w));
+ map(0xffff83b0, 0xffff83b1).rw(m_porte, FUNC(sh_port16_device::dr_r), FUNC(sh_port16_device::dr_w));
+ map(0xffff83b2, 0xffff83b3).r (m_portf, FUNC(sh_port16_device::dr_r));
+ map(0xffff83b4, 0xffff83b5).rw(m_porte, FUNC(sh_port16_device::io_r), FUNC(sh_port16_device::io_w));
+ map(0xffff83b8, 0xffff83bb).rw(FUNC(sh7042_device::pcf_e_r), FUNC(sh7042_device::pcf_e_w));
+ map(0xffff83c8, 0xffff83c9).rw(FUNC(sh7042_device::pcf_if_r), FUNC(sh7042_device::pcf_if_w));
+
+ map(0xffff83d0, 0xffff83d1).rw(m_cmt, FUNC(sh_cmt_device::cmstr_r), FUNC(sh_cmt_device::cmstr_w));
+ map(0xffff83d2, 0xffff83d3).rw(m_cmt, FUNC(sh_cmt_device::cmcsr0_r), FUNC(sh_cmt_device::cmcsr0_w));
+ map(0xffff83d4, 0xffff83d5).rw(m_cmt, FUNC(sh_cmt_device::cmcnt0_r), FUNC(sh_cmt_device::cmcnt0_w));
+ map(0xffff83d6, 0xffff83d7).rw(m_cmt, FUNC(sh_cmt_device::cmcor0_r), FUNC(sh_cmt_device::cmcor0_w));
+ map(0xffff83d8, 0xffff83d9).rw(m_cmt, FUNC(sh_cmt_device::cmcsr1_r), FUNC(sh_cmt_device::cmcsr1_w));
+ map(0xffff83da, 0xffff83db).rw(m_cmt, FUNC(sh_cmt_device::cmcnt1_r), FUNC(sh_cmt_device::cmcnt1_w));
+ map(0xffff83dc, 0xffff83dd).rw(m_cmt, FUNC(sh_cmt_device::cmcor1_r), FUNC(sh_cmt_device::cmcor1_w));
+
+ map(0xffff83e0, 0xffff83e0).rw(m_adc, FUNC(sh_adc_device::adcsr_r), FUNC(sh_adc_device::adcsr_w));
+ map(0xffff83e1, 0xffff83e1).rw(m_adc, FUNC(sh_adc_device::adcr_r), FUNC(sh_adc_device::adcr_w));
+ map(0xffff83f0, 0xffff83ff).r(m_adc, FUNC(sh_adc_device::addr_r));
map(0xfffff000, 0xffffffff).ram();
}
+void sh7042_device::device_add_mconfig(machine_config &config)
+{
+ SH_INTC(config, m_intc, *this);
+ SH_ADC(config, m_adc, *this, m_intc, 136);
+ SH_CMT(config, m_cmt, *this, m_intc, 144, 148);
+ SH_PORT32(config, m_porta, *this, 0, 0x00000000, 0xff000000);
+ SH_PORT16(config, m_portb, *this, 0, 0x0000, 0xfc00);
+ SH_PORT16(config, m_portc, *this, 1, 0x0000, 0x0000);
+ SH_PORT32(config, m_portd, *this, 1, 0x0000, 0x0000);
+ SH_PORT16(config, m_porte, *this, 2, 0x0000, 0x0000);
+ SH_PORT16(config, m_portf, *this, 3, 0x0000, 0xff00);
+}
-// ADC section
+void sh7042_device::do_sci_w(int sci, int state)
+{
+ logerror("sci %d %d\n", sci, state);
+}
-u16 sh7042_device::addr_r(offs_t offset)
+void sh7042_device::internal_update()
{
- logerror("addr16_r %d %03x\n", offset, m_addr[offset]);
- return m_addr[offset];
+ internal_update(current_cycles());
}
-u8 sh7042_device::adcsr_r()
+void sh7042_device::add_event(u64 &event_time, u64 new_event)
{
- logerror("adcsr_r %02x\n", m_adcsr);
- return m_adcsr;
+ if(!new_event)
+ return;
+ if(!event_time || event_time > new_event)
+ event_time = new_event;
}
-u8 sh7042_device::adcr_r()
+void sh7042_device::recompute_timer(u64 event_time)
{
- logerror("adcr_r %02x\n", m_adcr);
- return m_adcr;
+ if(!event_time) {
+ m_event_timer->adjust(attotime::never);
+ return;
+ }
+
+ m_event_timer->adjust(attotime::from_ticks(2*event_time + 1, 2*clock()) - machine().time());
}
-void sh7042_device::adcsr_w(u8 data)
+TIMER_CALLBACK_MEMBER(sh7042_device::event_timer_tick)
{
- logerror("adcsr_w %02x\n", data);
- // u8 prev = m_adcsr;
- m_adcsr = (data & 0x7f) | (m_adcsr & data & CSR_ADF);
+ internal_update();
}
-void sh7042_device::adcr_w(u8 data)
+void sh7042_device::internal_update(u64 current_time)
{
- static const char *const tg_modes[4] = { "soft", "mtu", "?", "external" };
- static const char *const buf_modes[4] = { "normal", "a->b", "a,b->c,d", "a->b->c->d" };
- logerror("adcr_w speed=%d trigger=%s mode=%s sampling=%s buffering=%s\n",
- BIT(data, 6) ? "high" : "low",
- tg_modes[(data >> 4) & 3],
- BIT(data, 3) ? "scan" : "single",
- BIT(data, 2) ? "simultaneous" : "normal",
- buf_modes[data & 3]);
- m_adcr = data;
+ u64 event_time = 0;
+
+ add_event(event_time, m_adc->internal_update(current_time));
+ add_event(event_time, m_cmt->internal_update(current_time));
+
+ recompute_timer(event_time);
}
-void sh7042_device::do_sci_w(int sci, int state)
+u16 sh7042_device::pcf_ah_r()
{
- logerror("sci %d %d\n", sci, state);
+ return m_pcf_ah;
+}
+
+void sh7042_device::pcf_ah_w(offs_t, u16 data, u16 mem_mask)
+{
+ COMBINE_DATA(&m_pcf_ah);
+ logerror("pcf ah = %04x\n", m_pcf_ah);
+}
+
+u32 sh7042_device::pcf_al_r()
+{
+ return m_pcf_al;
+}
+
+void sh7042_device::pcf_al_w(offs_t, u32 data, u32 mem_mask)
+{
+ COMBINE_DATA(&m_pcf_al);
+ logerror("pcf al = %08x\n", m_pcf_al);
+}
+
+u32 sh7042_device::pcf_b_r()
+{
+ return m_pcf_b;
+}
+
+void sh7042_device::pcf_b_w(offs_t, u32 data, u32 mem_mask)
+{
+ COMBINE_DATA(&m_pcf_b);
+ logerror("pcf b = %08x\n", m_pcf_b);
+}
+
+u16 sh7042_device::pcf_c_r()
+{
+ return m_pcf_c;
+}
+
+void sh7042_device::pcf_c_w(offs_t, u16 data, u16 mem_mask)
+{
+ COMBINE_DATA(&m_pcf_c);
+ logerror("pcf c = %04x\n", m_pcf_c);
+}
+
+u32 sh7042_device::pcf_dh_r()
+{
+ return m_pcf_dh;
+}
+
+void sh7042_device::pcf_dh_w(offs_t, u32 data, u32 mem_mask)
+{
+ COMBINE_DATA(&m_pcf_dh);
+ logerror("pcf dh = %08x\n", m_pcf_dh);
+}
+
+u16 sh7042_device::pcf_dl_r()
+{
+ return m_pcf_dl;
+}
+
+void sh7042_device::pcf_dl_w(offs_t, u16 data, u16 mem_mask)
+{
+ COMBINE_DATA(&m_pcf_dl);
+ logerror("pcf dl = %04x\n", m_pcf_dl);
+}
+
+u32 sh7042_device::pcf_e_r()
+{
+ return m_pcf_e;
+}
+
+void sh7042_device::pcf_e_w(offs_t, u32 data, u32 mem_mask)
+{
+ COMBINE_DATA(&m_pcf_e);
+ logerror("pcf e = %08x\n", m_pcf_e);
+}
+
+u16 sh7042_device::pcf_if_r()
+{
+ return m_pcf_if;
+}
+
+void sh7042_device::pcf_if_w(offs_t, u16 data, u16 mem_mask)
+{
+ COMBINE_DATA(&m_pcf_if);
+ logerror("pcf if = %04x\n", m_pcf_if);
}
diff --git a/src/devices/cpu/sh/sh7042.h b/src/devices/cpu/sh/sh7042.h
index dabcb7c272b..55795fd8282 100644
--- a/src/devices/cpu/sh/sh7042.h
+++ b/src/devices/cpu/sh/sh7042.h
@@ -1,7 +1,7 @@
// license:BSD-3-Clause
// copyright-holders:Olivier Galibert
-// SH7042, sh2 variant
+// SH704x, sh2 variant
#ifndef MAME_CPU_SH_SH7042_H
#define MAME_CPU_SH_SH7042_H
@@ -9,6 +9,10 @@
#pragma once
#include "sh2.h"
+#include "sh_intc.h"
+#include "sh_adc.h"
+#include "sh_cmt.h"
+#include "sh_port.h"
class sh7042_device : public sh2_device
{
@@ -19,8 +23,30 @@ public:
template<int Sci> void sci_rx_w(int state) { do_sci_w(Sci, state); }
template<int Sci> auto write_sci_tx() { return m_sci_tx[Sci].bind(); }
+ auto read_porta() { return m_read_port32 [0].bind(); }
+ auto write_porta() { return m_write_port32[0].bind(); }
+ auto read_portb() { return m_read_port16 [0].bind(); }
+ auto write_portb() { return m_write_port16[0].bind(); }
+ auto read_portc() { return m_read_port16 [1].bind(); }
+ auto write_portc() { return m_write_port16[1].bind(); }
+ auto read_portd() { return m_read_port32 [1].bind(); }
+ auto write_portd() { return m_write_port32[1].bind(); }
+ auto read_porte() { return m_read_port16 [2].bind(); }
+ auto write_porte() { return m_write_port16[2].bind(); }
+ auto read_portf() { return m_read_port16 [3].bind(); }
+
+ void internal_update();
+ u16 do_read_adc(int port) { return m_read_adc[port](); }
+ u16 do_read_port16(int port) { return m_read_port16[port](); }
+ void do_write_port16(int port, u16 data, u16 ddr) { m_write_port16[port](0, data, ddr); }
+ u32 do_read_port32(int port) { return m_read_port32[port](); }
+ void do_write_port32(int port, u32 data, u32 ddr) { m_write_port32[port](0, data, ddr); }
+
+ u64 current_cycles() { return machine().time().as_ticks(clock()); }
protected:
+ const char *m_port16_names;
+ const char *m_port32_names;
enum {
CSR_ADF = 0x80,
CSR_ADIE = 0x40,
@@ -42,25 +68,68 @@ protected:
virtual void device_start() override;
virtual void device_reset() override;
+ virtual void device_add_mconfig(machine_config &config) override;
private:
+ required_device<sh_intc_device> m_intc;
+ required_device<sh_adc_device> m_adc;
+ required_device<sh_cmt_device> m_cmt;
+ required_device<sh_port32_device> m_porta;
+ required_device<sh_port16_device> m_portb;
+ required_device<sh_port16_device> m_portc;
+ required_device<sh_port32_device> m_portd;
+ required_device<sh_port16_device> m_porte;
+ required_device<sh_port16_device> m_portf;
+
devcb_read16::array<8> m_read_adc;
devcb_write_line::array<2> m_sci_tx;
+ devcb_read16::array<4> m_read_port16;
+ devcb_write16::array<4> m_write_port16;
+ devcb_read32::array<2> m_read_port32;
+ devcb_write32::array<2> m_write_port32;
+
+ emu_timer *m_event_timer;
+
+ u16 m_pcf_ah;
+ u32 m_pcf_al;
+ u32 m_pcf_b;
+ u16 m_pcf_c;
+ u32 m_pcf_dh;
+ u16 m_pcf_dl;
+ u32 m_pcf_e;
+ u16 m_pcf_if;
void map(address_map &map);
- // ADC section
- uint16_t m_addr[8];
- uint8_t m_adcsr, m_adcr;
-
u16 adc_default(int adc);
- u16 addr_r(offs_t offset);
- u8 adcsr_r();
- u8 adcr_r();
- void adcsr_w(u8 data);
- void adcr_w(u8 data);
-
+ u16 port16_default_r(int port);
+ void port16_default_w(int port, u16 data);
+ u32 port32_default_r(int port);
+ void port32_default_w(int port, u32 data);
+
+ void add_event(u64 &event_time, u64 new_event);
+ void recompute_timer(u64 event_time);
+ TIMER_CALLBACK_MEMBER(event_timer_tick);
+ void internal_update(u64 current_time);
+
void do_sci_w(int sci, int state);
+
+ u16 pcf_ah_r();
+ void pcf_ah_w(offs_t, u16 data, u16 mem_mask);
+ u32 pcf_al_r();
+ void pcf_al_w(offs_t, u32 data, u32 mem_mask);
+ u32 pcf_b_r();
+ void pcf_b_w(offs_t, u32 data, u32 mem_mask);
+ u16 pcf_c_r();
+ void pcf_c_w(offs_t, u16 data, u16 mem_mask);
+ u32 pcf_dh_r();
+ void pcf_dh_w(offs_t, u32 data, u32 mem_mask);
+ u16 pcf_dl_r();
+ void pcf_dl_w(offs_t, u16 data, u16 mem_mask);
+ u32 pcf_e_r();
+ void pcf_e_w(offs_t, u32 data, u32 mem_mask);
+ u16 pcf_if_r();
+ void pcf_if_w(offs_t, u16 data, u16 mem_mask);
};
class sh7043_device : public sh7042_device
diff --git a/src/devices/cpu/sh/sh_adc.cpp b/src/devices/cpu/sh/sh_adc.cpp
new file mode 100644
index 00000000000..d9e1da01921
--- /dev/null
+++ b/src/devices/cpu/sh/sh_adc.cpp
@@ -0,0 +1,315 @@
+// license:BSD-3-Clause
+// copyright-holders:Olivier Galibert
+
+#include "emu.h"
+#include "sh_adc.h"
+#include "sh7042.h"
+#include "sh_intc.h"
+
+// Verbosity level
+// 0 = no messages
+// 1 = everything
+static constexpr int V = 0;
+
+DEFINE_DEVICE_TYPE(SH_ADC, sh_adc_device, "sh_adc", "SH2/704x ADC")
+
+sh_adc_device::sh_adc_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) :
+ device_t(mconfig, SH_ADC, tag, owner, clock),
+ m_cpu(*this, finder_base::DUMMY_TAG),
+ m_intc(*this, finder_base::DUMMY_TAG),
+ m_intc_vector(0), m_adcsr(0), m_adcr(0), m_register_mask(0), m_trigger(0), m_start_mode(0), m_start_channel(0),
+ m_end_channel(0), m_start_count(0), m_mode(0), m_channel(0), m_count(0), m_analog_powered(false), m_adtrg(false), m_next_event(0)
+{
+ m_suspend_on_interrupt = true;
+ m_register_mask = 7;
+ m_analog_power_control = false;
+}
+
+u16 sh_adc_device::addr_r(offs_t offset)
+{
+ if(V>=1) logerror("addr_r %d %03x\n", offset, m_addr[offset]);
+ return m_addr[offset];
+}
+
+u8 sh_adc_device::adcsr_r()
+{
+ if(V>=1) logerror("adcsr_r %02x\n", m_adcsr);
+ return m_adcsr;
+}
+
+u8 sh_adc_device::adcr_r()
+{
+ if(V>=1) logerror("adcr_r %02x\n", m_adcr);
+ return m_adcr;
+}
+
+void sh_adc_device::adcsr_w(u8 data)
+{
+ if(V>=1) logerror("adcsr_w %02x\n", data);
+ u8 prev = m_adcsr;
+ m_adcsr = (data & 0x7f) | (m_adcsr & data & F_ADF);
+ mode_update();
+ if((prev & F_ADF) && !(m_adcsr & F_ADF)) {
+ if(m_mode & HALTED) {
+ m_mode &= ~HALTED;
+ if(!(m_adcsr & F_ADST)) {
+ sampling();
+ conversion_wait(false, false);
+ } else
+ done();
+ }
+ }
+
+ if(!(prev & F_ADST) && (m_adcsr & F_ADST))
+ start_conversion();
+}
+
+void sh_adc_device::adcr_w(u8 data)
+{
+ if(V>=1) logerror("adcr_w %02x\n", data);
+ m_adcr = data;
+ mode_update();
+}
+
+void sh_adc_device::adtrg_w(int state)
+{
+ if(state != m_adtrg) {
+ m_adtrg = state;
+ if(!m_adtrg && (m_trigger & T_EXT) && !(m_adcsr & F_ADST)) {
+ m_adcsr |= F_ADST;
+ start_conversion();
+ }
+ }
+}
+
+void sh_adc_device::set_suspend(bool suspend)
+{
+}
+
+void sh_adc_device::device_start()
+{
+ save_item(NAME(m_addr));
+ save_item(NAME(m_buf));
+ save_item(NAME(m_adcsr));
+ save_item(NAME(m_adcr));
+ save_item(NAME(m_trigger));
+ save_item(NAME(m_start_mode));
+ save_item(NAME(m_start_channel));
+ save_item(NAME(m_end_channel));
+ save_item(NAME(m_start_count));
+ save_item(NAME(m_suspend_on_interrupt));
+ save_item(NAME(m_analog_power_control));
+ save_item(NAME(m_mode));
+ save_item(NAME(m_channel));
+ save_item(NAME(m_count));
+ save_item(NAME(m_analog_powered));
+ save_item(NAME(m_next_event));
+ save_item(NAME(m_adtrg));
+}
+
+void sh_adc_device::device_reset()
+{
+ memset(m_addr, 0, sizeof(m_addr));
+ memset(m_buf, 0, sizeof(m_buf));
+ m_adcsr = m_adcr = 0;
+ m_trigger = T_SOFT;
+ m_start_mode = IDLE;
+ m_start_channel = m_end_channel = 0;
+ m_start_count = 1;
+ m_mode = IDLE;
+ m_channel = 0;
+ m_count = 0;
+ m_next_event = 0;
+ mode_update();
+ m_analog_powered = !m_analog_power_control;
+ m_adtrg = true;
+}
+
+void sh_adc_device::done()
+{
+ m_mode = IDLE;
+ m_adcsr &= ~F_ADST;
+ if(m_analog_power_control)
+ m_analog_powered = false;
+}
+
+u64 sh_adc_device::internal_update(u64 current_time)
+{
+ if(m_next_event && m_next_event <= current_time) {
+ m_next_event = 0;
+ timeout(current_time);
+ }
+ return m_next_event;
+}
+
+void sh_adc_device::conversion_wait(bool first, bool poweron, u64 current_time)
+{
+ if(current_time)
+ m_next_event = current_time + conversion_time(first, poweron);
+ else {
+ m_next_event = m_cpu->total_cycles() + conversion_time(first, poweron);
+ m_cpu->internal_update();
+ }
+}
+
+void sh_adc_device::buffer_value(int port, int buffer)
+{
+ m_buf[buffer] = m_cpu->do_read_adc(port);
+ if(V>=1) logerror("adc buffer %d -> %d:%03x\n", port, buffer, m_buf[buffer]);
+}
+
+void sh_adc_device::commit_value(int reg, int buffer)
+{
+ reg &= m_register_mask;
+ if(V>=1) logerror("adc commit %d -> %d:%03x\n", buffer, reg, m_buf[buffer]);
+ m_addr[reg] = m_buf[buffer];
+}
+
+void sh_adc_device::sampling()
+{
+ if(m_mode & COUNTED)
+ m_channel = get_channel_index(m_start_count - m_count);
+ if(m_mode & DUAL) {
+ buffer_value(m_channel, 0);
+ buffer_value(m_channel+1, 1);
+ } else
+ buffer_value(m_channel);
+}
+
+void sh_adc_device::start_conversion()
+{
+ m_mode = m_start_mode;
+ m_channel = m_start_channel;
+ m_count = m_start_count;
+ sampling();
+ conversion_wait(true, !m_analog_powered);
+ m_analog_powered = true;
+}
+
+void sh_adc_device::timeout(u64 current_time)
+{
+ if(m_mode & BUFFER) {
+ do_buffering((m_mode & DUAL) && (m_channel & 1));
+ if((m_mode & DUAL) && !(m_channel & 1)) {
+ m_channel++;
+ conversion_wait(false, false, current_time);
+ return;
+ }
+ } else {
+ if(m_mode & DUAL) {
+ if(m_channel & 1)
+ commit_value(m_channel, 1);
+ else {
+ commit_value(m_channel, 0);
+ m_channel++;
+ conversion_wait(false, false, current_time);
+ return;
+ }
+ } else
+ commit_value(m_channel);
+ }
+
+ if(m_mode & ROTATE) {
+ if(m_channel != m_end_channel) {
+ m_channel++;
+ sampling();
+ conversion_wait(false, false, current_time);
+ return;
+ }
+ m_channel = m_start_channel;
+ }
+
+ if(m_mode & COUNTED) {
+ m_count--;
+ if(m_count) {
+ sampling();
+ conversion_wait(false, false, current_time);
+ return;
+ }
+ }
+
+ m_adcsr |= F_ADF;
+ if(m_adcsr & F_ADIE)
+ m_intc->internal_interrupt(m_intc_vector);
+
+ if(m_mode & REPEAT) {
+ if(m_suspend_on_interrupt && (m_adcsr & F_ADIE)) {
+ m_mode |= HALTED;
+ return;
+ }
+ m_channel = m_start_channel;
+ m_count = m_start_count;
+ sampling();
+ conversion_wait(false, false, current_time);
+ return;
+ }
+
+ done();
+}
+
+int sh_adc_device::conversion_time(bool first, bool poweron)
+{
+ int tm = m_adcsr & 0x10 ? 44 : 24;
+ if(first)
+ tm += m_adcsr & 0x10 ? 20 : 10;
+ if(poweron)
+ tm += 200;
+ return tm;
+}
+
+void sh_adc_device::mode_update()
+{
+ m_trigger = 1 << ((m_adcr >> 4) & 3);
+ m_analog_power_control = !(m_adcr & 0x40);
+
+ m_mode = ACTIVE | (m_adcr & 0x08 ? REPEAT : 0);
+
+ if(m_adcsr & 0x03) {
+ m_mode |= BUFFER;
+
+ }
+
+ if(m_adcsr & 0x08) {
+ m_mode |= ROTATE;
+ m_start_channel = 0;
+ if(m_adcr & 0x04) {
+ m_mode |= DUAL;
+ m_end_channel = (m_adcsr & 6)+1;
+ } else
+ m_end_channel = m_adcsr & 7;
+ } else
+ m_start_channel = m_end_channel = m_adcsr & 7;
+
+}
+
+void sh_adc_device::do_buffering(int buffer)
+{
+ if((m_mode & COUNTED) && m_channel >= 2) {
+ commit_value(m_channel, buffer);
+ return;
+ }
+ switch(m_adcsr & 3) {
+ case 0:
+ commit_value(m_channel, buffer);
+ break;
+ case 1:
+ m_addr[1] = m_addr[0];
+ commit_value(0, buffer);
+ break;
+ case 2:
+ m_addr[2+buffer] = m_addr[buffer];
+ commit_value(buffer, buffer);
+ break;
+ case 3:
+ m_addr[3] = m_addr[2];
+ m_addr[2] = m_addr[1];
+ m_addr[1] = m_addr[0];
+ commit_value(0, buffer);
+ break;
+ }
+}
+
+int sh_adc_device::get_channel_index(int count)
+{
+ abort();
+}
diff --git a/src/devices/cpu/sh/sh_adc.h b/src/devices/cpu/sh/sh_adc.h
new file mode 100644
index 00000000000..9a48e3f804b
--- /dev/null
+++ b/src/devices/cpu/sh/sh_adc.h
@@ -0,0 +1,100 @@
+// license:BSD-3-Clause
+// copyright-holders:Olivier Galibert
+/***************************************************************************
+
+ sh_adc.h
+
+ SH Analog to Digital Converter subsystem
+
+
+***************************************************************************/
+
+#ifndef MAME_CPU_SH_SH_ADC_H
+#define MAME_CPU_SH_SH_ADC_H
+
+#pragma once
+
+class sh7042_device;
+class sh_intc_device;
+
+class sh_adc_device : public device_t {
+public:
+ sh_adc_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock = 0);
+
+ template<typename T, typename U> sh_adc_device(const machine_config &mconfig, const char *tag, device_t *owner,
+ T &&cpu, U &&intc, int vect) :
+ sh_adc_device(mconfig, tag, owner)
+ {
+ m_cpu.set_tag(std::forward<T>(cpu));
+ m_intc.set_tag(std::forward<U>(intc));
+ m_intc_vector = vect;
+ }
+
+ u16 addr_r(offs_t offset);
+ u8 adcsr_r();
+ u8 adcr_r();
+ void adcsr_w(u8 data);
+ void adcr_w(u8 data);
+ void adtrg_w(int state);
+
+ void set_suspend(bool suspend);
+ u64 internal_update(u64 current_time);
+
+protected:
+ required_device<sh7042_device> m_cpu;
+ required_device<sh_intc_device> m_intc;
+ int m_intc_vector;
+
+ enum {
+ T_SOFT = 1<<0,
+ T_TPU = 1<<1,
+ T_TIMER = 1<<2,
+ T_EXT = 1<<3
+ };
+
+ enum {
+ F_ADF = 0x80,
+ F_ADIE = 0x40,
+ F_ADST = 0x20
+ };
+
+ enum {
+ IDLE = 0,
+ ACTIVE = 1,
+ HALTED = 2,
+ REPEAT = 4,
+ ROTATE = 8,
+ DUAL = 16,
+ BUFFER = 32,
+ COUNTED = 64
+ };
+
+ u16 m_addr[8], m_buf[2];
+ u8 m_adcsr, m_adcr;
+ int m_register_mask;
+ int m_trigger, m_start_mode, m_start_channel, m_end_channel, m_start_count;
+ bool m_suspend_on_interrupt, m_analog_power_control;
+ int m_mode, m_channel, m_count;
+ bool m_analog_powered, m_adtrg;
+ u64 m_next_event;
+
+ virtual void device_start() override;
+ virtual void device_reset() override;
+
+ void sampling();
+ void start_conversion();
+ void conversion_wait(bool first, bool poweron, u64 current_time = 0);
+ void buffer_value(int port, int buffer = 0);
+ void commit_value(int reg, int buffer = 0);
+ void timeout(u64 current_time);
+ void done();
+
+ int conversion_time(bool first, bool poweron);
+ void mode_update();
+ void do_buffering(int buffer);
+ int get_channel_index(int count);
+};
+
+DECLARE_DEVICE_TYPE(SH_ADC, sh_adc_device)
+
+#endif // MAME_CPU_SH_SH_ADC_H
diff --git a/src/devices/cpu/sh/sh_cmt.cpp b/src/devices/cpu/sh/sh_cmt.cpp
new file mode 100644
index 00000000000..1e659080e75
--- /dev/null
+++ b/src/devices/cpu/sh/sh_cmt.cpp
@@ -0,0 +1,197 @@
+// license:BSD-3-Clause
+// copyright-holders:Olivier Galibert
+/***************************************************************************
+
+ sh_cmt.h
+
+ SH Compare/Match timer subsystem
+
+
+***************************************************************************/
+
+#include "emu.h"
+#include "sh7042.h"
+#include "sh_intc.h"
+
+DEFINE_DEVICE_TYPE(SH_CMT, sh_cmt_device, "sh_cmt", "SH2/704x CMT")
+
+sh_cmt_device::sh_cmt_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) :
+ device_t(mconfig, SH_CMT, tag, owner, clock),
+ m_cpu(*this, finder_base::DUMMY_TAG),
+ m_intc(*this, finder_base::DUMMY_TAG),
+ m_intc_vector{0, 0},
+ m_str(0),
+ m_csr{ 0, 0 },
+ m_cnt{ 0, 0 },
+ m_cor{ 0xffff, 0xffff }
+{
+}
+
+void sh_cmt_device::device_start()
+{
+}
+
+void sh_cmt_device::device_reset()
+{
+}
+
+u64 sh_cmt_device::internal_update(u64 current_time)
+{
+ u64 next = 0;
+ for(int i = 0; i != 2; i++) {
+ if(m_next_event[i] && current_time >= m_next_event[i]) {
+ m_csr[i] |= 0x80;
+ if(BIT(m_csr[i], 6))
+ m_intc->internal_interrupt(m_intc_vector[i]);
+ cnt_update(i, current_time);
+ }
+ if(!next || (m_next_event[i] && m_next_event[i] < next))
+ next = m_next_event[i];
+ }
+ return next;
+}
+
+
+u16 sh_cmt_device::cmstr_r()
+{
+ return m_str;
+}
+
+u16 sh_cmt_device::cmcsr0_r()
+{
+ return m_csr[0];
+}
+
+u16 sh_cmt_device::cmcnt0_r()
+{
+ cnt_update(0, m_cpu->current_cycles());
+ return m_cnt[0];
+}
+
+u16 sh_cmt_device::cmcor0_r()
+{
+ return m_cor[0];
+}
+
+u16 sh_cmt_device::cmcsr1_r()
+{
+ return m_csr[1];
+}
+
+u16 sh_cmt_device::cmcnt1_r()
+{
+ cnt_update(1, m_cpu->current_cycles());
+ return m_cnt[1];
+}
+
+u16 sh_cmt_device::cmcor1_r()
+{
+ return m_cor[1];
+}
+
+void sh_cmt_device::cmcsr0_w(offs_t, u16 data, u16 mem_mask)
+{
+ csr_w(0, data, mem_mask);
+}
+
+void sh_cmt_device::cmcsr1_w(offs_t, u16 data, u16 mem_mask)
+{
+ csr_w(1, data, mem_mask);
+}
+
+void sh_cmt_device::cmcnt0_w(offs_t, u16 data, u16 mem_mask)
+{
+ cnt_w(0, data, mem_mask);
+}
+
+void sh_cmt_device::cmcnt1_w(offs_t, u16 data, u16 mem_mask)
+{
+ cnt_w(1, data, mem_mask);
+}
+
+void sh_cmt_device::cmcor0_w(offs_t, u16 data, u16 mem_mask)
+{
+ cor_w(0, data, mem_mask);
+}
+
+void sh_cmt_device::cmcor1_w(offs_t, u16 data, u16 mem_mask)
+{
+ cor_w(1, data, mem_mask);
+}
+
+void sh_cmt_device::cmstr_w(offs_t, u16 data, u16 mem_mask)
+{
+ cnt_update(0, m_cpu->current_cycles());
+ cnt_update(1, m_cpu->current_cycles());
+ u16 old = m_str;
+ COMBINE_DATA(&m_str);
+ logerror("active %c %c\n", m_str & 1 ? '0' : '-', m_str & 2 ? '1' : '-');
+ for(int i=0; i != 2; i++)
+ if(!BIT(old, i) && BIT(m_str, i))
+ clock_start(i);
+ else if(!BIT(m_str, i))
+ m_next_event[i] = 0;
+ m_cpu->internal_update();
+}
+
+void sh_cmt_device::csr_w(int reg, u16 data, u16 mem_mask)
+{
+ cnt_update(reg, m_cpu->current_cycles());
+ u16 old = m_csr[reg];
+ COMBINE_DATA(&m_csr[reg]);
+ if(!(old & 0x80))
+ m_csr[reg] &= ~0x80;
+ if((old ^ m_csr[reg]) & 0x7f)
+ logerror("csr_w %d f=%d ie=%d div=%d\n", reg, BIT(m_csr[reg], 7), BIT(m_csr[reg], 6), 8 << (2*BIT(m_csr[reg], 0, 2)));
+}
+
+void sh_cmt_device::cnt_w(int reg, u16 data, u16 mem_mask)
+{
+ COMBINE_DATA(&m_cnt[reg]);
+ logerror("cnt_w %d, %04x\n", reg, m_cnt[reg]);
+ if((m_str >> reg) & 1) {
+ compute_next_event(reg);
+ m_cpu->internal_update();
+ }
+}
+
+void sh_cmt_device::cor_w(int reg, u16 data, u16 mem_mask)
+{
+ cnt_update(reg, m_cpu->current_cycles());
+ COMBINE_DATA(&m_cor[reg]);
+ logerror("cor_w %d, %04x\n", reg, m_cor[reg]);
+ if((m_str >> reg) & 1) {
+ compute_next_event(reg);
+ m_cpu->internal_update();
+ }
+}
+
+void sh_cmt_device::clock_start(int clk)
+{
+ logerror("start clock %d %dHz\n", clk, (m_cpu->clock() >> (3 + 2*BIT(m_csr[clk], 0, 2))) / (m_cor[clk] + 1));
+ compute_next_event(clk);
+}
+
+void sh_cmt_device::compute_next_event(int clk)
+{
+ u64 step1 = 1 << (3 + 2*BIT(m_csr[clk], 0, 2));
+ u64 time = m_cpu->current_cycles();
+ if(time & (step1 - 1))
+ time = (time | (step1 - 1)) + 1;
+ s32 counts = m_cor[clk] + 1 - m_cnt[clk];
+ if(counts < 0)
+ counts += 0x10000;
+ time += step1 * counts;
+ m_next_event[clk] = time;
+}
+
+void sh_cmt_device::cnt_update(int clk, u64 current_time)
+{
+ if(!((m_str >> clk) & 1))
+ return;
+ u64 step = (m_cor[clk] + 1) << (3 + 2*BIT(m_csr[clk], 0, 2));
+ while(current_time >= m_next_event[clk])
+ m_next_event[clk] += step;
+ u64 delta = m_next_event[clk] - current_time;
+ m_cnt[clk] = m_cor[clk] - ((delta - 1) >> (3 + 2*BIT(m_csr[clk], 0, 2)));
+}
diff --git a/src/devices/cpu/sh/sh_cmt.h b/src/devices/cpu/sh/sh_cmt.h
new file mode 100644
index 00000000000..e365be37fb1
--- /dev/null
+++ b/src/devices/cpu/sh/sh_cmt.h
@@ -0,0 +1,75 @@
+// license:BSD-3-Clause
+// copyright-holders:Olivier Galibert
+/***************************************************************************
+
+ sh_cmt.h
+
+ SH Compare/Match timer subsystem
+
+
+***************************************************************************/
+
+#ifndef MAME_CPU_SH_SH_CMT_H
+#define MAME_CPU_SH_SH_CMT_H
+
+#pragma once
+
+class sh7042_device;
+class sh_intc_device;
+
+class sh_cmt_device : public device_t {
+public:
+ sh_cmt_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock = 0);
+
+ template<typename T, typename U> sh_cmt_device(const machine_config &mconfig, const char *tag, device_t *owner,
+ T &&cpu, U &&intc, int vect0, int vect1) :
+ sh_cmt_device(mconfig, tag, owner)
+ {
+ m_cpu.set_tag(std::forward<T>(cpu));
+ m_intc.set_tag(std::forward<U>(intc));
+ m_intc_vector[0] = vect0;
+ m_intc_vector[1] = vect1;
+ }
+
+ u64 internal_update(u64 current_time);
+
+ u16 cmstr_r();
+ void cmstr_w(offs_t, u16 data, u16 mem_mask);
+ u16 cmcsr0_r();
+ void cmcsr0_w(offs_t, u16 data, u16 mem_mask);
+ u16 cmcnt0_r();
+ void cmcnt0_w(offs_t, u16 data, u16 mem_mask);
+ u16 cmcor0_r();
+ void cmcor0_w(offs_t, u16 data, u16 mem_mask);
+ u16 cmcsr1_r();
+ void cmcsr1_w(offs_t, u16 data, u16 mem_mask);
+ u16 cmcnt1_r();
+ void cmcnt1_w(offs_t, u16 data, u16 mem_mask);
+ u16 cmcor1_r();
+ void cmcor1_w(offs_t, u16 data, u16 mem_mask);
+
+protected:
+ required_device<sh7042_device> m_cpu;
+ required_device<sh_intc_device> m_intc;
+ std::array<u64, 2> m_next_event;
+ std::array<int, 2> m_intc_vector;
+ u16 m_str;
+ std::array<u16, 2> m_csr;
+ std::array<u16, 2> m_cnt;
+ std::array<u16, 2> m_cor;
+
+ virtual void device_start() override;
+ virtual void device_reset() override;
+
+ void csr_w(int reg, u16 data, u16 mem_mask);
+ void cnt_w(int reg, u16 data, u16 mem_mask);
+ void cor_w(int reg, u16 data, u16 mem_mask);
+
+ void clock_start(int clk);
+ void compute_next_event(int clk);
+ void cnt_update(int clk, u64 current_time);
+};
+
+DECLARE_DEVICE_TYPE(SH_CMT, sh_cmt_device)
+
+#endif // MAME_CPU_SH_SH_CMT_H
diff --git a/src/devices/cpu/sh/sh_intc.cpp b/src/devices/cpu/sh/sh_intc.cpp
new file mode 100644
index 00000000000..d13f8f55853
--- /dev/null
+++ b/src/devices/cpu/sh/sh_intc.cpp
@@ -0,0 +1,75 @@
+// license:BSD-3-Clause
+// copyright-holders:Olivier Galibert
+/***************************************************************************
+
+ sh_intc.cpp
+
+ SH interrupt controllers family
+
+***************************************************************************/
+
+#include "emu.h"
+#include "sh_intc.h"
+
+#include "sh7042.h"
+
+DEFINE_DEVICE_TYPE(SH_INTC, sh_intc_device, "sh_intc", "SH interrupt controller")
+
+sh_intc_device::sh_intc_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) :
+ device_t(mconfig, SH_INTC, tag, owner, clock),
+ m_cpu(*this, finder_base::DUMMY_TAG)
+{
+}
+
+void sh_intc_device::device_start()
+{
+}
+
+void sh_intc_device::device_reset()
+{
+}
+
+int sh_intc_device::interrupt_taken(int vector)
+{
+ return 0;
+}
+
+void sh_intc_device::internal_interrupt(int vector)
+{
+ logerror("Internal interrupt %d\n", vector);
+}
+
+void sh_intc_device::set_input(int inputnum, int state)
+{
+}
+
+u16 sh_intc_device::icr_r()
+{
+ return 0;
+}
+
+void sh_intc_device::icr_w(offs_t, u16 data, u16 mem_mask)
+{
+ logerror("icr_w %04x @ %04x\n", data, mem_mask);
+}
+
+u16 sh_intc_device::isr_r()
+{
+ return 0;
+}
+
+void sh_intc_device::isr_w(offs_t, u16 data, u16 mem_mask)
+{
+ logerror("isr_w %04x @ %04x\n", data, mem_mask);
+}
+
+u16 sh_intc_device::ipr_r(offs_t offset)
+{
+ return 0;
+}
+
+void sh_intc_device::ipr_w(offs_t offset, u16 data, u16 mem_mask)
+{
+ logerror("ipr_w %x, %04x @ %04x\n", offset, data, mem_mask);
+}
+
diff --git a/src/devices/cpu/sh/sh_intc.h b/src/devices/cpu/sh/sh_intc.h
new file mode 100644
index 00000000000..b93444d8e32
--- /dev/null
+++ b/src/devices/cpu/sh/sh_intc.h
@@ -0,0 +1,47 @@
+// license:BSD-3-Clause
+// copyright-holders:Olivier Galibert
+/***************************************************************************
+
+ sh_intc.h
+
+ SH interrupt controllers family
+
+***************************************************************************/
+
+#ifndef MAME_CPU_SH_SH_INTC_H
+#define MAME_CPU_SH_SH_INTC_H
+
+#pragma once
+
+class sh7042_device;
+
+class sh_intc_device : public device_t {
+public:
+ sh_intc_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock = 0);
+ template<typename T> sh_intc_device(const machine_config &mconfig, const char *tag, device_t *owner, T &&cpu) :
+ sh_intc_device(mconfig, tag, owner)
+ {
+ m_cpu.set_tag(std::forward<T>(cpu));
+ }
+
+ int interrupt_taken(int vector);
+ void internal_interrupt(int vector);
+ void set_input(int inputnum, int state);
+
+ u16 icr_r();
+ void icr_w(offs_t, u16 data, u16 mem_mask);
+ u16 isr_r();
+ void isr_w(offs_t, u16 data, u16 mem_mask);
+ u16 ipr_r(offs_t offset);
+ void ipr_w(offs_t offset, u16 data, u16 mem_mask);
+
+protected:
+ required_device<sh7042_device> m_cpu;
+
+ virtual void device_start() override;
+ virtual void device_reset() override;
+};
+
+DECLARE_DEVICE_TYPE(SH_INTC, sh_intc_device)
+
+#endif // MAME_CPU_SH_SH_INTC_H
diff --git a/src/devices/cpu/sh/sh_port.cpp b/src/devices/cpu/sh/sh_port.cpp
new file mode 100644
index 00000000000..8bc962f65cd
--- /dev/null
+++ b/src/devices/cpu/sh/sh_port.cpp
@@ -0,0 +1,109 @@
+// license:BSD-3-Clause
+// copyright-holders:Olivier Galibert
+/***************************************************************************
+
+ sh_port.h
+
+ SH i/o ports
+
+***************************************************************************/
+
+#include "emu.h"
+#include "sh_intc.h"
+
+#include "sh7042.h"
+
+DEFINE_DEVICE_TYPE(SH_PORT16, sh_port16_device, "sh_port16", "SH 16-bits port")
+DEFINE_DEVICE_TYPE(SH_PORT32, sh_port32_device, "sh_port32", "SH 32-bits port")
+
+sh_port16_device::sh_port16_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) :
+ device_t(mconfig, SH_PORT16, tag, owner, clock),
+ m_cpu(*this, finder_base::DUMMY_TAG)
+{
+}
+
+void sh_port16_device::device_start()
+{
+ m_io = m_default_io;
+ save_item(NAME(m_dr));
+ save_item(NAME(m_io));
+}
+
+void sh_port16_device::device_reset()
+{
+}
+
+u16 sh_port16_device::dr_r()
+{
+ if(~m_io & ~m_mask)
+ return (m_dr & m_io) | (m_cpu->do_read_port16(m_index) & ~m_io);
+ return m_dr;
+}
+
+void sh_port16_device::dr_w(offs_t, u16 data, u16 mem_mask)
+{
+ COMBINE_DATA(&m_dr);
+ m_dr &= ~m_mask;
+ if(m_io)
+ m_cpu->do_write_port16(m_index, m_dr & m_io, m_io);
+}
+
+u16 sh_port16_device::io_r()
+{
+ return m_io;
+}
+
+void sh_port16_device::io_w(offs_t, u16 data, u16 mem_mask)
+{
+ COMBINE_DATA(&m_io);
+ m_io &= ~m_mask;
+ if(m_io)
+ m_cpu->do_write_port16(m_index, m_dr & m_io, m_io);
+}
+
+
+sh_port32_device::sh_port32_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) :
+ device_t(mconfig, SH_PORT32, tag, owner, clock),
+ m_cpu(*this, finder_base::DUMMY_TAG)
+{
+}
+
+void sh_port32_device::device_start()
+{
+ m_io = m_default_io;
+ save_item(NAME(m_dr));
+ save_item(NAME(m_io));
+}
+
+void sh_port32_device::device_reset()
+{
+}
+
+u32 sh_port32_device::dr_r()
+{
+ if(~m_io & ~m_mask)
+ return (m_dr & m_io) | (m_cpu->do_read_port32(m_index) & ~m_io);
+ return m_dr;
+}
+
+void sh_port32_device::dr_w(offs_t, u32 data, u32 mem_mask)
+{
+ COMBINE_DATA(&m_dr);
+ m_dr &= ~m_mask;
+ if(m_io)
+ m_cpu->do_write_port32(m_index, m_dr & m_io, m_io);
+}
+
+u32 sh_port32_device::io_r()
+{
+ return m_io;
+}
+
+void sh_port32_device::io_w(offs_t, u32 data, u32 mem_mask)
+{
+ COMBINE_DATA(&m_io);
+ m_io &= ~m_mask;
+ if(m_io)
+ m_cpu->do_write_port32(m_index, m_dr & m_io, m_io);
+}
+
diff --git a/src/devices/cpu/sh/sh_port.h b/src/devices/cpu/sh/sh_port.h
new file mode 100644
index 00000000000..ec2a19228ee
--- /dev/null
+++ b/src/devices/cpu/sh/sh_port.h
@@ -0,0 +1,75 @@
+// license:BSD-3-Clause
+// copyright-holders:Olivier Galibert
+/***************************************************************************
+
+ sh_port.h
+
+ SH i/o ports
+
+***************************************************************************/
+
+#ifndef MAME_CPU_SH_SH_PORT_H
+#define MAME_CPU_SH_SH_PORT_H
+
+#pragma once
+
+class sh7042_device;
+
+class sh_port16_device : public device_t {
+public:
+ sh_port16_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock = 0);
+ template<typename T> sh_port16_device(const machine_config &mconfig, const char *tag, device_t *owner, T &&cpu, int index, u16 default_io, u16 mask) :
+ sh_port16_device(mconfig, tag, owner)
+ {
+ m_index = index;
+ m_default_io = default_io;
+ m_mask = mask;
+ m_cpu.set_tag(std::forward<T>(cpu));
+ }
+
+ u16 dr_r();
+ void dr_w(offs_t, u16 data, u16 mem_mask);
+ u16 io_r();
+ void io_w(offs_t, u16 data, u16 mem_mask);
+
+protected:
+ required_device<sh7042_device> m_cpu;
+ int m_index;
+ u16 m_default_io, m_mask;
+ u16 m_dr, m_io;
+
+ virtual void device_start() override;
+ virtual void device_reset() override;
+};
+
+class sh_port32_device : public device_t {
+public:
+ sh_port32_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock = 0);
+ template<typename T> sh_port32_device(const machine_config &mconfig, const char *tag, device_t *owner, T &&cpu, int index, u32 default_io, u32 mask) :
+ sh_port32_device(mconfig, tag, owner)
+ {
+ m_index = index;
+ m_default_io = default_io;
+ m_mask = mask;
+ m_cpu.set_tag(std::forward<T>(cpu));
+ }
+
+ u32 dr_r();
+ void dr_w(offs_t, u32 data, u32 mem_mask);
+ u32 io_r();
+ void io_w(offs_t, u32 data, u32 mem_mask);
+
+protected:
+ required_device<sh7042_device> m_cpu;
+ int m_index;
+ u32 m_default_io, m_mask;
+ u32 m_dr, m_io;
+
+ virtual void device_start() override;
+ virtual void device_reset() override;
+};
+
+DECLARE_DEVICE_TYPE(SH_PORT16, sh_port16_device)
+DECLARE_DEVICE_TYPE(SH_PORT32, sh_port32_device)
+
+#endif // MAME_CPU_SH_SH_PORT_H
diff --git a/src/mame/tvgames/xavix_a.cpp b/src/mame/tvgames/xavix_a.cpp
index 9470f8536de..ebddb577444 100644
--- a/src/mame/tvgames/xavix_a.cpp
+++ b/src/mame/tvgames/xavix_a.cpp
@@ -116,7 +116,6 @@ bool xavix_sound_device::is_voice_enabled(int voice)
void xavix_sound_device::enable_voice(int voice, bool update_only)
{
m_stream->update();
-
int voicemembase = voice * 0x10;
uint16_t freq_mode = (m_readregs_cb(voicemembase + 0x1) << 8) | (m_readregs_cb(voicemembase + 0x0)); // sample rate maybe?
diff --git a/src/mame/yamaha/ymmu128.cpp b/src/mame/yamaha/ymmu128.cpp
index b0a15fcfc92..8743612aadc 100644
--- a/src/mame/yamaha/ymmu128.cpp
+++ b/src/mame/yamaha/ymmu128.cpp
@@ -53,25 +53,76 @@ private:
required_device<i8251_device> m_sci;
required_shared_ptr<u32> m_ram;
+ u16 m_pe;
+
void map(address_map &map);
void swp30_map(address_map &map);
virtual void machine_start() override;
virtual void machine_reset() override;
+
+ u16 pe_r();
+ void pe_w(u16 data);
};
-
+
void mu128_state::machine_start()
{
+ save_item(NAME(m_pe));
+ m_pe = 0;
}
-
+
void mu128_state::machine_reset()
{
}
+// Port E:
+// 0: lcd-r/w
+// 1: nc
+// 2: lcd-rs
+// 3: lcread (secondary functions on lcread edge)
+// 4: lcd-e
+// 5: 1mclk
+// 6: siclk
+// 7: sws
+// 8-a: db 0-2, lcdc a-c
+// b-c: db 3-4, mic/line
+// d: db 5, swp reset
+// e: db 6, sireset
+// f: db 7, breset
+
+u16 mu128_state::pe_r()
+{
+ if(BIT(m_pe, 4)) {
+ if(BIT(m_pe, 0)) {
+ if(BIT(m_pe, 2))
+ return m_lcd->data_read() << 8;
+ else
+ return m_lcd->control_read() << 8;
+ } else
+ return 0x0000;
+ }
+
+ return 0;
+}
+
+void mu128_state::pe_w(u16 data)
+{
+ u16 prev = m_pe;
+ m_pe = data;
+ if(BIT(m_pe, 4) && !BIT(prev, 4)) {
+ if(!BIT(m_pe, 0)) {
+ if(BIT(m_pe, 2))
+ m_lcd->data_write(m_pe >> 8);
+ else
+ m_lcd->control_write(m_pe >> 8);
+ }
+ }
+}
+
void mu128_state::map(address_map &map)
{
map(0x000000, 0x1fffff).rom().region("maincpu", 0);
- map(0x200000, 0x21ffff).ram().share(m_ram);
+ map(0x400000, 0x43ffff).ram().share(m_ram);
map(0x800000, 0x801fff).m(m_swp30m, FUNC(swp30_device::map));
map(0x802000, 0x803fff).m(m_swp30s, FUNC(swp30_device::map));
map(0xc00000, 0xc00000).rw(m_sci, FUNC(i8251_device::data_r), FUNC(i8251_device::data_w)).mirror(0x3ffffe);
@@ -87,6 +138,8 @@ void mu128_state::mu128(machine_config &config)
{
SH7043(config, m_maincpu, 7_MHz_XTAL * 4);
m_maincpu->set_addrmap(AS_PROGRAM, &mu128_state::map);
+ m_maincpu->read_porte().set(FUNC(mu128_state::pe_r));
+ m_maincpu->write_porte().set(FUNC(mu128_state::pe_w));
NVRAM(config, m_nvram, nvram_device::DEFAULT_NONE);