summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/cpu/sh
diff options
context:
space:
mode:
Diffstat (limited to 'src/devices/cpu/sh')
-rw-r--r--src/devices/cpu/sh/sh.cpp1540
-rw-r--r--src/devices/cpu/sh/sh.h34
-rw-r--r--src/devices/cpu/sh/sh2.cpp753
-rw-r--r--src/devices/cpu/sh/sh2.h389
-rw-r--r--src/devices/cpu/sh/sh2comn.cpp1204
-rw-r--r--src/devices/cpu/sh/sh2comn.h52
-rw-r--r--src/devices/cpu/sh/sh2fe.cpp3
-rw-r--r--src/devices/cpu/sh/sh3comn.cpp2403
-rw-r--r--src/devices/cpu/sh/sh3comn.h79
-rw-r--r--src/devices/cpu/sh/sh4.cpp2806
-rw-r--r--src/devices/cpu/sh/sh4.h1603
-rw-r--r--src/devices/cpu/sh/sh4comn.cpp2972
-rw-r--r--src/devices/cpu/sh/sh4comn.h33
-rw-r--r--src/devices/cpu/sh/sh4dmac.cpp511
-rw-r--r--src/devices/cpu/sh/sh4dmac.h35
-rw-r--r--src/devices/cpu/sh/sh4fe.cpp22
-rw-r--r--src/devices/cpu/sh/sh4regs.h165
-rw-r--r--src/devices/cpu/sh/sh4tmu.cpp269
-rw-r--r--src/devices/cpu/sh/sh7014.cpp201
-rw-r--r--src/devices/cpu/sh/sh7014.h83
-rw-r--r--src/devices/cpu/sh/sh7014_bsc.cpp148
-rw-r--r--src/devices/cpu/sh/sh7014_bsc.h62
-rw-r--r--src/devices/cpu/sh/sh7014_dmac.cpp400
-rw-r--r--src/devices/cpu/sh/sh7014_dmac.h173
-rw-r--r--src/devices/cpu/sh/sh7014_intc.cpp313
-rw-r--r--src/devices/cpu/sh/sh7014_intc.h147
-rw-r--r--src/devices/cpu/sh/sh7014_mtu.cpp571
-rw-r--r--src/devices/cpu/sh/sh7014_mtu.h211
-rw-r--r--src/devices/cpu/sh/sh7014_port.cpp243
-rw-r--r--src/devices/cpu/sh/sh7014_port.h98
-rw-r--r--src/devices/cpu/sh/sh7014_sci.cpp380
-rw-r--r--src/devices/cpu/sh/sh7014_sci.h135
-rw-r--r--src/devices/cpu/sh/sh7021.cpp2243
-rw-r--r--src/devices/cpu/sh/sh7021.h334
-rw-r--r--src/devices/cpu/sh/sh7032.cpp43
-rw-r--r--src/devices/cpu/sh/sh7032.h33
-rw-r--r--src/devices/cpu/sh/sh7042.cpp505
-rw-r--r--src/devices/cpu/sh/sh7042.h190
-rw-r--r--src/devices/cpu/sh/sh7604.cpp1540
-rw-r--r--src/devices/cpu/sh/sh7604.h264
-rw-r--r--src/devices/cpu/sh/sh7604_bus.cpp78
-rw-r--r--src/devices/cpu/sh/sh7604_bus.h46
-rw-r--r--src/devices/cpu/sh/sh7604_sci.cpp48
-rw-r--r--src/devices/cpu/sh/sh7604_sci.h41
-rw-r--r--src/devices/cpu/sh/sh7604_wdt.cpp20
-rw-r--r--src/devices/cpu/sh/sh7604_wdt.h17
-rw-r--r--src/devices/cpu/sh/sh_adc.cpp342
-rw-r--r--src/devices/cpu/sh/sh_adc.h124
-rw-r--r--src/devices/cpu/sh/sh_bsc.cpp139
-rw-r--r--src/devices/cpu/sh/sh_bsc.h47
-rw-r--r--src/devices/cpu/sh/sh_cmt.cpp202
-rw-r--r--src/devices/cpu/sh/sh_cmt.h75
-rw-r--r--src/devices/cpu/sh/sh_dasm.cpp73
-rw-r--r--src/devices/cpu/sh/sh_dasm.h6
-rw-r--r--src/devices/cpu/sh/sh_dmac.cpp115
-rw-r--r--src/devices/cpu/sh/sh_dmac.h79
-rw-r--r--src/devices/cpu/sh/sh_fe.cpp259
-rw-r--r--src/devices/cpu/sh/sh_intc.cpp151
-rw-r--r--src/devices/cpu/sh/sh_intc.h58
-rw-r--r--src/devices/cpu/sh/sh_mtu.cpp529
-rw-r--r--src/devices/cpu/sh/sh_mtu.h182
-rw-r--r--src/devices/cpu/sh/sh_port.cpp109
-rw-r--r--src/devices/cpu/sh/sh_port.h75
-rw-r--r--src/devices/cpu/sh/sh_sci.cpp765
-rw-r--r--src/devices/cpu/sh/sh_sci.h151
65 files changed, 20905 insertions, 6016 deletions
diff --git a/src/devices/cpu/sh/sh.cpp b/src/devices/cpu/sh/sh.cpp
index 03fecd135ac..08054e047fe 100644
--- a/src/devices/cpu/sh/sh.cpp
+++ b/src/devices/cpu/sh/sh.cpp
@@ -77,7 +77,7 @@ void sh_common_execution::device_start()
state_add(SH4_R15, "R15", m_sh2_state->r[15]).formatstr("%08X");
state_add(SH4_EA, "EA", m_sh2_state->ea).formatstr("%08X");
- state_add(STATE_GENSP, "GENSP", m_sh2_state->r[15]).noshow();
+ state_add(SH4_SP, "SP", m_sh2_state->r[15]).noshow();
state_add(STATE_GENFLAGS, "GENFLAGS", m_sh2_state->sr).formatstr("%20s").noshow();
set_icountptr(m_sh2_state->icount);
@@ -169,7 +169,7 @@ void sh_common_execution::ADD(uint32_t m, uint32_t n)
*/
void sh_common_execution::ADDI(uint32_t i, uint32_t n)
{
- m_sh2_state->r[n] += (int32_t)(int16_t)(int8_t)i;
+ m_sh2_state->r[n] += util::sext(i, 8);
}
/* code cycles t-bit
@@ -197,24 +197,16 @@ void sh_common_execution::ADDC(uint32_t m, uint32_t n)
*/
void sh_common_execution::ADDV(uint32_t m, uint32_t n)
{
- int32_t dest, src, ans;
-
- if ((int32_t) m_sh2_state->r[n] >= 0)
- dest = 0;
- else
- dest = 1;
- if ((int32_t) m_sh2_state->r[m] >= 0)
- src = 0;
- else
- src = 1;
+ int32_t dest = BIT(m_sh2_state->r[n], 31);
+ int32_t src = BIT(m_sh2_state->r[m], 31);
src += dest;
+
m_sh2_state->r[n] += m_sh2_state->r[m];
- if ((int32_t) m_sh2_state->r[n] >= 0)
- ans = 0;
- else
- ans = 1;
+
+ int32_t ans = BIT(m_sh2_state->r[n], 31);
ans += dest;
- if (src == 0 || src == 2)
+
+ if (src != 1)
{
if (ans == 1)
m_sh2_state->sr |= SH_T;
@@ -249,11 +241,9 @@ void sh_common_execution::ANDI(uint32_t i)
*/
void sh_common_execution::ANDM(uint32_t i)
{
- uint32_t temp;
-
m_sh2_state->ea = m_sh2_state->gbr + m_sh2_state->r[0];
- temp = i & RB( m_sh2_state->ea );
- WB( m_sh2_state->ea, temp );
+ uint32_t temp = i & read_byte(m_sh2_state->ea);
+ write_byte(m_sh2_state->ea, temp);
m_sh2_state->icount -= 2;
}
@@ -265,7 +255,7 @@ void sh_common_execution::BF(uint32_t d)
{
if ((m_sh2_state->sr & SH_T) == 0)
{
- int32_t disp = ((int32_t)d << 24) >> 24;
+ int32_t disp = util::sext(d, 8);
m_sh2_state->pc = m_sh2_state->ea = m_sh2_state->pc + disp * 2 + 2;
m_sh2_state->icount -= 2;
}
@@ -279,7 +269,7 @@ void sh_common_execution::BFS(uint32_t d)
{
if ((m_sh2_state->sr & SH_T) == 0)
{
- int32_t disp = ((int32_t)d << 24) >> 24;
+ int32_t disp = util::sext(d, 8);
m_sh2_state->m_delay = m_sh2_state->ea = m_sh2_state->pc + disp * 2 + 2;
m_sh2_state->icount--;
}
@@ -291,12 +281,12 @@ void sh_common_execution::BFS(uint32_t d)
*/
void sh_common_execution::BRA(uint32_t d)
{
- int32_t disp = ((int32_t)d << 20) >> 20;
+ int32_t disp = util::sext(d, 12);
#if BUSY_LOOP_HACKS
if (disp == -2)
{
- uint32_t next_opcode = RW(m_sh2_state->pc & AM);
+ uint32_t next_opcode = read_word(m_sh2_state->pc & m_am);
/* BRA $
* NOP
*/
@@ -324,7 +314,7 @@ void sh_common_execution::BRAF(uint32_t m)
*/
void sh_common_execution::BSR(uint32_t d)
{
- int32_t disp = ((int32_t)d << 20) >> 20;
+ int32_t disp = util::sext(d, 12);
m_sh2_state->pr = m_sh2_state->pc + 2;
m_sh2_state->m_delay = m_sh2_state->ea = m_sh2_state->pc + disp * 2 + 2;
@@ -350,7 +340,7 @@ void sh_common_execution::BT(uint32_t d)
{
if ((m_sh2_state->sr & SH_T) != 0)
{
- int32_t disp = ((int32_t)d << 24) >> 24;
+ int32_t disp = util::sext(d, 8);
m_sh2_state->pc = m_sh2_state->ea = m_sh2_state->pc + disp * 2 + 2;
m_sh2_state->icount -= 2;
}
@@ -364,7 +354,7 @@ void sh_common_execution::BTS(uint32_t d)
{
if ((m_sh2_state->sr & SH_T) != 0)
{
- int32_t disp = ((int32_t)d << 24) >> 24;
+ int32_t disp = util::sext(d, 8);
m_sh2_state->m_delay = m_sh2_state->ea = m_sh2_state->pc + disp * 2 + 2;
m_sh2_state->icount--;
}
@@ -407,7 +397,7 @@ void sh_common_execution::CMPEQ(uint32_t m, uint32_t n)
*/
void sh_common_execution::CMPGE(uint32_t m, uint32_t n)
{
- if ((int32_t) m_sh2_state->r[n] >= (int32_t) m_sh2_state->r[m])
+ if ((int32_t)m_sh2_state->r[n] >= (int32_t)m_sh2_state->r[m])
m_sh2_state->sr |= SH_T;
else
m_sh2_state->sr &= ~SH_T;
@@ -419,7 +409,7 @@ void sh_common_execution::CMPGE(uint32_t m, uint32_t n)
*/
void sh_common_execution::CMPGT(uint32_t m, uint32_t n)
{
- if ((int32_t) m_sh2_state->r[n] > (int32_t) m_sh2_state->r[m])
+ if ((int32_t)m_sh2_state->r[n] > (int32_t)m_sh2_state->r[m])
m_sh2_state->sr |= SH_T;
else
m_sh2_state->sr &= ~SH_T;
@@ -431,7 +421,7 @@ void sh_common_execution::CMPGT(uint32_t m, uint32_t n)
*/
void sh_common_execution::CMPHI(uint32_t m, uint32_t n)
{
- if ((uint32_t) m_sh2_state->r[n] > (uint32_t) m_sh2_state->r[m])
+ if (m_sh2_state->r[n] > m_sh2_state->r[m])
m_sh2_state->sr |= SH_T;
else
m_sh2_state->sr &= ~SH_T;
@@ -443,7 +433,7 @@ void sh_common_execution::CMPHI(uint32_t m, uint32_t n)
*/
void sh_common_execution::CMPHS(uint32_t m, uint32_t n)
{
- if ((uint32_t) m_sh2_state->r[n] >= (uint32_t) m_sh2_state->r[m])
+ if (m_sh2_state->r[n] >= m_sh2_state->r[m])
m_sh2_state->sr |= SH_T;
else
m_sh2_state->sr &= ~SH_T;
@@ -455,7 +445,7 @@ void sh_common_execution::CMPHS(uint32_t m, uint32_t n)
*/
void sh_common_execution::CMPPL(uint32_t n)
{
- if ((int32_t) m_sh2_state->r[n] > 0)
+ if ((int32_t)m_sh2_state->r[n] > 0)
m_sh2_state->sr |= SH_T;
else
m_sh2_state->sr &= ~SH_T;
@@ -467,7 +457,7 @@ void sh_common_execution::CMPPL(uint32_t n)
*/
void sh_common_execution::CMPPZ(uint32_t n)
{
- if ((int32_t) m_sh2_state->r[n] >= 0)
+ if ((int32_t)m_sh2_state->r[n] >= 0)
m_sh2_state->sr |= SH_T;
else
m_sh2_state->sr &= ~SH_T;
@@ -479,14 +469,12 @@ void sh_common_execution::CMPPZ(uint32_t n)
*/
void sh_common_execution::CMPSTR(uint32_t m, uint32_t n)
{
- uint32_t temp;
- int32_t HH, HL, LH, LL;
- temp = m_sh2_state->r[n] ^ m_sh2_state->r[m];
- HH = (temp >> 24) & 0xff;
- HL = (temp >> 16) & 0xff;
- LH = (temp >> 8) & 0xff;
- LL = temp & 0xff;
- if (HH && HL && LH && LL)
+ uint32_t temp = m_sh2_state->r[n] ^ m_sh2_state->r[m];
+ uint8_t upper_byte = (temp >> 24) & 0xff;
+ uint8_t mid_upper_byte = (temp >> 16) & 0xff;
+ uint8_t mid_lower_byte = (temp >> 8) & 0xff;
+ uint8_t lower_byte = temp & 0xff;
+ if (upper_byte && mid_upper_byte && mid_lower_byte && lower_byte)
m_sh2_state->sr &= ~SH_T;
else
m_sh2_state->sr |= SH_T;
@@ -498,7 +486,7 @@ void sh_common_execution::CMPSTR(uint32_t m, uint32_t n)
*/
void sh_common_execution::CMPIM(uint32_t i)
{
- uint32_t imm = (uint32_t)(int32_t)(int16_t)(int8_t)i;
+ uint32_t imm = (uint32_t)util::sext(i, 8);
if (m_sh2_state->r[0] == imm)
m_sh2_state->sr |= SH_T;
@@ -512,15 +500,17 @@ void sh_common_execution::CMPIM(uint32_t i)
*/
void sh_common_execution::DIV0S(uint32_t m, uint32_t n)
{
- if ((m_sh2_state->r[n] & 0x80000000) == 0)
+ if (!BIT(m_sh2_state->r[n], 31))
m_sh2_state->sr &= ~SH_Q;
else
m_sh2_state->sr |= SH_Q;
- if ((m_sh2_state->r[m] & 0x80000000) == 0)
+
+ if (!BIT(m_sh2_state->r[m], 31))
m_sh2_state->sr &= ~SH_M;
else
m_sh2_state->sr |= SH_M;
- if ((m_sh2_state->r[m] ^ m_sh2_state->r[n]) & 0x80000000)
+
+ if (BIT(m_sh2_state->r[m] ^ m_sh2_state->r[n], 31))
m_sh2_state->sr |= SH_T;
else
m_sh2_state->sr &= ~SH_T;
@@ -541,10 +531,7 @@ void sh_common_execution::DIV0U()
*/
void sh_common_execution::DIV1(uint32_t m, uint32_t n)
{
- uint32_t tmp0;
- uint32_t old_q;
-
- old_q = m_sh2_state->sr & SH_Q;
+ uint32_t old_q = m_sh2_state->sr & SH_Q;
if (0x80000000 & m_sh2_state->r[n])
m_sh2_state->sr |= SH_Q;
else
@@ -556,33 +543,33 @@ void sh_common_execution::DIV1(uint32_t m, uint32_t n)
{
if (!(m_sh2_state->sr & SH_M))
{
- tmp0 = m_sh2_state->r[n];
+ uint32_t tmp = m_sh2_state->r[n];
m_sh2_state->r[n] -= m_sh2_state->r[m];
- if(!(m_sh2_state->sr & SH_Q))
- if(m_sh2_state->r[n] > tmp0)
+ if (!(m_sh2_state->sr & SH_Q))
+ if (m_sh2_state->r[n] > tmp)
m_sh2_state->sr |= SH_Q;
else
m_sh2_state->sr &= ~SH_Q;
else
- if(m_sh2_state->r[n] > tmp0)
+ if (m_sh2_state->r[n] > tmp)
m_sh2_state->sr &= ~SH_Q;
else
m_sh2_state->sr |= SH_Q;
}
else
{
- tmp0 = m_sh2_state->r[n];
+ uint32_t tmp = m_sh2_state->r[n];
m_sh2_state->r[n] += m_sh2_state->r[m];
- if(!(m_sh2_state->sr & SH_Q))
+ if (!(m_sh2_state->sr & SH_Q))
{
- if(m_sh2_state->r[n] < tmp0)
+ if (m_sh2_state->r[n] < tmp)
m_sh2_state->sr &= ~SH_Q;
else
m_sh2_state->sr |= SH_Q;
}
else
{
- if(m_sh2_state->r[n] < tmp0)
+ if (m_sh2_state->r[n] < tmp)
m_sh2_state->sr |= SH_Q;
else
m_sh2_state->sr &= ~SH_Q;
@@ -593,38 +580,38 @@ void sh_common_execution::DIV1(uint32_t m, uint32_t n)
{
if (!(m_sh2_state->sr & SH_M))
{
- tmp0 = m_sh2_state->r[n];
+ uint32_t tmp = m_sh2_state->r[n];
m_sh2_state->r[n] += m_sh2_state->r[m];
- if(!(m_sh2_state->sr & SH_Q))
- if(m_sh2_state->r[n] < tmp0)
+ if (!(m_sh2_state->sr & SH_Q))
+ if (m_sh2_state->r[n] < tmp)
m_sh2_state->sr |= SH_Q;
else
m_sh2_state->sr &= ~SH_Q;
else
- if(m_sh2_state->r[n] < tmp0)
+ if (m_sh2_state->r[n] < tmp)
m_sh2_state->sr &= ~SH_Q;
else
m_sh2_state->sr |= SH_Q;
}
else
{
- tmp0 = m_sh2_state->r[n];
+ uint32_t tmp = m_sh2_state->r[n];
m_sh2_state->r[n] -= m_sh2_state->r[m];
- if(!(m_sh2_state->sr & SH_Q))
- if(m_sh2_state->r[n] > tmp0)
+ if (!(m_sh2_state->sr & SH_Q))
+ if (m_sh2_state->r[n] > tmp)
m_sh2_state->sr &= ~SH_Q;
else
m_sh2_state->sr |= SH_Q;
else
- if(m_sh2_state->r[n] > tmp0)
+ if (m_sh2_state->r[n] > tmp)
m_sh2_state->sr |= SH_Q;
else
m_sh2_state->sr &= ~SH_Q;
}
}
- tmp0 = (m_sh2_state->sr & (SH_Q | SH_M));
- if((!tmp0) || (tmp0 == 0x300)) /* if Q == M set T else clear T */
+ uint32_t tmp = (m_sh2_state->sr & (SH_Q | SH_M));
+ if (tmp == 0 || tmp == 0x300) /* if Q == M set T else clear T */
m_sh2_state->sr |= SH_T;
else
m_sh2_state->sr &= ~SH_T;
@@ -633,77 +620,77 @@ void sh_common_execution::DIV1(uint32_t m, uint32_t n)
/* DMULS.L Rm,Rn */
void sh_common_execution::DMULS(uint32_t m, uint32_t n)
{
- uint32_t RnL, RnH, RmL, RmH, Res0, Res1, Res2;
- uint32_t temp0, temp1, temp2, temp3;
- int32_t tempm, tempn, fnLmL;
+ int32_t tempn = (int32_t)m_sh2_state->r[n];
+ int32_t tempm = (int32_t)m_sh2_state->r[m];
+ bool fnlml = (bool)BIT(tempn ^ tempm, 31);
- tempn = (int32_t) m_sh2_state->r[n];
- tempm = (int32_t) m_sh2_state->r[m];
if (tempn < 0)
tempn = 0 - tempn;
if (tempm < 0)
tempm = 0 - tempm;
- if ((int32_t) (m_sh2_state->r[n] ^ m_sh2_state->r[m]) < 0)
- fnLmL = -1;
- else
- fnLmL = 0;
- temp1 = (uint32_t) tempn;
- temp2 = (uint32_t) tempm;
- RnL = temp1 & 0x0000ffff;
- RnH = (temp1 >> 16) & 0x0000ffff;
- RmL = temp2 & 0x0000ffff;
- RmH = (temp2 >> 16) & 0x0000ffff;
- temp0 = RmL * RnL;
- temp1 = RmH * RnL;
- temp2 = RmL * RnH;
- temp3 = RmH * RnH;
- Res2 = 0;
- Res1 = temp1 + temp2;
- if (Res1 < temp1)
- Res2 += 0x00010000;
- temp1 = (Res1 << 16) & 0xffff0000;
- Res0 = temp0 + temp1;
- if (Res0 < temp0)
- Res2++;
- Res2 = Res2 + ((Res1 >> 16) & 0x0000ffff) + temp3;
- if (fnLmL < 0)
+
+ uint32_t rn_l = (uint32_t)tempn & 0x0000ffff;
+ uint32_t rn_h = (uint32_t)tempn >> 16;
+ uint32_t rm_l = (uint32_t)tempm & 0x0000ffff;
+ uint32_t rm_h = (uint32_t)tempm >> 16;
+
+ uint32_t temp0 = rm_l * rn_l;
+ uint32_t temp1 = rm_h * rn_l;
+ uint32_t temp2 = rm_l * rn_h;
+ uint32_t temp3 = rm_h * rn_h;
+
+ uint32_t res2 = 0;
+ uint32_t res1 = temp1 + temp2;
+ if (res1 < temp1)
+ res2 += 0x00010000;
+ temp1 = res1 << 16;
+
+ uint32_t res0 = temp0 + temp1;
+ if (res0 < temp0)
+ res2++;
+ res2 = res2 + (res1 >> 16) + temp3;
+
+ if (fnlml)
{
- Res2 = ~Res2;
- if (Res0 == 0)
- Res2++;
+ res2 = ~res2;
+ if (res0 == 0)
+ res2++;
else
- Res0 = (~Res0) + 1;
+ res0 = (~res0) + 1;
}
- m_sh2_state->mach = Res2;
- m_sh2_state->macl = Res0;
+
+ m_sh2_state->mach = res2;
+ m_sh2_state->macl = res0;
m_sh2_state->icount--;
}
/* DMULU.L Rm,Rn */
void sh_common_execution::DMULU(uint32_t m, uint32_t n)
{
- uint32_t RnL, RnH, RmL, RmH, Res0, Res1, Res2;
- uint32_t temp0, temp1, temp2, temp3;
-
- RnL = m_sh2_state->r[n] & 0x0000ffff;
- RnH = (m_sh2_state->r[n] >> 16) & 0x0000ffff;
- RmL = m_sh2_state->r[m] & 0x0000ffff;
- RmH = (m_sh2_state->r[m] >> 16) & 0x0000ffff;
- temp0 = RmL * RnL;
- temp1 = RmH * RnL;
- temp2 = RmL * RnH;
- temp3 = RmH * RnH;
- Res2 = 0;
- Res1 = temp1 + temp2;
- if (Res1 < temp1)
- Res2 += 0x00010000;
- temp1 = (Res1 << 16) & 0xffff0000;
- Res0 = temp0 + temp1;
- if (Res0 < temp0)
- Res2++;
- Res2 = Res2 + ((Res1 >> 16) & 0x0000ffff) + temp3;
- m_sh2_state->mach = Res2;
- m_sh2_state->macl = Res0;
+ uint32_t rn_l = m_sh2_state->r[n] & 0x0000ffff;
+ uint32_t rn_h = m_sh2_state->r[n] >> 16;
+ uint32_t rm_l = m_sh2_state->r[m] & 0x0000ffff;
+ uint32_t rm_h = m_sh2_state->r[m] >> 16;
+
+ uint32_t temp0 = rm_l * rn_l;
+ uint32_t temp1 = rm_h * rn_l;
+ uint32_t temp2 = rm_l * rn_h;
+ uint32_t temp3 = rm_h * rn_h;
+
+ uint32_t res2 = 0;
+ uint32_t res1 = temp1 + temp2;
+ if (res1 < temp1)
+ res2 += 0x00010000;
+
+ temp1 = res1 << 16;
+ uint32_t res0 = temp0 + temp1;
+ if (res0 < temp0)
+ res2++;
+
+ res2 = res2 + (res1 >> 16) + temp3;
+
+ m_sh2_state->mach = res2;
+ m_sh2_state->macl = res0;
m_sh2_state->icount--;
}
@@ -717,7 +704,7 @@ void sh_common_execution::DT(uint32_t n)
m_sh2_state->sr &= ~SH_T;
#if BUSY_LOOP_HACKS
{
- uint32_t next_opcode = RW(m_sh2_state->pc & AM);
+ uint32_t next_opcode = read_word(m_sh2_state->pc & AM);
/* DT Rn
* BF $-2
*/
@@ -736,13 +723,13 @@ void sh_common_execution::DT(uint32_t n)
/* EXTS.B Rm,Rn */
void sh_common_execution::EXTSB(uint32_t m, uint32_t n)
{
- m_sh2_state->r[n] = ((int32_t)m_sh2_state->r[m] << 24) >> 24;
+ m_sh2_state->r[n] = util::sext(m_sh2_state->r[m], 8);
}
/* EXTS.W Rm,Rn */
void sh_common_execution::EXTSW(uint32_t m, uint32_t n)
{
- m_sh2_state->r[n] = ((int32_t)m_sh2_state->r[m] << 16) >> 16;
+ m_sh2_state->r[n] = util::sext(m_sh2_state->r[m], 16);
}
/* EXTU.B Rm,Rn */
@@ -788,7 +775,7 @@ void sh_common_execution::LDCVBR(uint32_t m)
void sh_common_execution::LDCMGBR(uint32_t m)
{
m_sh2_state->ea = m_sh2_state->r[m];
- m_sh2_state->gbr = RL( m_sh2_state->ea );
+ m_sh2_state->gbr = read_long(m_sh2_state->ea);
m_sh2_state->r[m] += 4;
m_sh2_state->icount -= 2;
}
@@ -797,7 +784,7 @@ void sh_common_execution::LDCMGBR(uint32_t m)
void sh_common_execution::LDCMVBR(uint32_t m)
{
m_sh2_state->ea = m_sh2_state->r[m];
- m_sh2_state->vbr = RL( m_sh2_state->ea );
+ m_sh2_state->vbr = read_long(m_sh2_state->ea);
m_sh2_state->r[m] += 4;
m_sh2_state->icount -= 2;
}
@@ -824,7 +811,7 @@ void sh_common_execution::LDSPR(uint32_t m)
void sh_common_execution::LDSMMACH(uint32_t m)
{
m_sh2_state->ea = m_sh2_state->r[m];
- m_sh2_state->mach = RL( m_sh2_state->ea );
+ m_sh2_state->mach = read_long(m_sh2_state->ea);
m_sh2_state->r[m] += 4;
}
@@ -832,7 +819,7 @@ void sh_common_execution::LDSMMACH(uint32_t m)
void sh_common_execution::LDSMMACL(uint32_t m)
{
m_sh2_state->ea = m_sh2_state->r[m];
- m_sh2_state->macl = RL( m_sh2_state->ea );
+ m_sh2_state->macl = read_long(m_sh2_state->ea);
m_sh2_state->r[m] += 4;
}
@@ -840,83 +827,83 @@ void sh_common_execution::LDSMMACL(uint32_t m)
void sh_common_execution::LDSMPR(uint32_t m)
{
m_sh2_state->ea = m_sh2_state->r[m];
- m_sh2_state->pr = RL( m_sh2_state->ea );
+ m_sh2_state->pr = read_long(m_sh2_state->ea);
m_sh2_state->r[m] += 4;
}
/* MAC.L @Rm+,@Rn+ */
void sh_common_execution::MAC_L(uint32_t m, uint32_t n)
{
- uint32_t RnL, RnH, RmL, RmH, Res0, Res1, Res2;
- uint32_t temp0, temp1, temp2, temp3;
- int32_t tempm, tempn, fnLmL;
-
- tempn = (int32_t) RL( m_sh2_state->r[n] );
+ int32_t tempn = (int32_t)read_long(m_sh2_state->r[n]);
m_sh2_state->r[n] += 4;
- tempm = (int32_t) RL( m_sh2_state->r[m] );
+
+ int32_t tempm = (int32_t)read_long(m_sh2_state->r[m]);
m_sh2_state->r[m] += 4;
- if ((int32_t) (tempn ^ tempm) < 0)
- fnLmL = -1;
- else
- fnLmL = 0;
+
+ bool fnlml = BIT(tempn ^ tempm, 31);
+
if (tempn < 0)
tempn = 0 - tempn;
if (tempm < 0)
tempm = 0 - tempm;
- temp1 = (uint32_t) tempn;
- temp2 = (uint32_t) tempm;
- RnL = temp1 & 0x0000ffff;
- RnH = (temp1 >> 16) & 0x0000ffff;
- RmL = temp2 & 0x0000ffff;
- RmH = (temp2 >> 16) & 0x0000ffff;
- temp0 = RmL * RnL;
- temp1 = RmH * RnL;
- temp2 = RmL * RnH;
- temp3 = RmH * RnH;
- Res2 = 0;
- Res1 = temp1 + temp2;
- if (Res1 < temp1)
- Res2 += 0x00010000;
- temp1 = (Res1 << 16) & 0xffff0000;
- Res0 = temp0 + temp1;
- if (Res0 < temp0)
- Res2++;
- Res2 = Res2 + ((Res1 >> 16) & 0x0000ffff) + temp3;
- if (fnLmL < 0)
+
+ uint32_t rn_l = (uint32_t)tempn & 0x0000ffff;
+ uint32_t rn_h = (uint32_t)tempn >> 16;
+ uint32_t rm_l = (uint32_t)tempm & 0x0000ffff;
+ uint32_t rm_h = (uint32_t)tempm >> 16;
+
+ uint32_t temp0 = rm_l * rn_l;
+ uint32_t temp1 = rm_h * rn_l;
+ uint32_t temp2 = rm_l * rn_h;
+ uint32_t temp3 = rm_h * rn_h;
+
+ uint32_t res2 = 0;
+ uint32_t res1 = temp1 + temp2;
+ if (res1 < temp1)
+ res2 += 0x00010000;
+ temp1 = res1 << 16;
+
+ uint32_t res0 = temp0 + temp1;
+ if (res0 < temp0)
+ res2++;
+ res2 = res2 + (res1 >> 16) + temp3;
+
+ if (fnlml)
{
- Res2 = ~Res2;
- if (Res0 == 0)
- Res2++;
+ res2 = ~res2;
+ if (res0 == 0)
+ res2++;
else
- Res0 = (~Res0) + 1;
+ res0 = (~res0) + 1;
}
+
if (m_sh2_state->sr & SH_S)
{
- Res0 = m_sh2_state->macl + Res0;
- if (m_sh2_state->macl > Res0)
- Res2++;
- Res2 += (m_sh2_state->mach & 0x0000ffff);
- if (((int32_t) Res2 < 0) && (Res2 < 0xffff8000))
+ res0 = m_sh2_state->macl + res0;
+ if (m_sh2_state->macl > res0)
+ res2++;
+ res2 += m_sh2_state->mach & 0x0000ffff;
+ if ((int32_t)res2 < 0 && res2 < 0xffff8000)
{
- Res2 = 0x00008000;
- Res0 = 0x00000000;
+ res2 = 0x00008000;
+ res0 = 0x00000000;
}
- else if (((int32_t) Res2 > 0) && (Res2 > 0x00007fff))
+ else if ((int32_t)res2 > 0 && res2 > 0x00007fff)
{
- Res2 = 0x00007fff;
- Res0 = 0xffffffff;
+ res2 = 0x00007fff;
+ res0 = 0xffffffff;
}
- m_sh2_state->mach = Res2;
- m_sh2_state->macl = Res0;
+ m_sh2_state->mach = res2;
+ m_sh2_state->macl = res0;
}
else
{
- Res0 = m_sh2_state->macl + Res0;
- if (m_sh2_state->macl > Res0)
- Res2++;
- Res2 += m_sh2_state->mach;
- m_sh2_state->mach = Res2;
- m_sh2_state->macl = Res0;
+ res0 = m_sh2_state->macl + res0;
+ if (m_sh2_state->macl > res0)
+ res2++;
+ res2 += m_sh2_state->mach;
+ m_sh2_state->mach = res2;
+ m_sh2_state->macl = res0;
}
m_sh2_state->icount -= 2;
}
@@ -924,45 +911,32 @@ void sh_common_execution::MAC_L(uint32_t m, uint32_t n)
/* MAC.W @Rm+,@Rn+ */
void sh_common_execution::MAC_W(uint32_t m, uint32_t n)
{
- int32_t tempm, tempn, dest, src, ans;
- uint32_t templ;
-
- tempn = (int32_t) RW( m_sh2_state->r[n] );
+ int32_t tempn = (int32_t)(int16_t)read_word(m_sh2_state->r[n]);
m_sh2_state->r[n] += 2;
- tempm = (int32_t) RW( m_sh2_state->r[m] );
+
+ int32_t tempm = (int32_t)(int16_t)read_word(m_sh2_state->r[m]);
m_sh2_state->r[m] += 2;
- templ = m_sh2_state->macl;
- tempm = ((int32_t) (short) tempn * (int32_t) (short) tempm);
- if ((int32_t) m_sh2_state->macl >= 0)
- dest = 0;
- else
- dest = 1;
- if ((int32_t) tempm >= 0)
- {
- src = 0;
- tempn = 0;
- }
- else
- {
- src = 1;
- tempn = 0xffffffff;
- }
- src += dest;
+
+ uint32_t templ = m_sh2_state->macl;
+ tempm *= tempn;
+
+ int32_t dest = BIT(m_sh2_state->macl, 31);
+ int32_t src = BIT(tempm, 31) + dest;
+ tempn = BIT(tempm, 31) ? -1 : 0;
+
m_sh2_state->macl += tempm;
- if ((int32_t) m_sh2_state->macl >= 0)
- ans = 0;
- else
- ans = 1;
- ans += dest;
+
+ int32_t ans = BIT(m_sh2_state->macl, 31) + dest;
+
if (m_sh2_state->sr & SH_S)
{
if (ans == 1)
- {
- if (src == 0)
- m_sh2_state->macl = 0x7fffffff;
- if (src == 2)
- m_sh2_state->macl = 0x80000000;
- }
+ {
+ if (src == 0)
+ m_sh2_state->macl = 0x7fffffff;
+ else if (src == 2)
+ m_sh2_state->macl = 0x80000000;
+ }
}
else
{
@@ -983,61 +957,60 @@ void sh_common_execution::MOV(uint32_t m, uint32_t n)
void sh_common_execution::MOVBS(uint32_t m, uint32_t n)
{
m_sh2_state->ea = m_sh2_state->r[n];
- WB( m_sh2_state->ea, m_sh2_state->r[m] & 0x000000ff);
+ write_byte(m_sh2_state->ea, m_sh2_state->r[m] & 0x000000ff);
}
/* MOV.W Rm,@Rn */
void sh_common_execution::MOVWS(uint32_t m, uint32_t n)
{
m_sh2_state->ea = m_sh2_state->r[n];
- WW( m_sh2_state->ea, m_sh2_state->r[m] & 0x0000ffff);
+ write_word(m_sh2_state->ea, m_sh2_state->r[m] & 0x0000ffff);
}
/* MOV.L Rm,@Rn */
void sh_common_execution::MOVLS(uint32_t m, uint32_t n)
{
m_sh2_state->ea = m_sh2_state->r[n];
- WL( m_sh2_state->ea, m_sh2_state->r[m] );
+ write_long(m_sh2_state->ea, m_sh2_state->r[m]);
}
/* MOV.B @Rm,Rn */
void sh_common_execution::MOVBL(uint32_t m, uint32_t n)
{
m_sh2_state->ea = m_sh2_state->r[m];
- m_sh2_state->r[n] = (uint32_t)(int32_t)(int16_t)(int8_t) RB( m_sh2_state->ea );
+ m_sh2_state->r[n] = (uint32_t)util::sext(read_byte(m_sh2_state->ea), 8);
}
/* MOV.W @Rm,Rn */
void sh_common_execution::MOVWL(uint32_t m, uint32_t n)
{
m_sh2_state->ea = m_sh2_state->r[m];
- m_sh2_state->r[n] = (uint32_t)(int32_t)(int16_t) RW( m_sh2_state->ea );
+ m_sh2_state->r[n] = (uint32_t)util::sext(read_word(m_sh2_state->ea), 16);
}
/* MOV.L @Rm,Rn */
void sh_common_execution::MOVLL(uint32_t m, uint32_t n)
{
m_sh2_state->ea = m_sh2_state->r[m];
- m_sh2_state->r[n] = RL( m_sh2_state->ea );
+ m_sh2_state->r[n] = read_long(m_sh2_state->ea);
}
/* MOV.B Rm,@-Rn */
void sh_common_execution::MOVBM(uint32_t m, uint32_t n)
{
- /* SMG : bug fix, was reading m_sh2_state->r[n] */
- uint32_t data = m_sh2_state->r[m] & 0x000000ff;
+ uint8_t data(m_sh2_state->r[m]);
m_sh2_state->r[n] -= 1;
- WB( m_sh2_state->r[n], data );
+ write_byte(m_sh2_state->r[n], data);
}
/* MOV.W Rm,@-Rn */
void sh_common_execution::MOVWM(uint32_t m, uint32_t n)
{
- uint32_t data = m_sh2_state->r[m] & 0x0000ffff;
+ uint16_t data(m_sh2_state->r[m]);
m_sh2_state->r[n] -= 2;
- WW( m_sh2_state->r[n], data );
+ write_word(m_sh2_state->r[n], data);
}
/* MOV.L Rm,@-Rn */
@@ -1046,13 +1019,13 @@ void sh_common_execution::MOVLM(uint32_t m, uint32_t n)
uint32_t data = m_sh2_state->r[m];
m_sh2_state->r[n] -= 4;
- WL( m_sh2_state->r[n], data );
+ write_long(m_sh2_state->r[n], data);
}
/* MOV.B @Rm+,Rn */
void sh_common_execution::MOVBP(uint32_t m, uint32_t n)
{
- m_sh2_state->r[n] = (uint32_t)(int32_t)(int16_t)(int8_t) RB( m_sh2_state->r[m] );
+ m_sh2_state->r[n] = (uint32_t)util::sext(read_byte(m_sh2_state->r[m]), 8);
if (n != m)
m_sh2_state->r[m] += 1;
}
@@ -1060,7 +1033,7 @@ void sh_common_execution::MOVBP(uint32_t m, uint32_t n)
/* MOV.W @Rm+,Rn */
void sh_common_execution::MOVWP(uint32_t m, uint32_t n)
{
- m_sh2_state->r[n] = (uint32_t)(int32_t)(int16_t) RW( m_sh2_state->r[m] );
+ m_sh2_state->r[n] = (uint32_t)util::sext(read_word(m_sh2_state->r[m]), 16);
if (n != m)
m_sh2_state->r[m] += 2;
}
@@ -1068,7 +1041,7 @@ void sh_common_execution::MOVWP(uint32_t m, uint32_t n)
/* MOV.L @Rm+,Rn */
void sh_common_execution::MOVLP(uint32_t m, uint32_t n)
{
- m_sh2_state->r[n] = RL( m_sh2_state->r[m] );
+ m_sh2_state->r[n] = read_long(m_sh2_state->r[m]);
if (n != m)
m_sh2_state->r[m] += 4;
}
@@ -1077,48 +1050,48 @@ void sh_common_execution::MOVLP(uint32_t m, uint32_t n)
void sh_common_execution::MOVBS0(uint32_t m, uint32_t n)
{
m_sh2_state->ea = m_sh2_state->r[n] + m_sh2_state->r[0];
- WB( m_sh2_state->ea, m_sh2_state->r[m] & 0x000000ff );
+ write_byte(m_sh2_state->ea, (uint8_t)m_sh2_state->r[m]);
}
/* MOV.W Rm,@(R0,Rn) */
void sh_common_execution::MOVWS0(uint32_t m, uint32_t n)
{
m_sh2_state->ea = m_sh2_state->r[n] + m_sh2_state->r[0];
- WW( m_sh2_state->ea, m_sh2_state->r[m] & 0x0000ffff );
+ write_word(m_sh2_state->ea, (uint16_t)m_sh2_state->r[m]);
}
/* MOV.L Rm,@(R0,Rn) */
void sh_common_execution::MOVLS0(uint32_t m, uint32_t n)
{
m_sh2_state->ea = m_sh2_state->r[n] + m_sh2_state->r[0];
- WL( m_sh2_state->ea, m_sh2_state->r[m] );
+ write_long(m_sh2_state->ea, m_sh2_state->r[m]);
}
/* MOV.B @(R0,Rm),Rn */
void sh_common_execution::MOVBL0(uint32_t m, uint32_t n)
{
m_sh2_state->ea = m_sh2_state->r[m] + m_sh2_state->r[0];
- m_sh2_state->r[n] = (uint32_t)(int32_t)(int16_t)(int8_t) RB( m_sh2_state->ea );
+ m_sh2_state->r[n] = (uint32_t)util::sext(read_byte(m_sh2_state->ea), 8);
}
/* MOV.W @(R0,Rm),Rn */
void sh_common_execution::MOVWL0(uint32_t m, uint32_t n)
{
m_sh2_state->ea = m_sh2_state->r[m] + m_sh2_state->r[0];
- m_sh2_state->r[n] = (uint32_t)(int32_t)(int16_t) RW( m_sh2_state->ea );
+ m_sh2_state->r[n] = (uint32_t)util::sext(read_word(m_sh2_state->ea), 16);
}
/* MOV.L @(R0,Rm),Rn */
void sh_common_execution::MOVLL0(uint32_t m, uint32_t n)
{
m_sh2_state->ea = m_sh2_state->r[m] + m_sh2_state->r[0];
- m_sh2_state->r[n] = RL( m_sh2_state->ea );
+ m_sh2_state->r[n] = read_long(m_sh2_state->ea);
}
/* MOV #imm,Rn */
void sh_common_execution::MOVI(uint32_t i, uint32_t n)
{
- m_sh2_state->r[n] = (uint32_t)(int32_t)(int16_t)(int8_t) i;
+ m_sh2_state->r[n] = (uint32_t)util::sext(i, 8);
}
/* MOV.W @(disp8,PC),Rn */
@@ -1126,7 +1099,7 @@ void sh_common_execution::MOVWI(uint32_t d, uint32_t n)
{
uint32_t disp = d & 0xff;
m_sh2_state->ea = m_sh2_state->pc + disp * 2 + 2;
- m_sh2_state->r[n] = (uint32_t)(int32_t)(int16_t) RW( m_sh2_state->ea );
+ m_sh2_state->r[n] = (uint32_t)util::sext(read_word(m_sh2_state->ea), 16);
}
/* MOV.L @(disp8,PC),Rn */
@@ -1134,7 +1107,7 @@ void sh_common_execution::MOVLI(uint32_t d, uint32_t n)
{
uint32_t disp = d & 0xff;
m_sh2_state->ea = ((m_sh2_state->pc + 2) & ~3) + disp * 4;
- m_sh2_state->r[n] = RL( m_sh2_state->ea );
+ m_sh2_state->r[n] = read_long(m_sh2_state->ea);
}
/* MOV.B @(disp8,GBR),R0 */
@@ -1142,7 +1115,7 @@ void sh_common_execution::MOVBLG(uint32_t d)
{
uint32_t disp = d & 0xff;
m_sh2_state->ea = m_sh2_state->gbr + disp;
- m_sh2_state->r[0] = (uint32_t)(int32_t)(int16_t)(int8_t) RB( m_sh2_state->ea );
+ m_sh2_state->r[0] = (uint32_t)util::sext(read_byte(m_sh2_state->ea), 8);
}
/* MOV.W @(disp8,GBR),R0 */
@@ -1150,7 +1123,7 @@ void sh_common_execution::MOVWLG(uint32_t d)
{
uint32_t disp = d & 0xff;
m_sh2_state->ea = m_sh2_state->gbr + disp * 2;
- m_sh2_state->r[0] = (int32_t)(int16_t) RW( m_sh2_state->ea );
+ m_sh2_state->r[0] = (int32_t)util::sext(read_word(m_sh2_state->ea), 16);
}
/* MOV.L @(disp8,GBR),R0 */
@@ -1158,7 +1131,7 @@ void sh_common_execution::MOVLLG(uint32_t d)
{
uint32_t disp = d & 0xff;
m_sh2_state->ea = m_sh2_state->gbr + disp * 4;
- m_sh2_state->r[0] = RL( m_sh2_state->ea );
+ m_sh2_state->r[0] = read_long(m_sh2_state->ea);
}
/* MOV.B R0,@(disp8,GBR) */
@@ -1166,7 +1139,7 @@ void sh_common_execution::MOVBSG(uint32_t d)
{
uint32_t disp = d & 0xff;
m_sh2_state->ea = m_sh2_state->gbr + disp;
- WB( m_sh2_state->ea, m_sh2_state->r[0] & 0x000000ff );
+ write_byte(m_sh2_state->ea, (uint8_t)m_sh2_state->r[0]);
}
/* MOV.W R0,@(disp8,GBR) */
@@ -1174,7 +1147,7 @@ void sh_common_execution::MOVWSG(uint32_t d)
{
uint32_t disp = d & 0xff;
m_sh2_state->ea = m_sh2_state->gbr + disp * 2;
- WW( m_sh2_state->ea, m_sh2_state->r[0] & 0x0000ffff );
+ write_word(m_sh2_state->ea, (uint16_t)m_sh2_state->r[0]);
}
/* MOV.L R0,@(disp8,GBR) */
@@ -1182,7 +1155,7 @@ void sh_common_execution::MOVLSG(uint32_t d)
{
uint32_t disp = d & 0xff;
m_sh2_state->ea = m_sh2_state->gbr + disp * 4;
- WL( m_sh2_state->ea, m_sh2_state->r[0] );
+ write_long(m_sh2_state->ea, m_sh2_state->r[0]);
}
/* MOV.B R0,@(disp4,Rn) */
@@ -1190,7 +1163,7 @@ void sh_common_execution::MOVBS4(uint32_t d, uint32_t n)
{
uint32_t disp = d & 0x0f;
m_sh2_state->ea = m_sh2_state->r[n] + disp;
- WB( m_sh2_state->ea, m_sh2_state->r[0] & 0x000000ff );
+ write_byte(m_sh2_state->ea, (uint8_t)m_sh2_state->r[0]);
}
/* MOV.W R0,@(disp4,Rn) */
@@ -1198,7 +1171,7 @@ void sh_common_execution::MOVWS4(uint32_t d, uint32_t n)
{
uint32_t disp = d & 0x0f;
m_sh2_state->ea = m_sh2_state->r[n] + disp * 2;
- WW( m_sh2_state->ea, m_sh2_state->r[0] & 0x0000ffff );
+ write_word(m_sh2_state->ea, (uint16_t)m_sh2_state->r[0]);
}
/* MOV.L Rm,@(disp4,Rn) */
@@ -1206,7 +1179,7 @@ void sh_common_execution::MOVLS4(uint32_t m, uint32_t d, uint32_t n)
{
uint32_t disp = d & 0x0f;
m_sh2_state->ea = m_sh2_state->r[n] + disp * 4;
- WL( m_sh2_state->ea, m_sh2_state->r[m] );
+ write_long(m_sh2_state->ea, m_sh2_state->r[m]);
}
/* MOV.B @(disp4,Rm),R0 */
@@ -1214,7 +1187,7 @@ void sh_common_execution::MOVBL4(uint32_t m, uint32_t d)
{
uint32_t disp = d & 0x0f;
m_sh2_state->ea = m_sh2_state->r[m] + disp;
- m_sh2_state->r[0] = (uint32_t)(int32_t)(int16_t)(int8_t) RB( m_sh2_state->ea );
+ m_sh2_state->r[0] = (uint32_t)util::sext(read_byte(m_sh2_state->ea), 8);
}
/* MOV.W @(disp4,Rm),R0 */
@@ -1222,7 +1195,7 @@ void sh_common_execution::MOVWL4(uint32_t m, uint32_t d)
{
uint32_t disp = d & 0x0f;
m_sh2_state->ea = m_sh2_state->r[m] + disp * 2;
- m_sh2_state->r[0] = (uint32_t)(int32_t)(int16_t) RW( m_sh2_state->ea );
+ m_sh2_state->r[0] = (uint32_t)util::sext(read_word(m_sh2_state->ea), 16);
}
/* MOV.L @(disp4,Rm),Rn */
@@ -1230,7 +1203,7 @@ void sh_common_execution::MOVLL4(uint32_t m, uint32_t d, uint32_t n)
{
uint32_t disp = d & 0x0f;
m_sh2_state->ea = m_sh2_state->r[m] + disp * 4;
- m_sh2_state->r[n] = RL( m_sh2_state->ea );
+ m_sh2_state->r[n] = read_long(m_sh2_state->ea);
}
/* MOVA @(disp8,PC),R0 */
@@ -1257,13 +1230,13 @@ void sh_common_execution::MULL(uint32_t m, uint32_t n)
/* MULS Rm,Rn */
void sh_common_execution::MULS(uint32_t m, uint32_t n)
{
- m_sh2_state->macl = (int16_t) m_sh2_state->r[n] * (int16_t) m_sh2_state->r[m];
+ m_sh2_state->macl = (int16_t)m_sh2_state->r[n] * (int16_t)m_sh2_state->r[m];
}
/* MULU Rm,Rn */
void sh_common_execution::MULU(uint32_t m, uint32_t n)
{
- m_sh2_state->macl = (uint16_t) m_sh2_state->r[n] * (uint16_t) m_sh2_state->r[m];
+ m_sh2_state->macl = (uint16_t)m_sh2_state->r[n] * (uint16_t)m_sh2_state->r[m];
}
/* NEG Rm,Rn */
@@ -1275,9 +1248,7 @@ void sh_common_execution::NEG(uint32_t m, uint32_t n)
/* NEGC Rm,Rn */
void sh_common_execution::NEGC(uint32_t m, uint32_t n)
{
- uint32_t temp;
-
- temp = m_sh2_state->r[m];
+ uint32_t temp = m_sh2_state->r[m];
m_sh2_state->r[n] = -temp - (m_sh2_state->sr & SH_T);
if (temp || (m_sh2_state->sr & SH_T))
m_sh2_state->sr |= SH_T;
@@ -1306,27 +1277,20 @@ void sh_common_execution::OR(uint32_t m, uint32_t n)
void sh_common_execution::ORI(uint32_t i)
{
m_sh2_state->r[0] |= i;
- m_sh2_state->icount -= 2; // not in SH2 implementation?
+ m_sh2_state->icount -= 2;
}
/* OR.B #imm,@(R0,GBR) */
void sh_common_execution::ORM(uint32_t i)
{
- uint32_t temp;
-
m_sh2_state->ea = m_sh2_state->gbr + m_sh2_state->r[0];
- temp = RB( m_sh2_state->ea );
- temp |= i;
- WB( m_sh2_state->ea, temp );
- //m_sh2_state->icount -= 2; // not in SH4 implementation?
+ write_byte(m_sh2_state->ea, read_byte(m_sh2_state->ea) | (uint8_t)i);
}
/* ROTCL Rn */
void sh_common_execution::ROTCL(uint32_t n)
{
- uint32_t temp;
-
- temp = (m_sh2_state->r[n] >> 31) & SH_T;
+ uint32_t temp = (m_sh2_state->r[n] >> 31) & SH_T;
m_sh2_state->r[n] = (m_sh2_state->r[n] << 1) | (m_sh2_state->sr & SH_T);
m_sh2_state->sr = (m_sh2_state->sr & ~SH_T) | temp;
}
@@ -1334,8 +1298,7 @@ void sh_common_execution::ROTCL(uint32_t n)
/* ROTCR Rn */
void sh_common_execution::ROTCR(uint32_t n)
{
- uint32_t temp;
- temp = (m_sh2_state->sr & SH_T) << 31;
+ uint32_t temp = (m_sh2_state->sr & SH_T) << 31;
if (m_sh2_state->r[n] & SH_T)
m_sh2_state->sr |= SH_T;
else
@@ -1347,14 +1310,14 @@ void sh_common_execution::ROTCR(uint32_t n)
void sh_common_execution::ROTL(uint32_t n)
{
m_sh2_state->sr = (m_sh2_state->sr & ~SH_T) | ((m_sh2_state->r[n] >> 31) & SH_T);
- m_sh2_state->r[n] = (m_sh2_state->r[n] << 1) | (m_sh2_state->r[n] >> 31);
+ m_sh2_state->r[n] = rotl_32(m_sh2_state->r[n], 1);
}
/* ROTR Rn */
void sh_common_execution::ROTR(uint32_t n)
{
m_sh2_state->sr = (m_sh2_state->sr & ~SH_T) | (m_sh2_state->r[n] & SH_T);
- m_sh2_state->r[n] = (m_sh2_state->r[n] >> 1) | (m_sh2_state->r[n] << 31);
+ m_sh2_state->r[n] = rotr_32(m_sh2_state->r[n], 1);
}
/* RTS */
@@ -1458,7 +1421,7 @@ void sh_common_execution::STCMSR(uint32_t n)
{
m_sh2_state->r[n] -= 4;
m_sh2_state->ea = m_sh2_state->r[n];
- WL( m_sh2_state->ea, m_sh2_state->sr );
+ write_long(m_sh2_state->ea, m_sh2_state->sr);
m_sh2_state->icount--;
}
@@ -1467,7 +1430,7 @@ void sh_common_execution::STCMGBR(uint32_t n)
{
m_sh2_state->r[n] -= 4;
m_sh2_state->ea = m_sh2_state->r[n];
- WL( m_sh2_state->ea, m_sh2_state->gbr );
+ write_long(m_sh2_state->ea, m_sh2_state->gbr);
m_sh2_state->icount--;
}
@@ -1476,7 +1439,7 @@ void sh_common_execution::STCMVBR(uint32_t n)
{
m_sh2_state->r[n] -= 4;
m_sh2_state->ea = m_sh2_state->r[n];
- WL( m_sh2_state->ea, m_sh2_state->vbr );
+ write_long(m_sh2_state->ea, m_sh2_state->vbr);
m_sh2_state->icount--;
}
@@ -1503,7 +1466,7 @@ void sh_common_execution::STSMMACH(uint32_t n)
{
m_sh2_state->r[n] -= 4;
m_sh2_state->ea = m_sh2_state->r[n];
- WL( m_sh2_state->ea, m_sh2_state->mach );
+ write_long(m_sh2_state->ea, m_sh2_state->mach);
}
/* STS.L MACL,@-Rn */
@@ -1511,7 +1474,7 @@ void sh_common_execution::STSMMACL(uint32_t n)
{
m_sh2_state->r[n] -= 4;
m_sh2_state->ea = m_sh2_state->r[n];
- WL( m_sh2_state->ea, m_sh2_state->macl );
+ write_long(m_sh2_state->ea, m_sh2_state->macl);
}
/* STS.L PR,@-Rn */
@@ -1519,7 +1482,7 @@ void sh_common_execution::STSMPR(uint32_t n)
{
m_sh2_state->r[n] -= 4;
m_sh2_state->ea = m_sh2_state->r[n];
- WL( m_sh2_state->ea, m_sh2_state->pr );
+ write_long(m_sh2_state->ea, m_sh2_state->pr);
}
/* SUB Rm,Rn */
@@ -1531,10 +1494,8 @@ void sh_common_execution::SUB(uint32_t m, uint32_t n)
/* SUBC Rm,Rn */
void sh_common_execution::SUBC(uint32_t m, uint32_t n)
{
- uint32_t tmp0, tmp1;
-
- tmp1 = m_sh2_state->r[n] - m_sh2_state->r[m];
- tmp0 = m_sh2_state->r[n];
+ uint32_t tmp1 = m_sh2_state->r[n] - m_sh2_state->r[m];
+ uint32_t tmp0 = m_sh2_state->r[n];
m_sh2_state->r[n] = tmp1 - (m_sh2_state->sr & SH_T);
if (tmp0 < tmp1)
m_sh2_state->sr |= SH_T;
@@ -1547,30 +1508,17 @@ void sh_common_execution::SUBC(uint32_t m, uint32_t n)
/* SUBV Rm,Rn */
void sh_common_execution::SUBV(uint32_t m, uint32_t n)
{
- int32_t dest, src, ans;
-
- if ((int32_t) m_sh2_state->r[n] >= 0)
- dest = 0;
- else
- dest = 1;
- if ((int32_t) m_sh2_state->r[m] >= 0)
- src = 0;
- else
- src = 1;
+ int32_t dest = BIT(m_sh2_state->r[n], 31);
+ int32_t src = BIT(m_sh2_state->r[m], 31);
src += dest;
+
m_sh2_state->r[n] -= m_sh2_state->r[m];
- if ((int32_t) m_sh2_state->r[n] >= 0)
- ans = 0;
- else
- ans = 1;
+
+ int32_t ans = BIT(m_sh2_state->r[n], 31);
ans += dest;
- if (src == 1)
- {
- if (ans == 1)
- m_sh2_state->sr |= SH_T;
- else
- m_sh2_state->sr &= ~SH_T;
- }
+
+ if (src == 1 && ans == 1)
+ m_sh2_state->sr |= SH_T;
else
m_sh2_state->sr &= ~SH_T;
}
@@ -1578,37 +1526,33 @@ void sh_common_execution::SUBV(uint32_t m, uint32_t n)
/* SWAP.B Rm,Rn */
void sh_common_execution::SWAPB(uint32_t m, uint32_t n)
{
- uint32_t temp0, temp1;
-
- temp0 = m_sh2_state->r[m] & 0xffff0000;
- temp1 = (m_sh2_state->r[m] & 0x000000ff) << 8;
- m_sh2_state->r[n] = (m_sh2_state->r[m] >> 8) & 0x000000ff;
- m_sh2_state->r[n] = m_sh2_state->r[n] | temp1 | temp0;
+ uint32_t temp = m_sh2_state->r[m] & 0xffff0000;
+ temp |= (m_sh2_state->r[m] & 0x000000ff) << 8;
+ m_sh2_state->r[n] = (uint8_t)(m_sh2_state->r[m] >> 8);
+ m_sh2_state->r[n] = m_sh2_state->r[n] | temp;
}
/* SWAP.W Rm,Rn */
void sh_common_execution::SWAPW(uint32_t m, uint32_t n)
{
- uint32_t temp;
-
- temp = (m_sh2_state->r[m] >> 16) & 0x0000ffff;
+ uint32_t temp = m_sh2_state->r[m] >> 16;
m_sh2_state->r[n] = (m_sh2_state->r[m] << 16) | temp;
}
/* TAS.B @Rn */
void sh_common_execution::TAS(uint32_t n)
{
- uint32_t temp;
m_sh2_state->ea = m_sh2_state->r[n];
+
/* Bus Lock enable */
- temp = RB( m_sh2_state->ea );
+ uint32_t temp = read_byte(m_sh2_state->ea);
if (temp == 0)
m_sh2_state->sr |= SH_T;
else
m_sh2_state->sr &= ~SH_T;
temp |= 0x80;
/* Bus Lock disable */
- WB( m_sh2_state->ea, temp );
+ write_byte(m_sh2_state->ea, temp);
m_sh2_state->icount -= 3;
}
@@ -1638,7 +1582,7 @@ void sh_common_execution::TSTM(uint32_t i)
uint32_t imm = i & 0xff;
m_sh2_state->ea = m_sh2_state->gbr + m_sh2_state->r[0];
- if ((imm & RB( m_sh2_state->ea )) == 0)
+ if ((imm & read_byte(m_sh2_state->ea)) == 0)
m_sh2_state->sr |= SH_T;
else
m_sh2_state->sr &= ~SH_T;
@@ -1654,31 +1598,21 @@ void sh_common_execution::XOR(uint32_t m, uint32_t n)
/* XOR #imm,R0 */
void sh_common_execution::XORI(uint32_t i)
{
- uint32_t imm = i & 0xff;
- m_sh2_state->r[0] ^= imm;
+ m_sh2_state->r[0] ^= i & 0x000000ff;
}
/* XOR.B #imm,@(R0,GBR) */
void sh_common_execution::XORM(uint32_t i)
{
- uint32_t imm = i & 0xff;
- uint32_t temp;
-
m_sh2_state->ea = m_sh2_state->gbr + m_sh2_state->r[0];
- temp = RB( m_sh2_state->ea );
- temp ^= imm;
- WB( m_sh2_state->ea, temp );
+ write_byte(m_sh2_state->ea, read_byte(m_sh2_state->ea) ^ (uint8_t)i);
m_sh2_state->icount -= 2;
}
/* XTRCT Rm,Rn */
void sh_common_execution::XTRCT(uint32_t m, uint32_t n)
{
- uint32_t temp;
-
- temp = (m_sh2_state->r[m] << 16) & 0xffff0000;
- m_sh2_state->r[n] = (m_sh2_state->r[n] >> 16) & 0x0000ffff;
- m_sh2_state->r[n] |= temp;
+ m_sh2_state->r[n] = (m_sh2_state->r[n] >> 16) | (m_sh2_state->r[m] << 16);
}
/* SLEEP */
@@ -1687,13 +1621,13 @@ void sh_common_execution::SLEEP()
/* 0 = normal mode */
/* 1 = enters into power-down mode */
/* 2 = go out the power-down mode after an exception */
- if(m_sh2_state->sleep_mode != 2)
+ if (m_sh2_state->sleep_mode != 2)
m_sh2_state->pc -= 2;
m_sh2_state->icount -= 2;
/* Wait_for_exception; */
- if(m_sh2_state->sleep_mode == 0)
+ if (m_sh2_state->sleep_mode == 0)
m_sh2_state->sleep_mode = 1;
- else if(m_sh2_state->sleep_mode == 2)
+ else if (m_sh2_state->sleep_mode == 2)
m_sh2_state->sleep_mode = 0;
}
@@ -1703,22 +1637,22 @@ void sh_common_execution::op0010(uint16_t opcode)
{
switch (opcode & 15)
{
- case 0: MOVBS(Rm, Rn); break;
- case 1: MOVWS(Rm, Rn); break;
- case 2: MOVLS(Rm, Rn); break;
- case 3: ILLEGAL(); break;
- case 4: MOVBM(Rm, Rn); break;
- case 5: MOVWM(Rm, Rn); break;
- case 6: MOVLM(Rm, Rn); break;
- case 7: DIV0S(Rm, Rn); break;
- case 8: TST(Rm, Rn); break;
- case 9: AND(Rm, Rn); break;
- case 10: XOR(Rm, Rn); break;
- case 11: OR(Rm, Rn); break;
- case 12: CMPSTR(Rm, Rn); break;
- case 13: XTRCT(Rm, Rn); break;
- case 14: MULU(Rm, Rn); break;
- case 15: MULS(Rm, Rn); break;
+ case 0: MOVBS(REG_M, REG_N); break;
+ case 1: MOVWS(REG_M, REG_N); break;
+ case 2: MOVLS(REG_M, REG_N); break;
+ case 3: ILLEGAL(); break;
+ case 4: MOVBM(REG_M, REG_N); break;
+ case 5: MOVWM(REG_M, REG_N); break;
+ case 6: MOVLM(REG_M, REG_N); break;
+ case 7: DIV0S(REG_M, REG_N); break;
+ case 8: TST(REG_M, REG_N); break;
+ case 9: AND(REG_M, REG_N); break;
+ case 10: XOR(REG_M, REG_N); break;
+ case 11: OR(REG_M, REG_N); break;
+ case 12: CMPSTR(REG_M, REG_N); break;
+ case 13: XTRCT(REG_M, REG_N); break;
+ case 14: MULU(REG_M, REG_N); break;
+ case 15: MULS(REG_M, REG_N); break;
}
}
@@ -1726,22 +1660,22 @@ void sh_common_execution::op0011(uint16_t opcode)
{
switch (opcode & 15)
{
- case 0: CMPEQ(Rm, Rn); break;
- case 1: ILLEGAL(); break;
- case 2: CMPHS(Rm, Rn); break;
- case 3: CMPGE(Rm, Rn); break;
- case 4: DIV1(Rm, Rn); break;
- case 5: DMULU(Rm, Rn); break;
- case 6: CMPHI(Rm, Rn); break;
- case 7: CMPGT(Rm, Rn); break;
- case 8: SUB(Rm, Rn); break;
- case 9: ILLEGAL(); break;
- case 10: SUBC(Rm, Rn); break;
- case 11: SUBV(Rm, Rn); break;
- case 12: ADD(Rm, Rn); break;
- case 13: DMULS(Rm, Rn); break;
- case 14: ADDC(Rm, Rn); break;
- case 15: ADDV(Rm, Rn); break;
+ case 0: CMPEQ(REG_M, REG_N); break;
+ case 1: ILLEGAL(); break;
+ case 2: CMPHS(REG_M, REG_N); break;
+ case 3: CMPGE(REG_M, REG_N); break;
+ case 4: DIV1(REG_M, REG_N); break;
+ case 5: DMULU(REG_M, REG_N); break;
+ case 6: CMPHI(REG_M, REG_N); break;
+ case 7: CMPGT(REG_M, REG_N); break;
+ case 8: SUB(REG_M, REG_N); break;
+ case 9: ILLEGAL(); break;
+ case 10: SUBC(REG_M, REG_N); break;
+ case 11: SUBV(REG_M, REG_N); break;
+ case 12: ADD(REG_M, REG_N); break;
+ case 13: DMULS(REG_M, REG_N); break;
+ case 14: ADDC(REG_M, REG_N); break;
+ case 15: ADDV(REG_M, REG_N); break;
}
}
@@ -1749,69 +1683,69 @@ void sh_common_execution::op0110(uint16_t opcode)
{
switch (opcode & 15)
{
- case 0: MOVBL(Rm, Rn); break;
- case 1: MOVWL(Rm, Rn); break;
- case 2: MOVLL(Rm, Rn); break;
- case 3: MOV(Rm, Rn); break;
- case 4: MOVBP(Rm, Rn); break;
- case 5: MOVWP(Rm, Rn); break;
- case 6: MOVLP(Rm, Rn); break;
- case 7: NOT(Rm, Rn); break;
- case 8: SWAPB(Rm, Rn); break;
- case 9: SWAPW(Rm, Rn); break;
- case 10: NEGC(Rm, Rn); break;
- case 11: NEG(Rm, Rn); break;
- case 12: EXTUB(Rm, Rn); break;
- case 13: EXTUW(Rm, Rn); break;
- case 14: EXTSB(Rm, Rn); break;
- case 15: EXTSW(Rm, Rn); break;
+ case 0: MOVBL(REG_M, REG_N); break;
+ case 1: MOVWL(REG_M, REG_N); break;
+ case 2: MOVLL(REG_M, REG_N); break;
+ case 3: MOV(REG_M, REG_N); break;
+ case 4: MOVBP(REG_M, REG_N); break;
+ case 5: MOVWP(REG_M, REG_N); break;
+ case 6: MOVLP(REG_M, REG_N); break;
+ case 7: NOT(REG_M, REG_N); break;
+ case 8: SWAPB(REG_M, REG_N); break;
+ case 9: SWAPW(REG_M, REG_N); break;
+ case 10: NEGC(REG_M, REG_N); break;
+ case 11: NEG(REG_M, REG_N); break;
+ case 12: EXTUB(REG_M, REG_N); break;
+ case 13: EXTUW(REG_M, REG_N); break;
+ case 14: EXTSB(REG_M, REG_N); break;
+ case 15: EXTSW(REG_M, REG_N); break;
}
}
void sh_common_execution::op1000(uint16_t opcode)
{
- switch ( opcode & (15<<8) )
+ switch ((opcode >> 8) & 15)
{
- case 0 << 8: MOVBS4(opcode & 0x0f, Rm); break;
- case 1 << 8: MOVWS4(opcode & 0x0f, Rm); break;
- case 2<< 8: ILLEGAL(); break;
- case 3<< 8: ILLEGAL(); break;
- case 4<< 8: MOVBL4(Rm, opcode & 0x0f); break;
- case 5<< 8: MOVWL4(Rm, opcode & 0x0f); break;
- case 6<< 8: ILLEGAL(); break;
- case 7<< 8: ILLEGAL(); break;
- case 8<< 8: CMPIM(opcode & 0xff); break;
- case 9<< 8: BT(opcode & 0xff); break;
- case 10<< 8: ILLEGAL(); break;
- case 11<< 8: BF(opcode & 0xff); break;
- case 12<< 8: ILLEGAL(); break;
- case 13<< 8: BTS(opcode & 0xff); break;
- case 14<< 8: ILLEGAL(); break;
- case 15<< 8: BFS(opcode & 0xff); break;
+ case 0: MOVBS4(opcode & 0x0f, REG_M); break;
+ case 1: MOVWS4(opcode & 0x0f, REG_M); break;
+ case 2: ILLEGAL(); break;
+ case 3: ILLEGAL(); break;
+ case 4: MOVBL4(REG_M, opcode & 0x0f); break;
+ case 5: MOVWL4(REG_M, opcode & 0x0f); break;
+ case 6: ILLEGAL(); break;
+ case 7: ILLEGAL(); break;
+ case 8: CMPIM(opcode & 0xff); break;
+ case 9: BT(opcode & 0xff); break;
+ case 10: ILLEGAL(); break;
+ case 11: BF(opcode & 0xff); break;
+ case 12: ILLEGAL(); break;
+ case 13: BTS(opcode & 0xff); break;
+ case 14: ILLEGAL(); break;
+ case 15: BFS(opcode & 0xff); break;
}
}
void sh_common_execution::op1100(uint16_t opcode)
{
- switch (opcode & (15<<8))
+ switch ((opcode >> 8) & 15)
{
- case 0<<8: MOVBSG(opcode & 0xff); break;
- case 1<<8: MOVWSG(opcode & 0xff); break;
- case 2<<8: MOVLSG(opcode & 0xff); break;
- case 3<<8: TRAPA(opcode & 0xff); break; // sh2/4 differ
- case 4<<8: MOVBLG(opcode & 0xff); break;
- case 5<<8: MOVWLG(opcode & 0xff); break;
- case 6<<8: MOVLLG(opcode & 0xff); break;
- case 7<<8: MOVA(opcode & 0xff); break;
- case 8<<8: TSTI(opcode & 0xff); break;
- case 9<<8: ANDI(opcode & 0xff); break;
- case 10<<8: XORI(opcode & 0xff); break;
- case 11<<8: ORI(opcode & 0xff); break;
- case 12<<8: TSTM(opcode & 0xff); break;
- case 13<<8: ANDM(opcode & 0xff); break;
- case 14<<8: XORM(opcode & 0xff); break;
- case 15<<8: ORM(opcode & 0xff); break;
+ case 0: MOVBSG(opcode & 0xff); break;
+ case 1: MOVWSG(opcode & 0xff); break;
+ case 2: MOVLSG(opcode & 0xff); break;
+ case 3: TRAPA(opcode & 0xff); break; // sh2/4 differ
+ case 4: MOVBLG(opcode & 0xff); break;
+ case 5: MOVWLG(opcode & 0xff); break;
+ case 6: MOVLLG(opcode & 0xff); break;
+ case 7: MOVA(opcode & 0xff); break;
+ case 8: TSTI(opcode & 0xff); break;
+ case 9: ANDI(opcode & 0xff); break;
+ case 10: XORI(opcode & 0xff); break;
+ case 11: ORI(opcode & 0xff); break;
+ case 12: TSTM(opcode & 0xff); break;
+ case 13: ANDM(opcode & 0xff); break;
+ case 14: XORM(opcode & 0xff); break;
+ case 15: ORM(opcode & 0xff); break;
}
}
@@ -1820,75 +1754,75 @@ void sh_common_execution::execute_one_0000(uint16_t opcode)
{
// 04,05,06,07 always the same, 0c,0d,0e,0f always the same, other change based on upper bits
- switch (opcode & 0x3F)
+ switch (opcode & 0x3f)
{
- case 0x00: ILLEGAL(); break;
- case 0x01: ILLEGAL(); break;
- case 0x02: STCSR(Rn); break;
- case 0x03: BSRF(Rn); break;
- case 0x04: MOVBS0(Rm, Rn); break;
- case 0x05: MOVWS0(Rm, Rn); break;
- case 0x06: MOVLS0(Rm, Rn); break;
- case 0x07: MULL(Rm, Rn); break;
- case 0x08: CLRT(); break;
- case 0x09: NOP(); break;
- case 0x0a: STSMACH(Rn); break;
- case 0x0b: RTS(); break;
- case 0x0c: MOVBL0(Rm, Rn); break;
- case 0x0d: MOVWL0(Rm, Rn); break;
- case 0x0e: MOVLL0(Rm, Rn); break;
- case 0x0f: MAC_L(Rm, Rn); break;
-
- case 0x10: ILLEGAL(); break;
- case 0x11: ILLEGAL(); break;
- case 0x12: STCGBR(Rn); break;
- case 0x13: ILLEGAL(); break;
- case 0x14: MOVBS0(Rm, Rn); break;
- case 0x15: MOVWS0(Rm, Rn); break;
- case 0x16: MOVLS0(Rm, Rn); break;
- case 0x17: MULL(Rm, Rn); break;
- case 0x18: SETT(); break;
- case 0x19: DIV0U(); break;
- case 0x1a: STSMACL(Rn); break;
- case 0x1b: SLEEP(); break;
- case 0x1c: MOVBL0(Rm, Rn); break;
- case 0x1d: MOVWL0(Rm, Rn); break;
- case 0x1e: MOVLL0(Rm, Rn); break;
- case 0x1f: MAC_L(Rm, Rn); break;
-
- case 0x20: ILLEGAL(); break;
- case 0x21: ILLEGAL(); break;
- case 0x22: STCVBR(Rn); break;
- case 0x23: BRAF(Rn); break;
- case 0x24: MOVBS0(Rm, Rn); break;
- case 0x25: MOVWS0(Rm, Rn); break;
- case 0x26: MOVLS0(Rm, Rn); break;
- case 0x27: MULL(Rm, Rn); break;
- case 0x28: CLRMAC(); break;
- case 0x29: MOVT(Rn); break;
- case 0x2a: STSPR(Rn); break;
- case 0x2b: RTE(); break;
- case 0x2c: MOVBL0(Rm, Rn); break;
- case 0x2d: MOVWL0(Rm, Rn); break;
- case 0x2e: MOVLL0(Rm, Rn); break;
- case 0x2f: MAC_L(Rm, Rn); break;
-
- case 0x30: ILLEGAL(); break;
- case 0x31: ILLEGAL(); break;
- case 0x32: ILLEGAL(); break;
- case 0x33: ILLEGAL(); break;
- case 0x34: MOVBS0(Rm, Rn); break;
- case 0x35: MOVWS0(Rm, Rn); break;
- case 0x36: MOVLS0(Rm, Rn); break;
- case 0x37: MULL(Rm, Rn); break;
- case 0x38: ILLEGAL(); break;
- case 0x39: ILLEGAL(); break;
- case 0x3a: ILLEGAL(); break;
- case 0x3b: ILLEGAL(); break;
- case 0x3c: MOVBL0(Rm, Rn); break;
- case 0x3d: MOVWL0(Rm, Rn); break;
- case 0x3e: MOVLL0(Rm, Rn); break;
- case 0x3f: MAC_L(Rm, Rn); break;
+ case 0x00: ILLEGAL(); break;
+ case 0x01: ILLEGAL(); break;
+ case 0x02: STCSR(REG_N); break;
+ case 0x03: BSRF(REG_N); break;
+ case 0x04: MOVBS0(REG_M, REG_N); break;
+ case 0x05: MOVWS0(REG_M, REG_N); break;
+ case 0x06: MOVLS0(REG_M, REG_N); break;
+ case 0x07: MULL(REG_M, REG_N); break;
+ case 0x08: CLRT(); break;
+ case 0x09: NOP(); break;
+ case 0x0a: STSMACH(REG_N); break;
+ case 0x0b: RTS(); break;
+ case 0x0c: MOVBL0(REG_M, REG_N); break;
+ case 0x0d: MOVWL0(REG_M, REG_N); break;
+ case 0x0e: MOVLL0(REG_M, REG_N); break;
+ case 0x0f: MAC_L(REG_M, REG_N); break;
+
+ case 0x10: ILLEGAL(); break;
+ case 0x11: ILLEGAL(); break;
+ case 0x12: STCGBR(REG_N); break;
+ case 0x13: ILLEGAL(); break;
+ case 0x14: MOVBS0(REG_M, REG_N); break;
+ case 0x15: MOVWS0(REG_M, REG_N); break;
+ case 0x16: MOVLS0(REG_M, REG_N); break;
+ case 0x17: MULL(REG_M, REG_N); break;
+ case 0x18: SETT(); break;
+ case 0x19: DIV0U(); break;
+ case 0x1a: STSMACL(REG_N); break;
+ case 0x1b: SLEEP(); break;
+ case 0x1c: MOVBL0(REG_M, REG_N); break;
+ case 0x1d: MOVWL0(REG_M, REG_N); break;
+ case 0x1e: MOVLL0(REG_M, REG_N); break;
+ case 0x1f: MAC_L(REG_M, REG_N); break;
+
+ case 0x20: ILLEGAL(); break;
+ case 0x21: ILLEGAL(); break;
+ case 0x22: STCVBR(REG_N); break;
+ case 0x23: BRAF(REG_N); break;
+ case 0x24: MOVBS0(REG_M, REG_N); break;
+ case 0x25: MOVWS0(REG_M, REG_N); break;
+ case 0x26: MOVLS0(REG_M, REG_N); break;
+ case 0x27: MULL(REG_M, REG_N); break;
+ case 0x28: CLRMAC(); break;
+ case 0x29: MOVT(REG_N); break;
+ case 0x2a: STSPR(REG_N); break;
+ case 0x2b: RTE(); break;
+ case 0x2c: MOVBL0(REG_M, REG_N); break;
+ case 0x2d: MOVWL0(REG_M, REG_N); break;
+ case 0x2e: MOVLL0(REG_M, REG_N); break;
+ case 0x2f: MAC_L(REG_M, REG_N); break;
+
+ case 0x30: ILLEGAL(); break;
+ case 0x31: ILLEGAL(); break;
+ case 0x32: ILLEGAL(); break;
+ case 0x33: ILLEGAL(); break;
+ case 0x34: MOVBS0(REG_M, REG_N); break;
+ case 0x35: MOVWS0(REG_M, REG_N); break;
+ case 0x36: MOVLS0(REG_M, REG_N); break;
+ case 0x37: MULL(REG_M, REG_N); break;
+ case 0x38: ILLEGAL(); break;
+ case 0x39: ILLEGAL(); break;
+ case 0x3a: ILLEGAL(); break;
+ case 0x3b: ILLEGAL(); break;
+ case 0x3c: MOVBL0(REG_M, REG_N); break;
+ case 0x3d: MOVWL0(REG_M, REG_N); break;
+ case 0x3e: MOVLL0(REG_M, REG_N); break;
+ case 0x3f: MAC_L(REG_M, REG_N); break;
}
}
@@ -1897,99 +1831,99 @@ void sh_common_execution::execute_one_4000(uint16_t opcode)
{
// 0f always the same, others differ
- switch (opcode & 0x3F)
+ switch (opcode & 0x3f)
{
- case 0x00: SHLL(Rn); break;
- case 0x01: SHLR(Rn); break;
- case 0x02: STSMMACH(Rn); break;
- case 0x03: STCMSR(Rn); break;
- case 0x04: ROTL(Rn); break;
- case 0x05: ROTR(Rn); break;
- case 0x06: LDSMMACH(Rn); break;
- case 0x07: LDCMSR(opcode); break;
- case 0x08: SHLL2(Rn); break;
- case 0x09: SHLR2(Rn); break;
- case 0x0a: LDSMACH(Rn); break;
- case 0x0b: JSR(Rn); break;
- case 0x0c: ILLEGAL(); break;
- case 0x0d: ILLEGAL(); break;
- case 0x0e: LDCSR(opcode); break;
- case 0x0f: MAC_W(Rm, Rn); break;
-
- case 0x10: DT(Rn); break;
- case 0x11: CMPPZ(Rn); break;
- case 0x12: STSMMACL(Rn); break;
- case 0x13: STCMGBR(Rn); break;
- case 0x14: ILLEGAL(); break;
- case 0x15: CMPPL(Rn); break;
- case 0x16: LDSMMACL(Rn); break;
- case 0x17: LDCMGBR(Rn); break;
- case 0x18: SHLL8(Rn); break;
- case 0x19: SHLR8(Rn); break;
- case 0x1a: LDSMACL(Rn); break;
- case 0x1b: TAS(Rn); break;
- case 0x1c: ILLEGAL(); break;
- case 0x1d: ILLEGAL(); break;
- case 0x1e: LDCGBR(Rn); break;
- case 0x1f: MAC_W(Rm, Rn); break;
-
- case 0x20: SHAL(Rn); break;
- case 0x21: SHAR(Rn); break;
- case 0x22: STSMPR(Rn); break;
- case 0x23: STCMVBR(Rn); break;
- case 0x24: ROTCL(Rn); break;
- case 0x25: ROTCR(Rn); break;
- case 0x26: LDSMPR(Rn); break;
- case 0x27: LDCMVBR(Rn); break;
- case 0x28: SHLL16(Rn); break;
- case 0x29: SHLR16(Rn); break;
- case 0x2a: LDSPR(Rn); break;
- case 0x2b: JMP(Rn); break;
- case 0x2c: ILLEGAL(); break;
- case 0x2d: ILLEGAL(); break;
- case 0x2e: LDCVBR(Rn); break;
- case 0x2f: MAC_W(Rm, Rn); break;
-
- case 0x30: ILLEGAL(); break;
- case 0x31: ILLEGAL(); break;
- case 0x32: ILLEGAL(); break;
- case 0x33: ILLEGAL(); break;
- case 0x34: ILLEGAL(); break;
- case 0x35: ILLEGAL(); break;
- case 0x36: ILLEGAL(); break;
- case 0x37: ILLEGAL(); break;
- case 0x38: ILLEGAL(); break;
- case 0x39: ILLEGAL(); break;
- case 0x3a: ILLEGAL(); break;
- case 0x3b: ILLEGAL(); break;
- case 0x3c: ILLEGAL(); break;
- case 0x3d: ILLEGAL(); break;
- case 0x3e: ILLEGAL(); break;
- case 0x3f: MAC_W(Rm, Rn); break;
+ case 0x00: SHLL(REG_N); break;
+ case 0x01: SHLR(REG_N); break;
+ case 0x02: STSMMACH(REG_N); break;
+ case 0x03: STCMSR(REG_N); break;
+ case 0x04: ROTL(REG_N); break;
+ case 0x05: ROTR(REG_N); break;
+ case 0x06: LDSMMACH(REG_N); break;
+ case 0x07: LDCMSR(opcode); break;
+ case 0x08: SHLL2(REG_N); break;
+ case 0x09: SHLR2(REG_N); break;
+ case 0x0a: LDSMACH(REG_N); break;
+ case 0x0b: JSR(REG_N); break;
+ case 0x0c: ILLEGAL(); break;
+ case 0x0d: ILLEGAL(); break;
+ case 0x0e: LDCSR(opcode); break;
+ case 0x0f: MAC_W(REG_M, REG_N); break;
+
+ case 0x10: DT(REG_N); break;
+ case 0x11: CMPPZ(REG_N); break;
+ case 0x12: STSMMACL(REG_N); break;
+ case 0x13: STCMGBR(REG_N); break;
+ case 0x14: ILLEGAL(); break;
+ case 0x15: CMPPL(REG_N); break;
+ case 0x16: LDSMMACL(REG_N); break;
+ case 0x17: LDCMGBR(REG_N); break;
+ case 0x18: SHLL8(REG_N); break;
+ case 0x19: SHLR8(REG_N); break;
+ case 0x1a: LDSMACL(REG_N); break;
+ case 0x1b: TAS(REG_N); break;
+ case 0x1c: ILLEGAL(); break;
+ case 0x1d: ILLEGAL(); break;
+ case 0x1e: LDCGBR(REG_N); break;
+ case 0x1f: MAC_W(REG_M, REG_N); break;
+
+ case 0x20: SHAL(REG_N); break;
+ case 0x21: SHAR(REG_N); break;
+ case 0x22: STSMPR(REG_N); break;
+ case 0x23: STCMVBR(REG_N); break;
+ case 0x24: ROTCL(REG_N); break;
+ case 0x25: ROTCR(REG_N); break;
+ case 0x26: LDSMPR(REG_N); break;
+ case 0x27: LDCMVBR(REG_N); break;
+ case 0x28: SHLL16(REG_N); break;
+ case 0x29: SHLR16(REG_N); break;
+ case 0x2a: LDSPR(REG_N); break;
+ case 0x2b: JMP(REG_N); break;
+ case 0x2c: ILLEGAL(); break;
+ case 0x2d: ILLEGAL(); break;
+ case 0x2e: LDCVBR(REG_N); break;
+ case 0x2f: MAC_W(REG_M, REG_N); break;
+
+ case 0x30: ILLEGAL(); break;
+ case 0x31: ILLEGAL(); break;
+ case 0x32: ILLEGAL(); break;
+ case 0x33: ILLEGAL(); break;
+ case 0x34: ILLEGAL(); break;
+ case 0x35: ILLEGAL(); break;
+ case 0x36: ILLEGAL(); break;
+ case 0x37: ILLEGAL(); break;
+ case 0x38: ILLEGAL(); break;
+ case 0x39: ILLEGAL(); break;
+ case 0x3a: ILLEGAL(); break;
+ case 0x3b: ILLEGAL(); break;
+ case 0x3c: ILLEGAL(); break;
+ case 0x3d: ILLEGAL(); break;
+ case 0x3e: ILLEGAL(); break;
+ case 0x3f: MAC_W(REG_M, REG_N); break;
}
}
void sh_common_execution::execute_one(const uint16_t opcode)
{
- switch(opcode & 0xf000)
+ switch ((opcode >> 12) & 15)
{
- case 0x0000: execute_one_0000(opcode); break;
- case 0x1000: MOVLS4(Rm, opcode & 0x0f, Rn); break;
- case 0x2000: op0010(opcode); break;
- case 0x3000: op0011(opcode); break;
- case 0x4000: execute_one_4000(opcode); break;
- case 0x5000: MOVLL4(Rm, opcode & 0x0f, Rn); break;
- case 0x6000: op0110(opcode); break;
- case 0x7000: ADDI(opcode & 0xff, Rn); break;
- case 0x8000: op1000(opcode); break;
- case 0x9000: MOVWI(opcode & 0xff, Rn); break;
- case 0xa000: BRA(opcode & 0xfff); break;
- case 0xb000: BSR(opcode & 0xfff); break;
- case 0xc000: op1100(opcode); break;
- case 0xd000: MOVLI(opcode & 0xff, Rn); break;
- case 0xe000: MOVI(opcode & 0xff, Rn); break;
- case 0xf000: execute_one_f000(opcode); break;
+ case 0: execute_one_0000(opcode); break;
+ case 1: MOVLS4(REG_M, opcode & 0xf, REG_N); break;
+ case 2: op0010(opcode); break;
+ case 3: op0011(opcode); break;
+ case 4: execute_one_4000(opcode); break;
+ case 5: MOVLL4(REG_M, opcode & 0x0f, REG_N); break;
+ case 6: op0110(opcode); break;
+ case 7: ADDI(opcode & 0xff, REG_N); break;
+ case 8: op1000(opcode); break;
+ case 9: MOVWI(opcode & 0xff, REG_N); break;
+ case 10: BRA(opcode & 0xfff); break;
+ case 11: BSR(opcode & 0xfff); break;
+ case 12: op1100(opcode); break;
+ case 13: MOVLI(opcode & 0xff, REG_N); break;
+ case 14: MOVI(opcode & 0xff, REG_N); break;
+ case 15: execute_one_f000(opcode); break;
}
}
@@ -2009,7 +1943,7 @@ void cfunc_printf_probe(void *param) { ((sh_common_execution *)param)->func_prin
void sh_common_execution::sh2drc_add_fastram(offs_t start, offs_t end, uint8_t readonly, void *base)
{
- if (m_fastram_select < ARRAY_LENGTH(m_fastram))
+ if (m_fastram_select < std::size(m_fastram))
{
m_fastram[m_fastram_select].start = start;
m_fastram[m_fastram_select].end = end;
@@ -2051,7 +1985,7 @@ void sh_common_execution::alloc_handle(uml::code_handle *&handleptr, const char
void sh_common_execution::load_fast_iregs(drcuml_block &block)
{
- for (int regnum = 0; regnum < ARRAY_LENGTH(m_regmap); regnum++)
+ for (int regnum = 0; regnum < std::size(m_regmap); regnum++)
{
if (m_regmap[regnum].is_int_register())
{
@@ -2068,7 +2002,7 @@ void sh_common_execution::load_fast_iregs(drcuml_block &block)
void sh_common_execution::save_fast_iregs(drcuml_block &block)
{
- for (int regnum = 0; regnum < ARRAY_LENGTH(m_regmap); regnum++)
+ for (int regnum = 0; regnum < std::size(m_regmap); regnum++)
{
if (m_regmap[regnum].is_int_register())
{
@@ -2343,7 +2277,7 @@ void sh_common_execution::code_compile_block(uint8_t mode, offs_t pc)
const opcode_desc *desclist;
bool override = false;
- g_profiler.start(PROFILER_DRC_COMPILE);
+ auto profile = g_profiler.start(PROFILER_DRC_COMPILE);
/* get a description of this sequence */
desclist = get_desclist(pc);
@@ -2436,7 +2370,6 @@ void sh_common_execution::code_compile_block(uint8_t mode, offs_t pc)
/* end the sequence */
block.end();
- g_profiler.stop();
succeeded = true;
}
catch (drcuml_block::abort_compilation &)
@@ -2569,7 +2502,7 @@ void sh_common_execution::generate_sequence_instruction(drcuml_block &block, com
}
/* if we are debugging, call the debugger */
- if ((machine().debug_flags & DEBUG_FLAG_ENABLED) != 0)
+ if (debugger_enabled())
{
UML_MOV(block, mem(&m_sh2_state->pc), desc->pc); // mov [pc],desc->pc
save_fast_iregs(block);
@@ -2643,7 +2576,7 @@ void sh_common_execution::generate_delay_slot(drcuml_block &block, compiler_stat
void sh_common_execution::func_unimplemented()
{
// set up an invalid opcode exception
- m_sh2_state->evec = RL( m_sh2_state->vbr + 4 * 4 );
+ m_sh2_state->evec = read_long(m_sh2_state->vbr + 4 * 4);
m_sh2_state->evec &= m_am;
m_sh2_state->irqsr = m_sh2_state->sr;
// claim it's an NMI, because it pretty much is
@@ -2652,15 +2585,12 @@ void sh_common_execution::func_unimplemented()
void sh_common_execution::func_MAC_W()
{
- uint16_t opcode;
- int n, m;
-
// recover the opcode
- opcode = m_sh2_state->arg0;
+ uint32_t opcode = m_sh2_state->arg0;
// extract the operands
- n = Rn;
- m = Rm;
+ uint32_t n = REG_N;
+ uint32_t m = REG_M;
MAC_W(m, n);
}
@@ -2668,15 +2598,12 @@ void sh_common_execution::func_MAC_W()
void sh_common_execution::func_MAC_L()
{
- uint16_t opcode;
- int n, m;
-
// recover the opcode
- opcode = m_sh2_state->arg0;
+ uint32_t opcode = m_sh2_state->arg0;
// extract the operands
- n = Rn;
- m = Rm;
+ uint32_t n = REG_N;
+ uint32_t m = REG_M;
MAC_L(m, n);
}
@@ -2684,15 +2611,12 @@ void sh_common_execution::func_MAC_L()
void sh_common_execution::func_DIV1()
{
- uint16_t opcode;
- int n, m;
-
// recover the opcode
- opcode = m_sh2_state->arg0;
+ uint32_t opcode = m_sh2_state->arg0;
// extract the operands
- n = Rn;
- m = Rm;
+ uint32_t n = REG_N;
+ uint32_t m = REG_M;
DIV1(m, n);
}
@@ -2700,15 +2624,12 @@ void sh_common_execution::func_DIV1()
void sh_common_execution::func_ADDV()
{
- uint16_t opcode;
- int n, m;
-
// recover the opcode
- opcode = m_sh2_state->arg0;
+ uint32_t opcode = m_sh2_state->arg0;
// extract the operands
- n = Rn;
- m = Rm;
+ uint32_t n = REG_N;
+ uint32_t m = REG_M;
ADDV(m, n);
}
@@ -2716,15 +2637,12 @@ void sh_common_execution::func_ADDV()
void sh_common_execution::func_SUBV()
{
- uint16_t opcode;
- int n, m;
-
// recover the opcode
- opcode = m_sh2_state->arg0;
+ uint32_t opcode = m_sh2_state->arg0;
// extract the operands
- n = Rn;
- m = Rm;
+ uint32_t n = REG_N;
+ uint32_t m = REG_M;
SUBV(m, n);
}
@@ -2786,8 +2704,8 @@ bool sh_common_execution::generate_opcode(drcuml_block &block, compiler_state &c
case 1: // MOVLS4
scratch = (opcode & 0x0f) * 4;
- UML_ADD(block, I0, R32(Rn), scratch); // add r0, Rn, scratch
- UML_MOV(block, I1, R32(Rm)); // mov r1, Rm
+ UML_ADD(block, I0, R32(REG_N), scratch); // add r0, Rn, scratch
+ UML_MOV(block, I1, R32(REG_M)); // mov r1, Rm
SETEA(0); // set ea for debug
UML_CALLH(block, *m_write32);
@@ -2804,10 +2722,10 @@ bool sh_common_execution::generate_opcode(drcuml_block &block, compiler_state &c
case 5: // MOVLL4
scratch = (opcode & 0x0f) * 4;
- UML_ADD(block, I0, R32(Rm), scratch); // add r0, Rm, scratch
+ UML_ADD(block, I0, R32(REG_M), scratch); // add r0, Rm, scratch
SETEA(0); // set ea for debug
UML_CALLH(block, *m_read32); // call read32
- UML_MOV(block, R32(Rn), I0); // mov Rn, r0
+ UML_MOV(block, R32(REG_N), I0); // mov Rn, r0
if (!in_delay_slot)
generate_update_cycles(block, compiler, desc->pc + 2, true);
@@ -2819,7 +2737,7 @@ bool sh_common_execution::generate_opcode(drcuml_block &block, compiler_state &c
case 7: // ADDI
scratch = opcode & 0xff;
scratch2 = (uint32_t)(int32_t)(int16_t)(int8_t)scratch;
- UML_ADD(block, R32(Rn), R32(Rn), scratch2); // add Rn, Rn, scratch2
+ UML_ADD(block, R32(REG_N), R32(REG_N), scratch2); // add Rn, Rn, scratch2
return true;
case 8:
@@ -2827,25 +2745,21 @@ bool sh_common_execution::generate_opcode(drcuml_block &block, compiler_state &c
case 9: // MOVWI
if (ovrpc == 0xffffffff)
- {
scratch = (desc->pc + 2) + ((opcode & 0xff) * 2) + 2;
- }
else
- {
scratch = (ovrpc + 2) + ((opcode & 0xff) * 2) + 2;
- }
if (m_drcoptions & SH2DRC_STRICT_PCREL)
{
UML_MOV(block, I0, scratch); // mov r0, scratch
SETEA(0); // set ea for debug
UML_CALLH(block, *m_read16); // read16(r0, r1)
- UML_SEXT(block, R32(Rn), I0, SIZE_WORD); // sext Rn, r0, WORD
+ UML_SEXT(block, R32(REG_N), I0, SIZE_WORD); // sext Rn, r0, WORD
}
else
{
- scratch2 = (uint32_t)(int32_t)(int16_t) RW(scratch);
- UML_MOV(block, R32(Rn), scratch2); // mov Rn, scratch2
+ scratch2 = (uint32_t)util::sext(read_word(scratch), 16);
+ UML_MOV(block, R32(REG_N), scratch2); // mov Rn, scratch2
}
if (!in_delay_slot)
@@ -2853,7 +2767,7 @@ bool sh_common_execution::generate_opcode(drcuml_block &block, compiler_state &c
return true;
case 10: // BRA
- disp = ((int32_t)opcode << 20) >> 20;
+ disp = util::sext(opcode, 12);
m_sh2_state->ea = (desc->pc + 2) + disp * 2 + 2; // m_sh2_state->ea = pc+4 + disp*2 + 2
generate_delay_slot(block, compiler, desc, m_sh2_state->ea-2);
@@ -2867,7 +2781,7 @@ bool sh_common_execution::generate_opcode(drcuml_block &block, compiler_state &c
// do this before running the delay slot
UML_ADD(block, mem(&m_sh2_state->pr), desc->pc, 4); // add m_pr, desc->pc, #4 (skip the current insn & delay slot)
- disp = ((int32_t)opcode << 20) >> 20;
+ disp = util::sext(opcode, 12);
m_sh2_state->ea = (desc->pc + 2) + disp * 2 + 2; // m_sh2_state->ea = pc+4 + disp*2 + 2
generate_delay_slot(block, compiler, desc, m_sh2_state->ea-2);
@@ -2893,12 +2807,12 @@ bool sh_common_execution::generate_opcode(drcuml_block &block, compiler_state &c
{
UML_MOV(block, I0, scratch); // mov r0, scratch
UML_CALLH(block, *m_read32); // read32(r0, r1)
- UML_MOV(block, R32(Rn), I0); // mov Rn, r0
+ UML_MOV(block, R32(REG_N), I0); // mov Rn, r0
}
else
{
- scratch2 = RL(scratch);
- UML_MOV(block, R32(Rn), scratch2); // mov Rn, scratch2
+ scratch2 = read_long(scratch);
+ UML_MOV(block, R32(REG_N), scratch2); // mov Rn, scratch2
}
if (!in_delay_slot)
@@ -2908,7 +2822,7 @@ bool sh_common_execution::generate_opcode(drcuml_block &block, compiler_state &c
case 14: // MOVI
scratch = opcode & 0xff;
scratch2 = (uint32_t)(int32_t)(int16_t)(int8_t)scratch;
- UML_MOV(block, R32(Rn), scratch2);
+ UML_MOV(block, R32(REG_N), scratch2);
return true;
case 15:
@@ -2929,8 +2843,8 @@ bool sh_common_execution::generate_group_2(drcuml_block &block, compiler_state &
switch (opcode & 15)
{
case 0: // MOVBS(Rm, Rn);
- UML_MOV(block, I0, R32(Rn)); // mov r0, Rn
- UML_AND(block, I1, R32(Rm), 0xff); // and r1, Rm, 0xff
+ UML_MOV(block, I0, R32(REG_N)); // mov r0, Rn
+ UML_AND(block, I1, R32(REG_M), 0xff); // and r1, Rm, 0xff
UML_CALLH(block, *m_write8);
if (!in_delay_slot)
@@ -2938,8 +2852,8 @@ bool sh_common_execution::generate_group_2(drcuml_block &block, compiler_state &
return true;
case 1: // MOVWS(Rm, Rn);
- UML_MOV(block, I0, R32(Rn)); // mov r0, Rn
- UML_AND(block, I1, R32(Rm), 0xffff); // and r1, Rm, 0xffff
+ UML_MOV(block, I0, R32(REG_N)); // mov r0, Rn
+ UML_AND(block, I1, R32(REG_M), 0xffff); // and r1, Rm, 0xffff
UML_CALLH(block, *m_write16);
if (!in_delay_slot)
@@ -2947,8 +2861,8 @@ bool sh_common_execution::generate_group_2(drcuml_block &block, compiler_state &
return true;
case 2: // MOVLS(Rm, Rn);
- UML_MOV(block, I0, R32(Rn)); // mov r0, Rn
- UML_MOV(block, I1, R32(Rm)); // mov r1, Rm
+ UML_MOV(block, I0, R32(REG_N)); // mov r0, Rn
+ UML_MOV(block, I1, R32(REG_M)); // mov r1, Rm
UML_CALLH(block, *m_write32);
if (!in_delay_slot)
@@ -2959,9 +2873,9 @@ bool sh_common_execution::generate_group_2(drcuml_block &block, compiler_state &
return false;
case 4: // MOVBM(Rm, Rn);
- UML_MOV(block, I1, R32(Rm)); // mov r1, Rm
- UML_SUB(block, R32(Rn), R32(Rn), 1); // sub Rn, Rn, 1
- UML_MOV(block, I0, R32(Rn)); // mov r0, Rn
+ UML_MOV(block, I1, R32(REG_M)); // mov r1, Rm
+ UML_SUB(block, R32(REG_N), R32(REG_N), 1); // sub Rn, Rn, 1
+ UML_MOV(block, I0, R32(REG_N)); // mov r0, Rn
UML_CALLH(block, *m_write8); // call write8
if (!in_delay_slot)
@@ -2969,9 +2883,9 @@ bool sh_common_execution::generate_group_2(drcuml_block &block, compiler_state &
return true;
case 5: // MOVWM(Rm, Rn);
- UML_MOV(block, I1, R32(Rm)); // mov r1, Rm
- UML_SUB(block, R32(Rn), R32(Rn), 2); // sub Rn, Rn, 2
- UML_MOV(block, I0, R32(Rn)); // mov r0, Rn
+ UML_MOV(block, I1, R32(REG_M)); // mov r1, Rm
+ UML_SUB(block, R32(REG_N), R32(REG_N), 2); // sub Rn, Rn, 2
+ UML_MOV(block, I0, R32(REG_N)); // mov r0, Rn
UML_CALLH(block, *m_write16); // call write16
if (!in_delay_slot)
@@ -2979,9 +2893,9 @@ bool sh_common_execution::generate_group_2(drcuml_block &block, compiler_state &
return true;
case 6: // MOVLM(Rm, Rn);
- UML_MOV(block, I1, R32(Rm)); // mov r1, Rm
- UML_SUB(block, R32(Rn), R32(Rn), 4); // sub Rn, Rn, 4
- UML_MOV(block, I0, R32(Rn)); // mov r0, Rn
+ UML_MOV(block, I1, R32(REG_M)); // mov r1, Rm
+ UML_SUB(block, R32(REG_N), R32(REG_N), 4); // sub Rn, Rn, 4
+ UML_MOV(block, I0, R32(REG_N)); // mov r0, Rn
UML_CALLH(block, *m_write32); // call write32
if (!in_delay_slot)
@@ -2989,32 +2903,32 @@ bool sh_common_execution::generate_group_2(drcuml_block &block, compiler_state &
return true;
case 13: // XTRCT(Rm, Rn);
- UML_SHL(block, I0, R32(Rm), 16); // shl r0, Rm, #16
+ UML_SHL(block, I0, R32(REG_M), 16); // shl r0, Rm, #16
UML_AND(block, I0, I0, 0xffff0000); // and r0, r0, #0xffff0000
- UML_SHR(block, I1, R32(Rn), 16); // shr, r1, Rn, #16
+ UML_SHR(block, I1, R32(REG_N), 16); // shr, r1, Rn, #16
UML_AND(block, I1, I1, 0xffff); // and r1, r1, #0x0000ffff
- UML_OR(block, R32(Rn), I0, I1); // or Rn, r0, r1
+ UML_OR(block, R32(REG_N), I0, I1); // or Rn, r0, r1
return true;
case 7: // DIV0S(Rm, Rn);
UML_MOV(block, I0, mem(&m_sh2_state->sr)); // move r0, sr
UML_AND(block, I0, I0, ~(SH_Q|SH_M|SH_T)); // and r0, r0, ~(Q|M|T) (clear the Q,M, and T bits)
- UML_TEST(block, R32(Rn), 0x80000000); // test Rn, #0x80000000
+ UML_TEST(block, R32(REG_N), 0x80000000); // test Rn, #0x80000000
UML_JMPc(block, COND_Z, compiler.labelnum); // jz labelnum
UML_OR(block, I0, I0, SH_Q); // or r0, r0, Q
UML_LABEL(block, compiler.labelnum++); // labelnum:
- UML_TEST(block, R32(Rm), 0x80000000); // test Rm, #0x80000000
+ UML_TEST(block, R32(REG_M), 0x80000000); // test Rm, #0x80000000
UML_JMPc(block, COND_Z, compiler.labelnum); // jz labelnum
UML_OR(block, I0, I0, SH_M); // or r0, r0, M
UML_LABEL(block, compiler.labelnum++); // labelnum:
- UML_XOR(block, I1, R32(Rn), R32(Rm)); // xor r1, Rn, Rm
+ UML_XOR(block, I1, R32(REG_N), R32(REG_M)); // xor r1, Rn, Rm
UML_TEST(block, I1, 0x80000000); // test r1, #0x80000000
UML_JMPc(block, COND_Z, compiler.labelnum); // jz labelnum
@@ -3025,7 +2939,7 @@ bool sh_common_execution::generate_group_2(drcuml_block &block, compiler_state &
case 8: // TST(Rm, Rn);
UML_AND(block, I0, mem(&m_sh2_state->sr), ~SH_T); // and r0, sr, ~T (clear the T bit)
- UML_TEST(block, R32(Rm), R32(Rn)); // test Rm, Rn
+ UML_TEST(block, R32(REG_M), R32(REG_N)); // test Rm, Rn
UML_JMPc(block, COND_NZ, compiler.labelnum); // jnz compiler.labelnum
UML_OR(block, I0, I0, SH_T); // or r0, r0, T
@@ -3035,7 +2949,7 @@ bool sh_common_execution::generate_group_2(drcuml_block &block, compiler_state &
return true;
case 12: // CMPSTR(Rm, Rn);
- UML_XOR(block, I0, R32(Rn), R32(Rm)); // xor r0, Rn, Rm (temp)
+ UML_XOR(block, I0, R32(REG_N), R32(REG_M)); // xor r0, Rn, Rm (temp)
UML_SHR(block, I1, I0, 24); // shr r1, r0, #24 (HH)
UML_AND(block, I1, I1, 0xff); // and r1, r1, #0xff
@@ -3066,26 +2980,26 @@ bool sh_common_execution::generate_group_2(drcuml_block &block, compiler_state &
return true;
case 9: // AND(Rm, Rn);
- UML_AND(block, R32(Rn), R32(Rn), R32(Rm)); // and Rn, Rn, Rm
+ UML_AND(block, R32(REG_N), R32(REG_N), R32(REG_M)); // and Rn, Rn, Rm
return true;
case 10: // XOR(Rm, Rn);
- UML_XOR(block, R32(Rn), R32(Rn), R32(Rm)); // xor Rn, Rn, Rm
+ UML_XOR(block, R32(REG_N), R32(REG_N), R32(REG_M)); // xor Rn, Rn, Rm
return true;
case 11: // OR(Rm, Rn);
- UML_OR(block, R32(Rn), R32(Rn), R32(Rm)); // or Rn, Rn, Rm
+ UML_OR(block, R32(REG_N), R32(REG_N), R32(REG_M)); // or Rn, Rn, Rm
return true;
case 14: // MULU(Rm, Rn);
- UML_AND(block, I0, R32(Rm), 0xffff); // and r0, Rm, 0xffff
- UML_AND(block, I1, R32(Rn), 0xffff); // and r1, Rn, 0xffff
+ UML_AND(block, I0, R32(REG_M), 0xffff); // and r0, Rm, 0xffff
+ UML_AND(block, I1, R32(REG_N), 0xffff); // and r1, Rn, 0xffff
UML_MULU(block, mem(&m_sh2_state->macl), mem(&m_sh2_state->ea), I0, I1); // mulu macl, ea, r0, r1
return true;
case 15: // MULS(Rm, Rn);
- UML_SEXT(block, I0, R32(Rm), SIZE_WORD); // sext r0, Rm
- UML_SEXT(block, I1, R32(Rn), SIZE_WORD); // sext r1, Rn
+ UML_SEXT(block, I0, R32(REG_M), SIZE_WORD); // sext r0, Rm
+ UML_SEXT(block, I1, R32(REG_N), SIZE_WORD); // sext r1, Rn
UML_MULS(block, mem(&m_sh2_state->macl), mem(&m_sh2_state->ea), I0, I1); // muls macl, ea, r0, r1
return true;
}
@@ -3099,31 +3013,31 @@ bool sh_common_execution::generate_group_3(drcuml_block &block, compiler_state &
switch (opcode & 15)
{
case 0: // CMPEQ(Rm, Rn); (equality)
- UML_CMP(block, R32(Rn), R32(Rm)); // cmp Rn, Rm
+ UML_CMP(block, R32(REG_N), R32(REG_M)); // cmp Rn, Rm
UML_SETc(block, COND_E, I0); // set E, r0
UML_ROLINS(block, mem(&m_sh2_state->sr), I0, 0, 1); // rolins sr, r0, 0, 1
return true;
case 2: // CMPHS(Rm, Rn); (unsigned greater than or equal)
- UML_CMP(block, R32(Rn), R32(Rm)); // cmp Rn, Rm
+ UML_CMP(block, R32(REG_N), R32(REG_M)); // cmp Rn, Rm
UML_SETc(block, COND_AE, I0); // set AE, r0
UML_ROLINS(block, mem(&m_sh2_state->sr), I0, 0, 1); // rolins sr, r0, 0, 1
return true;
case 3: // CMPGE(Rm, Rn); (signed greater than or equal)
- UML_CMP(block, R32(Rn), R32(Rm)); // cmp Rn, Rm
+ UML_CMP(block, R32(REG_N), R32(REG_M)); // cmp Rn, Rm
UML_SETc(block, COND_GE, I0); // set GE, r0
UML_ROLINS(block, mem(&m_sh2_state->sr), I0, 0, 1); // rolins sr, r0, 0, 1
return true;
case 6: // CMPHI(Rm, Rn); (unsigned greater than)
- UML_CMP(block, R32(Rn), R32(Rm)); // cmp Rn, Rm
+ UML_CMP(block, R32(REG_N), R32(REG_M)); // cmp Rn, Rm
UML_SETc(block, COND_A, I0); // set A, r0
UML_ROLINS(block, mem(&m_sh2_state->sr), I0, 0, 1); // rolins sr, r0, 0, 1
return true;
case 7: // CMPGT(Rm, Rn); (signed greater than)
- UML_CMP(block, R32(Rn), R32(Rm)); // cmp Rn, Rm
+ UML_CMP(block, R32(REG_N), R32(REG_M)); // cmp Rn, Rm
UML_SETc(block, COND_G, I0); // set G, r0
UML_ROLINS(block, mem(&m_sh2_state->sr), I0, 0, 1); // rolins sr, r0, 0, 1
return true;
@@ -3142,7 +3056,7 @@ bool sh_common_execution::generate_group_3(drcuml_block &block, compiler_state &
case 5: // DMULU(Rm, Rn);
if (m_cpu_type > CPU_TYPE_SH1)
{
- UML_MULU(block, mem(&m_sh2_state->macl), mem(&m_sh2_state->mach), R32(Rn), R32(Rm));
+ UML_MULU(block, mem(&m_sh2_state->macl), mem(&m_sh2_state->mach), R32(REG_N), R32(REG_M));
return true;
}
break;
@@ -3150,22 +3064,22 @@ bool sh_common_execution::generate_group_3(drcuml_block &block, compiler_state &
case 13: // DMULS(Rm, Rn);
if (m_cpu_type > CPU_TYPE_SH1)
{
- UML_MULS(block, mem(&m_sh2_state->macl), mem(&m_sh2_state->mach), R32(Rn), R32(Rm));
+ UML_MULS(block, mem(&m_sh2_state->macl), mem(&m_sh2_state->mach), R32(REG_N), R32(REG_M));
return true;
}
break;
case 8: // SUB(Rm, Rn);
- UML_SUB(block, R32(Rn), R32(Rn), R32(Rm)); // sub Rn, Rn, Rm
+ UML_SUB(block, R32(REG_N), R32(REG_N), R32(REG_M)); // sub Rn, Rn, Rm
return true;
case 12: // ADD(Rm, Rn);
- UML_ADD(block, R32(Rn), R32(Rn), R32(Rm)); // add Rn, Rn, Rm
+ UML_ADD(block, R32(REG_N), R32(REG_N), R32(REG_M)); // add Rn, Rn, Rm
return true;
case 10: // SUBC(Rm, Rn);
UML_CARRY(block, mem(&m_sh2_state->sr), 0); // carry = T (T is bit 0 of SR)
- UML_SUBB(block, R32(Rn), R32(Rn), R32(Rm)); // addc Rn, Rn, Rm
+ UML_SUBB(block, R32(REG_N), R32(REG_N), R32(REG_M)); // addc Rn, Rn, Rm
UML_SETc(block, COND_C, I0); // setc i0, C
UML_ROLINS(block, mem(&m_sh2_state->sr), I0, 0, SH_T); // rolins sr,i0,0,T
return true;
@@ -3179,7 +3093,7 @@ bool sh_common_execution::generate_group_3(drcuml_block &block, compiler_state &
case 14: // ADDC(Rm, Rn);
UML_CARRY(block, mem(&m_sh2_state->sr), 0); // carry = T (T is bit 0 of SR)
- UML_ADDC(block, R32(Rn), R32(Rn), R32(Rm)); // addc Rn, Rn, Rm
+ UML_ADDC(block, R32(REG_N), R32(REG_N), R32(REG_M)); // addc Rn, Rn, Rm
UML_SETc(block, COND_C, I0); // setc i0, C
UML_ROLINS(block, mem(&m_sh2_state->sr), I0, 0, SH_T); // rolins sr,i0,0,T
return true;
@@ -3200,118 +3114,118 @@ bool sh_common_execution::generate_group_6(drcuml_block &block, compiler_state &
switch (opcode & 15)
{
case 0: // MOVBL(Rm, Rn);
- UML_MOV(block, I0, R32(Rm)); // mov r0, Rm
+ UML_MOV(block, I0, R32(REG_M)); // mov r0, Rm
SETEA(0); // debug: ea = r0
UML_CALLH(block, *m_read8); // call read8
- UML_SEXT(block, R32(Rn), I0, SIZE_BYTE); // sext Rn, r0, BYTE
+ UML_SEXT(block, R32(REG_N), I0, SIZE_BYTE); // sext Rn, r0, BYTE
if (!in_delay_slot)
generate_update_cycles(block, compiler, desc->pc + 2, true);
return true;
case 1: // MOVWL(Rm, Rn);
- UML_MOV(block, I0, R32(Rm)); // mov r0, Rm
+ UML_MOV(block, I0, R32(REG_M)); // mov r0, Rm
SETEA(0); // debug: ea = r0
UML_CALLH(block, *m_read16); // call read16
- UML_SEXT(block, R32(Rn), I0, SIZE_WORD); // sext Rn, r0, WORD
+ UML_SEXT(block, R32(REG_N), I0, SIZE_WORD); // sext Rn, r0, WORD
if (!in_delay_slot)
generate_update_cycles(block, compiler, desc->pc + 2, true);
return true;
case 2: // MOVLL(Rm, Rn);
- UML_MOV(block, I0, R32(Rm)); // mov r0, Rm
+ UML_MOV(block, I0, R32(REG_M)); // mov r0, Rm
SETEA(0); // debug: ea = r0
UML_CALLH(block, *m_read32); // call read32
- UML_MOV(block, R32(Rn), I0); // mov Rn, r0
+ UML_MOV(block, R32(REG_N), I0); // mov Rn, r0
if (!in_delay_slot)
generate_update_cycles(block, compiler, desc->pc + 2, true);
return true;
case 3: // MOV(Rm, Rn);
- UML_MOV(block, R32(Rn), R32(Rm)); // mov Rn, Rm
+ UML_MOV(block, R32(REG_N), R32(REG_M)); // mov Rn, Rm
return true;
case 7: // NOT(Rm, Rn);
- UML_XOR(block, R32(Rn), R32(Rm), 0xffffffff); // xor Rn, Rm, 0xffffffff
+ UML_XOR(block, R32(REG_N), R32(REG_M), 0xffffffff); // xor Rn, Rm, 0xffffffff
return true;
case 9: // SWAPW(Rm, Rn);
- UML_ROL(block, R32(Rn), R32(Rm), 16); // rol Rn, Rm, 16
+ UML_ROL(block, R32(REG_N), R32(REG_M), 16); // rol Rn, Rm, 16
return true;
case 11: // NEG(Rm, Rn);
- UML_SUB(block, R32(Rn), 0, R32(Rm)); // sub Rn, 0, Rm
+ UML_SUB(block, R32(REG_N), 0, R32(REG_M)); // sub Rn, 0, Rm
return true;
case 12: // EXTUB(Rm, Rn);
- UML_AND(block, R32(Rn), R32(Rm), 0x000000ff); // and Rn, Rm, 0xff
+ UML_AND(block, R32(REG_N), R32(REG_M), 0x000000ff); // and Rn, Rm, 0xff
return true;
case 13: // EXTUW(Rm, Rn);
- UML_AND(block, R32(Rn), R32(Rm), 0x0000ffff); // and Rn, Rm, 0xffff
+ UML_AND(block, R32(REG_N), R32(REG_M), 0x0000ffff); // and Rn, Rm, 0xffff
return true;
case 14: // EXTSB(Rm, Rn);
- UML_SEXT(block, R32(Rn), R32(Rm), SIZE_BYTE); // sext Rn, Rm, BYTE
+ UML_SEXT(block, R32(REG_N), R32(REG_M), SIZE_BYTE); // sext Rn, Rm, BYTE
return true;
case 15: // EXTSW(Rm, Rn);
- UML_SEXT(block, R32(Rn), R32(Rm), SIZE_WORD); // sext Rn, Rm, WORD
+ UML_SEXT(block, R32(REG_N), R32(REG_M), SIZE_WORD); // sext Rn, Rm, WORD
return true;
case 4: // MOVBP(Rm, Rn);
- UML_MOV(block, I0, R32(Rm)); // mov r0, Rm
+ UML_MOV(block, I0, R32(REG_M)); // mov r0, Rm
UML_CALLH(block, *m_read8); // call read8
- UML_SEXT(block, R32(Rn), I0, SIZE_BYTE); // sext Rn, r0, BYTE
+ UML_SEXT(block, R32(REG_N), I0, SIZE_BYTE); // sext Rn, r0, BYTE
- if (Rm != Rn)
- UML_ADD(block, R32(Rm), R32(Rm), 1); // add Rm, Rm, #1
+ if (REG_M != REG_N)
+ UML_ADD(block, R32(REG_M), R32(REG_M), 1); // add Rm, Rm, #1
if (!in_delay_slot)
generate_update_cycles(block, compiler, desc->pc + 2, true);
return true;
case 5: // MOVWP(Rm, Rn);
- UML_MOV(block, I0, R32(Rm)); // mov r0, Rm
+ UML_MOV(block, I0, R32(REG_M)); // mov r0, Rm
UML_CALLH(block, *m_read16); // call read16
- UML_SEXT(block, R32(Rn), I0, SIZE_WORD); // sext Rn, r0, WORD
+ UML_SEXT(block, R32(REG_N), I0, SIZE_WORD); // sext Rn, r0, WORD
- if (Rm != Rn)
- UML_ADD(block, R32(Rm), R32(Rm), 2); // add Rm, Rm, #2
+ if (REG_M != REG_N)
+ UML_ADD(block, R32(REG_M), R32(REG_M), 2); // add Rm, Rm, #2
if (!in_delay_slot)
generate_update_cycles(block, compiler, desc->pc + 2, true);
return true;
case 6: // MOVLP(Rm, Rn);
- UML_MOV(block, I0, R32(Rm)); // mov r0, Rm
+ UML_MOV(block, I0, R32(REG_M)); // mov r0, Rm
UML_CALLH(block, *m_read32); // call read32
- UML_MOV(block, R32(Rn), I0); // mov Rn, r0
+ UML_MOV(block, R32(REG_N), I0); // mov Rn, r0
- if (Rm != Rn)
- UML_ADD(block, R32(Rm), R32(Rm), 4); // add Rm, Rm, #4
+ if (REG_M != REG_N)
+ UML_ADD(block, R32(REG_M), R32(REG_M), 4); // add Rm, Rm, #4
if (!in_delay_slot)
generate_update_cycles(block, compiler, desc->pc + 2, true);
return true;
case 8: // SWAPB(Rm, Rn);
- UML_AND(block, I0, R32(Rm), 0xffff0000); // and r0, Rm, #0xffff0000
- UML_AND(block, I1, R32(Rm), 0x000000ff); // and r0, Rm, #0x000000ff
- UML_AND(block, I2, R32(Rm), 0x0000ff00); // and r0, Rm, #0x0000ff00
+ UML_AND(block, I0, R32(REG_M), 0xffff0000); // and r0, Rm, #0xffff0000
+ UML_AND(block, I1, R32(REG_M), 0x000000ff); // and r0, Rm, #0x000000ff
+ UML_AND(block, I2, R32(REG_M), 0x0000ff00); // and r0, Rm, #0x0000ff00
UML_SHL(block, I1, I1, 8); // shl r1, r1, #8
UML_SHR(block, I2, I2, 8); // shr r2, r2, #8
UML_OR(block, I0, I0, I1); // or r0, r0, r1
- UML_OR(block, R32(Rn), I0, I2); // or Rn, r0, r2
+ UML_OR(block, R32(REG_N), I0, I2); // or Rn, r0, r2
return true;
case 10: // NEGC(Rm, Rn);
UML_MOV(block, I0, mem(&m_sh2_state->sr)); // mov r0, sr (save SR)
UML_AND(block, mem(&m_sh2_state->sr), mem(&m_sh2_state->sr), ~SH_T); // and sr, sr, ~T (clear the T bit)
UML_CARRY(block, I0, 0); // carry = T (T is bit 0 of SR)
- UML_SUBB(block, R32(Rn), 0, R32(Rm)); // subb Rn, #0, Rm
+ UML_SUBB(block, R32(REG_N), 0, R32(REG_M)); // subb Rn, #0, Rm
UML_JMPc(block, COND_NC, compiler.labelnum); // jnc labelnum
@@ -3331,11 +3245,11 @@ bool sh_common_execution::generate_group_8(drcuml_block &block, compiler_state &
uint32_t udisp;
uml::code_label templabel;
- switch ( opcode & (15<<8) )
+ switch ((opcode >> 8) & 15)
{
- case 0 << 8: // MOVBS4(opcode & 0x0f, Rm);
+ case 0: // MOVBS4(opcode & 0x0f, Rm);
udisp = (opcode & 0x0f);
- UML_ADD(block, I0, R32(Rm), udisp); // add r0, Rm, udisp
+ UML_ADD(block, I0, R32(REG_M), udisp); // add r0, Rm, udisp
UML_MOV(block, I1, R32(0)); // mov r1, R0
UML_CALLH(block, *m_write8); // call write8
@@ -3343,9 +3257,9 @@ bool sh_common_execution::generate_group_8(drcuml_block &block, compiler_state &
generate_update_cycles(block, compiler, desc->pc + 2, true);
return true;
- case 1 << 8: // MOVWS4(opcode & 0x0f, Rm);
+ case 1: // MOVWS4(opcode & 0x0f, Rm);
udisp = (opcode & 0x0f) * 2;
- UML_ADD(block, I0, R32(Rm), udisp); // add r0, Rm, udisp
+ UML_ADD(block, I0, R32(REG_M), udisp); // add r0, Rm, udisp
UML_MOV(block, I1, R32(0)); // mov r1, R0
UML_CALLH(block, *m_write16); // call write16
@@ -3353,18 +3267,18 @@ bool sh_common_execution::generate_group_8(drcuml_block &block, compiler_state &
generate_update_cycles(block, compiler, desc->pc + 2, true);
return true;
- case 2<< 8:
- case 3<< 8:
- case 6<< 8:
- case 7<< 8:
- case 10<< 8:
- case 12<< 8:
- case 14<< 8:
+ case 2:
+ case 3:
+ case 6:
+ case 7:
+ case 10:
+ case 12:
+ case 14:
return false;
- case 4<< 8: // MOVBL4(Rm, opcode & 0x0f);
+ case 4: // MOVBL4(Rm, opcode & 0x0f);
udisp = opcode & 0x0f;
- UML_ADD(block, I0, R32(Rm), udisp); // add r0, Rm, udisp
+ UML_ADD(block, I0, R32(REG_M), udisp); // add r0, Rm, udisp
SETEA(0);
UML_CALLH(block, *m_read8); // call read8
UML_SEXT(block, R32(0), I0, SIZE_BYTE); // sext R0, r0, BYTE
@@ -3373,9 +3287,9 @@ bool sh_common_execution::generate_group_8(drcuml_block &block, compiler_state &
generate_update_cycles(block, compiler, desc->pc + 2, true);
return true;
- case 5<< 8: // MOVWL4(Rm, opcode & 0x0f);
+ case 5: // MOVWL4(Rm, opcode & 0x0f);
udisp = (opcode & 0x0f)*2;
- UML_ADD(block, I0, R32(Rm), udisp); // add r0, Rm, udisp
+ UML_ADD(block, I0, R32(REG_M), udisp); // add r0, Rm, udisp
SETEA(0);
UML_CALLH(block, *m_read16); // call read16
UML_SEXT(block, R32(0), I0, SIZE_WORD); // sext R0, r0, WORD
@@ -3384,7 +3298,7 @@ bool sh_common_execution::generate_group_8(drcuml_block &block, compiler_state &
generate_update_cycles(block, compiler, desc->pc + 2, true);
return true;
- case 8<< 8: // CMPIM(opcode & 0xff);
+ case 8: // CMPIM(opcode & 0xff);
UML_AND(block, I0, mem(&m_sh2_state->sr), ~SH_T); // and r0, sr, ~T (clear the T bit)
UML_SEXT(block, I1, opcode&0xff, SIZE_BYTE); // sext r1, opcode&0xff, BYTE
@@ -3397,11 +3311,11 @@ bool sh_common_execution::generate_group_8(drcuml_block &block, compiler_state &
UML_MOV(block, mem(&m_sh2_state->sr), I0); // mov m_sh2_state->sr, r0
return true;
- case 9<< 8: // BT(opcode & 0xff);
+ case 9: // BT(opcode & 0xff);
UML_TEST(block, mem(&m_sh2_state->sr), SH_T); // test m_sh2_state->sr, T
UML_JMPc(block, COND_Z, compiler.labelnum); // jz compiler.labelnum
- disp = ((int32_t)opcode << 24) >> 24;
+ disp = util::sext(opcode, 8);
m_sh2_state->ea = (desc->pc + 2) + disp * 2 + 2; // m_sh2_state->ea = destination
generate_update_cycles(block, compiler, m_sh2_state->ea, true); // <subtract cycles>
@@ -3410,11 +3324,11 @@ bool sh_common_execution::generate_group_8(drcuml_block &block, compiler_state &
UML_LABEL(block, compiler.labelnum++); // labelnum:
return true;
- case 11<< 8: // BF(opcode & 0xff);
+ case 11: // BF(opcode & 0xff);
UML_TEST(block, mem(&m_sh2_state->sr), SH_T); // test m_sh2_state->sr, T
UML_JMPc(block, COND_NZ, compiler.labelnum); // jnz compiler.labelnum
- disp = ((int32_t)opcode << 24) >> 24;
+ disp = util::sext(opcode, 8);
m_sh2_state->ea = (desc->pc + 2) + disp * 2 + 2; // m_sh2_state->ea = destination
generate_update_cycles(block, compiler, m_sh2_state->ea, true); // <subtract cycles>
@@ -3423,13 +3337,13 @@ bool sh_common_execution::generate_group_8(drcuml_block &block, compiler_state &
UML_LABEL(block, compiler.labelnum++); // labelnum:
return true;
- case 13<< 8: // BTS(opcode & 0xff);
+ case 13: // BTS(opcode & 0xff);
if (m_cpu_type > CPU_TYPE_SH1)
{
UML_TEST(block, mem(&m_sh2_state->sr), SH_T); // test m_sh2_state->sr, T
UML_JMPc(block, COND_Z, compiler.labelnum); // jz compiler.labelnum
- disp = ((int32_t)opcode << 24) >> 24;
+ disp = util::sext(opcode, 8);
m_sh2_state->ea = (desc->pc + 2) + disp * 2 + 2; // m_sh2_state->ea = destination
templabel = compiler.labelnum; // save our label
@@ -3444,13 +3358,13 @@ bool sh_common_execution::generate_group_8(drcuml_block &block, compiler_state &
}
break;
- case 15<< 8: // BFS(opcode & 0xff);
+ case 15: // BFS(opcode & 0xff);
if (m_cpu_type > CPU_TYPE_SH1)
{
UML_TEST(block, mem(&m_sh2_state->sr), SH_T); // test m_sh2_state->sr, T
UML_JMPc(block, COND_NZ, compiler.labelnum); // jnz compiler.labelnum
- disp = ((int32_t)opcode << 24) >> 24;
+ disp = util::sext(opcode, 8);
m_sh2_state->ea = (desc->pc + 2) + disp * 2 + 2; // m_sh2_state->ea = destination
templabel = compiler.labelnum; // save our label
@@ -3495,9 +3409,9 @@ bool sh_common_execution::generate_group_12(drcuml_block &block, compiler_state
{
uint32_t scratch;
- switch (opcode & (15<<8))
+ switch ((opcode >> 8) & 15)
{
- case 0<<8: // MOVBSG(opcode & 0xff);
+ case 0: // MOVBSG(opcode & 0xff);
scratch = (opcode & 0xff);
UML_ADD(block, I0, mem(&m_sh2_state->gbr), scratch); // add r0, gbr, scratch
UML_AND(block, I1, R32(0), 0xff); // and r1, R0, 0xff
@@ -3507,7 +3421,7 @@ bool sh_common_execution::generate_group_12(drcuml_block &block, compiler_state
generate_update_cycles(block, compiler, desc->pc + 2, true);
return true;
- case 1<<8: // MOVWSG(opcode & 0xff);
+ case 1: // MOVWSG(opcode & 0xff);
scratch = (opcode & 0xff) * 2;
UML_ADD(block, I0, mem(&m_sh2_state->gbr), scratch); // add r0, gbr, scratch
UML_AND(block, I1, R32(0), 0xffff); // and r1, R0, 0xffff
@@ -3517,7 +3431,7 @@ bool sh_common_execution::generate_group_12(drcuml_block &block, compiler_state
generate_update_cycles(block, compiler, desc->pc + 2, true);
return true;
- case 2<<8: // MOVLSG(opcode & 0xff);
+ case 2: // MOVLSG(opcode & 0xff);
scratch = (opcode & 0xff) * 4;
UML_ADD(block, I0, mem(&m_sh2_state->gbr), scratch); // add r0, gbr, scratch
UML_MOV(block, I1, R32(0)); // mov r1, R0
@@ -3527,10 +3441,10 @@ bool sh_common_execution::generate_group_12(drcuml_block &block, compiler_state
generate_update_cycles(block, compiler, desc->pc + 2, true);
return true;
- case 3<<8: // TRAPA(opcode & 0xff);
+ case 3: // TRAPA(opcode & 0xff);
return generate_group_12_TRAPA(block, compiler, desc, opcode, in_delay_slot, ovrpc);
- case 4<<8: // MOVBLG(opcode & 0xff);
+ case 4: // MOVBLG(opcode & 0xff);
scratch = (opcode & 0xff);
UML_ADD(block, I0, mem(&m_sh2_state->gbr), scratch); // add r0, gbr, scratch
UML_CALLH(block, *m_read8); // call read16
@@ -3540,7 +3454,7 @@ bool sh_common_execution::generate_group_12(drcuml_block &block, compiler_state
generate_update_cycles(block, compiler, desc->pc + 2, true);
return true;
- case 5<<8: // MOVWLG(opcode & 0xff);
+ case 5: // MOVWLG(opcode & 0xff);
scratch = (opcode & 0xff) * 2;
UML_ADD(block, I0, mem(&m_sh2_state->gbr), scratch); // add r0, gbr, scratch
UML_CALLH(block, *m_read16); // call read16
@@ -3550,7 +3464,7 @@ bool sh_common_execution::generate_group_12(drcuml_block &block, compiler_state
generate_update_cycles(block, compiler, desc->pc + 2, true);
return true;
- case 6<<8: // MOVLLG(opcode & 0xff);
+ case 6: // MOVLLG(opcode & 0xff);
scratch = (opcode & 0xff) * 4;
UML_ADD(block, I0, mem(&m_sh2_state->gbr), scratch); // add r0, gbr, scratch
UML_CALLH(block, *m_read32); // call read32
@@ -3560,14 +3474,14 @@ bool sh_common_execution::generate_group_12(drcuml_block &block, compiler_state
generate_update_cycles(block, compiler, desc->pc + 2, true);
return true;
- case 7<<8: // MOVA(opcode & 0xff);
+ case 7: // MOVA(opcode & 0xff);
scratch = (opcode & 0xff) * 4;
scratch += ((desc->pc + 4) & ~3);
UML_MOV(block, R32(0), scratch); // mov R0, scratch
return true;
- case 8<<8: // TSTI(opcode & 0xff);
+ case 8: // TSTI(opcode & 0xff);
scratch = opcode & 0xff;
UML_AND(block, mem(&m_sh2_state->sr), mem(&m_sh2_state->sr), ~SH_T); // and sr, sr, ~T (clear the T bit)
@@ -3580,19 +3494,19 @@ bool sh_common_execution::generate_group_12(drcuml_block &block, compiler_state
UML_LABEL(block, compiler.labelnum++); // labelnum:
return true;
- case 9<<8: // ANDI(opcode & 0xff);
+ case 9: // ANDI(opcode & 0xff);
UML_AND(block, R32(0), R32(0), opcode & 0xff); // and r0, r0, opcode & 0xff
return true;
- case 10<<8: // XORI(opcode & 0xff);
+ case 10: // XORI(opcode & 0xff);
UML_XOR(block, R32(0), R32(0), opcode & 0xff); // xor r0, r0, opcode & 0xff
return true;
- case 11<<8: // ORI(opcode & 0xff);
+ case 11: // ORI(opcode & 0xff);
UML_OR(block, R32(0), R32(0), opcode & 0xff); // or r0, r0, opcode & 0xff
return true;
- case 12<<8: // TSTM(opcode & 0xff);
+ case 12: // TSTM(opcode & 0xff);
UML_AND(block, mem(&m_sh2_state->sr), mem(&m_sh2_state->sr), ~SH_T); // and sr, sr, ~T (clear the T bit)
UML_ADD(block, I0, R32(0), mem(&m_sh2_state->gbr)); // add r0, R0, gbr
UML_CALLH(block, *m_read8); // read8
@@ -3606,7 +3520,7 @@ bool sh_common_execution::generate_group_12(drcuml_block &block, compiler_state
UML_LABEL(block, compiler.labelnum++); // labelnum:
return true;
- case 13<<8: // ANDM(opcode & 0xff);
+ case 13: // ANDM(opcode & 0xff);
UML_ADD(block, I0, R32(0), mem(&m_sh2_state->gbr)); // add r0, R0, gbr
UML_CALLH(block, *m_read8); // read8
@@ -3616,7 +3530,7 @@ bool sh_common_execution::generate_group_12(drcuml_block &block, compiler_state
UML_CALLH(block, *m_write8); // write8
return true;
- case 14<<8: // XORM(opcode & 0xff);
+ case 14: // XORM(opcode & 0xff);
UML_ADD(block, I0, R32(0), mem(&m_sh2_state->gbr)); // add r0, R0, gbr
UML_CALLH(block, *m_read8); // read8
@@ -3626,7 +3540,7 @@ bool sh_common_execution::generate_group_12(drcuml_block &block, compiler_state
UML_CALLH(block, *m_write8); // write8
return true;
- case 15<<8: // ORM(opcode & 0xff);
+ case 15: // ORM(opcode & 0xff);
UML_ADD(block, I0, R32(0), mem(&m_sh2_state->gbr)); // add r0, R0, gbr
UML_CALLH(block, *m_read8); // read8
@@ -3688,13 +3602,13 @@ bool sh_common_execution::generate_group_0(drcuml_block &block, compiler_state &
return true;
case 0x02: // STCSR(Rn);
- UML_MOV(block, R32(Rn), mem(&m_sh2_state->sr));
+ UML_MOV(block, R32(REG_N), mem(&m_sh2_state->sr));
return true;
case 0x03: // BSRF(Rn);
if (m_cpu_type > CPU_TYPE_SH1)
{
- UML_ADD(block, mem(&m_sh2_state->target), R32(Rn), 4); // add target, Rm, #4
+ UML_ADD(block, mem(&m_sh2_state->target), R32(REG_N), 4); // add target, Rm, #4
UML_ADD(block, mem(&m_sh2_state->target), mem(&m_sh2_state->target), desc->pc); // add target, target, pc
// 32x Cosmic Carnage @ 6002cb0 relies on the delay slot
@@ -3713,8 +3627,8 @@ bool sh_common_execution::generate_group_0(drcuml_block &block, compiler_state &
case 0x14: // MOVBS0(Rm, Rn);
case 0x24: // MOVBS0(Rm, Rn);
case 0x34: // MOVBS0(Rm, Rn);
- UML_ADD(block, I0, R32(0), R32(Rn)); // add r0, R0, Rn
- UML_AND(block, I1, R32(Rm), 0x000000ff); // and r1, Rm, 0xff
+ UML_ADD(block, I0, R32(0), R32(REG_N)); // add r0, R0, Rn
+ UML_AND(block, I1, R32(REG_M), 0x000000ff); // and r1, Rm, 0xff
UML_CALLH(block, *m_write8); // call write8
if (!in_delay_slot)
@@ -3725,8 +3639,8 @@ bool sh_common_execution::generate_group_0(drcuml_block &block, compiler_state &
case 0x15: // MOVWS0(Rm, Rn);
case 0x25: // MOVWS0(Rm, Rn);
case 0x35: // MOVWS0(Rm, Rn);
- UML_ADD(block, I0, R32(0), R32(Rn)); // add r0, R0, Rn
- UML_AND(block, I1, R32(Rm), 0x0000ffff); // and r1, Rm, 0xffff
+ UML_ADD(block, I0, R32(0), R32(REG_N)); // add r0, R0, Rn
+ UML_AND(block, I1, R32(REG_M), 0x0000ffff); // and r1, Rm, 0xffff
UML_CALLH(block, *m_write16); // call write16
if (!in_delay_slot)
@@ -3737,8 +3651,8 @@ bool sh_common_execution::generate_group_0(drcuml_block &block, compiler_state &
case 0x16: // MOVLS0(Rm, Rn);
case 0x26: // MOVLS0(Rm, Rn);
case 0x36: // MOVLS0(Rm, Rn);
- UML_ADD(block, I0, R32(0), R32(Rn)); // add r0, R0, Rn
- UML_MOV(block, I1, R32(Rm)); // mov r1, Rm
+ UML_ADD(block, I0, R32(0), R32(REG_N)); // add r0, R0, Rn
+ UML_MOV(block, I1, R32(REG_M)); // mov r1, Rm
UML_CALLH(block, *m_write32); // call write32
if (!in_delay_slot)
@@ -3751,7 +3665,7 @@ bool sh_common_execution::generate_group_0(drcuml_block &block, compiler_state &
case 0x37: // MULL(Rm, Rn);
if (m_cpu_type > CPU_TYPE_SH1)
{
- UML_MULU(block, mem(&m_sh2_state->macl), mem(&m_sh2_state->ea), R32(Rn), R32(Rm)); // mulu macl, ea, Rn, Rm
+ UML_MULU(block, mem(&m_sh2_state->macl), mem(&m_sh2_state->ea), R32(REG_N), R32(REG_M)); // mulu macl, ea, Rn, Rm
return true;
}
break;
@@ -3761,7 +3675,7 @@ bool sh_common_execution::generate_group_0(drcuml_block &block, compiler_state &
return true;
case 0x0a: // STSMACH(Rn);
- UML_MOV(block, R32(Rn), mem(&m_sh2_state->mach)); // mov Rn, mach
+ UML_MOV(block, R32(REG_N), mem(&m_sh2_state->mach)); // mov Rn, mach
return true;
case 0x0b: // RTS();
@@ -3777,9 +3691,9 @@ bool sh_common_execution::generate_group_0(drcuml_block &block, compiler_state &
case 0x1c: // MOVBL0(Rm, Rn);
case 0x2c: // MOVBL0(Rm, Rn);
case 0x3c: // MOVBL0(Rm, Rn);
- UML_ADD(block, I0, R32(0), R32(Rm)); // add r0, R0, Rm
+ UML_ADD(block, I0, R32(0), R32(REG_M)); // add r0, R0, Rm
UML_CALLH(block, *m_read8); // call read8
- UML_SEXT(block, R32(Rn), I0, SIZE_BYTE); // sext Rn, r0, BYTE
+ UML_SEXT(block, R32(REG_N), I0, SIZE_BYTE); // sext Rn, r0, BYTE
if (!in_delay_slot)
generate_update_cycles(block, compiler, desc->pc + 2, true);
@@ -3789,9 +3703,9 @@ bool sh_common_execution::generate_group_0(drcuml_block &block, compiler_state &
case 0x1d: // MOVWL0(Rm, Rn);
case 0x2d: // MOVWL0(Rm, Rn);
case 0x3d: // MOVWL0(Rm, Rn);
- UML_ADD(block, I0, R32(0), R32(Rm)); // add r0, R0, Rm
+ UML_ADD(block, I0, R32(0), R32(REG_M)); // add r0, R0, Rm
UML_CALLH(block, *m_read16); // call read16
- UML_SEXT(block, R32(Rn), I0, SIZE_WORD); // sext Rn, r0, WORD
+ UML_SEXT(block, R32(REG_N), I0, SIZE_WORD); // sext Rn, r0, WORD
if (!in_delay_slot)
generate_update_cycles(block, compiler, desc->pc + 2, true);
@@ -3801,9 +3715,9 @@ bool sh_common_execution::generate_group_0(drcuml_block &block, compiler_state &
case 0x1e: // MOVLL0(Rm, Rn);
case 0x2e: // MOVLL0(Rm, Rn);
case 0x3e: // MOVLL0(Rm, Rn);
- UML_ADD(block, I0, R32(0), R32(Rm)); // add r0, R0, Rm
+ UML_ADD(block, I0, R32(0), R32(REG_M)); // add r0, R0, Rm
UML_CALLH(block, *m_read32); // call read32
- UML_MOV(block, R32(Rn), I0); // mov Rn, r0
+ UML_MOV(block, R32(REG_N), I0); // mov Rn, r0
if (!in_delay_slot)
generate_update_cycles(block, compiler, desc->pc + 2, true);
@@ -3824,7 +3738,7 @@ bool sh_common_execution::generate_group_0(drcuml_block &block, compiler_state &
break;
case 0x12: // STCGBR(Rn);
- UML_MOV(block, R32(Rn), mem(&m_sh2_state->gbr)); // mov Rn, gbr
+ UML_MOV(block, R32(REG_N), mem(&m_sh2_state->gbr)); // mov Rn, gbr
return true;
case 0x18: // SETT();
@@ -3836,7 +3750,7 @@ bool sh_common_execution::generate_group_0(drcuml_block &block, compiler_state &
return true;
case 0x1a: // STSMACL(Rn);
- UML_MOV(block, R32(Rn), mem(&m_sh2_state->macl)); // mov Rn, macl
+ UML_MOV(block, R32(REG_N), mem(&m_sh2_state->macl)); // mov Rn, macl
return true;
case 0x1b: // SLEEP();
@@ -3857,13 +3771,13 @@ bool sh_common_execution::generate_group_0(drcuml_block &block, compiler_state &
return true;
case 0x22: // STCVBR(Rn);
- UML_MOV(block, R32(Rn), mem(&m_sh2_state->vbr)); // mov Rn, vbr
+ UML_MOV(block, R32(REG_N), mem(&m_sh2_state->vbr)); // mov Rn, vbr
return true;
case 0x23: // BRAF(Rn);
if (m_cpu_type > CPU_TYPE_SH1)
{
- UML_ADD(block, mem(&m_sh2_state->target), R32(Rn), desc->pc+4); // add target, Rn, pc+4
+ UML_ADD(block, mem(&m_sh2_state->target), R32(REG_N), desc->pc+4); // add target, Rn, pc+4
generate_delay_slot(block, compiler, desc, m_sh2_state->target);
@@ -3879,11 +3793,11 @@ bool sh_common_execution::generate_group_0(drcuml_block &block, compiler_state &
return true;
case 0x29: // MOVT(Rn);
- UML_AND(block, R32(Rn), mem(&m_sh2_state->sr), SH_T); // and Rn, sr, T
+ UML_AND(block, R32(REG_N), mem(&m_sh2_state->sr), SH_T); // and Rn, sr, T
return true;
case 0x2a: // STSPR(Rn);
- UML_MOV(block, R32(Rn), mem(&m_sh2_state->pr)); // mov Rn, pr
+ UML_MOV(block, R32(REG_N), mem(&m_sh2_state->pr)); // mov Rn, pr
return true;
case 0x2b: // RTE();
@@ -3896,7 +3810,7 @@ bool sh_common_execution::generate_group_0(drcuml_block &block, compiler_state &
bool sh_common_execution::generate_group_4_LDCSR(drcuml_block &block, compiler_state &compiler, const opcode_desc *desc, uint16_t opcode, int in_delay_slot, uint32_t ovrpc)
{
// needs to be different on SH2 / 4
- UML_MOV(block, I0, R32(Rn)); // mov r0, Rn
+ UML_MOV(block, I0, R32(REG_N)); // mov r0, Rn
UML_AND(block, I0, I0, SH_FLAGS); // and r0, r0, FLAGS
UML_MOV(block, mem(&m_sh2_state->sr), I0);
@@ -3906,10 +3820,10 @@ bool sh_common_execution::generate_group_4_LDCSR(drcuml_block &block, compiler_s
bool sh_common_execution::generate_group_4_LDCMSR(drcuml_block &block, compiler_state &compiler, const opcode_desc *desc, uint16_t opcode, int in_delay_slot, uint32_t ovrpc)
{
- UML_MOV(block, I0, R32(Rn)); // mov r0, Rn
+ UML_MOV(block, I0, R32(REG_N)); // mov r0, Rn
SETEA(0);
UML_CALLH(block, *m_read32); // call read32
- UML_ADD(block, R32(Rn), R32(Rn), 4); // add Rn, #4
+ UML_ADD(block, R32(REG_N), R32(REG_N), 4); // add Rn, #4
UML_MOV(block, mem(&m_sh2_state->sr), I0); // mov sr, r0
compiler.checkints = true;
@@ -3923,32 +3837,32 @@ bool sh_common_execution::generate_group_4(drcuml_block &block, compiler_state &
switch (opcode & 0x3F)
{
case 0x00: // SHLL(Rn);
- UML_SHL(block, R32(Rn), R32(Rn), 1); // shl Rn, Rn, 1
+ UML_SHL(block, R32(REG_N), R32(REG_N), 1); // shl Rn, Rn, 1
UML_SETc(block, COND_C, I0); // set i0,C
UML_ROLINS(block, mem(&m_sh2_state->sr), I0, 0, SH_T); // rolins [sr],i0,0,T
return true;
case 0x01: // SHLR(Rn);
- UML_SHR(block, R32(Rn), R32(Rn), 1); // shr Rn, Rn, 1
+ UML_SHR(block, R32(REG_N), R32(REG_N), 1); // shr Rn, Rn, 1
UML_SETc(block, COND_C, I0); // set i0,C
UML_ROLINS(block, mem(&m_sh2_state->sr), I0, 0, SH_T); // rolins [sr],i0,0,T
return true;
case 0x04: // ROTL(Rn);
- UML_ROL(block, R32(Rn), R32(Rn), 1); // rol Rn, Rn, 1
+ UML_ROL(block, R32(REG_N), R32(REG_N), 1); // rol Rn, Rn, 1
UML_SETc(block, COND_C, I0); // set i0,C
UML_ROLINS(block, mem(&m_sh2_state->sr), I0, 0, SH_T); // rolins [sr],i0,0,T
return true;
case 0x05: // ROTR(Rn);
- UML_ROR(block, R32(Rn), R32(Rn), 1); // ror Rn, Rn, 1
+ UML_ROR(block, R32(REG_N), R32(REG_N), 1); // ror Rn, Rn, 1
UML_SETc(block, COND_C, I0); // set i0,C
UML_ROLINS(block, mem(&m_sh2_state->sr), I0, 0, SH_T); // rolins [sr],i0,0,T
return true;
case 0x02: // STSMMACH(Rn);
- UML_SUB(block, R32(Rn), R32(Rn), 4); // sub Rn, Rn, #4
- UML_MOV(block, I0, R32(Rn)); // mov r0, Rn
+ UML_SUB(block, R32(REG_N), R32(REG_N), 4); // sub Rn, Rn, #4
+ UML_MOV(block, I0, R32(REG_N)); // mov r0, Rn
UML_MOV(block, I1, mem(&m_sh2_state->mach)); // mov r1, mach
SETEA(0); // set ea for debug
UML_CALLH(block, *m_write32); // call write32
@@ -3958,8 +3872,8 @@ bool sh_common_execution::generate_group_4(drcuml_block &block, compiler_state &
return true;
case 0x03: // STCMSR(Rn);
- UML_SUB(block, R32(Rn), R32(Rn), 4); // sub Rn, Rn, #4
- UML_MOV(block, I0, R32(Rn)); // mov r0, Rn
+ UML_SUB(block, R32(REG_N), R32(REG_N), 4); // sub Rn, Rn, #4
+ UML_MOV(block, I0, R32(REG_N)); // mov r0, Rn
UML_MOV(block, I1, mem(&m_sh2_state->sr)); // mov r1, sr
SETEA(0); // set ea for debug
UML_CALLH(block, *m_write32); // call write32
@@ -3969,10 +3883,10 @@ bool sh_common_execution::generate_group_4(drcuml_block &block, compiler_state &
return true;
case 0x06: // LDSMMACH(Rn);
- UML_MOV(block, I0, R32(Rn)); // mov r0, Rn
+ UML_MOV(block, I0, R32(REG_N)); // mov r0, Rn
SETEA(0);
UML_CALLH(block, *m_read32); // call read32
- UML_ADD(block, R32(Rn), R32(Rn), 4); // add Rn, #4
+ UML_ADD(block, R32(REG_N), R32(REG_N), 4); // add Rn, #4
UML_MOV(block, mem(&m_sh2_state->mach), I0); // mov mach, r0
if (!in_delay_slot)
@@ -3983,35 +3897,35 @@ bool sh_common_execution::generate_group_4(drcuml_block &block, compiler_state &
return generate_group_4_LDCMSR(block, compiler, desc, opcode, in_delay_slot, ovrpc);
case 0x08: // SHLL2(Rn);
- UML_SHL(block, R32(Rn), R32(Rn), 2);
+ UML_SHL(block, R32(REG_N), R32(REG_N), 2);
return true;
case 0x09: // SHLR2(Rn);
- UML_SHR(block, R32(Rn), R32(Rn), 2);
+ UML_SHR(block, R32(REG_N), R32(REG_N), 2);
return true;
case 0x18: // SHLL8(Rn);
- UML_SHL(block, R32(Rn), R32(Rn), 8);
+ UML_SHL(block, R32(REG_N), R32(REG_N), 8);
return true;
case 0x19: // SHLR8(Rn);
- UML_SHR(block, R32(Rn), R32(Rn), 8);
+ UML_SHR(block, R32(REG_N), R32(REG_N), 8);
return true;
case 0x28: // SHLL16(Rn);
- UML_SHL(block, R32(Rn), R32(Rn), 16);
+ UML_SHL(block, R32(REG_N), R32(REG_N), 16);
return true;
case 0x29: // SHLR16(Rn);
- UML_SHR(block, R32(Rn), R32(Rn), 16);
+ UML_SHR(block, R32(REG_N), R32(REG_N), 16);
return true;
case 0x0a: // LDSMACH(Rn);
- UML_MOV(block, mem(&m_sh2_state->mach), R32(Rn)); // mov mach, Rn
+ UML_MOV(block, mem(&m_sh2_state->mach), R32(REG_N)); // mov mach, Rn
return true;
case 0x0b: // JSR(Rn);
- UML_MOV(block, mem(&m_sh2_state->target), R32(Rn)); // mov target, Rn
+ UML_MOV(block, mem(&m_sh2_state->target), R32(REG_N)); // mov target, Rn
UML_ADD(block, mem(&m_sh2_state->pr), desc->pc, 4); // add m_pr, desc->pc, #4 (skip the current insn & delay slot)
@@ -4038,7 +3952,7 @@ bool sh_common_execution::generate_group_4(drcuml_block &block, compiler_state &
if (m_cpu_type > CPU_TYPE_SH1)
{
UML_AND(block, I0, mem(&m_sh2_state->sr), ~SH_T); // and r0, sr, ~T (clear the T bit)
- UML_SUB(block, R32(Rn), R32(Rn), 1); // sub Rn, Rn, 1
+ UML_SUB(block, R32(REG_N), R32(REG_N), 1); // sub Rn, Rn, 1
UML_JMPc(block, COND_NZ, compiler.labelnum); // jz compiler.labelnum
UML_OR(block, I0, I0, SH_T); // or r0, r0, T
@@ -4052,7 +3966,7 @@ bool sh_common_execution::generate_group_4(drcuml_block &block, compiler_state &
case 0x11: // CMPPZ(Rn);
UML_AND(block, I0, mem(&m_sh2_state->sr), ~SH_T); // and r0, sr, ~T (clear the T bit)
- UML_CMP(block, R32(Rn), 0); // cmp Rn, 0
+ UML_CMP(block, R32(REG_N), 0); // cmp Rn, 0
UML_JMPc(block, COND_S, compiler.labelnum); // js compiler.labelnum (if negative)
UML_OR(block, I0, I0, SH_T); // or r0, r0, T
@@ -4064,7 +3978,7 @@ bool sh_common_execution::generate_group_4(drcuml_block &block, compiler_state &
case 0x15: // CMPPL(Rn);
UML_AND(block, I0, mem(&m_sh2_state->sr), ~SH_T); // and r0, sr, ~T (clear the T bit)
- UML_CMP(block, R32(Rn), 0); // cmp Rn, 0
+ UML_CMP(block, R32(REG_N), 0); // cmp Rn, 0
UML_JMPc(block, COND_S, compiler.labelnum); // js compiler.labelnum (if negative)
UML_JMPc(block, COND_Z, compiler.labelnum); // jz compiler.labelnum (if zero)
@@ -4076,8 +3990,8 @@ bool sh_common_execution::generate_group_4(drcuml_block &block, compiler_state &
return true;
case 0x12: // STSMMACL(Rn);
- UML_SUB(block, R32(Rn), R32(Rn), 4); // sub Rn, Rn, #4
- UML_MOV(block, I0, R32(Rn)); // mov r0, Rn
+ UML_SUB(block, R32(REG_N), R32(REG_N), 4); // sub Rn, Rn, #4
+ UML_MOV(block, I0, R32(REG_N)); // mov r0, Rn
UML_MOV(block, I1, mem(&m_sh2_state->macl)); // mov r1, macl
SETEA(0); // set ea for debug
UML_CALLH(block, *m_write32); // call write32
@@ -4087,8 +4001,8 @@ bool sh_common_execution::generate_group_4(drcuml_block &block, compiler_state &
return true;
case 0x13: // STCMGBR(Rn);
- UML_SUB(block, R32(Rn), R32(Rn), 4); // sub Rn, Rn, #4
- UML_MOV(block, I0, R32(Rn)); // mov r0, Rn
+ UML_SUB(block, R32(REG_N), R32(REG_N), 4); // sub Rn, Rn, #4
+ UML_MOV(block, I0, R32(REG_N)); // mov r0, Rn
UML_MOV(block, I1, mem(&m_sh2_state->gbr)); // mov r1, gbr
SETEA(0); // set ea for debug
UML_CALLH(block, *m_write32); // call write32
@@ -4098,10 +4012,10 @@ bool sh_common_execution::generate_group_4(drcuml_block &block, compiler_state &
return true;
case 0x16: // LDSMMACL(Rn);
- UML_MOV(block, I0, R32(Rn)); // mov r0, Rn
+ UML_MOV(block, I0, R32(REG_N)); // mov r0, Rn
SETEA(0);
UML_CALLH(block, *m_read32); // call read32
- UML_ADD(block, R32(Rn), R32(Rn), 4); // add Rn, #4
+ UML_ADD(block, R32(REG_N), R32(REG_N), 4); // add Rn, #4
UML_MOV(block, mem(&m_sh2_state->macl), I0); // mov macl, r0
if (!in_delay_slot)
@@ -4109,10 +4023,10 @@ bool sh_common_execution::generate_group_4(drcuml_block &block, compiler_state &
return true;
case 0x17: // LDCMGBR(Rn);
- UML_MOV(block, I0, R32(Rn)); // mov r0, Rn
+ UML_MOV(block, I0, R32(REG_N)); // mov r0, Rn
SETEA(0);
UML_CALLH(block, *m_read32); // call read32
- UML_ADD(block, R32(Rn), R32(Rn), 4); // add Rn, #4
+ UML_ADD(block, R32(REG_N), R32(REG_N), 4); // add Rn, #4
UML_MOV(block, mem(&m_sh2_state->gbr), I0); // mov gbr, r0
if (!in_delay_slot)
@@ -4120,11 +4034,11 @@ bool sh_common_execution::generate_group_4(drcuml_block &block, compiler_state &
return true;
case 0x1a: // LDSMACL(Rn);
- UML_MOV(block, mem(&m_sh2_state->macl), R32(Rn)); // mov macl, Rn
+ UML_MOV(block, mem(&m_sh2_state->macl), R32(REG_N)); // mov macl, Rn
return true;
case 0x1b: // TAS(Rn);
- UML_MOV(block, I0, R32(Rn)); // mov r0, Rn
+ UML_MOV(block, I0, R32(REG_N)); // mov r0, Rn
SETEA(0);
UML_CALLH(block, *m_read8); // call read8
@@ -4139,7 +4053,7 @@ bool sh_common_execution::generate_group_4(drcuml_block &block, compiler_state &
UML_OR(block, I1, I0, 0x80); // or r1, r0, #0x80
- UML_MOV(block, I0, R32(Rn)); // mov r0, Rn
+ UML_MOV(block, I0, R32(REG_N)); // mov r0, Rn
UML_CALLH(block, *m_write8); // write the value back
if (!in_delay_slot)
@@ -4147,27 +4061,27 @@ bool sh_common_execution::generate_group_4(drcuml_block &block, compiler_state &
return true;
case 0x1e: // LDCGBR(Rn);
- UML_MOV(block, mem(&m_sh2_state->gbr), R32(Rn)); // mov gbr, Rn
+ UML_MOV(block, mem(&m_sh2_state->gbr), R32(REG_N)); // mov gbr, Rn
return true;
case 0x20: // SHAL(Rn);
UML_AND(block, mem(&m_sh2_state->sr), mem(&m_sh2_state->sr), ~SH_T); // and sr, sr, ~T
- UML_SHR(block, I0, R32(Rn), 31); // shr r0, Rn, 31
+ UML_SHR(block, I0, R32(REG_N), 31); // shr r0, Rn, 31
UML_AND(block, I0, I0, SH_T); // and r0, r0, T
UML_OR(block, mem(&m_sh2_state->sr), mem(&m_sh2_state->sr), I0); // or sr, sr, r0
- UML_SHL(block, R32(Rn), R32(Rn), 1); // shl Rn, Rn, 1
+ UML_SHL(block, R32(REG_N), R32(REG_N), 1); // shl Rn, Rn, 1
return true;
case 0x21: // SHAR(Rn);
UML_AND(block, mem(&m_sh2_state->sr), mem(&m_sh2_state->sr), ~SH_T); // and sr, sr, ~T
- UML_AND(block, I0, R32(Rn), SH_T); // and r0, Rn, T
+ UML_AND(block, I0, R32(REG_N), SH_T); // and r0, Rn, T
UML_OR(block, mem(&m_sh2_state->sr), mem(&m_sh2_state->sr), I0); // or sr, sr, r0
- UML_SAR(block, R32(Rn), R32(Rn), 1); // sar Rn, Rn, 1
+ UML_SAR(block, R32(REG_N), R32(REG_N), 1); // sar Rn, Rn, 1
return true;
case 0x22: // STSMPR(Rn);
- UML_SUB(block, R32(Rn), R32(Rn), 4); // sub Rn, Rn, 4
- UML_MOV(block, I0, R32(Rn)); // mov r0, Rn
+ UML_SUB(block, R32(REG_N), R32(REG_N), 4); // sub Rn, Rn, 4
+ UML_MOV(block, I0, R32(REG_N)); // mov r0, Rn
SETEA(0);
UML_MOV(block, I1, mem(&m_sh2_state->pr)); // mov r1, pr
UML_CALLH(block, *m_write32); // call write32
@@ -4177,8 +4091,8 @@ bool sh_common_execution::generate_group_4(drcuml_block &block, compiler_state &
return true;
case 0x23: // STCMVBR(Rn);
- UML_SUB(block, R32(Rn), R32(Rn), 4); // sub Rn, Rn, 4
- UML_MOV(block, I0, R32(Rn)); // mov r0, Rn
+ UML_SUB(block, R32(REG_N), R32(REG_N), 4); // sub Rn, Rn, 4
+ UML_MOV(block, I0, R32(REG_N)); // mov r0, Rn
SETEA(0);
UML_MOV(block, I1, mem(&m_sh2_state->vbr)); // mov r1, vbr
UML_CALLH(block, *m_write32); // call write32
@@ -4189,46 +4103,46 @@ bool sh_common_execution::generate_group_4(drcuml_block &block, compiler_state &
case 0x24: // ROTCL(Rn);
UML_CARRY(block, mem(&m_sh2_state->sr), 0); // carry sr,0
- UML_ROLC(block, R32(Rn), R32(Rn), 1); // rolc Rn,Rn,1
+ UML_ROLC(block, R32(REG_N), R32(REG_N), 1); // rolc Rn,Rn,1
UML_SETc(block, COND_C, I0); // set i0,C
UML_ROLINS(block, mem(&m_sh2_state->sr), I0, 0, SH_T); // rolins sr,i0,0,T
return true;
case 0x25: // ROTCR(Rn);
UML_CARRY(block, mem(&m_sh2_state->sr), 0); // carry sr,0
- UML_RORC(block, R32(Rn), R32(Rn), 1); // rorc Rn,Rn,1
+ UML_RORC(block, R32(REG_N), R32(REG_N), 1); // rorc Rn,Rn,1
UML_SETc(block, COND_C, I0); // set i0,C
UML_ROLINS(block, mem(&m_sh2_state->sr), I0, 0, SH_T); // rolins sr,i0,0,T
return true;
case 0x26: // LDSMPR(Rn);
- UML_MOV(block, I0, R32(Rn)); // mov r0, Rn
+ UML_MOV(block, I0, R32(REG_N)); // mov r0, Rn
SETEA(0);
UML_CALLH(block, *m_read32); // call read32
UML_MOV(block, mem(&m_sh2_state->pr), I0); // mov m_pr, r0
- UML_ADD(block, R32(Rn), R32(Rn), 4); // add Rn, Rn, #4
+ UML_ADD(block, R32(REG_N), R32(REG_N), 4); // add Rn, Rn, #4
if (!in_delay_slot)
generate_update_cycles(block, compiler, desc->pc + 2, true);
return true;
case 0x27: // LDCMVBR(Rn);
- UML_MOV(block, I0, R32(Rn)); // mov r0, Rn
+ UML_MOV(block, I0, R32(REG_N)); // mov r0, Rn
SETEA(0);
UML_CALLH(block, *m_read32); // call read32
UML_MOV(block, mem(&m_sh2_state->vbr), I0); // mov m_sh2_state->vbr, r0
- UML_ADD(block, R32(Rn), R32(Rn), 4); // add Rn, Rn, #4
+ UML_ADD(block, R32(REG_N), R32(REG_N), 4); // add Rn, Rn, #4
if (!in_delay_slot)
generate_update_cycles(block, compiler, desc->pc + 2, true);
return true;
case 0x2a: // LDSPR(Rn);
- UML_MOV(block, mem(&m_sh2_state->pr), R32(Rn)); // mov m_pr, Rn
+ UML_MOV(block, mem(&m_sh2_state->pr), R32(REG_N)); // mov m_pr, Rn
return true;
case 0x2b: // JMP(Rn);
- UML_MOV(block, mem(&m_sh2_state->target), R32(Rn)); // mov target, Rn
+ UML_MOV(block, mem(&m_sh2_state->target), R32(REG_N)); // mov target, Rn
generate_delay_slot(block, compiler, desc, m_sh2_state->target);
@@ -4237,7 +4151,7 @@ bool sh_common_execution::generate_group_4(drcuml_block &block, compiler_state &
return true;
case 0x2e: // LDCVBR(Rn);
- UML_MOV(block, mem(&m_sh2_state->vbr), R32(Rn)); // mov vbr, Rn
+ UML_MOV(block, mem(&m_sh2_state->vbr), R32(REG_N)); // mov vbr, Rn
return true;
case 0x0c:
@@ -4293,6 +4207,6 @@ void sh_common_execution::sh2drc_add_pcflush(offs_t address)
{
if (!allow_drc()) return;
- if (m_pcfsel < ARRAY_LENGTH(m_pcflushes))
+ if (m_pcfsel < std::size(m_pcflushes))
m_pcflushes[m_pcfsel++] = address;
}
diff --git a/src/devices/cpu/sh/sh.h b/src/devices/cpu/sh/sh.h
index 7c84bdffb8a..9980fa87709 100644
--- a/src/devices/cpu/sh/sh.h
+++ b/src/devices/cpu/sh/sh.h
@@ -51,8 +51,8 @@
#define CPU_TYPE_SH3 (2)
#define CPU_TYPE_SH4 (3)
-#define Rn ((opcode>>8)&15)
-#define Rm ((opcode>>4)&15)
+#define REG_N ((opcode >> 8) & 15)
+#define REG_M ((opcode >> 4) & 15)
/* Bits in SR */
#define SH_T 0x00000001
@@ -84,9 +84,9 @@
MACROS
***************************************************************************/
-#define SH2_CODE_XOR(a) ((a) ^ NATIVE_ENDIAN_VALUE_LE_BE(2,0)) // sh2
-#define SH34LE_CODE_XOR(a) ((a) ^ NATIVE_ENDIAN_VALUE_LE_BE(0,6)) // naomi
-#define SH34BE_CODE_XOR(a) ((a) ^ NATIVE_ENDIAN_VALUE_LE_BE(6,0)) // cave
+#define SH2_CODE_XOR(a) ((a) ^ NATIVE_ENDIAN_VALUE_LE_BE(2, 0)) // sh2
+#define SH34LE_CODE_XOR(a) ((a) ^ NATIVE_ENDIAN_VALUE_LE_BE(0, 6)) // naomi
+#define SH34BE_CODE_XOR(a) ((a) ^ NATIVE_ENDIAN_VALUE_LE_BE(6, 0)) // cave
#define R32(reg) m_regmap[reg]
@@ -94,7 +94,7 @@ enum
{
SH4_PC = 1, SH_SR, SH4_PR, SH4_GBR, SH4_VBR, SH4_DBR, SH4_MACH, SH4_MACL,
SH4_R0, SH4_R1, SH4_R2, SH4_R3, SH4_R4, SH4_R5, SH4_R6, SH4_R7,
- SH4_R8, SH4_R9, SH4_R10, SH4_R11, SH4_R12, SH4_R13, SH4_R14, SH4_R15, SH4_EA
+ SH4_R8, SH4_R9, SH4_R10, SH4_R11, SH4_R12, SH4_R13, SH4_R14, SH4_R15, SH4_EA, SH4_SP
};
class sh_common_execution : public cpu_device
@@ -168,12 +168,13 @@ public:
internal_sh2_state *m_sh2_state;
- virtual uint8_t RB(offs_t A) = 0;
- virtual uint16_t RW(offs_t A) = 0;
- virtual uint32_t RL(offs_t A) = 0;
- virtual void WB(offs_t A, uint8_t V) = 0;
- virtual void WW(offs_t A, uint16_t V) = 0;
- virtual void WL(offs_t A, uint32_t V) = 0;
+ virtual uint8_t read_byte(offs_t offset) = 0;
+ virtual uint16_t read_word(offs_t offset) = 0;
+ virtual uint32_t read_long(offs_t offset) = 0;
+ virtual uint16_t decrypted_read_word(offs_t offset) = 0;
+ virtual void write_byte(offs_t offset, uint8_t data) = 0;
+ virtual void write_word(offs_t offset, uint16_t data) = 0;
+ virtual void write_long(offs_t offset, uint32_t data) = 0;
virtual void set_frt_input(int state) = 0;
void pulse_frt_input() { set_frt_input(ASSERT_LINE); set_frt_input(CLEAR_LINE); }
@@ -385,6 +386,9 @@ public:
std::function<u16 (offs_t)> m_pr16;
std::function<const void * (offs_t)> m_prptr;
address_space *m_program;
+ memory_access<32, 2, 0, ENDIANNESS_BIG>::cache m_cache32;
+ memory_access<32, 3, 0, ENDIANNESS_BIG>::cache m_cache64be;
+ memory_access<32, 3, 0, ENDIANNESS_LITTLE>::cache m_cache64le;
std::unique_ptr<drcuml_state> m_drcuml; /* DRC UML generator state */
uint32_t m_drcoptions; /* configurable DRC options */
@@ -417,7 +421,7 @@ public:
uml::code_label labelnum; /* index for local labels */
};
- virtual void sh2_exception(const char *message, int irqline) { fatalerror("sh2_exception in base classs\n"); };
+ virtual void sh2_exception(const char *message, int irqline) { fatalerror("sh2_exception in base classs\n"); }
virtual void generate_update_cycles(drcuml_block &block, compiler_state &compiler, uml::parameter param, bool allow_exception) = 0;
@@ -476,7 +480,7 @@ public:
protected:
// device-level overrides
- virtual void device_start() override;
+ virtual void device_start() override ATTR_COLD;
};
class sh_frontend : public drc_frontend
@@ -503,4 +507,4 @@ protected:
sh_common_execution *m_sh;
};
-#endif // MAME_CPU_SH2_SH2_H
+#endif // MAME_CPU_SH_SH_H
diff --git a/src/devices/cpu/sh/sh2.cpp b/src/devices/cpu/sh/sh2.cpp
index c0fab41f9b0..ae8acd76ee4 100644
--- a/src/devices/cpu/sh/sh2.cpp
+++ b/src/devices/cpu/sh/sh2.cpp
@@ -1,8 +1,8 @@
// license:BSD-3-Clause
-// copyright-holders:Juergen Buchmueller
+// copyright-holders:Juergen Buchmueller, R. Belmont
/*****************************************************************************
*
- * sh2.c
+ * sh2.cpp
* Portable Hitachi SH-2 (SH7600 family) emulator
*
* This work is based on <tiraniddo@hotmail.com> C/C++ implementation of
@@ -12,276 +12,98 @@
*
*****************************************************************************/
-/*****************************************************************************
- Changes
- 20130129 Angelo Salese
- - added illegal opcode exception handling, side effect of some Saturn games
- on loading like Feda or Falcom Classics Vol. 1
- (i.e. Master CPU Incautiously transfers memory from CD to work RAM H, and
- wipes out Slave CPU program code too while at it).
-
- 20051129 Mariusz Wojcieszek
- - introduced memory_decrypted_read_word() for opcode fetching
-
- 20050813 Mariusz Wojcieszek
- - fixed 64 bit / 32 bit division in division unit
-
- 20031015 O. Galibert
- - dma fixes, thanks to sthief
-
- 20031013 O. Galibert, A. Giles
- - timer fixes
- - multi-cpu simplifications
-
- 20030915 O. Galibert
- - fix DMA1 irq vector
- - ignore writes to DRCRx
- - fix cpu number issues
- - fix slave/master recognition
- - fix wrong-cpu-in-context problem with the timers
-
- 20021020 O. Galibert
- - DMA implementation, lightly tested
- - delay slot in debugger fixed
- - add divide box mirrors
- - Nicola-ify the indentation
- - Uncrapify sh2_internal_*
- - Put back nmi support that had been lost somehow
-
- 20020914 R. Belmont
- - Initial SH2 internal timers implementation, based on code by O. Galibert.
- Makes music work in galspanic4/s/s2, panic street, cyvern, other SKNS games.
- - Fix to external division, thanks to "spice" on the E2J board.
- Corrects behavior of s1945ii turret boss.
-
- 20020302 Olivier Galibert (galibert@mame.net)
- - Fixed interrupt in delay slot
- - Fixed rotcr
- - Fixed div1
- - Fixed mulu
- - Fixed negc
-
- 20020301 R. Belmont
- - Fixed external division
-
- 20020225 Olivier Galibert (galibert@mame.net)
- - Fixed interrupt handling
-
- 20010207 Sylvain Glaize (mokona@puupuu.org)
-
- - Bug fix in void MOVBM(uint32_t m, uint32_t n) (see comment)
- - Support of full 32 bit addressing (RB, RW, RL and WB, WW, WL functions)
- reason : when the two high bits of the address are set, access is
- done directly in the cache data array. The SUPER KANEKO NOVA SYSTEM
- sets the stack pointer here, using these addresses as usual RAM access.
-
- No real cache support has been added.
- - Read/Write memory format correction (_bew to _bedw) (see also SH2
- definition in cpuintrf.c and DasmSH2(..) in sh2dasm.c )
-
- 20010623 James Forshaw (TyRaNiD@totalise.net)
-
- - Modified operation of sh2_exception. Done cause mame irq system is stupid, and
- doesnt really seem designed for any more than 8 interrupt lines.
-
- 20010701 James Forshaw (TyRaNiD@totalise.net)
-
- - Fixed DIV1 operation. Q bit now correctly generated
-
- 20020218 Added save states (mokona@puupuu.org)
-
- *****************************************************************************/
#include "emu.h"
#include "sh2.h"
-#include "sh2comn.h"
#include "sh_dasm.h"
-#include "debugger.h"
+#include "cpu/drcumlsh.h"
//#define VERBOSE 1
#include "logmacro.h"
+constexpr int SH2_INT_15 = 15;
-
-
-DEFINE_DEVICE_TYPE(SH1, sh1_device, "sh1", "Hitachi SH-1")
-DEFINE_DEVICE_TYPE(SH2, sh2_device, "sh2", "Hitachi SH-2")
-DEFINE_DEVICE_TYPE(SH2A, sh2a_device, "sh21", "Hitachi SH-2A")
-
-/*-------------------------------------------------
- sh2_internal_a5 - read handler for
- SH2 internal map
--------------------------------------------------*/
-
-READ32_MEMBER(sh2_device::sh2_internal_a5)
-{
- return 0xa5a5a5a5;
-}
-
-
-/*-------------------------------------------------
- sh2_internal_map - maps SH2 built-ins
--------------------------------------------------*/
-
-
-void sh2_device::sh7604_map(address_map &map)
+sh2_device::sh2_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock, int cpu_type, address_map_constructor internal_map, int addrlines, uint32_t address_mask)
+ : sh_common_execution(mconfig, type, tag, owner, clock, ENDIANNESS_BIG, internal_map)
+ , m_am(address_mask)
+ , m_program_config("program", ENDIANNESS_BIG, 32, addrlines, 0, internal_map)
+ , m_decrypted_program_config("decrypted_opcodes", ENDIANNESS_BIG, 32, addrlines, 0)
+ , m_drcfe(nullptr)
{
- map(0x40000000, 0xbfffffff).r(FUNC(sh2_device::sh2_internal_a5));
-
-// TODO: cps3boot breaks with this enabled. Needs callback
-// AM_RANGE(0xc0000000, 0xc0000fff) AM_RAM // cache data array
-
-// map(0xe0000000, 0xe00001ff).mirror(0x1ffffe00).rw(FUNC(sh2_device::sh7604_r), FUNC(sh2_device::sh7604_w));
- // TODO: internal map takes way too much resources if mirrored with 0x1ffffe00
- // we eventually internalize again via trampoline & sh7604_device
- // Also area 0xffff8000-0xffffbfff is for synchronous DRAM mode,
- // so this isn't actually a full mirror
- // SCI
- map(0xfffffe00, 0xfffffe00).rw(FUNC(sh2_device::smr_r), FUNC(sh2_device::smr_w));
- map(0xfffffe01, 0xfffffe01).rw(FUNC(sh2_device::brr_r), FUNC(sh2_device::brr_w));
- map(0xfffffe02, 0xfffffe02).rw(FUNC(sh2_device::scr_r), FUNC(sh2_device::scr_w));
- map(0xfffffe03, 0xfffffe03).rw(FUNC(sh2_device::tdr_r), FUNC(sh2_device::tdr_w));
- map(0xfffffe04, 0xfffffe04).rw(FUNC(sh2_device::ssr_r), FUNC(sh2_device::ssr_w));
- map(0xfffffe05, 0xfffffe05).r(FUNC(sh2_device::rdr_r));
-
- // FRC
- map(0xfffffe10, 0xfffffe10).rw(FUNC(sh2_device::tier_r), FUNC(sh2_device::tier_w));
- map(0xfffffe11, 0xfffffe11).rw(FUNC(sh2_device::ftcsr_r), FUNC(sh2_device::ftcsr_w));
- map(0xfffffe12, 0xfffffe13).rw(FUNC(sh2_device::frc_r), FUNC(sh2_device::frc_w));
- map(0xfffffe14, 0xfffffe15).rw(FUNC(sh2_device::ocra_b_r), FUNC(sh2_device::ocra_b_w));
- map(0xfffffe16, 0xfffffe16).rw(FUNC(sh2_device::frc_tcr_r), FUNC(sh2_device::frc_tcr_w));
- map(0xfffffe17, 0xfffffe17).rw(FUNC(sh2_device::tocr_r), FUNC(sh2_device::tocr_w));
- map(0xfffffe18, 0xfffffe19).r(FUNC(sh2_device::frc_icr_r));
-
- // INTC
- map(0xfffffe60, 0xfffffe61).rw(FUNC(sh2_device::iprb_r), FUNC(sh2_device::iprb_w));
- map(0xfffffe62, 0xfffffe63).rw(FUNC(sh2_device::vcra_r), FUNC(sh2_device::vcra_w));
- map(0xfffffe64, 0xfffffe65).rw(FUNC(sh2_device::vcrb_r), FUNC(sh2_device::vcrb_w));
- map(0xfffffe66, 0xfffffe67).rw(FUNC(sh2_device::vcrc_r), FUNC(sh2_device::vcrc_w));
- map(0xfffffe68, 0xfffffe69).rw(FUNC(sh2_device::vcrd_r), FUNC(sh2_device::vcrd_w));
-
- map(0xfffffe71, 0xfffffe71).rw(FUNC(sh2_device::drcr_r<0>), FUNC(sh2_device::drcr_w<0>));
- map(0xfffffe72, 0xfffffe72).rw(FUNC(sh2_device::drcr_r<1>), FUNC(sh2_device::drcr_w<1>));
-
- // WTC
- map(0xfffffe80, 0xfffffe81).rw(FUNC(sh2_device::wtcnt_r), FUNC(sh2_device::wtcnt_w));
- map(0xfffffe82, 0xfffffe83).rw(FUNC(sh2_device::rstcsr_r), FUNC(sh2_device::rstcsr_w));
-
- // standby and cache control
- map(0xfffffe90, 0xfffffe91).rw(FUNC(sh2_device::fmr_sbycr_r), FUNC(sh2_device::fmr_sbycr_w));
- map(0xfffffe92, 0xfffffe92).rw(FUNC(sh2_device::ccr_r), FUNC(sh2_device::ccr_w));
-
- // INTC second section
- map(0xfffffee0, 0xfffffee1).rw(FUNC(sh2_device::intc_icr_r), FUNC(sh2_device::intc_icr_w));
- map(0xfffffee2, 0xfffffee3).rw(FUNC(sh2_device::ipra_r), FUNC(sh2_device::ipra_w));
- map(0xfffffee4, 0xfffffee5).rw(FUNC(sh2_device::vcrwdt_r), FUNC(sh2_device::vcrwdt_w));
-
- // DIVU
- map(0xffffff00, 0xffffff03).rw(FUNC(sh2_device::dvsr_r), FUNC(sh2_device::dvsr_w));
- map(0xffffff04, 0xffffff07).rw(FUNC(sh2_device::dvdnt_r), FUNC(sh2_device::dvdnt_w));
- map(0xffffff08, 0xffffff0b).rw(FUNC(sh2_device::dvcr_r), FUNC(sh2_device::dvcr_w));
- // INTC third section
- map(0xffffff0c, 0xffffff0f).rw(FUNC(sh2_device::vcrdiv_r), FUNC(sh2_device::vcrdiv_w));
- // DIVU continued (64-bit plus mirrors)
- map(0xffffff10, 0xffffff13).rw(FUNC(sh2_device::dvdnth_r), FUNC(sh2_device::dvdnth_w));
- map(0xffffff14, 0xffffff17).rw(FUNC(sh2_device::dvdntl_r), FUNC(sh2_device::dvdntl_w));
- map(0xffffff18, 0xffffff1b).r(FUNC(sh2_device::dvdnth_r));
- map(0xffffff1c, 0xffffff1f).r(FUNC(sh2_device::dvdntl_r));
-
- // DMAC
- map(0xffffff80, 0xffffff83).rw(FUNC(sh2_device::sar_r<0>), FUNC(sh2_device::sar_w<0>));
- map(0xffffff84, 0xffffff87).rw(FUNC(sh2_device::dar_r<0>), FUNC(sh2_device::dar_w<0>));
- map(0xffffff88, 0xffffff8b).rw(FUNC(sh2_device::dmac_tcr_r<0>), FUNC(sh2_device::dmac_tcr_w<0>));
- map(0xffffff8c, 0xffffff8f).rw(FUNC(sh2_device::chcr_r<0>), FUNC(sh2_device::chcr_w<0>));
-
- map(0xffffff90, 0xffffff93).rw(FUNC(sh2_device::sar_r<1>), FUNC(sh2_device::sar_w<1>));
- map(0xffffff94, 0xffffff97).rw(FUNC(sh2_device::dar_r<1>), FUNC(sh2_device::dar_w<1>));
- map(0xffffff98, 0xffffff9b).rw(FUNC(sh2_device::dmac_tcr_r<1>), FUNC(sh2_device::dmac_tcr_w<1>));
- map(0xffffff9c, 0xffffff9f).rw(FUNC(sh2_device::chcr_r<1>), FUNC(sh2_device::chcr_w<1>));
-
- map(0xffffffa0, 0xffffffa3).rw(FUNC(sh2_device::vcrdma_r<0>), FUNC(sh2_device::vcrdma_w<0>));
- map(0xffffffa8, 0xffffffab).rw(FUNC(sh2_device::vcrdma_r<1>), FUNC(sh2_device::vcrdma_w<1>));
- map(0xffffffb0, 0xffffffb3).rw(FUNC(sh2_device::dmaor_r), FUNC(sh2_device::dmaor_w));
-
- // BSC
- map(0xffffffe0, 0xffffffe3).rw(FUNC(sh2_device::bcr1_r), FUNC(sh2_device::bcr1_w));
- map(0xffffffe4, 0xffffffe7).rw(FUNC(sh2_device::bcr2_r), FUNC(sh2_device::bcr2_w));
- map(0xffffffe8, 0xffffffeb).rw(FUNC(sh2_device::wcr_r), FUNC(sh2_device::wcr_w));
- map(0xffffffec, 0xffffffef).rw(FUNC(sh2_device::mcr_r), FUNC(sh2_device::mcr_w));
- map(0xfffffff0, 0xfffffff3).rw(FUNC(sh2_device::rtcsr_r), FUNC(sh2_device::rtcsr_w));
- map(0xfffffff4, 0xfffffff7).rw(FUNC(sh2_device::rtcnt_r), FUNC(sh2_device::rtcnt_w));
- map(0xfffffff8, 0xfffffffb).rw(FUNC(sh2_device::rtcor_r), FUNC(sh2_device::rtcor_w));
+ m_cpu_type = cpu_type;
+ m_isdrc = allow_drc();
}
-void sh2a_device::sh7021_map(address_map &map)
+void sh2_device::device_start()
{
-// fall-back
- map(0x05fffe00, 0x05ffffff).rw(FUNC(sh2a_device::sh7021_r), FUNC(sh2a_device::sh7021_w)); // SH-7032H internal i/o
-// overrides
- map(0x05ffff40, 0x05ffff43).rw(FUNC(sh2a_device::dma_sar0_r), FUNC(sh2a_device::dma_sar0_w));
- map(0x05ffff44, 0x05ffff47).rw(FUNC(sh2a_device::dma_dar0_r), FUNC(sh2a_device::dma_dar0_w));
- map(0x05ffff48, 0x05ffff49).rw(FUNC(sh2a_device::dmaor_r), FUNC(sh2a_device::dmaor_w));
- map(0x05ffff4a, 0x05ffff4b).rw(FUNC(sh2a_device::dma_tcr0_r), FUNC(sh2a_device::dma_tcr0_w));
- map(0x05ffff4e, 0x05ffff4f).rw(FUNC(sh2a_device::dma_chcr0_r), FUNC(sh2a_device::dma_chcr0_w));
-// AM_RANGE(0x07000000, 0x070003ff) AM_RAM AM_SHARE("oram")// on-chip RAM, actually at 0xf000000 (1 kb)
-// AM_RANGE(0x0f000000, 0x0f0003ff) AM_RAM AM_SHARE("oram")// on-chip RAM, actually at 0xf000000 (1 kb)
-}
+ sh_common_execution::device_start();
-void sh1_device::sh7032_map(address_map &map)
-{
-// fall-back
- map(0x05fffe00, 0x05ffffff).rw(FUNC(sh1_device::sh7032_r), FUNC(sh1_device::sh7032_w)); // SH-7032H internal i/o
-}
+ m_decrypted_program = has_space(AS_OPCODES) ? &space(AS_OPCODES) : &space(AS_PROGRAM);
+ m_decrypted_program->cache(m_cache32);
+ m_pr16 = [this](offs_t address) -> u16 { return m_cache32.read_word(address); };
+ if (m_decrypted_program->endianness() != ENDIANNESS_NATIVE)
+ m_prptr = [this](offs_t address) -> const void * {
+ const u16 *ptr = reinterpret_cast<u16 *>(m_cache32.read_ptr(address & ~3));
+ if (!(address & 2))
+ ptr++;
+ return ptr;
+ };
+ else
+ m_prptr = [this](offs_t address) -> const void * {
+ const u16 *ptr = reinterpret_cast<u16 *>(m_cache32.read_ptr(address & ~3));
+ if (address & 2)
+ ptr++;
+ return ptr;
+ };
-sh2_device::sh2_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : sh2_device(mconfig, SH2, tag, owner, clock, CPU_TYPE_SH2, address_map_constructor(FUNC(sh2_device::sh7604_map), this), 32)
-{
-}
+ // internals
+ save_item(NAME(m_cpu_off));
+ save_item(NAME(m_test_irq));
+ save_item(NAME(m_irq_line_state));
+ save_item(NAME(m_nmi_line_state));
+ save_item(NAME(m_internal_irq_vector));
-sh2_device::~sh2_device()
-{
-}
+ state_add(STATE_GENPC, "PC", m_sh2_state->pc).mask(m_am).callimport();
+ state_add(STATE_GENPCBASE, "CURPC", m_sh2_state->pc).callimport().noshow();
+ m_nmi_line_state = 0;
-void sh2_device::device_stop()
-{
+ drc_start();
}
-
-
-
-sh2_device::sh2_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock, int cpu_type, address_map_constructor internal_map, int addrlines)
- : sh_common_execution(mconfig, type, tag, owner, clock, ENDIANNESS_BIG, internal_map)
- , m_program_config("program", ENDIANNESS_BIG, 32, addrlines, 0, internal_map)
- , m_decrypted_program_config("decrypted_opcodes", ENDIANNESS_BIG, 32, addrlines, 0)
- , m_is_slave(0)
- , m_drcfe(nullptr)
- , m_debugger_temp(0)
+void sh2_device::device_reset()
{
- m_cpu_type = cpu_type;
- m_am = SH12_AM;
- m_isdrc = allow_drc();
-}
+ std::fill(std::begin(m_sh2_state->r), std::end(m_sh2_state->r), 0);
+ std::fill(std::begin(m_irq_line_state), std::end(m_irq_line_state), 0);
-sh2a_device::sh2a_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : sh2_device(mconfig, SH2A, tag, owner, clock, CPU_TYPE_SH2, address_map_constructor(FUNC(sh2a_device::sh7021_map), this), 28)
-{
-}
+ m_sh2_state->pc = m_sh2_state->pr = m_sh2_state->sr = m_sh2_state->gbr = m_sh2_state->vbr = m_sh2_state->mach = m_sh2_state->macl = 0;
+ m_sh2_state->evec = m_sh2_state->irqsr = 0;
+ m_sh2_state->ea = m_sh2_state->m_delay = 0;
+ m_sh2_state->pending_irq = 0;
+ m_sh2_state->pending_nmi = 0;
+ m_sh2_state->sleep_mode = 0;
+ m_sh2_state->internal_irq_level = -1;
+ m_sh2_state->sr = SH_I;
+ m_sh2_state->pc = read_long(0);
+ m_sh2_state->r[15] = read_long(4);
-sh1_device::sh1_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : sh2_device(mconfig, SH1, tag, owner, clock, CPU_TYPE_SH1, address_map_constructor(FUNC(sh1_device::sh7032_map), this), 28)
-{
+ m_test_irq = 0;
+ m_cpu_off = 0;
+ m_internal_irq_vector = 0;
+ m_cache_dirty = true;
}
device_memory_interface::space_config_vector sh2_device::memory_space_config() const
{
- if(has_configured_map(AS_OPCODES))
- return space_config_vector {
+ if (has_configured_map(AS_OPCODES))
+ return space_config_vector
+ {
std::make_pair(AS_PROGRAM, &m_program_config),
std::make_pair(AS_OPCODES, &m_decrypted_program_config)
};
else
- return space_config_vector {
+ return space_config_vector
+ {
std::make_pair(AS_PROGRAM, &m_program_config)
};
}
@@ -291,75 +113,105 @@ std::unique_ptr<util::disasm_interface> sh2_device::create_disassembler()
return std::make_unique<sh_disassembler>(false);
}
-uint8_t sh2_device::RB(offs_t A)
+uint8_t sh2_device::read_byte(offs_t offset)
{
- if((A & 0xf0000000) == 0 || (A & 0xf0000000) == 0x20000000)
- return m_program->read_byte(A & SH12_AM);
+ if ((offset & 0xf0000000) == 0 || (offset & 0xf0000000) == 0x20000000)
+ return m_program->read_byte(offset & m_am);
- return m_program->read_byte(A);
+ return m_program->read_byte(offset);
}
-uint16_t sh2_device::RW(offs_t A)
+uint16_t sh2_device::read_word(offs_t offset)
{
- if((A & 0xf0000000) == 0 || (A & 0xf0000000) == 0x20000000)
- return m_program->read_word(A & SH12_AM);
+ if ((offset & 0xf0000000) == 0 || (offset & 0xf0000000) == 0x20000000)
+ return m_program->read_word(offset & m_am);
- return m_program->read_word(A);
+ return m_program->read_word(offset);
}
-uint32_t sh2_device::RL(offs_t A)
+uint32_t sh2_device::read_long(offs_t offset)
{
/* 0x20000000 no Cache */
/* 0x00000000 read thru Cache if CE bit is 1 */
- if((A & 0xf0000000) == 0 || (A & 0xf0000000) == 0x20000000)
- return m_program->read_dword(A & SH12_AM);
+ if ((offset & 0xf0000000) == 0 || (offset & 0xf0000000) == 0x20000000)
+ return m_program->read_dword(offset & m_am);
+
+ return m_program->read_dword(offset);
+}
- return m_program->read_dword(A);
+uint16_t sh2_device::decrypted_read_word(offs_t offset)
+{
+ return m_decrypted_program->read_word(offset);
}
-void sh2_device::WB(offs_t A, uint8_t V)
+void sh2_device::write_byte(offs_t offset, uint8_t data)
{
- if((A & 0xf0000000) == 0 || (A & 0xf0000000) == 0x20000000)
+ if ((offset & 0xf0000000) == 0 || (offset & 0xf0000000) == 0x20000000)
{
- m_program->write_byte(A & SH12_AM,V);
+ m_program->write_byte(offset & m_am, data);
return;
}
- m_program->write_byte(A,V);
+ m_program->write_byte(offset, data);
}
-void sh2_device::WW(offs_t A, uint16_t V)
+void sh2_device::write_word(offs_t offset, uint16_t data)
{
- if((A & 0xf0000000) == 0 || (A & 0xf0000000) == 0x20000000)
+ if ((offset & 0xf0000000) == 0 || (offset & 0xf0000000) == 0x20000000)
{
- m_program->write_word(A & SH12_AM,V);
+ m_program->write_word(offset & m_am, data);
return;
}
- m_program->write_word(A,V);
+ m_program->write_word(offset, data);
}
-void sh2_device::WL(offs_t A, uint32_t V)
+void sh2_device::write_long(offs_t offset, uint32_t data)
{
- if((A & 0xf0000000) == 0 || (A & 0xf0000000) == 0x20000000)
+ if ((offset & 0xf0000000) == 0 || (offset & 0xf0000000) == 0x20000000)
{
- m_program->write_dword(A & SH12_AM,V);
+ m_program->write_dword(offset & m_am, data);
return;
}
/* 0x20000000 no Cache */
/* 0x00000000 read thru Cache if CE bit is 1 */
- m_program->write_dword(A,V);
+ m_program->write_dword(offset, data);
+}
+
+void sh2_device::check_pending_irq(const char *message)
+{
+ if (m_sh2_state->pending_nmi)
+ {
+ sh2_exception(message, 16);
+ m_sh2_state->pending_nmi = 0;
+ }
+ else
+ {
+ int irq = m_sh2_state->internal_irq_level;
+ if (m_sh2_state->pending_irq)
+ {
+ int external_irq = 15 - (count_leading_zeros_32(m_sh2_state->pending_irq) - 16);
+ if (external_irq >= irq)
+ {
+ irq = external_irq;
+ }
+ }
+
+ if (irq >= 0)
+ {
+ sh2_exception(message, irq);
+ }
+ }
}
/* LDC.L @Rm+,SR */
inline void sh2_device::LDCMSR(const uint16_t opcode) // passes Rn
{
- uint32_t x = Rn;
-
- m_sh2_state->ea = m_sh2_state->r[x];
- m_sh2_state->sr = RL( m_sh2_state->ea ) & SH_FLAGS;
- m_sh2_state->r[x] += 4;
+ const uint32_t rn = REG_N;
+ m_sh2_state->ea = m_sh2_state->r[rn];
+ m_sh2_state->sr = read_long(m_sh2_state->ea) & SH_FLAGS;
+ m_sh2_state->r[rn] += 4;
m_sh2_state->icount -= 2;
m_test_irq = 1;
}
@@ -367,9 +219,7 @@ inline void sh2_device::LDCMSR(const uint16_t opcode) // passes Rn
/* LDC Rm,SR */
inline void sh2_device::LDCSR(const uint16_t opcode) // passes Rn
{
- uint32_t x = Rn;
-
- m_sh2_state->sr = m_sh2_state->r[x] & SH_FLAGS;
+ m_sh2_state->sr = m_sh2_state->r[REG_N] & SH_FLAGS;
m_test_irq = 1;
}
@@ -377,10 +227,10 @@ inline void sh2_device::LDCSR(const uint16_t opcode) // passes Rn
inline void sh2_device::RTE()
{
m_sh2_state->ea = m_sh2_state->r[15];
- m_sh2_state->m_delay = RL( m_sh2_state->ea );
+ m_sh2_state->m_delay = read_long(m_sh2_state->ea);
m_sh2_state->r[15] += 4;
m_sh2_state->ea = m_sh2_state->r[15];
- m_sh2_state->sr = RL( m_sh2_state->ea ) & SH_FLAGS;
+ m_sh2_state->sr = read_long(m_sh2_state->ea) & SH_FLAGS;
m_sh2_state->r[15] += 4;
m_sh2_state->icount -= 3;
m_test_irq = 1;
@@ -390,15 +240,16 @@ inline void sh2_device::RTE()
inline void sh2_device::TRAPA(uint32_t i)
{
uint32_t imm = i & 0xff;
+ debugger_exception_hook(imm);
m_sh2_state->ea = m_sh2_state->vbr + imm * 4;
m_sh2_state->r[15] -= 4;
- WL( m_sh2_state->r[15], m_sh2_state->sr );
+ write_long(m_sh2_state->r[15], m_sh2_state->sr);
m_sh2_state->r[15] -= 4;
- WL( m_sh2_state->r[15], m_sh2_state->pc );
+ write_long(m_sh2_state->r[15], m_sh2_state->pc);
- m_sh2_state->pc = RL( m_sh2_state->ea );
+ m_sh2_state->pc = read_long(m_sh2_state->ea);
m_sh2_state->icount -= 7;
}
@@ -407,63 +258,28 @@ inline void sh2_device::TRAPA(uint32_t i)
inline void sh2_device::ILLEGAL()
{
//logerror("Illegal opcode at %08x\n", m_sh2_state->pc - 2);
+ debugger_exception_hook(4);
+
m_sh2_state->r[15] -= 4;
- WL( m_sh2_state->r[15], m_sh2_state->sr ); /* push SR onto stack */
+ write_long(m_sh2_state->r[15], m_sh2_state->sr); /* push SR onto stack */
m_sh2_state->r[15] -= 4;
- WL( m_sh2_state->r[15], m_sh2_state->pc - 2 ); /* push PC onto stack */
+ write_long(m_sh2_state->r[15], m_sh2_state->pc - 2); /* push PC onto stack */
/* fetch PC */
- m_sh2_state->pc = RL( m_sh2_state->vbr + 4 * 4 );
+ m_sh2_state->pc = read_long(m_sh2_state->vbr + 4 * 4);
/* TODO: timing is a guess */
m_sh2_state->icount -= 5;
}
-/*****************************************************************************
- * OPCODE DISPATCHERS
- *****************************************************************************/
-
-
void sh2_device::execute_one_f000(uint16_t opcode)
{
ILLEGAL();
}
-/*****************************************************************************
- * MAME CPU INTERFACE
- *****************************************************************************/
-
-void sh2_device::device_reset()
-{
- m_sh2_state->pc = m_sh2_state->pr = m_sh2_state->sr = m_sh2_state->gbr = m_sh2_state->vbr = m_sh2_state->mach = m_sh2_state->macl = 0;
- m_sh2_state->evec = m_sh2_state->irqsr = 0;
- memset(&m_sh2_state->r[0], 0, sizeof(m_sh2_state->r[0])*16);
- m_sh2_state->ea = m_sh2_state->m_delay = m_cpu_off = 0;
- //m_dvsr = m_dvdnth = m_dvdntl = m_dvcr = 0;
- m_sh2_state->pending_irq = m_test_irq = 0;
- //memset(&m_irq_queue[0], 0, sizeof(m_irq_queue[0])*16);
- memset(&m_irq_line_state[0], 0, sizeof(m_irq_line_state[0])*17);
- m_frc = m_ocra = m_ocrb = m_frc_icr = 0;
- m_frc_base = 0;
- m_frt_input = m_sh2_state->internal_irq_level = m_internal_irq_vector = 0;
- m_dma_timer_active[0] = m_dma_timer_active[1] = 0;
- m_dma_irq[0] = m_dma_irq[1] = 0;
-
- m_sh2_state->pc = RL(0);
- m_sh2_state->r[15] = RL(4);
- m_sh2_state->sr = SH_I;
- m_sh2_state->sleep_mode = 0;
-
- m_sh2_state->internal_irq_level = -1;
-
- m_cache_dirty = true;
-}
-
-
-/* Execute cycles - returns number of cycles actually run */
void sh2_device::execute_run()
{
- if ( m_isdrc )
+ if (m_isdrc)
{
execute_run_drc();
return;
@@ -471,6 +287,7 @@ void sh2_device::execute_run()
if (m_cpu_off)
{
+ debugger_wait_hook();
m_sh2_state->icount = 0;
return;
}
@@ -479,7 +296,7 @@ void sh2_device::execute_run()
{
debugger_instruction_hook(m_sh2_state->pc);
- const uint16_t opcode = m_decrypted_program->read_word(m_sh2_state->pc >= 0x40000000 ? m_sh2_state->pc : m_sh2_state->pc & SH12_AM);
+ const uint16_t opcode = m_decrypted_program->read_word(m_sh2_state->pc >= 0x40000000 ? m_sh2_state->pc : m_sh2_state->pc & m_am);
if (m_sh2_state->m_delay)
{
@@ -491,204 +308,20 @@ void sh2_device::execute_run()
execute_one(opcode);
- if(m_test_irq && !m_sh2_state->m_delay)
+ if (m_test_irq && !m_sh2_state->m_delay)
{
- CHECK_PENDING_IRQ("mame_sh2_execute");
+ check_pending_irq("mame_sh2_execute");
m_test_irq = 0;
}
m_sh2_state->icount--;
- } while( m_sh2_state->icount > 0 );
+ } while (m_sh2_state->icount > 0);
}
-
void sh2_device::init_drc_frontend()
{
m_drcfe = std::make_unique<sh2_frontend>(this, COMPILE_BACKWARDS_BYTES, COMPILE_FORWARDS_BYTES, SINGLE_INSTRUCTION_MODE ? 1 : COMPILE_MAX_SEQUENCE);
}
-void sh2_device::device_start()
-{
- sh_common_execution::device_start();
-
- m_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(sh2_device::sh2_timer_callback), this));
- m_timer->adjust(attotime::never);
-
- m_dma_current_active_timer[0] = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(sh2_device::sh2_dma_current_active_callback), this));
- m_dma_current_active_timer[0]->adjust(attotime::never);
-
- m_dma_current_active_timer[1] = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(sh2_device::sh2_dma_current_active_callback), this));
- m_dma_current_active_timer[1]->adjust(attotime::never);
-
- /* resolve callbacks */
- m_dma_kludge_cb.bind_relative_to(*owner());
- m_dma_fifo_data_available_cb.bind_relative_to(*owner());
- m_ftcsr_read_cb.bind_relative_to(*owner());
-
- m_decrypted_program = has_space(AS_OPCODES) ? &space(AS_OPCODES) : &space(AS_PROGRAM);
- auto cache = m_decrypted_program->cache<2, 0, ENDIANNESS_BIG>();
- m_pr16 = [cache](offs_t address) -> u16 { return cache->read_word(address); };
- if (m_decrypted_program->endianness() != ENDIANNESS_NATIVE)
- m_prptr = [cache](offs_t address) -> const void * {
- const u16 *ptr = static_cast<u16 *>(cache->read_ptr(address & ~3));
- if(!(address & 2))
- ptr++;
- return ptr;
- };
- else
- m_prptr = [cache](offs_t address) -> const void * {
- const u16 *ptr = static_cast<u16 *>(cache->read_ptr(address & ~3));
- if(address & 2)
- ptr++;
- return ptr;
- };
-
- m_internal = &space(AS_PROGRAM);
-
- // SCI
- save_item(NAME(m_smr));
- save_item(NAME(m_brr));
- save_item(NAME(m_scr));
- save_item(NAME(m_tdr));
- save_item(NAME(m_ssr));
-
- // FRT / FRC
- save_item(NAME(m_tier));
- save_item(NAME(m_ftcsr));
- save_item(NAME(m_frc_tcr));
- save_item(NAME(m_tocr));
- save_item(NAME(m_frc));
- save_item(NAME(m_ocra));
- save_item(NAME(m_ocrb));
- save_item(NAME(m_frc_icr));
- save_item(NAME(m_frc_base));
- save_item(NAME(m_frt_input));
-
- // INTC
- save_item(NAME(m_irq_level.frc));
- save_item(NAME(m_irq_level.sci));
- save_item(NAME(m_irq_level.divu));
- save_item(NAME(m_irq_level.dmac));
- save_item(NAME(m_irq_level.wdt));
- save_item(NAME(m_irq_vector.fic));
- save_item(NAME(m_irq_vector.foc));
- save_item(NAME(m_irq_vector.fov));
- save_item(NAME(m_irq_vector.divu));
- save_item(NAME(m_irq_vector.dmac[0]));
- save_item(NAME(m_irq_vector.dmac[1]));
-
- save_item(NAME(m_ipra));
- save_item(NAME(m_iprb));
- save_item(NAME(m_vcra));
- save_item(NAME(m_vcrb));
- save_item(NAME(m_vcrc));
- save_item(NAME(m_vcrd));
- save_item(NAME(m_vcrwdt));
- save_item(NAME(m_vcrdiv));
- save_item(NAME(m_intc_icr));
- save_item(NAME(m_vcrdma[0]));
- save_item(NAME(m_vcrdma[1]));
-
- save_item(NAME(m_vecmd));
- save_item(NAME(m_nmie));
-
- // DIVU
- save_item(NAME(m_divu_ovf));
- save_item(NAME(m_divu_ovfie));
- save_item(NAME(m_dvsr));
- save_item(NAME(m_dvdntl));
- save_item(NAME(m_dvdnth));
-
- // WTC
- save_item(NAME(m_wtcnt));
- save_item(NAME(m_wtcsr));
- save_item(NAME(m_rstcsr));
- save_item(NAME(m_wtcw[0]));
- save_item(NAME(m_wtcw[1]));
-
- // DMAC
- save_item(NAME(m_dmaor));
- save_item(NAME(m_dmac[0].drcr));
- save_item(NAME(m_dmac[1].drcr));
- save_item(NAME(m_dmac[0].sar));
- save_item(NAME(m_dmac[1].sar));
- save_item(NAME(m_dmac[0].dar));
- save_item(NAME(m_dmac[1].dar));
- save_item(NAME(m_dmac[0].tcr));
- save_item(NAME(m_dmac[1].tcr));
- save_item(NAME(m_dmac[0].chcr));
- save_item(NAME(m_dmac[1].chcr));
-
- // misc
- save_item(NAME(m_sbycr));
- save_item(NAME(m_ccr));
-
- // BSC
- save_item(NAME(m_bcr1));
- save_item(NAME(m_bcr2));
- save_item(NAME(m_wcr));
- save_item(NAME(m_mcr));
- save_item(NAME(m_rtcsr));
- save_item(NAME(m_rtcor));
- save_item(NAME(m_rtcnt));
-
- /*
- for (int i = 0; i < 16; ++i)
- {
- save_item(NAME(m_irq_queue[i].irq_vector), i);
- save_item(NAME(m_irq_queue[i].irq_priority), i);
- }
- */
-
- // internals
- save_item(NAME(m_cpu_off));
- save_item(NAME(m_test_irq));
- save_item(NAME(m_irq_line_state));
- save_item(NAME(m_nmi_line_state));
- save_item(NAME(m_internal_irq_vector));
- save_item(NAME(m_dma_timer_active));
- save_item(NAME(m_dma_irq));
-
- state_add( STATE_GENPC, "PC", m_sh2_state->pc).mask(SH12_AM).callimport();
- state_add( STATE_GENPCBASE, "CURPC", m_sh2_state->pc ).callimport().noshow();
-
- // Clear state
- m_cpu_off = 0;
- //m_dvsr = 0;
- //m_dvdnth = 0;
- //m_dvdntl = 0;
- //m_dvcr = 0;
- m_test_irq = 0;
-
- memset(m_irq_line_state, 0, sizeof(m_irq_line_state));
-
- m_nmi_line_state = 0;
- m_frc = 0;
- m_ocra = 0;
- m_ocrb = 0;
- m_frc_icr = 0;
- m_frc_base = 0;
- m_frt_input = 0;
- m_internal_irq_vector = 0;
-
- for ( int i = 0; i < 2; i++ )
- {
- m_dma_timer_active[i] = 0;
- m_dma_irq[i] = 0;
- m_active_dma_incs[i] = 0;
- m_active_dma_incd[i] = 0;
- m_active_dma_size[i] = 0;
- m_active_dma_steal[i] = 0;
- m_active_dma_src[i] = 0;
- m_active_dma_dst[i] = 0;
- m_active_dma_count[i] = 0;
- }
- m_wtcnt = 0;
- m_wtcsr = 0;
-
- drc_start();
-}
-
-
void sh2_device::state_string_export(const device_state_entry &entry, std::string &str) const
{
switch (entry.index())
@@ -704,7 +337,6 @@ void sh2_device::state_string_export(const device_state_entry &entry, std::strin
}
}
-
void sh2_device::state_import(const device_state_entry &entry)
{
switch (entry.index())
@@ -715,38 +347,48 @@ void sh2_device::state_import(const device_state_entry &entry)
break;
case SH_SR:
- CHECK_PENDING_IRQ("sh2_set_reg");
+ check_pending_irq("sh2_set_reg");
break;
}
}
-
void sh2_device::execute_set_input(int irqline, int state)
{
if (irqline == INPUT_LINE_NMI)
{
if (m_nmi_line_state == state)
return;
+
m_nmi_line_state = state;
if (state == CLEAR_LINE)
{
- LOG("SH-2 cleared nmi\n");
+ LOG("SH-2 cleared NMI\n");
}
else
{
- LOG("SH-2 asserted nmi\n");
+ LOG("SH-2 asserted NMI\n");
- sh2_exception("Set IRQ line", 16);
+ m_sh2_state->pending_nmi = 1;
if (m_isdrc)
- m_sh2_state->pending_nmi = 1;
+ {
+ sh2_exception("Set IRQ line", 16);
+ }
+ else
+ {
+ if (m_sh2_state->m_delay)
+ m_test_irq = 1;
+ else
+ check_pending_irq("sh2_set_nmi_line");
+ }
}
}
else
{
if (m_irq_line_state[irqline] == state)
return;
+
m_irq_line_state[irqline] = state;
if (state == CLEAR_LINE)
@@ -758,14 +400,17 @@ void sh2_device::execute_set_input(int irqline, int state)
{
LOG("SH-2 asserted irq #%d\n", irqline);
m_sh2_state->pending_irq |= 1 << irqline;
+
if (m_isdrc)
{
m_test_irq = 1;
- } else {
- if(m_sh2_state->m_delay)
+ }
+ else
+ {
+ if (m_sh2_state->m_delay)
m_test_irq = 1;
else
- CHECK_PENDING_IRQ("sh2_set_irq_line");
+ check_pending_irq("sh2_set_irq_line");
}
}
}
@@ -773,6 +418,7 @@ void sh2_device::execute_set_input(int irqline, int state)
void sh2_device::sh2_exception(const char *message, int irqline)
{
+ // override this at the individual CPU level when special logic is required
int vector;
if (irqline != 16)
@@ -790,17 +436,9 @@ void sh2_device::sh2_exception(const char *message, int irqline)
}
else
{
- if(m_vecmd == true)
- {
- vector = standard_irq_callback(irqline);
- LOG("SH-2 exception #%d (external vector: $%x) after [%s]\n", irqline, vector, message);
- }
- else
- {
- standard_irq_callback(irqline);
- vector = 64 + irqline/2;
- LOG("SH-2 exception #%d (autovector: $%x) after [%s]\n", irqline, vector, message);
- }
+ standard_irq_callback(irqline, m_sh2_state->pc);
+ vector = 64 + irqline/2;
+ LOG("SH-2 exception #%d (autovector: $%x) after [%s]\n", irqline, vector, message);
}
}
else
@@ -809,10 +447,17 @@ void sh2_device::sh2_exception(const char *message, int irqline)
LOG("SH-2 nmi exception (autovector: $%x) after [%s]\n", vector, message);
}
+ sh2_exception_internal(message, irqline, vector);
+}
+
+void sh2_device::sh2_exception_internal(const char *message, int irqline, int vector)
+{
+ debugger_exception_hook(vector);
+
if (m_isdrc)
{
- m_sh2_state->evec = RL( m_sh2_state->vbr + vector * 4 );
- m_sh2_state->evec &= SH12_AM;
+ m_sh2_state->evec = read_long(m_sh2_state->vbr + vector * 4);
+ m_sh2_state->evec &= m_am;
m_sh2_state->irqsr = m_sh2_state->sr;
/* set I flags in SR */
@@ -822,11 +467,13 @@ void sh2_device::sh2_exception(const char *message, int irqline)
m_sh2_state->sr = (m_sh2_state->sr & ~SH_I) | (irqline << 4);
// printf("sh2_exception [%s] irqline %x evec %x save SR %x new SR %x\n", message, irqline, m_sh2_state->evec, m_sh2_state->irqsr, m_sh2_state->sr);
- } else {
+ }
+ else
+ {
m_sh2_state->r[15] -= 4;
- WL( m_sh2_state->r[15], m_sh2_state->sr ); /* push SR onto stack */
+ write_long(m_sh2_state->r[15], m_sh2_state->sr); /* push SR onto stack */
m_sh2_state->r[15] -= 4;
- WL( m_sh2_state->r[15], m_sh2_state->pc ); /* push PC onto stack */
+ write_long(m_sh2_state->r[15], m_sh2_state->pc); /* push PC onto stack */
/* set I flags in SR */
if (irqline > SH2_INT_15)
@@ -835,46 +482,32 @@ void sh2_device::sh2_exception(const char *message, int irqline)
m_sh2_state->sr = (m_sh2_state->sr & ~SH_I) | (irqline << 4);
/* fetch PC */
- m_sh2_state->pc = RL( m_sh2_state->vbr + vector * 4 );
+ m_sh2_state->pc = read_long(m_sh2_state->vbr + vector * 4);
}
- if(m_sh2_state->sleep_mode == 1) { m_sh2_state->sleep_mode = 2; }
+ if (m_sh2_state->sleep_mode == 1)
+ m_sh2_state->sleep_mode = 2;
}
-// license:BSD-3-Clause
-// copyright-holders:R. Belmont
-/***************************************************************************
-
- sh2drc.c
- Universal machine language-based SH-2 emulator.
-
-***************************************************************************/
-
-#include "emu.h"
-#include "sh2.h"
-#include "sh2comn.h"
-#include "cpu/drcumlsh.h"
-#include "debugger.h"
-
+/////////
+// DRC
const opcode_desc* sh2_device::get_desclist(offs_t pc)
{
return m_drcfe->describe_code(pc);
}
-
+void sh2_device::func_fastirq()
+{
+ sh2_exception("fastirq", m_sh2_state->irqline);
+}
+static void cfunc_fastirq(void *param) { ((sh2_device *)param)->func_fastirq(); };
/*-------------------------------------------------
static_generate_entry_point - generate a
static entry point
-------------------------------------------------*/
-void sh2_device::func_fastirq()
-{
- sh2_exception("fastirq",m_sh2_state->irqline);
-}
-static void cfunc_fastirq(void *param) { ((sh2_device *)param)->func_fastirq(); };
-
void sh2_device::static_generate_entry_point()
{
uml::code_label const skip = 1;
@@ -1054,11 +687,11 @@ void sh2_device::static_generate_memory_accessor(int size, int iswrite, const ch
UML_CMP(block, I0, 0x40000000); // cmp #0x40000000, r0
UML_JMPc(block, COND_AE, label); // bae label
- UML_AND(block, I0, I0, SH12_AM); // and r0, r0, #AM (0xc7ffffff)
+ UML_AND(block, I0, I0, m_am); // and r0, r0, #AM (0xc7ffffff)
UML_LABEL(block, label++); // label:
- if ((machine().debug_flags & DEBUG_FLAG_ENABLED) == 0)
+ if (!debugger_enabled())
{
for (auto & elem : m_fastram)
{
@@ -1158,5 +791,3 @@ void sh2_device::static_generate_memory_accessor(int size, int iswrite, const ch
block.end();
}
-
-
diff --git a/src/devices/cpu/sh/sh2.h b/src/devices/cpu/sh/sh2.h
index 0226c346407..7e7af7c7d1e 100644
--- a/src/devices/cpu/sh/sh2.h
+++ b/src/devices/cpu/sh/sh2.h
@@ -12,37 +12,13 @@
*
*****************************************************************************/
-#ifndef MAME_CPU_SH2_SH2_H
-#define MAME_CPU_SH2_SH2_H
+#ifndef MAME_CPU_SH_SH2_H
+#define MAME_CPU_SH_SH2_H
#pragma once
-
#include "sh.h"
-#define SH2_INT_NONE -1
-#define SH2_INT_VBLIN 0
-#define SH2_INT_VBLOUT 1
-#define SH2_INT_HBLIN 2
-#define SH2_INT_TIMER0 3
-#define SH2_INT_TIMER1 4
-#define SH2_INT_DSP 5
-#define SH2_INT_SOUND 6
-#define SH2_INT_SMPC 7
-#define SH2_INT_PAD 8
-#define SH2_INT_DMA2 9
-#define SH2_INT_DMA1 10
-#define SH2_INT_DMA0 11
-#define SH2_INT_DMAILL 12
-#define SH2_INT_SPRITE 13
-#define SH2_INT_14 14
-#define SH2_INT_15 15
-#define SH2_INT_ABUS 16
-
-#define SH2_DMA_KLUDGE_CB(name) int name(uint32_t src, uint32_t dst, uint32_t data, int size)
-#define SH2_DMA_FIFO_DATA_AVAILABLE_CB(name) int name(uint32_t src, uint32_t dst, uint32_t data, int size)
-#define SH2_FTCSR_READ_CB(name) void name(uint32_t data)
-
class sh2_frontend;
class sh2_device : public sh_common_execution
@@ -50,191 +26,24 @@ class sh2_device : public sh_common_execution
friend class sh2_frontend;
public:
- typedef device_delegate<int (uint32_t src, uint32_t dst, uint32_t data, int size)> dma_kludge_delegate;
- typedef device_delegate<int (uint32_t src, uint32_t dst, uint32_t data, int size)> dma_fifo_data_available_delegate;
- typedef device_delegate<void (uint32_t data)> ftcsr_read_delegate;
-
- // construction/destruction
- sh2_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- virtual ~sh2_device() override;
-
- void set_is_slave(int slave) { m_is_slave = slave; }
-
- template <typename Object> void set_dma_kludge_callback(Object &&cb) { m_dma_kludge_cb = std::forward<Object>(cb); }
- template <class FunctionClass> void set_dma_kludge_callback(
- int (FunctionClass::*callback)(uint32_t, uint32_t, uint32_t, int), const char *name)
- {
- set_dma_kludge_callback(dma_kludge_delegate(callback, name, nullptr, static_cast<FunctionClass *>(nullptr)));
- }
-
- template <typename Object> void set_dma_fifo_data_available_callback(Object &&cb) { m_dma_fifo_data_available_cb = std::forward<Object>(cb); }
- template <class FunctionClass> void set_dma_fifo_data_available_callback(
- int (FunctionClass::*callback)(uint32_t, uint32_t, uint32_t, int), const char *name)
- {
- set_dma_fifo_data_available_callback(dma_fifo_data_available_delegate(callback, name, nullptr, static_cast<FunctionClass *>(nullptr)));
- }
-
- template <typename Object> void set_ftcsr_read_callback(Object &&cb) { m_ftcsr_read_cb = std::forward<Object>(cb); }
- template <class FunctionClass> void set_ftcsr_read_callback(void (FunctionClass::*callback)(uint32_t), const char *name)
- {
- set_ftcsr_read_callback(ftcsr_read_delegate(callback, name, nullptr, static_cast<FunctionClass *>(nullptr)));
- }
-
-
- DECLARE_READ32_MEMBER(sh2_internal_a5);
-
- // SCI
- DECLARE_READ8_MEMBER( smr_r );
- DECLARE_WRITE8_MEMBER( smr_w );
- DECLARE_READ8_MEMBER( brr_r );
- DECLARE_WRITE8_MEMBER( brr_w );
- DECLARE_READ8_MEMBER( scr_r );
- DECLARE_WRITE8_MEMBER( scr_w );
- DECLARE_READ8_MEMBER( tdr_r );
- DECLARE_WRITE8_MEMBER( tdr_w );
- DECLARE_READ8_MEMBER( ssr_r );
- DECLARE_WRITE8_MEMBER( ssr_w );
- DECLARE_READ8_MEMBER( rdr_r );
-
- // FRT / FRC
- DECLARE_READ8_MEMBER( tier_r );
- DECLARE_WRITE8_MEMBER( tier_w );
- DECLARE_READ16_MEMBER( frc_r );
- DECLARE_WRITE16_MEMBER( frc_w );
- DECLARE_READ8_MEMBER( ftcsr_r );
- DECLARE_WRITE8_MEMBER( ftcsr_w );
- DECLARE_READ16_MEMBER( ocra_b_r );
- DECLARE_WRITE16_MEMBER( ocra_b_w );
- DECLARE_READ8_MEMBER( frc_tcr_r );
- DECLARE_WRITE8_MEMBER( frc_tcr_w );
- DECLARE_READ8_MEMBER( tocr_r );
- DECLARE_WRITE8_MEMBER( tocr_w );
- DECLARE_READ16_MEMBER( frc_icr_r );
-
- // INTC
- DECLARE_READ16_MEMBER( ipra_r );
- DECLARE_WRITE16_MEMBER( ipra_w );
- DECLARE_READ16_MEMBER( iprb_r );
- DECLARE_WRITE16_MEMBER( iprb_w );
- DECLARE_READ16_MEMBER( vcra_r );
- DECLARE_WRITE16_MEMBER( vcra_w );
- DECLARE_READ16_MEMBER( vcrb_r );
- DECLARE_WRITE16_MEMBER( vcrb_w );
- DECLARE_READ16_MEMBER( vcrc_r );
- DECLARE_WRITE16_MEMBER( vcrc_w );
- DECLARE_READ16_MEMBER( vcrd_r );
- DECLARE_WRITE16_MEMBER( vcrd_w );
- DECLARE_READ16_MEMBER( vcrwdt_r );
- DECLARE_WRITE16_MEMBER( vcrwdt_w );
- DECLARE_READ32_MEMBER( vcrdiv_r );
- DECLARE_WRITE32_MEMBER( vcrdiv_w );
- DECLARE_READ16_MEMBER( intc_icr_r );
- DECLARE_WRITE16_MEMBER( intc_icr_w );
-
- // DIVU
- DECLARE_READ32_MEMBER( dvsr_r );
- DECLARE_WRITE32_MEMBER( dvsr_w );
- DECLARE_READ32_MEMBER( dvdnt_r );
- DECLARE_WRITE32_MEMBER( dvdnt_w );
- DECLARE_READ32_MEMBER( dvdnth_r );
- DECLARE_WRITE32_MEMBER( dvdnth_w );
- DECLARE_READ32_MEMBER( dvdntl_r );
- DECLARE_WRITE32_MEMBER( dvdntl_w );
-
- DECLARE_READ32_MEMBER( dvcr_r );
- DECLARE_WRITE32_MEMBER( dvcr_w );
+ void set_frt_input(int state) override {} // not every CPU needs this, let the ones that do override it
- // DMAC
- template <int Channel> READ32_MEMBER(vcrdma_r)
- {
- return m_vcrdma[Channel] & 0x7f;
- }
+ void func_fastirq(); // required for DRC, needs to be public to be accessible through non-classed static trampoline function
- template <int Channel> WRITE32_MEMBER(vcrdma_w)
- {
- COMBINE_DATA(&m_vcrdma[Channel]);
- m_irq_vector.dmac[Channel] = m_vcrdma[Channel] & 0x7f;
- sh2_recalc_irq();
- }
-
- template <int Channel> READ8_MEMBER(drcr_r) { return m_dmac[Channel].drcr & 3; }
- template <int Channel> WRITE8_MEMBER(drcr_w) { m_dmac[Channel].drcr = data & 3; sh2_recalc_irq(); }
- template <int Channel> READ32_MEMBER(sar_r) { return m_dmac[Channel].sar; }
- template <int Channel> WRITE32_MEMBER(sar_w) { COMBINE_DATA(&m_dmac[Channel].sar); }
- template <int Channel> READ32_MEMBER(dar_r) { return m_dmac[Channel].dar; }
- template <int Channel> WRITE32_MEMBER(dar_w) { COMBINE_DATA(&m_dmac[Channel].dar); }
- template <int Channel> READ32_MEMBER(dmac_tcr_r) { return m_dmac[Channel].tcr; }
- template <int Channel> WRITE32_MEMBER(dmac_tcr_w) { COMBINE_DATA(&m_dmac[Channel].tcr); m_dmac[Channel].tcr &= 0xffffff; }
- template <int Channel> READ32_MEMBER(chcr_r) { return m_dmac[Channel].chcr; }
- template <int Channel> WRITE32_MEMBER(chcr_w)
- {
- uint32_t old;
- old = m_dmac[Channel].chcr;
- COMBINE_DATA(&m_dmac[Channel].chcr);
- m_dmac[Channel].chcr = (data & ~2) | (old & m_dmac[Channel].chcr & 2);
- sh2_dmac_check(Channel);
- }
- READ32_MEMBER( dmaor_r ) { return m_dmaor & 0xf; }
- WRITE32_MEMBER( dmaor_w )
- {
- if(ACCESSING_BITS_0_7)
- {
- uint8_t old;
- old = m_dmaor & 0xf;
- m_dmaor = (data & ~6) | (old & m_dmaor & 6);
- sh2_dmac_check(0);
- sh2_dmac_check(1);
- }
- }
-
- // WTC
- DECLARE_READ16_MEMBER( wtcnt_r );
- DECLARE_WRITE16_MEMBER( wtcnt_w );
- DECLARE_READ16_MEMBER( rstcsr_r );
- DECLARE_WRITE16_MEMBER( rstcsr_w );
-
- // misc
- DECLARE_READ16_MEMBER( fmr_sbycr_r );
- DECLARE_WRITE16_MEMBER( fmr_sbycr_w );
- DECLARE_READ8_MEMBER( ccr_r );
- DECLARE_WRITE8_MEMBER( ccr_w );
-
- // BSC
- DECLARE_READ32_MEMBER( bcr1_r );
- DECLARE_WRITE32_MEMBER( bcr1_w );
- DECLARE_READ32_MEMBER( bcr2_r );
- DECLARE_WRITE32_MEMBER( bcr2_w );
- DECLARE_READ32_MEMBER( wcr_r );
- DECLARE_WRITE32_MEMBER( wcr_w );
- DECLARE_READ32_MEMBER( mcr_r );
- DECLARE_WRITE32_MEMBER( mcr_w );
- DECLARE_READ32_MEMBER( rtcsr_r );
- DECLARE_WRITE32_MEMBER( rtcsr_w );
- DECLARE_READ32_MEMBER( rtcor_r );
- DECLARE_WRITE32_MEMBER( rtcor_w );
- DECLARE_READ32_MEMBER( rtcnt_r );
- DECLARE_WRITE32_MEMBER( rtcnt_w );
-
-
- virtual void set_frt_input(int state) override;
- void sh2_notify_dma_data_available();
- void func_fastirq();
-
- void sh7604_map(address_map &map);
protected:
- sh2_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock, int cpu_type,address_map_constructor internal_map, int addrlines);
+ sh2_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock, int cpu_type, address_map_constructor internal_map, int addrlines, uint32_t address_mask);
+
+ void check_pending_irq(const char *message);
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
- virtual void device_stop() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// device_execute_interface overrides
- virtual uint32_t execute_min_cycles() const override { return 1; }
- virtual uint32_t execute_max_cycles() const override { return 4; }
- virtual uint32_t execute_input_lines() const override { return 16; }
- virtual uint32_t execute_default_irq_vector(int inputnum) const override { return 0; }
- virtual bool execute_input_edge_triggered(int inputnum) const override { return inputnum == INPUT_LINE_NMI; }
+ virtual uint32_t execute_min_cycles() const noexcept override { return 1; }
+ virtual uint32_t execute_max_cycles() const noexcept override { return 4; }
+ virtual uint32_t execute_default_irq_vector(int inputnum) const noexcept override { return 0; }
+ virtual bool execute_input_edge_triggered(int inputnum) const noexcept override { return inputnum == INPUT_LINE_NMI; }
virtual void execute_run() override;
virtual void execute_set_input(int inputnum, int state) override;
@@ -248,102 +57,24 @@ protected:
// device_disasm_interface overrides
virtual std::unique_ptr<util::disasm_interface> create_disassembler() override;
- address_space *m_decrypted_program;
-
-private:
- address_space_config m_program_config, m_decrypted_program_config;
-
- uint32_t m_cpu_off;
- uint32_t m_test_irq;
-
- int8_t m_irq_line_state[17];
-
- address_space *m_internal;
- // SCI
- uint8_t m_smr, m_brr, m_scr, m_tdr, m_ssr;
- // FRT / FRC
- uint8_t m_tier, m_ftcsr, m_frc_tcr, m_tocr;
- uint16_t m_frc;
- uint16_t m_ocra, m_ocrb, m_frc_icr;
- // INTC
- struct {
- uint8_t frc;
- uint8_t sci;
- uint8_t divu;
- uint8_t dmac;
- uint8_t wdt;
- } m_irq_level;
- struct {
- uint8_t fic;
- uint8_t foc;
- uint8_t fov;
- uint8_t divu;
- uint8_t dmac[2];
- } m_irq_vector;
- uint16_t m_ipra, m_iprb;
- uint16_t m_vcra, m_vcrb, m_vcrc, m_vcrd, m_vcrwdt, m_vcrdiv, m_intc_icr, m_vcrdma[2];
- bool m_vecmd, m_nmie;
-
- // DIVU
- bool m_divu_ovf, m_divu_ovfie;
- uint32_t m_dvsr, m_dvdntl, m_dvdnth;
-
- // WTC
- uint8_t m_wtcnt, m_wtcsr;
- uint8_t m_rstcsr;
- uint16_t m_wtcw[2];
-
- // DMAC
- struct {
- uint8_t drcr;
- uint32_t sar;
- uint32_t dar;
- uint32_t tcr;
- uint32_t chcr;
- } m_dmac[2];
- uint8_t m_dmaor;
-
- // misc
- uint8_t m_sbycr, m_ccr;
-
- // BSC
- uint32_t m_bcr1, m_bcr2, m_wcr, m_mcr, m_rtcsr, m_rtcor, m_rtcnt;
-
- int8_t m_nmi_line_state;
-
- uint64_t m_frc_base;
-
- int m_frt_input;
- int m_internal_irq_vector;
-
- emu_timer *m_timer;
- emu_timer *m_dma_current_active_timer[2];
- int m_dma_timer_active[2];
- uint8_t m_dma_irq[2];
-
- int m_active_dma_incs[2];
- int m_active_dma_incd[2];
- int m_active_dma_size[2];
- int m_active_dma_steal[2];
- uint32_t m_active_dma_src[2];
- uint32_t m_active_dma_dst[2];
- uint32_t m_active_dma_count[2];
-
- int m_is_slave;
- dma_kludge_delegate m_dma_kludge_cb;
- dma_fifo_data_available_delegate m_dma_fifo_data_available_cb;
- ftcsr_read_delegate m_ftcsr_read_cb;
+ virtual void sh2_exception(const char *message, int irqline) override;
+ virtual void sh2_exception_internal(const char *message, int irqline, int vector);
- std::unique_ptr<sh2_frontend> m_drcfe; /* pointer to the DRC front-end state */
+ address_space *m_decrypted_program;
+ const uint32_t m_am;
- uint32_t m_debugger_temp;
+ uint32_t m_test_irq;
+ int32_t m_internal_irq_vector;
+ int8_t m_nmi_line_state;
- virtual uint8_t RB(offs_t A) override;
- virtual uint16_t RW(offs_t A) override;
- virtual uint32_t RL(offs_t A) override;
- virtual void WB(offs_t A, uint8_t V) override;
- virtual void WW(offs_t A, uint16_t V) override;
- virtual void WL(offs_t A, uint32_t V) override;
+private:
+ virtual uint8_t read_byte(offs_t A) override;
+ virtual uint16_t read_word(offs_t A) override;
+ virtual uint32_t read_long(offs_t A) override;
+ virtual uint16_t decrypted_read_word(offs_t offset) override;
+ virtual void write_byte(offs_t A, uint8_t V) override;
+ virtual void write_word(offs_t A, uint16_t V) override;
+ virtual void write_long(offs_t A, uint32_t V) override;
virtual void LDCMSR(const uint16_t opcode) override;
virtual void LDCSR(const uint16_t opcode) override;
@@ -353,15 +84,6 @@ private:
virtual void execute_one_f000(uint16_t opcode) override;
- TIMER_CALLBACK_MEMBER( sh2_timer_callback );
- TIMER_CALLBACK_MEMBER( sh2_dma_current_active_callback );
- void sh2_timer_resync();
- void sh2_timer_activate();
- void sh2_do_dma(int dmach);
- virtual void sh2_exception(const char *message, int irqline) override;
- void sh2_dmac_check(int dma);
- void sh2_recalc_irq();
-
virtual void init_drc_frontend() override;
virtual const opcode_desc* get_desclist(offs_t pc) override;
@@ -369,53 +91,12 @@ private:
virtual void static_generate_entry_point() override;
virtual void static_generate_memory_accessor(int size, int iswrite, const char *name, uml::code_handle *&handleptr) override;
-};
-
-class sh2a_device : public sh2_device
-{
-public:
- // construction/destruction
- sh2a_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
-
- DECLARE_READ32_MEMBER(dma_sar0_r);
- DECLARE_WRITE32_MEMBER(dma_sar0_w);
- DECLARE_READ32_MEMBER(dma_dar0_r);
- DECLARE_WRITE32_MEMBER(dma_dar0_w);
- DECLARE_READ16_MEMBER(dmaor_r);
- DECLARE_WRITE16_MEMBER(dmaor_w);
- DECLARE_READ16_MEMBER(dma_tcr0_r);
- DECLARE_WRITE16_MEMBER(dma_tcr0_w);
- DECLARE_READ16_MEMBER(dma_chcr0_r);
- DECLARE_WRITE16_MEMBER(dma_chcr0_w);
- DECLARE_READ16_MEMBER(sh7021_r);
- DECLARE_WRITE16_MEMBER(sh7021_w);
- void sh7032_dma_exec(int ch);
-
- void sh7021_map(address_map &map);
-private:
- uint16_t m_sh7021_regs[0x200];
- struct
- {
- uint32_t sar; /**< Source Address Register */
- uint32_t dar; /**< Destination Address Register */
- uint16_t tcr; /**< Transfer Count Register */
- uint16_t chcr; /**< Channel Control Register */
- } m_dma[4];
- uint16_t m_dmaor; /**< DMA Operation Register (status flags) */
+ address_space_config m_program_config, m_decrypted_program_config;
-};
+ std::unique_ptr<sh2_frontend> m_drcfe; /* pointer to the DRC front-end state */
-class sh1_device : public sh2_device
-{
-public:
- // construction/destruction
- sh1_device(const machine_config &mconfig, const char *_tag, device_t *_owner, uint32_t _clock);
-
- DECLARE_READ16_MEMBER(sh7032_r);
- DECLARE_WRITE16_MEMBER(sh7032_w);
- void sh7032_map(address_map &map);
-private:
- uint16_t m_sh7032_regs[0x200];
+ uint32_t m_cpu_off;
+ int8_t m_irq_line_state[17];
};
@@ -430,8 +111,4 @@ private:
virtual bool describe_group_15(opcode_desc &desc, const opcode_desc *prev, uint16_t opcode) override;
};
-DECLARE_DEVICE_TYPE(SH1, sh1_device)
-DECLARE_DEVICE_TYPE(SH2, sh2_device)
-DECLARE_DEVICE_TYPE(SH2A, sh2a_device)
-
-#endif // MAME_CPU_SH2_SH2_H
+#endif // MAME_CPU_SH_SH2_H
diff --git a/src/devices/cpu/sh/sh2comn.cpp b/src/devices/cpu/sh/sh2comn.cpp
deleted file mode 100644
index bb17a818c17..00000000000
--- a/src/devices/cpu/sh/sh2comn.cpp
+++ /dev/null
@@ -1,1204 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:R. Belmont
-/*****************************************************************************
- *
- * sh2common.c
- *
- * SH-2 non-specific components
- *
- *****************************************************************************/
-
-#include "emu.h"
-#include "sh2.h"
-#include "sh2comn.h"
-
-#include "debugger.h"
-
-//#define VERBOSE 1
-#include "logmacro.h"
-
-static const int div_tab[4] = { 3, 5, 7, 0 };
-
-
-void sh2_device::sh2_timer_resync()
-{
- // TODO: setting 3 is "External clock: count on rising edge"
- int divider = div_tab[m_frc_tcr & 3];
- uint64_t cur_time = total_cycles();
- uint64_t add = (cur_time - m_frc_base) >> divider;
-
- if (add > 0)
- {
- if(divider)
- m_frc += add;
-
- m_frc_base = cur_time;
- }
-}
-
-void sh2_device::sh2_timer_activate()
-{
- int max_delta = 0xfffff;
- uint16_t frc;
-
- m_timer->adjust(attotime::never);
-
- frc = m_frc;
- if(!(m_ftcsr & OCFA)) {
- uint16_t delta = m_ocra - frc;
- if(delta < max_delta)
- max_delta = delta;
- }
-
- if(!(m_ftcsr & OCFB) && (m_ocra <= m_ocrb || !(m_ftcsr & CCLRA))) {
- uint16_t delta = m_ocrb - frc;
- if(delta < max_delta)
- max_delta = delta;
- }
-
- if(!(m_ftcsr & OVF) && !(m_ftcsr & CCLRA)) {
- int delta = 0x10000 - frc;
- if(delta < max_delta)
- max_delta = delta;
- }
-
- if(max_delta != 0xfffff) {
- int divider = div_tab[m_frc_tcr & 3];
- if(divider) {
- max_delta <<= divider;
- m_frc_base = total_cycles();
- m_timer->adjust(cycles_to_attotime(max_delta));
- } else {
- logerror("SH2.%s: Timer event in %d cycles of external clock", tag(), max_delta);
- }
- }
-}
-
-TIMER_CALLBACK_MEMBER( sh2_device::sh2_timer_callback )
-{
- uint16_t frc;
-
- sh2_timer_resync();
-
- frc = m_frc;
-
- if(frc == m_ocrb)
- m_ftcsr |= OCFB;
-
- if(frc == 0x0000)
- m_ftcsr |= OVF;
-
- if(frc == m_ocra)
- {
- m_ftcsr |= OCFA;
-
- if(m_ftcsr & CCLRA)
- m_frc = 0;
- }
-
- sh2_recalc_irq();
- sh2_timer_activate();
-}
-
-
-/*
- We have to do DMA on a timer (or at least, in chunks) due to the way some systems use it.
- The 32x is a difficult case, they set the SOURCE of the DMA to a FIFO buffer, which at most
- can have 8 words in it. Attempting to do an 'instant DMA' in this scenario is impossible
- because the game is expecting the 68k of the system to feed data into the FIFO at the same
- time as the SH2 is transfering it out via DMA
-
- There are two ways we can do this
-
- a) with a high frequency timer (more accurate, but a large performance hit)
-
- or
-
- b) in the CPU_EXECUTE loop
-
-
- we're currently doing a)
-
- b) causes problems with ST-V games
-
-*/
-
-
-
-void sh2_device::sh2_notify_dma_data_available()
-{
- //printf("call notify\n");
-
- for (int dmach=0;dmach<2;dmach++)
- {
- //printf("m_dma_timer_active[dmach] %04x\n",m_dma_timer_active[dmach]);
-
- if (m_dma_timer_active[dmach]==2) // 2 = stalled
- {
- // printf("resuming stalled dma\n");
- m_dma_timer_active[dmach]=1;
- m_dma_current_active_timer[dmach]->adjust(attotime::zero, dmach);
- }
- }
-
-}
-
-void sh2_device::sh2_do_dma(int dmach)
-{
- uint32_t dmadata;
-
- uint32_t tempsrc, tempdst;
-
- if (m_active_dma_count[dmach] > 0)
- {
- // process current DMA
- switch(m_active_dma_size[dmach])
- {
- case 0:
- {
- // we need to know the src / dest ahead of time without changing them
- // to allow for the callback to check if we can process the DMA at this
- // time (we need to know where we're reading / writing to/from)
-
- if(m_active_dma_incs[dmach] == 2)
- tempsrc = m_active_dma_src[dmach] - 1;
- else
- tempsrc = m_active_dma_src[dmach];
-
- if(m_active_dma_incd[dmach] == 2)
- tempdst = m_active_dma_dst[dmach] - 1;
- else
- tempdst = m_active_dma_dst[dmach];
-
- if (!m_dma_fifo_data_available_cb.isnull())
- {
- int available = m_dma_fifo_data_available_cb(tempsrc, tempdst, 0, m_active_dma_size[dmach]);
-
- if (!available)
- {
- //printf("dma stalled\n");
- m_dma_timer_active[dmach]=2;// mark as stalled
- return;
- }
- }
-
- //schedule next DMA callback
- m_dma_current_active_timer[dmach]->adjust(cycles_to_attotime(2), dmach);
-
- dmadata = m_program->read_byte(tempsrc);
- if (!m_dma_kludge_cb.isnull()) dmadata = m_dma_kludge_cb(tempsrc, tempdst, dmadata, m_active_dma_size[dmach]);
- m_program->write_byte(tempdst, dmadata);
-
- if(m_active_dma_incs[dmach] == 2)
- m_active_dma_src[dmach] --;
- if(m_active_dma_incd[dmach] == 2)
- m_active_dma_dst[dmach] --;
-
-
- if(m_active_dma_incs[dmach] == 1)
- m_active_dma_src[dmach] ++;
- if(m_active_dma_incd[dmach] == 1)
- m_active_dma_dst[dmach] ++;
-
- m_active_dma_count[dmach] --;
- }
- break;
- case 1:
- {
- if(m_active_dma_incs[dmach] == 2)
- tempsrc = m_active_dma_src[dmach] - 2;
- else
- tempsrc = m_active_dma_src[dmach];
-
- if(m_active_dma_incd[dmach] == 2)
- tempdst = m_active_dma_dst[dmach] - 2;
- else
- tempdst = m_active_dma_dst[dmach];
-
- if (!m_dma_fifo_data_available_cb.isnull())
- {
- int available = m_dma_fifo_data_available_cb(tempsrc, tempdst, 0, m_active_dma_size[dmach]);
-
- if (!available)
- {
- //printf("dma stalled\n");
- m_dma_timer_active[dmach]=2;// mark as stalled
- return;
- }
- }
-
- //schedule next DMA callback
- m_dma_current_active_timer[dmach]->adjust(cycles_to_attotime(2), dmach);
-
- // check: should this really be using read_word_32 / write_word_32?
- dmadata = m_program->read_word(tempsrc);
- if (!m_dma_kludge_cb.isnull()) dmadata = m_dma_kludge_cb(tempsrc, tempdst, dmadata, m_active_dma_size[dmach]);
- m_program->write_word(tempdst, dmadata);
-
- if(m_active_dma_incs[dmach] == 2)
- m_active_dma_src[dmach] -= 2;
- if(m_active_dma_incd[dmach] == 2)
- m_active_dma_dst[dmach] -= 2;
-
- if(m_active_dma_incs[dmach] == 1)
- m_active_dma_src[dmach] += 2;
- if(m_active_dma_incd[dmach] == 1)
- m_active_dma_dst[dmach] += 2;
-
- m_active_dma_count[dmach] --;
- }
- break;
- case 2:
- {
- if(m_active_dma_incs[dmach] == 2)
- tempsrc = m_active_dma_src[dmach] - 4;
- else
- tempsrc = m_active_dma_src[dmach];
-
- if(m_active_dma_incd[dmach] == 2)
- tempdst = m_active_dma_dst[dmach] - 4;
- else
- tempdst = m_active_dma_dst[dmach];
-
- if (!m_dma_fifo_data_available_cb.isnull())
- {
- int available = m_dma_fifo_data_available_cb(tempsrc, tempdst, 0, m_active_dma_size[dmach]);
-
- if (!available)
- {
- //printf("dma stalled\n");
- m_dma_timer_active[dmach]=2;// mark as stalled
- return;
- }
- }
-
- //schedule next DMA callback
- m_dma_current_active_timer[dmach]->adjust(cycles_to_attotime(2), dmach);
-
- dmadata = m_program->read_dword(tempsrc);
- if (!m_dma_kludge_cb.isnull()) dmadata = m_dma_kludge_cb(tempsrc, tempdst, dmadata, m_active_dma_size[dmach]);
- m_program->write_dword(tempdst, dmadata);
-
- if(m_active_dma_incs[dmach] == 2)
- m_active_dma_src[dmach] -= 4;
- if(m_active_dma_incd[dmach] == 2)
- m_active_dma_dst[dmach] -= 4;
-
- if(m_active_dma_incs[dmach] == 1)
- m_active_dma_src[dmach] += 4;
- if(m_active_dma_incd[dmach] == 1)
- m_active_dma_dst[dmach] += 4;
-
- m_active_dma_count[dmach] --;
- }
- break;
- case 3:
- {
- // shouldn't this really be 4 calls here instead?
-
- tempsrc = m_active_dma_src[dmach];
-
- if(m_active_dma_incd[dmach] == 2)
- tempdst = m_active_dma_dst[dmach] - 16;
- else
- tempdst = m_active_dma_dst[dmach];
-
- if (!m_dma_fifo_data_available_cb.isnull())
- {
- int available = m_dma_fifo_data_available_cb(tempsrc, tempdst, 0, m_active_dma_size[dmach]);
-
- if (!available)
- {
- //printf("dma stalled\n");
- m_dma_timer_active[dmach]=2;// mark as stalled
- fatalerror("SH2 dma_callback_fifo_data_available == 0 in unsupported mode\n");
- }
- }
-
- //schedule next DMA callback
- m_dma_current_active_timer[dmach]->adjust(cycles_to_attotime(2), dmach);
-
- dmadata = m_program->read_dword(tempsrc);
- if (!m_dma_kludge_cb.isnull()) dmadata = m_dma_kludge_cb(tempsrc, tempdst, dmadata, m_active_dma_size[dmach]);
- m_program->write_dword(tempdst, dmadata);
-
- dmadata = m_program->read_dword(tempsrc+4);
- if (!m_dma_kludge_cb.isnull()) dmadata = m_dma_kludge_cb(tempsrc, tempdst, dmadata, m_active_dma_size[dmach]);
- m_program->write_dword(tempdst+4, dmadata);
-
- dmadata = m_program->read_dword(tempsrc+8);
- if (!m_dma_kludge_cb.isnull()) dmadata = m_dma_kludge_cb(tempsrc, tempdst, dmadata, m_active_dma_size[dmach]);
- m_program->write_dword(tempdst+8, dmadata);
-
- dmadata = m_program->read_dword(tempsrc+12);
- if (!m_dma_kludge_cb.isnull()) dmadata = m_dma_kludge_cb(tempsrc, tempdst, dmadata, m_active_dma_size[dmach]);
- m_program->write_dword(tempdst+12, dmadata);
-
- if(m_active_dma_incd[dmach] == 2)
- m_active_dma_dst[dmach] -= 16;
-
- m_active_dma_src[dmach] += 16;
- if(m_active_dma_incd[dmach] == 1)
- m_active_dma_dst[dmach] += 16;
-
- m_active_dma_count[dmach]-=4;
- }
- break;
- }
- }
- else // the dma is complete
- {
- // int dma = param & 1;
-
- // fever soccer uses cycle-stealing mode, resume the CPU now DMA has finished
- if (m_active_dma_steal[dmach])
- {
- resume(SUSPEND_REASON_HALT );
- }
-
-
- LOG("SH2: DMA %d complete\n", dmach);
- m_dmac[dmach].tcr = 0;
- m_dmac[dmach].chcr |= 2;
- m_dma_timer_active[dmach] = 0;
- m_dma_irq[dmach] |= 1;
- sh2_recalc_irq();
-
- }
-}
-
-TIMER_CALLBACK_MEMBER( sh2_device::sh2_dma_current_active_callback )
-{
- int dma = param & 1;
-
- sh2_do_dma(dma);
-}
-
-
-void sh2_device::sh2_dmac_check(int dmach)
-{
- if(m_dmac[dmach].chcr & m_dmaor & 1)
- {
- if(!m_dma_timer_active[dmach] && !(m_dmac[dmach].chcr & 2))
- {
- m_active_dma_incd[dmach] = (m_dmac[dmach].chcr >> 14) & 3;
- m_active_dma_incs[dmach] = (m_dmac[dmach].chcr >> 12) & 3;
- m_active_dma_size[dmach] = (m_dmac[dmach].chcr >> 10) & 3;
- m_active_dma_steal[dmach] = (m_dmac[dmach].chcr & 0x10);
-
- if(m_active_dma_incd[dmach] == 3 || m_active_dma_incs[dmach] == 3)
- {
- logerror("SH2: DMA: bad increment values (%d, %d, %d, %04x)\n", m_active_dma_incd[dmach], m_active_dma_incs[dmach], m_active_dma_size[dmach], m_dmac[dmach].chcr);
- return;
- }
- m_active_dma_src[dmach] = m_dmac[dmach].sar;
- m_active_dma_dst[dmach] = m_dmac[dmach].dar;
- m_active_dma_count[dmach] = m_dmac[dmach].tcr;
- if(!m_active_dma_count[dmach])
- m_active_dma_count[dmach] = 0x1000000;
-
- LOG("SH2: DMA %d start %x, %x, %x, %04x, %d, %d, %d\n", dmach, m_active_dma_src[dmach], m_active_dma_dst[dmach], m_active_dma_count[dmach], m_dmac[dmach].chcr, m_active_dma_incs[dmach], m_active_dma_incd[dmach], m_active_dma_size[dmach]);
-
- m_dma_timer_active[dmach] = 1;
-
- m_active_dma_src[dmach] &= SH12_AM;
- m_active_dma_dst[dmach] &= SH12_AM;
-
- switch(m_active_dma_size[dmach])
- {
- case 0:
- break;
- case 1:
- m_active_dma_src[dmach] &= ~1;
- m_active_dma_dst[dmach] &= ~1;
- break;
- case 2:
- m_active_dma_src[dmach] &= ~3;
- m_active_dma_dst[dmach] &= ~3;
- break;
- case 3:
- m_active_dma_src[dmach] &= ~3;
- m_active_dma_dst[dmach] &= ~3;
- m_active_dma_count[dmach] &= ~3;
- break;
- }
-
- // start DMA timer
-
- // fever soccer uses cycle-stealing mode, requiring the CPU to be halted
- if (m_active_dma_steal[dmach])
- {
- //printf("cycle stealing DMA\n");
- suspend(SUSPEND_REASON_HALT, 1 );
- }
-
- m_dma_current_active_timer[dmach]->adjust(cycles_to_attotime(2), dmach);
- }
- }
- else
- {
- if(m_dma_timer_active[dmach])
- {
- logerror("SH2: DMA %d cancelled in-flight\n", dmach);
- //m_dma_complete_timer[dmach]->adjust(attotime::never);
- m_dma_current_active_timer[dmach]->adjust(attotime::never, dmach);
-
- m_dma_timer_active[dmach] = 0;
- }
- }
-}
-
-/*
- * SCI
- */
-// TODO: identical to H8 counterpart
-
-READ8_MEMBER( sh2_device::smr_r )
-{
- return m_smr;
-}
-
-WRITE8_MEMBER( sh2_device::smr_w )
-{
- m_smr = data;
-}
-
-READ8_MEMBER( sh2_device::brr_r )
-{
- return m_brr;
-}
-
-WRITE8_MEMBER( sh2_device::brr_w )
-{
- m_brr = data;
-}
-
-READ8_MEMBER( sh2_device::scr_r )
-{
- return m_scr;
-}
-
-WRITE8_MEMBER( sh2_device::scr_w )
-{
- m_scr = data;
-}
-
-READ8_MEMBER( sh2_device::tdr_r )
-{
- return m_tdr;
-}
-
-WRITE8_MEMBER( sh2_device::tdr_w )
-{
- m_tdr = data;
- // printf("%c",data & 0xff);
-}
-
-READ8_MEMBER( sh2_device::ssr_r )
-{
- // 0x84 is needed by EGWord on Saturn to make it to boot for some reason.
- return m_ssr | 0x84;
-}
-
-WRITE8_MEMBER( sh2_device::ssr_w )
-{
- m_ssr = data;
-}
-
-READ8_MEMBER( sh2_device::rdr_r )
-{
- return 0;
-}
-
-/*
- * FRC
- */
-
-READ8_MEMBER( sh2_device::tier_r )
-{
- return m_tier;
-}
-
-WRITE8_MEMBER( sh2_device::tier_w )
-{
- sh2_timer_resync();
- m_tier = data;
- sh2_timer_activate();
- sh2_recalc_irq();
-}
-
-READ8_MEMBER( sh2_device::ftcsr_r )
-{
- // TODO: to be tested
- if (!m_ftcsr_read_cb.isnull())
- m_ftcsr_read_cb((((m_tier<<24) | (m_ftcsr<<16)) & 0xffff0000) | m_frc);
-
- return m_ftcsr;
-}
-
-WRITE8_MEMBER( sh2_device::ftcsr_w )
-{
- uint8_t old;
- old = m_ftcsr;
-
- m_ftcsr = data;
- sh2_timer_resync();
- m_ftcsr = (m_ftcsr & ~(ICF|OCFA|OCFB|OVF)) | (old & m_ftcsr & (ICF|OCFA|OCFB|OVF));
- sh2_timer_activate();
- sh2_recalc_irq();
-}
-
-READ16_MEMBER( sh2_device::frc_r )
-{
- sh2_timer_resync();
- return m_frc;
-}
-
-WRITE16_MEMBER( sh2_device::frc_w )
-{
- sh2_timer_resync();
- COMBINE_DATA(&m_frc);
- sh2_timer_activate();
- sh2_recalc_irq();
-}
-
-READ16_MEMBER( sh2_device::ocra_b_r )
-{
- return (m_tocr & 0x10) ? m_ocrb : m_ocra;
-}
-
-WRITE16_MEMBER( sh2_device::ocra_b_w )
-{
- sh2_timer_resync();
- if(m_tocr & 0x10)
- m_ocrb = (m_ocrb & (~mem_mask)) | (data & mem_mask);
- else
- m_ocra = (m_ocra & (~mem_mask)) | (data & mem_mask);
- sh2_timer_activate();
- sh2_recalc_irq();
-}
-
-READ8_MEMBER( sh2_device::frc_tcr_r )
-{
- return m_frc_tcr & 0x83;
-}
-
-WRITE8_MEMBER( sh2_device::frc_tcr_w )
-{
- sh2_timer_resync();
- m_frc_tcr = data & 0x83;
- sh2_timer_activate();
- sh2_recalc_irq();
-}
-
-READ8_MEMBER( sh2_device::tocr_r )
-{
- return (m_tocr & 0x13) | 0xe0;
-}
-
-WRITE8_MEMBER( sh2_device::tocr_w )
-{
- sh2_timer_resync();
- // TODO: output levels A/B (bits 1-0)
- m_tocr = data & 0x13;
- sh2_timer_activate();
- sh2_recalc_irq();
-}
-
-READ16_MEMBER( sh2_device::frc_icr_r )
-{
- return m_frc_icr;
-}
-
-/*
- * INTC
- */
-
-READ16_MEMBER( sh2_device::intc_icr_r )
-{
- // TODO: flip meaning based off NMI edge select bit (NMIE)
- uint16_t nmilv = m_nmi_line_state == ASSERT_LINE ? 0 : 0x8000;
- return (nmilv) | (m_intc_icr & 0x0101);
-}
-
-WRITE16_MEMBER( sh2_device::intc_icr_w )
-{
- COMBINE_DATA(&m_intc_icr);
- m_nmie = bool(BIT(m_intc_icr, 8));
- m_vecmd = bool(BIT(m_intc_icr, 0));
-}
-
-READ16_MEMBER( sh2_device::ipra_r )
-{
- return m_ipra & 0xfff0;
-}
-
-WRITE16_MEMBER( sh2_device::ipra_w )
-{
- COMBINE_DATA(&m_ipra);
- m_irq_level.divu = (m_ipra >> 12) & 0xf;
- m_irq_level.dmac = (m_ipra >> 8) & 0xf;
- m_irq_level.wdt = (m_ipra >> 4) & 0xf;
- sh2_recalc_irq();
-}
-
-READ16_MEMBER( sh2_device::iprb_r )
-{
- return m_iprb & 0xff00;
-}
-
-WRITE16_MEMBER( sh2_device::iprb_w )
-{
- COMBINE_DATA(&m_iprb);
- m_irq_level.sci = (m_iprb >> 12) & 0xf;
- m_irq_level.frc = (m_iprb >> 8) & 0xf;
- sh2_recalc_irq();
-}
-
-READ16_MEMBER( sh2_device::vcra_r )
-{
- return m_vcra & 0x7f7f;
-}
-
-WRITE16_MEMBER( sh2_device::vcra_w )
-{
- COMBINE_DATA(&m_vcra);
- // ...
- sh2_recalc_irq();
-}
-
-READ16_MEMBER( sh2_device::vcrb_r )
-{
- return m_vcrb;
-}
-
-WRITE16_MEMBER( sh2_device::vcrb_w )
-{
- COMBINE_DATA(&m_vcrb);
- // ...
- sh2_recalc_irq();
-}
-
-READ16_MEMBER( sh2_device::vcrc_r )
-{
- return m_vcrc & 0x7f7f;
-}
-
-WRITE16_MEMBER( sh2_device::vcrc_w )
-{
- COMBINE_DATA(&m_vcrc);
- m_irq_vector.fic = (m_vcrc >> 8) & 0x7f;
- m_irq_vector.foc = (m_vcrc >> 0) & 0x7f;
- sh2_recalc_irq();
-}
-
-READ16_MEMBER( sh2_device::vcrd_r )
-{
- return m_vcrd & 0x7f00;
-}
-
-WRITE16_MEMBER( sh2_device::vcrd_w )
-{
- COMBINE_DATA(&m_vcrd);
- m_irq_vector.fov = (m_vcrc >> 8) & 0x7f;
- sh2_recalc_irq();
-}
-
-READ16_MEMBER( sh2_device::vcrwdt_r )
-{
- return m_vcrwdt & 0x7f7f;
-}
-
-WRITE16_MEMBER( sh2_device::vcrwdt_w )
-{
- COMBINE_DATA(&m_vcrwdt);
- // ...
- sh2_recalc_irq();
-}
-
-READ32_MEMBER( sh2_device::vcrdiv_r )
-{
- return m_vcrdiv & 0x7f;
-}
-
-WRITE32_MEMBER( sh2_device::vcrdiv_w )
-{
- COMBINE_DATA(&m_vcrdiv);
- // TODO: unemulated, level is seemingly not documented/settable?
- m_irq_vector.divu = data & 0x7f;
- sh2_recalc_irq();
-}
-
-/*
- * DIVU
- */
-
-READ32_MEMBER( sh2_device::dvcr_r )
-{
- return (m_divu_ovfie == true ? 2 : 0) | (m_divu_ovf == true ? 1 : 0);
-}
-
-WRITE32_MEMBER( sh2_device::dvcr_w )
-{
- if(ACCESSING_BITS_0_7)
- {
- if (data & 1)
- m_divu_ovf = false;
- if (data & 2)
- {
- m_divu_ovfie = bool(BIT(data, 1));
- if (m_divu_ovfie == true)
- logerror("SH2: unemulated DIVU OVF interrupt enable\n");
- }
- sh2_recalc_irq();
- }
-}
-
-READ32_MEMBER( sh2_device::dvsr_r )
-{
- return m_dvsr;
-}
-
-WRITE32_MEMBER( sh2_device::dvsr_w )
-{
- COMBINE_DATA(&m_dvsr);
-}
-
-READ32_MEMBER( sh2_device::dvdnt_r )
-{
- return m_dvdntl;
-}
-
-WRITE32_MEMBER( sh2_device::dvdnt_w )
-{
- COMBINE_DATA(&m_dvdntl);
- int32_t a = m_dvdntl;
- int32_t b = m_dvsr;
- LOG("SH2 div32+mod %d/%d\n", a, b);
- if (b)
- {
- m_dvdntl = a / b;
- m_dvdnth = a % b;
- }
- else
- {
- m_divu_ovf = true;
- m_dvdntl = 0x7fffffff;
- m_dvdnth = 0x7fffffff;
- sh2_recalc_irq();
- }
-}
-
-READ32_MEMBER( sh2_device::dvdnth_r )
-{
- return m_dvdnth;
-}
-
-READ32_MEMBER( sh2_device::dvdntl_r )
-{
- return m_dvdntl;
-}
-
-WRITE32_MEMBER( sh2_device::dvdnth_w )
-{
- COMBINE_DATA(&m_dvdnth);
-}
-
-WRITE32_MEMBER( sh2_device::dvdntl_w )
-{
- COMBINE_DATA(&m_dvdntl);
- int64_t a = m_dvdntl | ((uint64_t)(m_dvdnth) << 32);
- int64_t b = (int32_t)m_dvsr;
- LOG("SH2 div64+mod %d/%d\n", a, b);
- if (b)
- {
- int64_t q = a / b;
- if (q != (int32_t)q)
- {
- m_divu_ovf = true;
- m_dvdntl = 0x7fffffff;
- m_dvdnth = 0x7fffffff;
- sh2_recalc_irq();
- }
- else
- {
- m_dvdntl = q;
- m_dvdnth = a % b;
- }
- }
- else
- {
- m_divu_ovf = true;
- m_dvdntl = 0x7fffffff;
- m_dvdnth = 0x7fffffff;
- sh2_recalc_irq();
- }
-}
-
-/*
- * WTC
- */
-
-READ16_MEMBER( sh2_device::wtcnt_r )
-{
- return ((m_wtcsr | 0x18) << 8) | (m_wtcnt & 0xff);
-}
-
-READ16_MEMBER( sh2_device::rstcsr_r )
-{
- return (m_rstcsr & 0xe0) | 0x1f;
-}
-
-WRITE16_MEMBER( sh2_device::wtcnt_w )
-{
- COMBINE_DATA(&m_wtcw[0]);
- switch (m_wtcw[0] & 0xff00)
- {
- case 0x5a00:
- m_wtcnt = m_wtcw[0] & 0xff;
- break;
- case 0xa500:
- /*
- WTCSR
- x--- ---- Overflow in IT mode
- -x-- ---- Timer mode (0: IT 1: watchdog)
- --x- ---- Timer enable
- ---1 1---
- ---- -xxx Clock select
- */
- m_wtcsr = m_wtcw[0] & 0xff;
- break;
- }
-}
-
-WRITE16_MEMBER( sh2_device::rstcsr_w )
-{
- COMBINE_DATA(&m_wtcw[1]);
- switch (m_wtcw[1] & 0xff00)
- {
- case 0xa500:
- // clear WOVF flag
- if ((m_wtcw[1] & 0x80) == 0)
- m_rstcsr &= 0x7f;
- break;
- case 0x5a00:
- m_rstcsr = (m_rstcsr & 0x80) | (m_wtcw[1] & 0x60);
- break;
- }
-}
-
-READ16_MEMBER( sh2_device::fmr_sbycr_r )
-{
- return m_sbycr;
-}
-
-WRITE16_MEMBER( sh2_device::fmr_sbycr_w )
-{
- switch (mem_mask)
- {
- case 0xff00: // FMR 8bit
- logerror("SH2 set clock multiplier x%d\n", 1 << ((data >> 8) & 3));
- break;
- case 0xffff: // FMR 16bit
- // SH7604 docs says FMR register must be set using 8-bit write, however at practice 16-bit works too.
- // has been verified for CPS3 custom SH2, SH7604 and SH7095 (clock multiplier feature is not officially documented for SH7095).
- logerror("SH2 set clock multiplier x%d\n", 1 << (data & 3));
- break;
- case 0x00ff: // SBYCR
- m_sbycr = data;
- if (data & 0x1f)
- logerror("SH2 module stop selected %02x\n", data);
- break;
- }
-}
-
-READ8_MEMBER( sh2_device::ccr_r )
-{
- return m_ccr & ~0x30;
-}
-
-WRITE8_MEMBER( sh2_device::ccr_w )
-{
- /*
- xx-- ---- Way 0/1
- ---x ---- Cache Purge (CP), write only
- ---- x--- Two-Way Mode (TW)
- ---- -x-- Data Replacement Disable (OD)
- ---- --x- Instruction Replacement Disable (ID)
- ---- ---x Cache Enable (CE)
- */
- m_ccr = data;
-}
-
-READ32_MEMBER( sh2_device::bcr1_r )
-{
- return (m_bcr1 & ~0xe008) | (m_is_slave ? 0x8000 : 0);
-}
-
-WRITE32_MEMBER( sh2_device::bcr1_w )
-{
- COMBINE_DATA(&m_bcr1);
-}
-
-READ32_MEMBER( sh2_device::bcr2_r )
-{
- return m_bcr2;
-}
-
-WRITE32_MEMBER( sh2_device::bcr2_w )
-{
- COMBINE_DATA(&m_bcr2);
-}
-
-READ32_MEMBER( sh2_device::wcr_r )
-{
- return m_wcr;
-}
-
-WRITE32_MEMBER( sh2_device::wcr_w )
-{
- COMBINE_DATA(&m_wcr);
-}
-
-READ32_MEMBER( sh2_device::mcr_r )
-{
- return m_mcr & ~0x103;
-}
-
-WRITE32_MEMBER( sh2_device::mcr_w )
-{
- COMBINE_DATA(&m_mcr);
-}
-
-READ32_MEMBER( sh2_device::rtcsr_r )
-{
- return m_rtcsr & 0xf8;
-}
-
-WRITE32_MEMBER( sh2_device::rtcsr_w )
-{
- COMBINE_DATA(&m_rtcsr);
-}
-
-READ32_MEMBER( sh2_device::rtcnt_r )
-{
- return m_rtcnt & 0xff;
-}
-
-WRITE32_MEMBER( sh2_device::rtcnt_w )
-{
- COMBINE_DATA(&m_rtcnt);
- m_rtcnt &= 0xff;
-}
-
-READ32_MEMBER( sh2_device::rtcor_r )
-{
- return m_rtcor & 0xff;
-}
-
-WRITE32_MEMBER( sh2_device::rtcor_w )
-{
- COMBINE_DATA(&m_rtcor);
- m_rtcor &= 0xff;
-}
-
-void sh2_device::set_frt_input(int state)
-{
- if(m_frt_input == state) {
- return;
- }
-
- m_frt_input = state;
-
- if(m_frc_tcr & 0x80) {
- if(state == CLEAR_LINE) {
- return;
- }
- } else {
- if(state == ASSERT_LINE) {
- return;
- }
- }
-
- sh2_timer_resync();
- m_frc_icr = m_frc;
- m_ftcsr |= ICF;
- //logerror("SH2.%s: ICF activated (%x)\n", tag(), m_sh2_state->pc & AM);
- sh2_recalc_irq();
-}
-
-void sh2_device::sh2_recalc_irq()
-{
- int irq = 0, vector = -1;
- int level;
-
- // Timer irqs
- if (m_tier & m_ftcsr & (ICF|OCFA|OCFB|OVF))
- {
- level = (m_irq_level.frc & 15);
- if (level > irq)
- {
- int mask = m_tier & m_ftcsr;
- irq = level;
- if(mask & ICF)
- vector = m_irq_vector.fic & 0x7f;
- else if(mask & (OCFA|OCFB))
- vector = m_irq_vector.foc & 0x7f;
- else
- vector = m_irq_vector.fov & 0x7f;
- }
- }
-
- // DMA irqs
- if((m_dmac[0].chcr & 6) == 6 && m_dma_irq[0]) {
- level = m_irq_level.dmac & 15;
- if(level > irq) {
- irq = level;
- m_dma_irq[0] &= ~1;
- vector = m_irq_vector.dmac[0] & 0x7f;
- }
- }
- else if((m_dmac[1].chcr & 6) == 6 && m_dma_irq[1]) {
- level = m_irq_level.dmac & 15;
- if(level > irq) {
- irq = level;
- m_dma_irq[1] &= ~1;
- vector = m_irq_vector.dmac[1] & 0x7f;
- }
- }
-
- m_sh2_state->internal_irq_level = irq;
- m_internal_irq_vector = vector;
- m_test_irq = 1;
-}
-
-/*
- SH-7021 on-chip device
- */
-
-void sh2a_device::sh7032_dma_exec(int ch)
-{
- const short dma_word_size[4] = { 0, +1, -1, 0 };
- uint8_t rs = (m_dma[ch].chcr >> 8) & 0xf; /**< Resource Select bits */
- if(rs != 0xc) // Auto-Request
- {
- logerror("Warning: SH7032 DMA enables non auto-request transfer\n");
- return;
- }
-
- // channel enable & master enable
- if((m_dma[ch].chcr & 1) == 0 || (m_dmaor & 1) == 0)
- return;
-
- printf("%08x %08x %04x\n",m_dma[ch].sar,m_dma[ch].dar,m_dma[ch].chcr);
- uint8_t dm = (m_dma[ch].chcr >> 14) & 3; /**< Destination Address Mode bits */
- uint8_t sm = (m_dma[ch].chcr >> 12) & 3; /**< Source Address Mode bits */
- bool ts = (m_dma[ch].chcr & 8); /**< Transfer Size bit */
- int src_word_size = dma_word_size[sm] * ((ts == true) ? 2 : 1);
- int dst_word_size = dma_word_size[dm] * ((ts == true) ? 2 : 1);
- uint32_t src_addr = m_dma[ch].sar;
- uint32_t dst_addr = m_dma[ch].dar;
- uint32_t size_index = m_dma[ch].tcr;
- if(size_index == 0)
- size_index = 0x10000;
-
- if(ts == false)
- logerror("SH7032: DMA byte mode check\n");
-
- for(int index = size_index;index>-1;index--)
- {
- if(ts == true)
- m_program->write_word(dst_addr,m_program->read_word(src_addr));
- else
- m_program->write_byte(dst_addr,m_program->read_byte(src_addr));
-
- src_addr += src_word_size;
- dst_addr += dst_word_size;
- }
-
- m_dma[ch].chcr &= ~1; /**< @todo non-instant DMA */
- printf("%02x %02x %02x %1d\n",sm,dm,rs,ts);
-}
-
-READ32_MEMBER(sh2a_device::dma_sar0_r)
-{
- return m_dma[0].sar;
-}
-
-WRITE32_MEMBER(sh2a_device::dma_sar0_w)
-{
- COMBINE_DATA(&m_dma[0].sar);
-}
-
-READ32_MEMBER(sh2a_device::dma_dar0_r)
-{
- return m_dma[0].dar;
-}
-
-WRITE32_MEMBER(sh2a_device::dma_dar0_w)
-{
- COMBINE_DATA(&m_dma[0].dar);
-}
-
-READ16_MEMBER(sh2a_device::dma_tcr0_r)
-{
- return m_dma[0].tcr;
-}
-
-WRITE16_MEMBER(sh2a_device::dma_tcr0_w)
-{
- //printf("%04x\n",data);
- COMBINE_DATA(&m_dma[0].tcr);
-}
-
-READ16_MEMBER(sh2a_device::dma_chcr0_r)
-{
- return m_dma[0].chcr;
-}
-
-WRITE16_MEMBER(sh2a_device::dma_chcr0_w)
-{
- //printf("%04x CHCR0\n",data);
- COMBINE_DATA(&m_dma[0].chcr);
- sh7032_dma_exec(0);
-}
-
-READ16_MEMBER(sh2a_device::dmaor_r)
-{
- return m_dmaor;
-}
-
-WRITE16_MEMBER(sh2a_device::dmaor_w)
-{
- COMBINE_DATA(&m_dmaor);
- sh7032_dma_exec(0);
-}
-
-/*!
- @brief Dummy debug interface
- */
-READ16_MEMBER(sh1_device::sh7032_r)
-{
- return m_sh7032_regs[offset];
-}
-
-/*!
- @brief Dummy debug interface
- */
-WRITE16_MEMBER(sh1_device::sh7032_w)
-{
- COMBINE_DATA(&m_sh7032_regs[offset]);
-}
-
-READ16_MEMBER(sh2a_device::sh7021_r)
-{
- return m_sh7021_regs[offset];
-}
-
-/*!
- @brief Dummy debug interface
- */
-WRITE16_MEMBER(sh2a_device::sh7021_w)
-{
- COMBINE_DATA(&m_sh7021_regs[offset]);
-}
diff --git a/src/devices/cpu/sh/sh2comn.h b/src/devices/cpu/sh/sh2comn.h
deleted file mode 100644
index 53f5e04d2e6..00000000000
--- a/src/devices/cpu/sh/sh2comn.h
+++ /dev/null
@@ -1,52 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:R. Belmont
-/*****************************************************************************
- *
- * sh2common.h
- *
- * SH-2 non-specific components
- *
- *****************************************************************************/
-
-#ifndef MAME_CPU_SH2_SH2COMN_H
-#define MAME_CPU_SH2_SH2COMN_H
-
-#pragma once
-
-enum
-{
- ICF = 0x80,
- OCFA = 0x08,
- OCFB = 0x04,
- OVF = 0x02,
- CCLRA = 0x01
-};
-
-#define SH12_AM 0xc7ffffff
-
-#define CHECK_PENDING_IRQ(message) \
-do { \
- int irq = -1; \
- if (m_sh2_state->pending_irq & (1 << 0)) irq = 0; \
- if (m_sh2_state->pending_irq & (1 << 1)) irq = 1; \
- if (m_sh2_state->pending_irq & (1 << 2)) irq = 2; \
- if (m_sh2_state->pending_irq & (1 << 3)) irq = 3; \
- if (m_sh2_state->pending_irq & (1 << 4)) irq = 4; \
- if (m_sh2_state->pending_irq & (1 << 5)) irq = 5; \
- if (m_sh2_state->pending_irq & (1 << 6)) irq = 6; \
- if (m_sh2_state->pending_irq & (1 << 7)) irq = 7; \
- if (m_sh2_state->pending_irq & (1 << 8)) irq = 8; \
- if (m_sh2_state->pending_irq & (1 << 9)) irq = 9; \
- if (m_sh2_state->pending_irq & (1 << 10)) irq = 10; \
- if (m_sh2_state->pending_irq & (1 << 11)) irq = 11; \
- if (m_sh2_state->pending_irq & (1 << 12)) irq = 12; \
- if (m_sh2_state->pending_irq & (1 << 13)) irq = 13; \
- if (m_sh2_state->pending_irq & (1 << 14)) irq = 14; \
- if (m_sh2_state->pending_irq & (1 << 15)) irq = 15; \
- if ((m_sh2_state->internal_irq_level != -1) && (m_sh2_state->internal_irq_level > irq)) irq = m_sh2_state->internal_irq_level; \
- if (irq >= 0) \
- sh2_exception(message,irq); \
-} while(0)
-
-
-#endif // MAME_CPU_SH2_SH2COMN_H
diff --git a/src/devices/cpu/sh/sh2fe.cpp b/src/devices/cpu/sh/sh2fe.cpp
index 3019dc02ab7..b21ea334ba0 100644
--- a/src/devices/cpu/sh/sh2fe.cpp
+++ b/src/devices/cpu/sh/sh2fe.cpp
@@ -2,7 +2,7 @@
// copyright-holders:R. Belmont
/***************************************************************************
- sh2fe.c
+ sh2fe.cpp
Front end for SH-2 recompiler
@@ -10,7 +10,6 @@
#include "emu.h"
#include "sh2.h"
-#include "sh2comn.h"
#include "cpu/drcfe.h"
diff --git a/src/devices/cpu/sh/sh3comn.cpp b/src/devices/cpu/sh/sh3comn.cpp
index 6871a1aef01..3d5942aa363 100644
--- a/src/devices/cpu/sh/sh3comn.cpp
+++ b/src/devices/cpu/sh/sh3comn.cpp
@@ -3,679 +3,1798 @@
/* Handlers for SH3 internals */
#include "emu.h"
-#include "debugger.h"
#include "sh4.h"
#include "sh4comn.h"
#include "sh3comn.h"
#include "sh4tmu.h"
#include "sh4dmac.h"
-/* High internal area (ffffxxxx) */
+// CCN
+uint32_t sh3_base_device::pteh_r(offs_t offset, uint32_t mem_mask)
+{
+ logerror("'%s' (%08x): CCN unmapped internal read mask %08x (PTEH) %08x\n", tag(), m_sh2_state->pc, mem_mask, m_pteh);
+ return m_pteh;
+}
-WRITE32_MEMBER( sh3_base_device::sh3_internal_high_w )
+void sh3_base_device::pteh_w(offs_t offset, uint32_t data, uint32_t mem_mask)
{
- COMBINE_DATA(&m_sh3internal_upper[offset]);
+ COMBINE_DATA(&m_pteh);
+ logerror("'%s' (%08x): CCN unmapped internal write %08x & %08x (PTEH)\n", tag(), m_sh2_state->pc, data, mem_mask);
+}
- switch (offset)
- {
- case SH3_ICR0_IPRA_ADDR:
- if (mem_mask & 0xffff0000)
- {
- logerror("'%s' (%08x): INTC internal write to %08x = %08x & %08x (SH3_ICR0_IPRA_ADDR - ICR0)\n",tag(), m_sh2_state->pc & SH34_AM,(offset *4)+SH3_UPPER_REGBASE,data,mem_mask);
- }
-
- if (mem_mask & 0x0000ffff)
- {
- logerror("'%s' (%08x): INTC internal write to %08x = %08x & %08x (SH3_ICR0_IPRA_ADDR - IPRA)\n",tag(), m_sh2_state->pc & SH34_AM,(offset *4)+SH3_UPPER_REGBASE,data,mem_mask);
- sh4_handler_ipra_w(data&0xffff,mem_mask&0xffff);
- }
-
- break;
-
- case SH3_IPRB_ADDR:
- logerror("'%s' (%08x): INTC internal write to %08x = %08x & %08x (SH3_IPRB_ADDR)\n",tag(), m_sh2_state->pc & SH34_AM,(offset *4)+SH3_UPPER_REGBASE,data,mem_mask);
- break;
-
- case SH3_TOCR_TSTR_ADDR:
- logerror("'%s' (%08x): TMU internal write to %08x = %08x & %08x (SH3_TOCR_TSTR_ADDR)\n",tag(), m_sh2_state->pc & SH34_AM,(offset *4)+SH3_UPPER_REGBASE,data,mem_mask);
- if (mem_mask&0xff000000)
- {
- sh4_handle_tocr_addr_w((data>>24)&0xffff, (mem_mask>>24)&0xff);
- }
- if (mem_mask&0x0000ff00)
- {
- sh4_handle_tstr_addr_w((data>>8)&0xff, (mem_mask>>8)&0xff);
- }
- if (mem_mask&0x00ff00ff)
- {
- fatalerror("SH3_TOCR_TSTR_ADDR unused bits accessed (write)\n");
- }
- break;
- case SH3_TCOR0_ADDR: sh4_handle_tcor0_addr_w(data, mem_mask);break;
- case SH3_TCOR1_ADDR: sh4_handle_tcor1_addr_w(data, mem_mask);break;
- case SH3_TCOR2_ADDR: sh4_handle_tcor2_addr_w(data, mem_mask);break;
- case SH3_TCNT0_ADDR: sh4_handle_tcnt0_addr_w(data, mem_mask);break;
- case SH3_TCNT1_ADDR: sh4_handle_tcnt1_addr_w(data, mem_mask);break;
- case SH3_TCNT2_ADDR: sh4_handle_tcnt2_addr_w(data, mem_mask);break;
- case SH3_TCR0_ADDR: sh4_handle_tcr0_addr_w(data>>16, mem_mask>>16);break;
- case SH3_TCR1_ADDR: sh4_handle_tcr1_addr_w(data>>16, mem_mask>>16);break;
- case SH3_TCR2_ADDR: sh4_handle_tcr2_addr_w(data>>16, mem_mask>>16);break;
- case SH3_TCPR2_ADDR: sh4_handle_tcpr2_addr_w(data, mem_mask);break;
-
- default:
- logerror("'%s' (%08x): unmapped internal write to %08x = %08x & %08x (unk)\n",tag(), m_sh2_state->pc & SH34_AM,(offset *4)+SH3_UPPER_REGBASE,data,mem_mask);
- break;
+uint32_t sh3_base_device::ptel_r(offs_t offset, uint32_t mem_mask)
+{
+ logerror("'%s' (%08x): CCN unmapped internal read mask %08x (PTEL) %08x\n", tag(), m_sh2_state->pc, mem_mask, m_ptel);
+ return m_ptel;
+}
- }
+void sh3_base_device::ptel_w(offs_t offset, uint32_t data, uint32_t mem_mask)
+{
+ COMBINE_DATA(&m_ptel);
+ logerror("'%s' (%08x): CCN unmapped internal write %08x & %08x (PTEL)\n", tag(), m_sh2_state->pc, data, mem_mask);
+}
+uint32_t sh3_base_device::ttb_r(offs_t offset, uint32_t mem_mask)
+{
+ logerror("'%s' (%08x): CCN unmapped internal read mask %08x (TTB) %08x\n", tag(), m_sh2_state->pc, mem_mask, m_ttb);
+ return m_ttb;
+}
+void sh3_base_device::ttb_w(offs_t offset, uint32_t data, uint32_t mem_mask)
+{
+ COMBINE_DATA(&m_ttb);
+ logerror("'%s' (%08x): CCN unmapped internal write %08x & %08x (TTB)\n", tag(), m_sh2_state->pc, data, mem_mask);
+}
+uint32_t sh3_base_device::tea_r(offs_t offset, uint32_t mem_mask)
+{
+ logerror("'%s' (%08x): CCN unmapped internal read mask %08x (TEA) %08x\n", tag(), m_sh2_state->pc, mem_mask, m_tea);
+ return m_tea;
+}
+void sh3_base_device::tea_w(offs_t offset, uint32_t data, uint32_t mem_mask)
+{
+ COMBINE_DATA(&m_tea);
+ logerror("'%s' (%08x): CCN unmapped internal write %08x & %08x (TEA)\n", tag(), m_sh2_state->pc, data, mem_mask);
}
-READ32_MEMBER( sh3_base_device::sh3_internal_high_r )
+uint32_t sh3_base_device::mmucr_r(offs_t offset, uint32_t mem_mask)
{
- uint32_t ret = 0;
+ logerror("'%s' (%08x): CCN unmapped internal read mask %08x (MMUCR) %08x\n", tag(), m_sh2_state->pc, mem_mask, m_mmucr);
+ return m_mmucr;
+}
- switch (offset)
- {
- case SH3_ICR0_IPRA_ADDR:
- logerror("'%s' (%08x): INTC internal read from %08x mask %08x (SH3_ICR0_IPRA_ADDR - %08x)\n",tag(), m_sh2_state->pc & SH34_AM,(offset *4)+SH3_UPPER_REGBASE,mem_mask, m_sh3internal_upper[offset]);
- return (m_sh3internal_upper[offset] & 0xffff0000) | (m_SH4_IPRA & 0xffff);
-
- case SH3_IPRB_ADDR:
- logerror("'%s' (%08x): INTC internal read from %08x mask %08x (SH3_IPRB_ADDR - %08x)\n",tag(), m_sh2_state->pc & SH34_AM,(offset *4)+SH3_UPPER_REGBASE,mem_mask, m_sh3internal_upper[offset]);
- return m_sh3internal_upper[offset];
-
- case SH3_TOCR_TSTR_ADDR:
-
- if (mem_mask&0xff00000)
- {
- ret |= (sh4_handle_tocr_addr_r(mem_mask)&0xff)<<24;
- }
- if (mem_mask&0x0000ff00)
- {
- ret |= (sh4_handle_tstr_addr_r(mem_mask)&0xff)<<8;
- }
- if (mem_mask&0x00ff00ff)
- {
- fatalerror("SH3_TOCR_TSTR_ADDR unused bits accessed (read)\n");
- }
- return ret;
- case SH3_TCOR0_ADDR: return sh4_handle_tcor0_addr_r(mem_mask);
- case SH3_TCOR1_ADDR: return sh4_handle_tcor1_addr_r(mem_mask);
- case SH3_TCOR2_ADDR: return sh4_handle_tcor2_addr_r(mem_mask);
- case SH3_TCNT0_ADDR: return sh4_handle_tcnt0_addr_r(mem_mask);
- case SH3_TCNT1_ADDR: return sh4_handle_tcnt1_addr_r(mem_mask);
- case SH3_TCNT2_ADDR: return sh4_handle_tcnt2_addr_r(mem_mask);
- case SH3_TCR0_ADDR: return sh4_handle_tcr0_addr_r(mem_mask)<<16;
- case SH3_TCR1_ADDR: return sh4_handle_tcr1_addr_r(mem_mask)<<16;
- case SH3_TCR2_ADDR: return sh4_handle_tcr2_addr_r(mem_mask)<<16;
- case SH3_TCPR2_ADDR: return sh4_handle_tcpr2_addr_r(mem_mask);
-
-
- case SH3_TRA_ADDR:
- logerror("'%s' (%08x): unmapped internal read from %08x mask %08x (SH3 TRA - %08x)\n",tag(), m_sh2_state->pc & SH34_AM,(offset *4)+SH3_UPPER_REGBASE,mem_mask, m_sh3internal_upper[offset]);
- return m_sh3internal_upper[offset];
-
- case SH3_EXPEVT_ADDR:
- logerror("'%s' (%08x): unmapped internal read from %08x mask %08x (SH3 EXPEVT - %08x)\n",tag(), m_sh2_state->pc & SH34_AM,(offset *4)+SH3_UPPER_REGBASE,mem_mask, m_sh3internal_upper[offset]);
- return m_sh3internal_upper[offset];
-
- case SH3_INTEVT_ADDR:
- logerror("'%s' (%08x): unmapped internal read from %08x mask %08x (SH3 INTEVT - %08x)\n",tag(), m_sh2_state->pc & SH34_AM,(offset *4)+SH3_UPPER_REGBASE,mem_mask, m_sh3internal_upper[offset]);
- fatalerror("INTEVT unsupported on SH3\n");
- // never executed
- //return m_sh3internal_upper[offset];
-
-
- default:
- logerror("'%s' (%08x): unmapped internal read from %08x mask %08x\n",tag(), m_sh2_state->pc & SH34_AM,(offset *4)+SH3_UPPER_REGBASE,mem_mask);
- return m_sh3internal_upper[offset];
- }
+void sh3_base_device::mmucr_w(offs_t offset, uint32_t data, uint32_t mem_mask)
+{
+ COMBINE_DATA(&m_mmucr);
+ logerror("'%s' (%08x): CCN unmapped internal write %08x & %08x (MMUCR)\n", tag(), m_sh2_state->pc, data, mem_mask);
}
+uint8_t sh3_base_device::basra_r(offs_t offset, uint8_t mem_mask)
+{
+ logerror("'%s' (%08x): CCN unmapped internal read mask %02x (BASRA) %02x\n", tag(), m_sh2_state->pc, mem_mask, m_basra);
+ return m_basra;
+}
-READ32_MEMBER( sh3_base_device::sh3_internal_r )
+void sh3_base_device::basra_w(offs_t offset, uint8_t data, uint8_t mem_mask)
{
- if (offset<0x1000)
- {
- switch (offset)
- {
- case SH3_SAR0_ADDR: return sh4_handle_sar0_addr_r(mem_mask);
- case SH3_SAR1_ADDR: return sh4_handle_sar1_addr_r(mem_mask);
- case SH3_SAR2_ADDR: return sh4_handle_sar2_addr_r(mem_mask);
- case SH3_SAR3_ADDR: return sh4_handle_sar3_addr_r(mem_mask);
- case SH3_DAR0_ADDR: return sh4_handle_dar0_addr_r(mem_mask);
- case SH3_DAR1_ADDR: return sh4_handle_dar1_addr_r(mem_mask);
- case SH3_DAR2_ADDR: return sh4_handle_dar2_addr_r(mem_mask);
- case SH3_DAR3_ADDR: return sh4_handle_dar3_addr_r(mem_mask);
- case SH3_DMATCR0_ADDR: return sh4_handle_dmatcr0_addr_r(mem_mask);
- case SH3_DMATCR1_ADDR: return sh4_handle_dmatcr1_addr_r(mem_mask);
- case SH3_DMATCR2_ADDR: return sh4_handle_dmatcr2_addr_r(mem_mask);
- case SH3_DMATCR3_ADDR: return sh4_handle_dmatcr3_addr_r(mem_mask);
- case SH3_CHCR0_ADDR: return sh4_handle_chcr0_addr_r(mem_mask);
- case SH3_CHCR1_ADDR: return sh4_handle_chcr1_addr_r(mem_mask);
- case SH3_CHCR2_ADDR: return sh4_handle_chcr2_addr_r(mem_mask);
- case SH3_CHCR3_ADDR: return sh4_handle_chcr3_addr_r(mem_mask);
- case SH3_DMAOR_ADDR: return sh4_handle_dmaor_addr_r(mem_mask)<<16;
-
-
- case INTEVT2:
- {
- // logerror("'%s' (%08x): unmapped internal read from %08x mask %08x (INTEVT2)\n",tag(), m_sh2_state->pc & SH34_AM,(offset *4)+0x4000000,mem_mask);
- return m_sh3internal_lower[offset];
- }
-
-
- case IRR0_IRR1:
- {
- {
- if (mem_mask & 0xff000000)
- {
- logerror("'%s' (%08x): unmapped internal read from %08x mask %08x (IRR0)\n",tag(), m_sh2_state->pc & SH34_AM,(offset *4)+0x4000000,mem_mask);
- return m_sh3internal_lower[offset];
- }
-
- if (mem_mask & 0x0000ff00)
- {
- logerror("'%s' (%08x): unmapped internal read from %08x mask %08x (IRR1)\n",tag(), m_sh2_state->pc & SH34_AM,(offset *4)+0x4000000,mem_mask);
- return m_sh3internal_lower[offset];
- }
-
- fatalerror("'%s' (%08x): unmapped internal read from %08x mask %08x (IRR0/1 unused bits)\n",tag(), m_sh2_state->pc & SH34_AM,(offset *4)+0x4000000,mem_mask);
- }
- }
-
- case PADR_PBDR:
- {
- if (mem_mask & 0xffff0000)
- {
- //logerror("'%s' (%08x): unmapped internal read from %08x mask %08x (PADR)\n",tag(), m_sh2_state->pc & SH34_AM,(offset *4)+0x4000000,mem_mask);
- return m_io->read_qword(SH3_PORT_A)<<24;
- }
-
- if (mem_mask & 0x0000ffff)
- {
- //logerror("'%s' (%08x): unmapped internal read from %08x mask %08x (PBDR)\n",tag(), m_sh2_state->pc & SH34_AM,(offset *4)+0x4000000,mem_mask);
- return m_io->read_qword(SH3_PORT_B)<<8;
- }
- }
- break;
-
- case PCDR_PDDR:
- {
- if (mem_mask & 0xffff0000)
- {
- //logerror("'%s' (%08x): unmapped internal read from %08x mask %08x (PCDR)\n",tag(), m_sh2_state->pc & SH34_AM,(offset *4)+0x4000000,mem_mask);
- return m_io->read_qword(SH3_PORT_C)<<24;
- }
-
- if (mem_mask & 0x0000ffff)
- {
- //logerror("'%s' (%08x): unmapped internal read from %08x mask %08x (PDDR)\n",tag(), m_sh2_state->pc & SH34_AM,(offset *4)+0x4000000,mem_mask);
- return m_io->read_qword(SH3_PORT_D)<<8;
- }
- }
- break;
-
- case PEDR_PFDR:
- {
- if (mem_mask & 0xffff0000)
- {
- //logerror("'%s' (%08x): unmapped internal read from %08x mask %08x (PEDR)\n",tag(), m_sh2_state->pc & SH34_AM,(offset *4)+0x4000000,mem_mask);
- return m_io->read_qword(SH3_PORT_E)<<24;
- }
-
- if (mem_mask & 0x0000ffff)
- {
- //logerror("'%s' (%08x): unmapped internal read from %08x mask %08x (PFDR)\n",tag(), m_sh2_state->pc & SH34_AM,(offset *4)+0x4000000,mem_mask);
- return m_io->read_qword(SH3_PORT_F)<<8;
- }
- }
- break;
-
- case PGDR_PHDR:
- {
- if (mem_mask & 0xffff0000)
- {
- //logerror("'%s' (%08x): unmapped internal read from %08x mask %08x (PGDR)\n",tag(), m_sh2_state->pc & SH34_AM,(offset *4)+0x4000000,mem_mask);
- return m_io->read_qword(SH3_PORT_G)<<24;
- }
-
- if (mem_mask & 0x0000ffff)
- {
- //logerror("'%s' (%08x): unmapped internal read from %08x mask %08x (PHDR)\n",tag(), m_sh2_state->pc & SH34_AM,(offset *4)+0x4000000,mem_mask);
- return m_io->read_qword(SH3_PORT_H)<<8;
- }
- }
- break;
-
- case PJDR_PKDR:
- {
- if (mem_mask & 0xffff0000)
- {
- //logerror("'%s' (%08x): unmapped internal read from %08x mask %08x (PJDR)\n",tag(), m_sh2_state->pc & SH34_AM,(offset *4)+0x4000000,mem_mask);
- return m_io->read_qword(SH3_PORT_J)<<24;
- }
-
- if (mem_mask & 0x0000ffff)
- {
- //logerror("'%s' (%08x): unmapped internal read from %08x mask %08x (PKDR)\n",tag(), m_sh2_state->pc & SH34_AM,(offset *4)+0x4000000,mem_mask);
- return m_io->read_qword(SH3_PORT_K)<<8;
- }
- }
- break;
-
- case PLDR_SCPDR:
- {
- if (mem_mask & 0xffff0000)
- {
- //logerror("'%s' (%08x): unmapped internal read from %08x mask %08x (PLDR)\n",tag(), m_sh2_state->pc & SH34_AM,(offset *4)+0x4000000,mem_mask);
- return m_io->read_qword(SH3_PORT_L)<<24;
- }
-
- if (mem_mask & 0x0000ffff)
- {
- logerror("'%s' (%08x): unmapped internal read from %08x mask %08x (SCPDR)\n",tag(), m_sh2_state->pc & SH34_AM,(offset *4)+0x4000000,mem_mask);
- //return m_io->read_qword(SH3_PORT_K)<<8;
- }
- }
- break;
-
-
- case SCSMR2_SCBRR2:
- {
- if (mem_mask & 0xff000000)
- {
- logerror("'%s' (%08x): SCIF internal read from %08x mask %08x (SCSMR2 - Serial Mode Register 2)\n",tag(), m_sh2_state->pc & SH34_AM,(offset *4)+0x4000000,mem_mask);
- return m_sh3internal_lower[offset];
- }
-
- if (mem_mask & 0x0000ff00)
- {
- logerror("'%s' (%08x): SCIF internal read from %08x mask %08x (SCBRR2 - Bit Rate Register 2)\n",tag(), m_sh2_state->pc & SH34_AM,(offset *4)+0x4000000,mem_mask);
- return m_sh3internal_lower[offset];
- }
- }
- break;
-
- case SCSCR2_SCFTDR2:
- {
- if (mem_mask & 0xff000000)
- {
- logerror("'%s' (%08x): SCIF internal read from %08x mask %08x (SCSCR2 - Serial Control Register 2)\n",tag(), m_sh2_state->pc & SH34_AM,(offset *4)+0x4000000,mem_mask);
- return m_sh3internal_lower[offset];
- }
-
- if (mem_mask & 0x0000ff00)
- {
- logerror("'%s' (%08x): SCIF internal read from %08x mask %08x (SCFTDR2 - Transmit FIFO Data Register 2)\n",tag(), m_sh2_state->pc & SH34_AM,(offset *4)+0x4000000,mem_mask);
- return m_sh3internal_lower[offset];
- }
- }
- break;
-
- case SCSSR2_SCFRDR2:
- {
- if (mem_mask & 0xffff0000)
- {
- logerror("'%s' (%08x): SCIF internal read from %08x mask %08x (SCSSR2 - Serial Status Register 2)\n",tag(), m_sh2_state->pc & SH34_AM,(offset *4)+0x4000000,mem_mask);
- return m_sh3internal_lower[offset];
- }
-
- if (mem_mask & 0x0000ff00)
- {
- logerror("'%s' (%08x): SCIF internal read from %08x mask %08x (SCFRDR2 - Receive FIFO Data Register 2)\n",tag(), m_sh2_state->pc & SH34_AM,(offset *4)+0x4000000,mem_mask);
- return m_sh3internal_lower[offset];
- }
- }
- break;
-
- case SCFCR2_SCFDR2:
- {
- if (mem_mask & 0xff000000)
- {
- logerror("'%s' (%08x): SCIF internal read from %08x mask %08x (SCFCR2 - Fifo Control Register 2)\n",tag(), m_sh2_state->pc & SH34_AM,(offset *4)+0x4000000,mem_mask);
- return m_sh3internal_lower[offset];
- }
-
- if (mem_mask & 0x0000ffff)
- {
- logerror("'%s' (%08x): SCIF internal read from %08x mask %08x (SCFDR2 - Fifo Data Count Register 2)\n",tag(), m_sh2_state->pc & SH34_AM,(offset *4)+0x4000000,mem_mask);
- return m_sh3internal_lower[offset];
- }
- }
- break;
-
-
- default:
- {
- logerror("'%s' (%08x): unmapped internal read from %08x mask %08x\n",
- tag(), m_sh2_state->pc & SH34_AM,
- (offset *4)+0x4000000,
- mem_mask);
- }
- break;
-
- }
+ COMBINE_DATA(&m_basra);
+ logerror("'%s' (%08x): CCN unmapped internal write %02x & %02x (BASRA)\n", tag(), m_sh2_state->pc, data, mem_mask);
+}
- }
- else
- {
- logerror("'%s' (%08x): unmapped internal read from %08x mask %08x\n",
- tag(), m_sh2_state->pc & SH34_AM,
- (offset *4)+0x4000000,
- mem_mask);
- }
+uint8_t sh3_base_device::basrb_r(offs_t offset, uint8_t mem_mask)
+{
+ logerror("'%s' (%08x): CCN unmapped internal read mask %02x (BASRB) %02x\n", tag(), m_sh2_state->pc, mem_mask, m_basrb);
+ return m_basrb;
+}
+
+void sh3_base_device::basrb_w(offs_t offset, uint8_t data, uint8_t mem_mask)
+{
+ COMBINE_DATA(&m_basrb);
+ logerror("'%s' (%08x): CCN unmapped internal write %02x & %02x (BASRB)\n", tag(), m_sh2_state->pc, data, mem_mask);
+}
+
+uint32_t sh3_base_device::ccr_r(offs_t offset, uint32_t mem_mask)
+{
+ logerror("'%s' (%08x): CCN unmapped internal read mask %08x (CCR) %08x\n", tag(), m_sh2_state->pc, mem_mask, m_ccr);
+ return m_ccr;
+}
+
+void sh3_base_device::ccr_w(offs_t offset, uint32_t data, uint32_t mem_mask)
+{
+ COMBINE_DATA(&m_ccr);
+ logerror("'%s' (%08x): CCN unmapped internal write %08x & %08x (CCR)\n", tag(), m_sh2_state->pc, data, mem_mask);
+}
+
+uint32_t sh3_base_device::tra_r(offs_t offset, uint32_t mem_mask)
+{
+ logerror("'%s' (%08x): CCN unmapped internal read mask %08x (TRA) %08x\n", tag(), m_sh2_state->pc, mem_mask, m_tra);
+ return m_tra;
+}
+
+void sh3_base_device::tra_w(offs_t offset, uint32_t data, uint32_t mem_mask)
+{
+ COMBINE_DATA(&m_tra);
+ logerror("'%s' (%08x): CCN unmapped internal write %08x & %08x (TRA)\n", tag(), m_sh2_state->pc, data, mem_mask);
+}
+
+uint32_t sh3_base_device::expevt_r(offs_t offset, uint32_t mem_mask)
+{
+ logerror("'%s' (%08x): CCN unmapped internal read mask %08x (EXPEVT) %08x\n", tag(), m_sh2_state->pc, mem_mask, m_expevt);
+ return m_expevt;
+}
+
+void sh3_base_device::expevt_w(offs_t offset, uint32_t data, uint32_t mem_mask)
+{
+ COMBINE_DATA(&m_expevt);
+ logerror("'%s' (%08x): CCN unmapped internal write %08x & %08x (EXPEVT)\n", tag(), m_sh2_state->pc, data, mem_mask);
+}
+
+uint32_t sh3_base_device::intevt_r(offs_t offset, uint32_t mem_mask)
+{
+ //logerror("'%s' (%08x): CCN unmapped internal read mask %08x (INTEVT) %08x\n", tag(), m_sh2_state->pc, mem_mask, m_intevt);
+ return m_intevt;
+}
+
+void sh3_base_device::intevt_w(offs_t offset, uint32_t data, uint32_t mem_mask)
+{
+ COMBINE_DATA(&m_intevt);
+ logerror("'%s' (%08x): CCN unmapped internal write %08x & %08x (INTEVT)\n", tag(), m_sh2_state->pc, data, mem_mask);
+}
+
+// CCN 7709S
+uint32_t sh3_base_device::ccr2_r(offs_t offset, uint32_t mem_mask)
+{
+ logerror("'%s' (%08x): CCN unmapped internal read mask %08x (CCR2) %08x\n", tag(), m_sh2_state->pc, mem_mask, m_ccr2);
+ return m_ccr2;
+}
+
+void sh3_base_device::ccr2_w(offs_t offset, uint32_t data, uint32_t mem_mask)
+{
+ COMBINE_DATA(&m_ccr2);
+ logerror("'%s' (%08x): CCN unmapped internal write %08x & %08x (CCR2)\n", tag(), m_sh2_state->pc, data, mem_mask);
+}
+
+// UBC
+uint32_t sh3_base_device::bara_r(offs_t offset, uint32_t mem_mask)
+{
+ logerror("'%s' (%08x): UBC unmapped internal read mask %08x (BARA) %08x\n", tag(), m_sh2_state->pc, mem_mask, m_bara);
+ return m_bara;
+}
+
+void sh3_base_device::bara_w(offs_t offset, uint32_t data, uint32_t mem_mask)
+{
+ COMBINE_DATA(&m_bara);
+ logerror("'%s' (%08x): UBC unmapped internal write %08x & %08x (BARA)\n", tag(), m_sh2_state->pc, data, mem_mask);
+}
+
+uint8_t sh3_base_device::bamra_r(offs_t offset, uint8_t mem_mask)
+{
+ logerror("'%s' (%08x): UBC unmapped internal read mask %02x (BAMRA) %02x\n", tag(), m_sh2_state->pc, mem_mask, m_bamra);
+ return m_bamra;
+}
+
+void sh3_base_device::bamra_w(offs_t offset, uint8_t data, uint8_t mem_mask)
+{
+ COMBINE_DATA(&m_bamra);
+ logerror("'%s' (%08x): UBC unmapped internal write %02x & %02x (BAMRA)\n", tag(), m_sh2_state->pc, data, mem_mask);
+}
+
+uint16_t sh3_base_device::bbra_r(offs_t offset, uint16_t mem_mask)
+{
+ logerror("'%s' (%08x): UBC unmapped internal read mask %04x (BBRA) %04x\n", tag(), m_sh2_state->pc, mem_mask, m_bbra);
+ return m_bbra;
+}
+
+void sh3_base_device::bbra_w(offs_t offset, uint16_t data, uint16_t mem_mask)
+{
+ COMBINE_DATA(&m_bbra);
+ logerror("'%s' (%08x): UBC unmapped internal write %04x & %04x (BBRA)\n", tag(), m_sh2_state->pc, data, mem_mask);
+}
+
+uint32_t sh3_base_device::barb_r(offs_t offset, uint32_t mem_mask)
+{
+ logerror("'%s' (%08x): UBC unmapped internal read mask %08x (BARB) %08x\n", tag(), m_sh2_state->pc, mem_mask, m_barb);
+ return m_barb;
+}
+
+void sh3_base_device::barb_w(offs_t offset, uint32_t data, uint32_t mem_mask)
+{
+ COMBINE_DATA(&m_barb);
+ logerror("'%s' (%08x): UBC unmapped internal write %08x & %08x (BARB)\n", tag(), m_sh2_state->pc, data, mem_mask);
+}
+
+uint8_t sh3_base_device::bamrb_r(offs_t offset, uint8_t mem_mask)
+{
+ logerror("'%s' (%08x): UBC unmapped internal read mask %02x (BAMRB) %02x\n", tag(), m_sh2_state->pc, mem_mask, m_bamrb);
+ return m_bamrb;
+}
+
+void sh3_base_device::bamrb_w(offs_t offset, uint8_t data, uint8_t mem_mask)
+{
+ COMBINE_DATA(&m_bamrb);
+ logerror("'%s' (%08x): UBC unmapped internal write %02x & %02x (BAMRB)\n", tag(), m_sh2_state->pc, data, mem_mask);
+}
+
+uint16_t sh3_base_device::bbrb_r(offs_t offset, uint16_t mem_mask)
+{
+ logerror("'%s' (%08x): UBC unmapped internal read mask %04x (BBRB) %04x\n", tag(), m_sh2_state->pc, mem_mask, m_bbrb);
+ return m_bbrb;
+}
+
+void sh3_base_device::bbrb_w(offs_t offset, uint16_t data, uint16_t mem_mask)
+{
+ COMBINE_DATA(&m_bbrb);
+ logerror("'%s' (%08x): UBC unmapped internal write %04x & %04x (BBRB)\n", tag(), m_sh2_state->pc, data, mem_mask);
+}
+
+uint32_t sh3_base_device::bdrb_r(offs_t offset, uint32_t mem_mask)
+{
+ logerror("'%s' (%08x): UBC unmapped internal read mask %08x (BDRB) %08x\n", tag(), m_sh2_state->pc, mem_mask, m_bdrb);
+ return m_bdrb;
+}
+
+void sh3_base_device::bdrb_w(offs_t offset, uint32_t data, uint32_t mem_mask)
+{
+ COMBINE_DATA(&m_bdrb);
+ logerror("'%s' (%08x): UBC unmapped internal write %08x & %08x (BDRB)\n", tag(), m_sh2_state->pc, data, mem_mask);
+}
+
+uint32_t sh3_base_device::bdmrb_r(offs_t offset, uint32_t mem_mask)
+{
+ logerror("'%s' (%08x): UBC unmapped internal read mask %08x (BDMRB) %08x\n", tag(), m_sh2_state->pc, mem_mask, m_bdmrb);
+ return m_bdmrb;
+}
+
+void sh3_base_device::bdmrb_w(offs_t offset, uint32_t data, uint32_t mem_mask)
+{
+ COMBINE_DATA(&m_bdmrb);
+ logerror("'%s' (%08x): UBC unmapped internal write %08x & %08x (BDMRB)\n", tag(), m_sh2_state->pc, data, mem_mask);
+}
+
+uint16_t sh3_base_device::brcr_r(offs_t offset, uint16_t mem_mask)
+{
+ logerror("'%s' (%08x): UBC unmapped internal read mask %04x (BRCR) %04x\n", tag(), m_sh2_state->pc, mem_mask, m_brcr);
+ return m_brcr;
+}
+
+void sh3_base_device::brcr_w(offs_t offset, uint16_t data, uint16_t mem_mask)
+{
+ COMBINE_DATA(&m_brcr);
+ logerror("'%s' (%08x): UBC unmapped internal write %04x & %04x (BRCR)\n", tag(), m_sh2_state->pc, data, mem_mask);
+}
+
+// UBC 7709S
+uint16_t sh3_base_device::betr_r(offs_t offset, uint16_t mem_mask)
+{
+ logerror("'%s' (%08x): UBC unmapped internal read mask %04x (BETR) %04x\n", tag(), m_sh2_state->pc, mem_mask, m_betr);
+ return m_betr;
+}
+
+void sh3_base_device::betr_w(offs_t offset, uint16_t data, uint16_t mem_mask)
+{
+ COMBINE_DATA(&m_betr);
+ logerror("'%s' (%08x): UBC unmapped internal write %04x & %04x (BETR)\n", tag(), m_sh2_state->pc, data, mem_mask);
+}
+
+uint32_t sh3_base_device::brsr_r(offs_t offset, uint32_t mem_mask)
+{
+ logerror("'%s' (%08x): UBC unmapped internal read mask %08x (BRSR) %08x\n", tag(), m_sh2_state->pc, mem_mask, m_brsr);
+ return m_brsr;
+}
+
+void sh3_base_device::brsr_w(offs_t offset, uint32_t data, uint32_t mem_mask)
+{
+ COMBINE_DATA(&m_brsr);
+ logerror("'%s' (%08x): UBC unmapped internal write %08x & %08x (BRSR)\n", tag(), m_sh2_state->pc, data, mem_mask);
+}
+
+uint32_t sh3_base_device::brdr_r(offs_t offset, uint32_t mem_mask)
+{
+ logerror("'%s' (%08x): UBC unmapped internal read mask %08x (BRDR) %08x\n", tag(), m_sh2_state->pc, mem_mask, m_brdr);
+ return m_brdr;
+}
+
+void sh3_base_device::brdr_w(offs_t offset, uint32_t data, uint32_t mem_mask)
+{
+ COMBINE_DATA(&m_brdr);
+ logerror("'%s' (%08x): UBC unmapped internal write %08x & %08x (BRDR)\n", tag(), m_sh2_state->pc, data, mem_mask);
+}
+
+// CPG
+uint16_t sh3_base_device::frqcr_r(offs_t offset, uint16_t mem_mask)
+{
+ logerror("'%s' (%08x): CPG unmapped internal read mask %04x (FRQCR) %04x\n", tag(), m_sh2_state->pc, mem_mask, m_frqcr);
+ return m_frqcr;
+}
+
+void sh3_base_device::frqcr_w(offs_t offset, uint16_t data, uint16_t mem_mask)
+{
+ COMBINE_DATA(&m_frqcr);
+ logerror("'%s' (%08x): CPG unmapped internal write %04x & %04x (FRQCR)\n", tag(), m_sh2_state->pc, data, mem_mask);
+}
+
+uint8_t sh3_base_device::stbcr_r(offs_t offset, uint8_t mem_mask)
+{
+ logerror("'%s' (%08x): CPG unmapped internal read mask %02x (STBCR) %02x\n", tag(), m_sh2_state->pc, mem_mask, m_stbcr);
+ return m_stbcr;
+}
+
+void sh3_base_device::stbcr_w(offs_t offset, uint8_t data, uint8_t mem_mask)
+{
+ COMBINE_DATA(&m_stbcr);
+ logerror("'%s' (%08x): CPG unmapped internal write %02x & %02x (STBCR)\n", tag(), m_sh2_state->pc, data, mem_mask);
+}
+
+uint8_t sh3_base_device::wtcnt_r(offs_t offset, uint8_t mem_mask)
+{
+ logerror("'%s' (%08x): CPG unmapped internal read mask %02x (WTCNT) %02x\n", tag(), m_sh2_state->pc, mem_mask, m_stbcr);
+ return m_wtcnt;
+}
+
+void sh3_base_device::wtcnt_w(offs_t offset, uint16_t data, uint16_t mem_mask)
+{
+ if ((data & 0xff00) == 0x5a00)
+ COMBINE_DATA(&m_wtcnt);
+
+ logerror("'%s' (%08x): CPG unmapped internal write %04x & %04x (WTCNT)\n", tag(), m_sh2_state->pc, data, mem_mask);
+}
+
+uint8_t sh3_base_device::wtcsr_r(offs_t offset, uint8_t mem_mask)
+{
+ logerror("'%s' (%08x): CPG unmapped internal read mask %02x (WTCSR) %02x\n", tag(), m_sh2_state->pc, mem_mask, m_wtcsr);
+ return m_wtcsr;
+}
+
+void sh3_base_device::wtcsr_w(offs_t offset, uint16_t data, uint16_t mem_mask)
+{
+ if ((data & 0xff00) == 0xa500)
+ COMBINE_DATA(&m_wtcsr);
+ logerror("'%s' (%08x): CPG unmapped internal write %04x & %04x (WTCSR)\n", tag(), m_sh2_state->pc, data, mem_mask);
+}
+
+// CPG 7709
+uint8_t sh3_base_device::stbcr2_r(offs_t offset, uint8_t mem_mask)
+{
+ logerror("'%s' (%08x): CPG unmapped internal read mask %02x (STBCR2) %02x\n", tag(), m_sh2_state->pc, mem_mask, m_stbcr2);
+ return m_stbcr2;
+}
+
+void sh3_base_device::stbcr2_w(offs_t offset, uint8_t data, uint8_t mem_mask)
+{
+ COMBINE_DATA(&m_stbcr2);
+ logerror("'%s' (%08x): CPG unmapped internal write %02x & %02x (STBCR2)\n", tag(), m_sh2_state->pc, data, mem_mask);
+}
+
+// BSC
+uint16_t sh3_base_device::bcr1_r(offs_t offset, uint16_t mem_mask)
+{
+ logerror("'%s' (%08x): BSC unmapped internal read mask %04x (BCR1) %04x\n", tag(), m_sh2_state->pc, mem_mask, m_bcr1);
+ return m_bcr1;
+}
+
+void sh3_base_device::bcr1_w(offs_t offset, uint16_t data, uint16_t mem_mask)
+{
+ COMBINE_DATA(&m_bcr1);
+ logerror("'%s' (%08x): BSC unmapped internal write %04x & %04x (BCR1)\n", tag(), m_sh2_state->pc, data, mem_mask);
+}
+
+uint16_t sh3_base_device::bcr2_r(offs_t offset, uint16_t mem_mask)
+{
+ logerror("'%s' (%08x): BSC unmapped internal read mask %04x (BCR2) %04x\n", tag(), m_sh2_state->pc, mem_mask, m_bcr2);
+ return m_bcr2;
+}
+
+void sh3_base_device::bcr2_w(offs_t offset, uint16_t data, uint16_t mem_mask)
+{
+ COMBINE_DATA(&m_bcr2);
+ logerror("'%s' (%08x): BSC unmapped internal write %04x & %04x (BCR2)\n", tag(), m_sh2_state->pc, data, mem_mask);
+}
+
+uint16_t sh3_base_device::wcr1_r(offs_t offset, uint16_t mem_mask)
+{
+ logerror("'%s' (%08x): BSC unmapped internal read mask %04x (WCR1) %04x\n", tag(), m_sh2_state->pc, mem_mask, m_wcr1);
+ return m_wcr1;
+}
+
+void sh3_base_device::wcr1_w(offs_t offset, uint16_t data, uint16_t mem_mask)
+{
+ COMBINE_DATA(&m_wcr1);
+ logerror("'%s' (%08x): BSC unmapped internal write %04x & %04x (WCR1)\n", tag(), m_sh2_state->pc, data, mem_mask);
+}
+
+uint16_t sh3_base_device::wcr2_r(offs_t offset, uint16_t mem_mask)
+{
+ logerror("'%s' (%08x): BSC unmapped internal read mask %04x (WCR2) %04x\n", tag(), m_sh2_state->pc, mem_mask, m_wcr2);
+ return m_wcr2;
+}
+
+void sh3_base_device::wcr2_w(offs_t offset, uint16_t data, uint16_t mem_mask)
+{
+ COMBINE_DATA(&m_wcr2);
+ logerror("'%s' (%08x): BSC unmapped internal write %04x & %04x (WCR2)\n", tag(), m_sh2_state->pc, data, mem_mask);
+}
+
+uint16_t sh3_base_device::mcr_r(offs_t offset, uint16_t mem_mask)
+{
+ logerror("'%s' (%08x): BSC unmapped internal read mask %04x (MCR) %04x\n", tag(), m_sh2_state->pc, mem_mask, m_mcr);
+ return m_mcr;
+}
+
+void sh3_base_device::mcr_w(offs_t offset, uint16_t data, uint16_t mem_mask)
+{
+ COMBINE_DATA(&m_mcr);
+ logerror("'%s' (%08x): BSC unmapped internal write %04x & %04x (MCR)\n", tag(), m_sh2_state->pc, data, mem_mask);
+}
+
+uint16_t sh3_base_device::pcr_r(offs_t offset, uint16_t mem_mask)
+{
+ logerror("'%s' (%08x): BSC unmapped internal read mask %04x (PCR) %04x\n", tag(), m_sh2_state->pc, mem_mask, m_pcr);
+ return m_pcr;
+}
+
+void sh3_base_device::pcr_w(offs_t offset, uint16_t data, uint16_t mem_mask)
+{
+ COMBINE_DATA(&m_pcr);
+ logerror("'%s' (%08x): BSC unmapped internal write %04x & %04x (PCR)\n", tag(), m_sh2_state->pc, data, mem_mask);
+}
+
+uint16_t sh3_base_device::rtcsr_r(offs_t offset, uint16_t mem_mask)
+{
+ logerror("'%s' (%08x): BSC unmapped internal read mask %04x (RTCSR) %04x\n", tag(), m_sh2_state->pc, mem_mask, m_rtcsr);
+ return m_rtcsr;
+}
+
+void sh3_base_device::rtcsr_w(offs_t offset, uint16_t data, uint16_t mem_mask)
+{
+ COMBINE_DATA(&m_rtcsr);
+ logerror("'%s' (%08x): BSC unmapped internal write %04x & %04x (RTCSR)\n", tag(), m_sh2_state->pc, data, mem_mask);
+}
+
+uint16_t sh3_base_device::rtcnt_r(offs_t offset, uint16_t mem_mask)
+{
+ logerror("'%s' (%08x): BSC unmapped internal read mask %04x (RTCNT) %04x\n", tag(), m_sh2_state->pc, mem_mask, m_rtcnt);
+ return m_rtcnt;
+}
+
+void sh3_base_device::rtcnt_w(offs_t offset, uint16_t data, uint16_t mem_mask)
+{
+ COMBINE_DATA(&m_rtcnt);
+ logerror("'%s' (%08x): BSC unmapped internal write %04x & %04x (RTCNT)\n", tag(), m_sh2_state->pc, data, mem_mask);
+}
+
+uint16_t sh3_base_device::rtcor_r(offs_t offset, uint16_t mem_mask)
+{
+ logerror("'%s' (%08x): BSC unmapped internal read mask %04x (RTCOR) %04x\n", tag(), m_sh2_state->pc, mem_mask, m_rtcor);
+ return m_rtcor;
+}
+
+void sh3_base_device::rtcor_w(offs_t offset, uint16_t data, uint16_t mem_mask)
+{
+ COMBINE_DATA(&m_rtcor);
+ logerror("'%s' (%08x): BSC unmapped internal write %04x & %04x (RTCOR)\n", tag(), m_sh2_state->pc, data, mem_mask);
+}
+
+uint16_t sh3_base_device::rfcr_r(offs_t offset, uint16_t mem_mask)
+{
+ logerror("'%s' (%08x): BSC unmapped internal read mask %04x (RFCR) %04x\n", tag(), m_sh2_state->pc, mem_mask, m_rfcr);
+ return m_rfcr;
+}
+
+void sh3_base_device::rfcr_w(offs_t offset, uint16_t data, uint16_t mem_mask)
+{
+ COMBINE_DATA(&m_rfcr);
+ logerror("'%s' (%08x): BSC unmapped internal write %04x & %04x (RFCR)\n", tag(), m_sh2_state->pc, data, mem_mask);
+}
+uint8_t sh3_base_device::sdmr_r(offs_t offset, uint8_t mem_mask)
+{
+ logerror("'%s' (%08x): BSC unmapped internal read mask %02x @ %05x (SDMR)\n", tag(), m_sh2_state->pc, mem_mask, offset);
return 0;
}
-/* Lower internal area */
+void sh3_base_device::sdmr_w(offs_t offset, uint8_t data, uint8_t mem_mask)
+{
+ logerror("'%s' (%08x): BSC unmapped internal write %02x & %02x @ %05x (SDMR)\n", tag(), m_sh2_state->pc, data, mem_mask, offset);
+}
-WRITE32_MEMBER( sh3_base_device::sh3_internal_w )
+// BSC 7708
+uint16_t sh3_base_device::dcr_r(offs_t offset, uint16_t mem_mask)
{
- if (offset<0x1000)
- {
- //uint32_t old = m_sh3internal_lower[offset];
- COMBINE_DATA(&m_sh3internal_lower[offset]);
-
- switch (offset)
- {
- case SH3_SAR0_ADDR: sh4_handle_sar0_addr_w(data,mem_mask); break;
- case SH3_SAR1_ADDR: sh4_handle_sar1_addr_w(data,mem_mask); break;
- case SH3_SAR2_ADDR: sh4_handle_sar2_addr_w(data,mem_mask); break;
- case SH3_SAR3_ADDR: sh4_handle_sar3_addr_w(data,mem_mask); break;
- case SH3_DAR0_ADDR: sh4_handle_dar0_addr_w(data,mem_mask); break;
- case SH3_DAR1_ADDR: sh4_handle_dar1_addr_w(data,mem_mask); break;
- case SH3_DAR2_ADDR: sh4_handle_dar2_addr_w(data,mem_mask); break;
- case SH3_DAR3_ADDR: sh4_handle_dar3_addr_w(data,mem_mask); break;
- case SH3_DMATCR0_ADDR: sh4_handle_dmatcr0_addr_w(data,mem_mask); break;
- case SH3_DMATCR1_ADDR: sh4_handle_dmatcr1_addr_w(data,mem_mask); break;
- case SH3_DMATCR2_ADDR: sh4_handle_dmatcr2_addr_w(data,mem_mask); break;
- case SH3_DMATCR3_ADDR: sh4_handle_dmatcr3_addr_w(data,mem_mask); break;
- case SH3_CHCR0_ADDR: sh4_handle_chcr0_addr_w(data,mem_mask); break;
- case SH3_CHCR1_ADDR: sh4_handle_chcr1_addr_w(data,mem_mask); break;
- case SH3_CHCR2_ADDR: sh4_handle_chcr2_addr_w(data,mem_mask); break;
- case SH3_CHCR3_ADDR: sh4_handle_chcr3_addr_w(data,mem_mask); break;
- case SH3_DMAOR_ADDR: sh4_handle_dmaor_addr_w(data>>16,mem_mask>>16); break;
-
-
- case IRR0_IRR1:
- {
- {
- if (mem_mask & 0xff000000)
- {
- logerror("'%s' (%08x): unmapped internal write to %08x = %08x & %08x (IRR0)\n",tag(), m_sh2_state->pc & SH34_AM,(offset *4)+0x4000000,data,mem_mask);
- // not sure if this is how we should clear lines in this core...
- if (!(data & 0x01000000)) execute_set_input(0, CLEAR_LINE);
- if (!(data & 0x02000000)) execute_set_input(1, CLEAR_LINE);
- if (!(data & 0x04000000)) execute_set_input(2, CLEAR_LINE);
- if (!(data & 0x08000000)) execute_set_input(3, CLEAR_LINE);
-
- }
- if (mem_mask & 0x0000ff00)
- {
- logerror("'%s' (%08x): unmapped internal write to %08x = %08x & %08x (IRR1)\n",tag(), m_sh2_state->pc & SH34_AM,(offset *4)+0x4000000,data,mem_mask);
- }
- if (mem_mask & 0x00ff00ff)
- {
- fatalerror("'%s' (%08x): unmapped internal write to %08x = %08x & %08x (IRR0/1 unused bits)\n",tag(), m_sh2_state->pc & SH34_AM,(offset *4)+0x4000000,data,mem_mask);
- }
- }
- }
- break;
-
- case PINTER_IPRC:
- {
- if (mem_mask & 0xffff0000)
- {
- logerror("'%s' (%08x): unmapped internal write to %08x = %08x & %08x (PINTER)\n",tag(), m_sh2_state->pc & SH34_AM,(offset *4)+0x4000000,data,mem_mask);
- }
-
- if (mem_mask & 0x0000ffff)
- {
- data &= 0xffff; mem_mask &= 0xffff;
- COMBINE_DATA(&m_SH4_IPRC);
- logerror("'%s' (%08x): INTC internal write to %08x = %08x & %08x (IPRC)\n",tag(), m_sh2_state->pc & SH34_AM,(offset *4)+0x4000000,data,mem_mask);
- m_exception_priority[SH4_INTC_IRL0] = INTPRI((m_SH4_IPRC & 0x000f)>>0, SH4_INTC_IRL0);
- m_exception_priority[SH4_INTC_IRL1] = INTPRI((m_SH4_IPRC & 0x00f0)>>4, SH4_INTC_IRL1);
- m_exception_priority[SH4_INTC_IRL2] = INTPRI((m_SH4_IPRC & 0x0f00)>>8, SH4_INTC_IRL2);
- m_exception_priority[SH4_INTC_IRL3] = INTPRI((m_SH4_IPRC & 0xf000)>>12,SH4_INTC_IRL3);
- sh4_exception_recompute();
- }
- }
- break;
-
- case PCCR_PDCR:
- {
- if (mem_mask & 0xffff0000)
- {
- logerror("'%s' (%08x): unmapped internal write to %08x = %08x & %08x (PCCR)\n",tag(), m_sh2_state->pc & SH34_AM,(offset *4)+0x4000000,data,mem_mask);
- }
-
- if (mem_mask & 0x0000ffff)
- {
- logerror("'%s' (%08x): unmapped internal write to %08x = %08x & %08x (PDCR)\n",tag(), m_sh2_state->pc & SH34_AM,(offset *4)+0x4000000,data,mem_mask);
- }
- }
- break;
-
- case PECR_PFCR:
- {
- if (mem_mask & 0xffff0000)
- {
- logerror("'%s' (%08x): unmapped internal write to %08x = %08x & %08x (PECR)\n",tag(), m_sh2_state->pc & SH34_AM,(offset *4)+0x4000000,data,mem_mask);
- }
-
- if (mem_mask & 0x0000ffff)
- {
- logerror("'%s' (%08x): unmapped internal write to %08x = %08x & %08x (PFCR)\n",tag(), m_sh2_state->pc & SH34_AM,(offset *4)+0x4000000,data,mem_mask);
- }
- }
- break;
-
-
- case PGCR_PHCR:
- {
- if (mem_mask & 0xffff0000)
- {
- logerror("'%s' (%08x): unmapped internal write to %08x = %08x & %08x (PGCR)\n",tag(), m_sh2_state->pc & SH34_AM,(offset *4)+0x4000000,data,mem_mask);
- }
-
- if (mem_mask & 0x0000ffff)
- {
- logerror("'%s' (%08x): unmapped internal write to %08x = %08x & %08x (PHCR)\n",tag(), m_sh2_state->pc & SH34_AM,(offset *4)+0x4000000,data,mem_mask);
- }
- }
- break;
-
-
- case PJCR_PKCR:
- {
- if (mem_mask & 0xffff0000)
- {
- logerror("'%s' (%08x): unmapped internal write to %08x = %08x & %08x (PJCR)\n",tag(), m_sh2_state->pc & SH34_AM,(offset *4)+0x4000000,data,mem_mask);
- }
-
- if (mem_mask & 0x0000ffff)
- {
- logerror("'%s' (%08x): unmapped internal write to %08x = %08x & %08x (PKCR)\n",tag(), m_sh2_state->pc & SH34_AM,(offset *4)+0x4000000,data,mem_mask);
- }
- }
- break;
-
-
- case PLCR_SCPCR:
- {
- if (mem_mask & 0xffff0000)
- {
- logerror("'%s' (%08x): unmapped internal write to %08x = %08x & %08x (PLCR)\n",tag(), m_sh2_state->pc & SH34_AM,(offset *4)+0x4000000,data,mem_mask);
- }
-
- if (mem_mask & 0x0000ffff)
- {
- logerror("'%s' (%08x): unmapped internal write to %08x = %08x & %08x (SCPCR)\n",tag(), m_sh2_state->pc & SH34_AM,(offset *4)+0x4000000,data,mem_mask);
- }
- }
- break;
-
- case PADR_PBDR:
- {
- if (mem_mask & 0xffff0000)
- {
- m_io->write_qword(SH3_PORT_A, (data>>24)&0xff);
- // logerror("'%s' (%08x): unmapped internal write to %08x = %08x & %08x (PADR)\n",tag(), m_sh2_state->pc & SH34_AM,(offset *4)+0x4000000,data,mem_mask);
- }
-
- if (mem_mask & 0x0000ffff)
- {
- m_io->write_qword(SH3_PORT_B, (data>>8)&0xff);
- // logerror("'%s' (%08x): unmapped internal write to %08x = %08x & %08x (PBDR)\n",tag(), m_sh2_state->pc & SH34_AM,(offset *4)+0x4000000,data,mem_mask);
- }
- }
- break;
-
- case PCDR_PDDR:
- {
- if (mem_mask & 0xffff0000)
- {
- m_io->write_qword(SH3_PORT_C, (data>>24)&0xff);
- // logerror("'%s' (%08x): unmapped internal write to %08x = %08x & %08x (PADR)\n",tag(), m_sh2_state->pc & SH34_AM,(offset *4)+0x4000000,data,mem_mask);
- }
-
- if (mem_mask & 0x0000ffff)
- {
- m_io->write_qword(SH3_PORT_D, (data>>8)&0xff);
- // logerror("'%s' (%08x): unmapped internal write to %08x = %08x & %08x (PBDR)\n",tag(), m_sh2_state->pc & SH34_AM,(offset *4)+0x4000000,data,mem_mask);
- }
- }
- break;
- case PEDR_PFDR:
- {
- if (mem_mask & 0xffff0000)
- {
- m_io->write_qword(SH3_PORT_E, (data>>24)&0xff);
- // logerror("'%s' (%08x): unmapped internal write to %08x = %08x & %08x (PEDR)\n",tag(), m_sh2_state->pc & SH34_AM,(offset *4)+0x4000000,data,mem_mask);
- }
-
- if (mem_mask & 0x0000ffff)
- {
- m_io->write_qword(SH3_PORT_F, (data>>8)&0xff);
- // logerror("'%s' (%08x): unmapped internal write to %08x = %08x & %08x (PFDR)\n",tag(), m_sh2_state->pc & SH34_AM,(offset *4)+0x4000000,data,mem_mask);
- }
- }
- break;
-
- case PGDR_PHDR:
- {
- if (mem_mask & 0xffff0000)
- {
- m_io->write_qword(SH3_PORT_G, (data>>24)&0xff);
- // logerror("'%s' (%08x): unmapped internal write to %08x = %08x & %08x (PGDR)\n",tag(), m_sh2_state->pc & SH34_AM,(offset *4)+0x4000000,data,mem_mask);
- }
-
- if (mem_mask & 0x0000ffff)
- {
- m_io->write_qword(SH3_PORT_H, (data>>8)&0xff);
- // logerror("'%s' (%08x): unmapped internal write to %08x = %08x & %08x (PHDR)\n",tag(), m_sh2_state->pc & SH34_AM,(offset *4)+0x4000000,data,mem_mask);
- }
- }
- break;
-
-
- case PJDR_PKDR:
- {
- if (mem_mask & 0xffff0000)
- {
- m_io->write_qword(SH3_PORT_J, (data>>24)&0xff);
- // logerror("'%s' (%08x): unmapped internal write to %08x = %08x & %08x (PJDR)\n",tag(), m_sh2_state->pc & SH34_AM,(offset *4)+0x4000000,data,mem_mask);
- }
-
- if (mem_mask & 0x0000ffff)
- {
- m_io->write_qword(SH3_PORT_K, (data>>8)&0xff);
- //logerror("'%s' (%08x): unmapped internal write to %08x = %08x & %08x (PKDR)\n",tag(), m_sh2_state->pc & SH34_AM,(offset *4)+0x4000000,data,mem_mask);
- }
- }
- break;
-
- case SCSMR2_SCBRR2:
- {
- if (mem_mask & 0xff000000)
- {
- logerror("'%s' (%08x): SCIF internal write to %08x = %08x & %08x (SCSMR2 - Serial Mode Register 2)\n",tag(), m_sh2_state->pc & SH34_AM,(offset *4)+0x4000000,data,mem_mask);
- }
-
- if (mem_mask & 0x0000ff00)
- {
- logerror("'%s' (%08x): SCIF internal write to %08x = %08x & %08x (SCBRR2 - Bit Rate Register 2)\n",tag(), m_sh2_state->pc & SH34_AM,(offset *4)+0x4000000,data,mem_mask);
- }
- }
- break;
-
- case SCSCR2_SCFTDR2:
- {
- if (mem_mask & 0xff000000)
- {
- logerror("'%s' (%08x): SCIF internal write to %08x = %08x & %08x (SCSCR2 - Serial Control Register 2)\n",tag(), m_sh2_state->pc & SH34_AM,(offset *4)+0x4000000,data,mem_mask);
- }
-
- if (mem_mask & 0x0000ff00)
- {
- logerror("'%s' (%08x): SCIF internal write to %08x = %08x & %08x (SCFTDR2 - Transmit FIFO Data Register 2)\n",tag(), m_sh2_state->pc & SH34_AM,(offset *4)+0x4000000,data,mem_mask);
- }
- }
- break;
-
- case SCSSR2_SCFRDR2:
- {
- if (mem_mask & 0xffff0000)
- {
- logerror("'%s' (%08x): SCIF internal write to %08x = %08x & %08x (SCSSR2 - Serial Status Register 2)\n",tag(), m_sh2_state->pc & SH34_AM,(offset *4)+0x4000000,data,mem_mask);
- }
-
- if (mem_mask & 0x0000ff00)
- {
- logerror("'%s' (%08x): SCIF internal write to %08x = %08x & %08x (SCFRDR2 - Receive FIFO Data Register 2)\n",tag(), m_sh2_state->pc & SH34_AM,(offset *4)+0x4000000,data,mem_mask);
- }
- }
- break;
-
- case SCFCR2_SCFDR2:
- {
- if (mem_mask & 0xff000000)
- {
- logerror("'%s' (%08x): SCIF internal write to %08x = %08x & %08x (SCFCR2 - Fifo Control Register 2)\n",tag(), m_sh2_state->pc & SH34_AM,(offset *4)+0x4000000,data,mem_mask);
- }
-
- if (mem_mask & 0x0000ffff)
- {
- logerror("'%s' (%08x): SCIF internal write to %08x = %08x & %08x (SCFDR2 - Fifo Data Count Register 2)\n",tag(), m_sh2_state->pc & SH34_AM,(offset *4)+0x4000000,data,mem_mask);
- }
- }
- break;
-
- default:
- {
- logerror("'%s' (%08x): unmapped internal write to %08x = %08x & %08x\n",
- tag(), m_sh2_state->pc & SH34_AM,
- (offset *4)+0x4000000,
- data,
- mem_mask);
- }
- break;
- }
+ logerror("'%s' (%08x): BSC unmapped internal read mask %04x (DCR) %04x\n", tag(), m_sh2_state->pc, mem_mask, m_dcr);
+ return m_dcr;
+}
- }
- else
+void sh3_base_device::dcr_w(offs_t offset, uint16_t data, uint16_t mem_mask)
+{
+ COMBINE_DATA(&m_dcr);
+ logerror("'%s' (%08x): BSC unmapped internal write %04x & %04x (DCR)\n", tag(), m_sh2_state->pc, data, mem_mask);
+}
+
+uint16_t sh3_base_device::pctr_r(offs_t offset, uint16_t mem_mask)
+{
+ logerror("'%s' (%08x): BSC unmapped internal read mask %04x (PCTR) %04x\n", tag(), m_sh2_state->pc, mem_mask, m_pctr);
+ return m_pctr;
+}
+
+void sh3_base_device::pctr_w(offs_t offset, uint16_t data, uint16_t mem_mask)
+{
+ COMBINE_DATA(&m_pctr);
+ logerror("'%s' (%08x): BSC unmapped internal write %04x & %04x (PCTR)\n", tag(), m_sh2_state->pc, data, mem_mask);
+}
+
+uint16_t sh3_base_device::pdtr_r(offs_t offset, uint16_t mem_mask)
+{
+ logerror("'%s' (%08x): BSC unmapped internal read mask %04x (PDTR) %04x\n", tag(), m_sh2_state->pc, mem_mask, m_pdtr);
+ return m_pdtr;
+}
+
+void sh3_base_device::pdtr_w(offs_t offset, uint16_t data, uint16_t mem_mask)
+{
+ COMBINE_DATA(&m_pdtr);
+ logerror("'%s' (%08x): BSC unmapped internal write %04x & %04x (PDTR)\n", tag(), m_sh2_state->pc, data, mem_mask);
+}
+
+// BSC 7709
+uint16_t sh3_base_device::bcr3_r(offs_t offset, uint16_t mem_mask)
+{
+ logerror("'%s' (%08x): BSC unmapped internal read mask %04x (BCR3) %04x\n", tag(), m_sh2_state->pc, mem_mask, m_bcr3);
+ return m_bcr3;
+}
+
+void sh3_base_device::bcr3_w(offs_t offset, uint16_t data, uint16_t mem_mask)
+{
+ COMBINE_DATA(&m_bcr3);
+ logerror("'%s' (%08x): BSC unmapped internal write %04x & %04x (BCR3)\n", tag(), m_sh2_state->pc, data, mem_mask);
+}
+
+// BSC 7709S
+uint16_t sh3_base_device::mcscr0_r(offs_t offset, uint16_t mem_mask)
+{
+ logerror("'%s' (%08x): BSC unmapped internal read mask %04x (MCSCR0) %04x\n", tag(), m_sh2_state->pc, mem_mask, m_mcscr0);
+ return m_mcscr0;
+}
+
+void sh3_base_device::mcscr0_w(offs_t offset, uint16_t data, uint16_t mem_mask)
+{
+ COMBINE_DATA(&m_mcscr0);
+ logerror("'%s' (%08x): BSC unmapped internal write %04x & %04x (MCSCR0)\n", tag(), m_sh2_state->pc, data, mem_mask);
+}
+
+uint16_t sh3_base_device::mcscr1_r(offs_t offset, uint16_t mem_mask)
+{
+ logerror("'%s' (%08x): BSC unmapped internal read mask %04x (MCSCR1) %04x\n", tag(), m_sh2_state->pc, mem_mask, m_mcscr1);
+ return m_mcscr1;
+}
+
+void sh3_base_device::mcscr1_w(offs_t offset, uint16_t data, uint16_t mem_mask)
+{
+ COMBINE_DATA(&m_mcscr1);
+ logerror("'%s' (%08x): BSC unmapped internal write %04x & %04x (MCSCR1)\n", tag(), m_sh2_state->pc, data, mem_mask);
+}
+
+uint16_t sh3_base_device::mcscr2_r(offs_t offset, uint16_t mem_mask)
+{
+ logerror("'%s' (%08x): BSC unmapped internal read mask %04x (MCSCR2) %04x\n", tag(), m_sh2_state->pc, mem_mask, m_mcscr2);
+ return m_mcscr2;
+}
+
+void sh3_base_device::mcscr2_w(offs_t offset, uint16_t data, uint16_t mem_mask)
+{
+ COMBINE_DATA(&m_mcscr2);
+ logerror("'%s' (%08x): BSC unmapped internal write %04x & %04x (MCSCR2)\n", tag(), m_sh2_state->pc, data, mem_mask);
+}
+
+uint16_t sh3_base_device::mcscr3_r(offs_t offset, uint16_t mem_mask)
+{
+ logerror("'%s' (%08x): BSC unmapped internal read mask %04x (MCSCR3) %04x\n", tag(), m_sh2_state->pc, mem_mask, m_mcscr3);
+ return m_mcscr3;
+}
+
+void sh3_base_device::mcscr3_w(offs_t offset, uint16_t data, uint16_t mem_mask)
+{
+ COMBINE_DATA(&m_mcscr3);
+ logerror("'%s' (%08x): BSC unmapped internal write %04x & %04x (MCSCR3)\n", tag(), m_sh2_state->pc, data, mem_mask);
+}
+
+uint16_t sh3_base_device::mcscr4_r(offs_t offset, uint16_t mem_mask)
+{
+ logerror("'%s' (%08x): BSC unmapped internal read mask %04x (MCSCR4) %04x\n", tag(), m_sh2_state->pc, mem_mask, m_mcscr4);
+ return m_mcscr4;
+}
+
+void sh3_base_device::mcscr4_w(offs_t offset, uint16_t data, uint16_t mem_mask)
+{
+ COMBINE_DATA(&m_mcscr4);
+ logerror("'%s' (%08x): BSC unmapped internal write %04x & %04x (MCSCR4)\n", tag(), m_sh2_state->pc, data, mem_mask);
+}
+
+uint16_t sh3_base_device::mcscr5_r(offs_t offset, uint16_t mem_mask)
+{
+ logerror("'%s' (%08x): BSC unmapped internal read mask %04x (MCSCR5) %04x\n", tag(), m_sh2_state->pc, mem_mask, m_mcscr5);
+ return m_mcscr5;
+}
+
+void sh3_base_device::mcscr5_w(offs_t offset, uint16_t data, uint16_t mem_mask)
+{
+ COMBINE_DATA(&m_mcscr5);
+ logerror("'%s' (%08x): BSC unmapped internal write %04x & %04x (MCSCR5)\n", tag(), m_sh2_state->pc, data, mem_mask);
+}
+
+uint16_t sh3_base_device::mcscr6_r(offs_t offset, uint16_t mem_mask)
+{
+ logerror("'%s' (%08x): BSC unmapped internal read mask %04x (MCSCR6) %04x\n", tag(), m_sh2_state->pc, mem_mask, m_mcscr6);
+ return m_mcscr6;
+}
+
+void sh3_base_device::mcscr6_w(offs_t offset, uint16_t data, uint16_t mem_mask)
+{
+ COMBINE_DATA(&m_mcscr6);
+ logerror("'%s' (%08x): BSC unmapped internal write %04x & %04x (MCSCR6)\n", tag(), m_sh2_state->pc, data, mem_mask);
+}
+
+uint16_t sh3_base_device::mcscr7_r(offs_t offset, uint16_t mem_mask)
+{
+ logerror("'%s' (%08x): BSC unmapped internal read mask %04x (MCSCR7) %04x\n", tag(), m_sh2_state->pc, mem_mask, m_mcscr7);
+ return m_mcscr7;
+}
+
+void sh3_base_device::mcscr7_w(offs_t offset, uint16_t data, uint16_t mem_mask)
+{
+ COMBINE_DATA(&m_mcscr7);
+ logerror("'%s' (%08x): BSC unmapped internal write %04x & %04x (MCSCR7)\n", tag(), m_sh2_state->pc, data, mem_mask);
+}
+
+// RTC
+uint8_t sh3_base_device::r64cnt_r(offs_t offset, uint8_t mem_mask)
+{
+ logerror("'%s' (%08x): RTC unmapped internal read mask %02x (R64CNT) %02x\n", tag(), m_sh2_state->pc, mem_mask, m_r64cnt);
+ return m_r64cnt;
+}
+
+uint8_t sh3_base_device::rseccnt_r(offs_t offset, uint8_t mem_mask)
+{
+ logerror("'%s' (%08x): RTC unmapped internal read mask %02x (RSECCNT) %02x\n", tag(), m_sh2_state->pc, mem_mask, m_rseccnt);
+ return m_rseccnt;
+}
+
+void sh3_base_device::rseccnt_w(offs_t offset, uint8_t data, uint8_t mem_mask)
+{
+ COMBINE_DATA(&m_rseccnt);
+ logerror("'%s' (%08x): RTC unmapped internal write %02x & %02x (RSECCNT)\n", tag(), m_sh2_state->pc, data, mem_mask);
+}
+
+uint8_t sh3_base_device::rmincnt_r(offs_t offset, uint8_t mem_mask)
+{
+ logerror("'%s' (%08x): RTC unmapped internal read mask %02x (RMINCNT) %02x\n", tag(), m_sh2_state->pc, mem_mask, m_rseccnt);
+ return m_rmincnt;
+}
+
+void sh3_base_device::rmincnt_w(offs_t offset, uint8_t data, uint8_t mem_mask)
+{
+ COMBINE_DATA(&m_rmincnt);
+ logerror("'%s' (%08x): RTC unmapped internal write %02x & %02x (RMINCNT)\n", tag(), m_sh2_state->pc, data, mem_mask);
+}
+
+uint8_t sh3_base_device::rhrcnt_r(offs_t offset, uint8_t mem_mask)
+{
+ logerror("'%s' (%08x): RTC unmapped internal read mask %02x (RHRCNT) %02x\n", tag(), m_sh2_state->pc, mem_mask, m_rhrcnt);
+ return m_rhrcnt;
+}
+
+void sh3_base_device::rhrcnt_w(offs_t offset, uint8_t data, uint8_t mem_mask)
+{
+ COMBINE_DATA(&m_rhrcnt);
+ logerror("'%s' (%08x): RTC unmapped internal write %02x & %02x (RHRCNT)\n", tag(), m_sh2_state->pc, data, mem_mask);
+}
+
+uint8_t sh3_base_device::rwkcnt_r(offs_t offset, uint8_t mem_mask)
+{
+ logerror("'%s' (%08x): RTC unmapped internal read mask %02x (RWKCNT) %02x\n", tag(), m_sh2_state->pc, mem_mask, m_rhrcnt);
+ return m_rwkcnt;
+}
+
+void sh3_base_device::rwkcnt_w(offs_t offset, uint8_t data, uint8_t mem_mask)
+{
+ COMBINE_DATA(&m_rwkcnt);
+ logerror("'%s' (%08x): RTC unmapped internal write %02x & %02x (RWKCNT)\n", tag(), m_sh2_state->pc, data, mem_mask);
+}
+
+uint8_t sh3_base_device::rdaycnt_r(offs_t offset, uint8_t mem_mask)
+{
+ logerror("'%s' (%08x): RTC unmapped internal read mask %02x (RDAYCNT) %02x\n", tag(), m_sh2_state->pc, mem_mask, m_rdaycnt);
+ return m_rdaycnt;
+}
+
+void sh3_base_device::rdaycnt_w(offs_t offset, uint8_t data, uint8_t mem_mask)
+{
+ COMBINE_DATA(&m_rdaycnt);
+ logerror("'%s' (%08x): RTC unmapped internal write %02x & %02x (RDAYCNT)\n", tag(), m_sh2_state->pc, data, mem_mask);
+}
+
+uint8_t sh3_base_device::rmoncnt_r(offs_t offset, uint8_t mem_mask)
+{
+ logerror("'%s' (%08x): RTC unmapped internal read mask %02x (RMONCNT) %02x\n", tag(), m_sh2_state->pc, mem_mask, m_rmoncnt);
+ return m_rmoncnt;
+}
+
+void sh3_base_device::rmoncnt_w(offs_t offset, uint8_t data, uint8_t mem_mask)
+{
+ COMBINE_DATA(&m_rmoncnt);
+ logerror("'%s' (%08x): RTC unmapped internal write %02x & %02x (RMONCNT)\n", tag(), m_sh2_state->pc, data, mem_mask);
+}
+
+uint8_t sh3_base_device::ryrcnt_r(offs_t offset, uint8_t mem_mask)
+{
+ logerror("'%s' (%08x): RTC unmapped internal read mask %02x (RYRCNT) %02x\n", tag(), m_sh2_state->pc, mem_mask, m_ryrcnt);
+ return m_ryrcnt;
+}
+
+void sh3_base_device::ryrcnt_w(offs_t offset, uint8_t data, uint8_t mem_mask)
+{
+ COMBINE_DATA(&m_ryrcnt);
+ logerror("'%s' (%08x): RTC unmapped internal write %02x & %02x (RYRCNT)\n", tag(), m_sh2_state->pc, data, mem_mask);
+}
+
+uint8_t sh3_base_device::rsecar_r(offs_t offset, uint8_t mem_mask)
+{
+ logerror("'%s' (%08x): RTC unmapped internal read mask %02x (RSECAR) %02x\n", tag(), m_sh2_state->pc, mem_mask, m_rsecar);
+ return m_rsecar;
+}
+
+void sh3_base_device::rsecar_w(offs_t offset, uint8_t data, uint8_t mem_mask)
+{
+ COMBINE_DATA(&m_rsecar);
+ logerror("'%s' (%08x): RTC unmapped internal write %02x & %02x (RSECAR)\n", tag(), m_sh2_state->pc, data, mem_mask);
+}
+
+uint8_t sh3_base_device::rminar_r(offs_t offset, uint8_t mem_mask)
+{
+ logerror("'%s' (%08x): RTC unmapped internal read mask %02x (RMINAR) %02x\n", tag(), m_sh2_state->pc, mem_mask, m_rminar);
+ return m_rminar;
+}
+
+void sh3_base_device::rminar_w(offs_t offset, uint8_t data, uint8_t mem_mask)
+{
+ COMBINE_DATA(&m_rminar);
+ logerror("'%s' (%08x): RTC unmapped internal write %02x & %02x (RMINAR)\n", tag(), m_sh2_state->pc, data, mem_mask);
+}
+
+uint8_t sh3_base_device::rhrar_r(offs_t offset, uint8_t mem_mask)
+{
+ logerror("'%s' (%08x): RTC unmapped internal read mask %02x (RHRAR) %02x\n", tag(), m_sh2_state->pc, mem_mask, m_rhrar);
+ return m_rhrar;
+}
+
+void sh3_base_device::rhrar_w(offs_t offset, uint8_t data, uint8_t mem_mask)
+{
+ COMBINE_DATA(&m_rhrar);
+ logerror("'%s' (%08x): RTC unmapped internal write %02x & %02x (RHRAR)\n", tag(), m_sh2_state->pc, data, mem_mask);
+}
+
+uint8_t sh3_base_device::rwkar_r(offs_t offset, uint8_t mem_mask)
+{
+ logerror("'%s' (%08x): RTC unmapped internal read mask %02x (RWKAR) %02x\n", tag(), m_sh2_state->pc, mem_mask, m_rhrar);
+ return m_rwkar;
+}
+
+void sh3_base_device::rwkar_w(offs_t offset, uint8_t data, uint8_t mem_mask)
+{
+ COMBINE_DATA(&m_rwkar);
+ logerror("'%s' (%08x): RTC unmapped internal write %02x & %02x (RWKAR)\n", tag(), m_sh2_state->pc, data, mem_mask);
+}
+
+uint8_t sh3_base_device::rdayar_r(offs_t offset, uint8_t mem_mask)
+{
+ logerror("'%s' (%08x): RTC unmapped internal read mask %02x (RDAYAR) %02x\n", tag(), m_sh2_state->pc, mem_mask, m_rdayar);
+ return m_rdayar;
+}
+
+void sh3_base_device::rdayar_w(offs_t offset, uint8_t data, uint8_t mem_mask)
+{
+ COMBINE_DATA(&m_rdayar);
+ logerror("'%s' (%08x): RTC unmapped internal write %02x & %02x (RDAYAR)\n", tag(), m_sh2_state->pc, data, mem_mask);
+}
+
+uint8_t sh3_base_device::rmonar_r(offs_t offset, uint8_t mem_mask)
+{
+ logerror("'%s' (%08x): RTC unmapped internal read mask %02x (RMONAR) %02x\n", tag(), m_sh2_state->pc, mem_mask, m_rmonar);
+ return m_rmonar;
+}
+
+void sh3_base_device::rmonar_w(offs_t offset, uint8_t data, uint8_t mem_mask)
+{
+ COMBINE_DATA(&m_rmonar);
+ logerror("'%s' (%08x): RTC unmapped internal write %02x & %02x (RMONAR)\n", tag(), m_sh2_state->pc, data, mem_mask);
+}
+
+uint8_t sh3_base_device::rcr1_r(offs_t offset, uint8_t mem_mask)
+{
+ logerror("'%s' (%08x): RTC unmapped internal read mask %02x (RCR1) %02x\n", tag(), m_sh2_state->pc, mem_mask, m_rcr1);
+ return m_rcr1;
+}
+
+void sh3_base_device::rcr1_w(offs_t offset, uint8_t data, uint8_t mem_mask)
+{
+ COMBINE_DATA(&m_rcr1);
+ logerror("'%s' (%08x): RTC unmapped internal write %02x & %02x (RCR1)\n", tag(), m_sh2_state->pc, data, mem_mask);
+}
+
+uint8_t sh3_base_device::rcr2_r(offs_t offset, uint8_t mem_mask)
+{
+ logerror("'%s' (%08x): RTC unmapped internal read mask %04x (RCR2) %04x\n", tag(), m_sh2_state->pc, mem_mask, m_rcr2);
+ return m_rcr2;
+}
+
+void sh3_base_device::rcr2_w(offs_t offset, uint8_t data, uint8_t mem_mask)
+{
+ COMBINE_DATA(&m_rcr2);
+ logerror("'%s' (%08x): RTC unmapped internal write %02x & %02x (RCR2)\n", tag(), m_sh2_state->pc, data, mem_mask);
+}
+
+// INTC
+uint16_t sh3_base_device::icr0_r(offs_t offset, uint16_t mem_mask)
+{
+ logerror("'%s' (%08x): INTC unmapped internal read mask %04x (ICR0) %04x\n", tag(), m_sh2_state->pc, mem_mask, m_icr0);
+ return m_icr0;
+}
+
+void sh3_base_device::icr0_w(offs_t offset, uint16_t data, uint16_t mem_mask)
+{
+ COMBINE_DATA(&m_icr0);
+ logerror("'%s' (%08x): INTC unmapped internal write %04x & %04x (ICR0)\n", tag(), m_sh2_state->pc, data, mem_mask);
+}
+
+uint16_t sh3_base_device::iprb_r(offs_t offset, uint16_t mem_mask)
+{
+ logerror("'%s' (%08x): INTC unmapped internal read mask %04x (IPRB) %04x\n", tag(), m_sh2_state->pc, mem_mask, m_iprb);
+ return m_iprb;
+}
+
+void sh3_base_device::iprb_w(offs_t offset, uint16_t data, uint16_t mem_mask)
+{
+ COMBINE_DATA(&m_iprb);
+ logerror("'%s' (%08x): INTC unmapped internal write %04x & %04x (IPRB)\n", tag(), m_sh2_state->pc, data, mem_mask);
+}
+
+// INTC 7709
+uint32_t sh3_base_device::intevt2_r(offs_t offset, uint32_t mem_mask)
+{
+ //logerror("'%s' (%08x): INTC unmapped internal read mask %08x (INTEVT2) %08x\n", tag(), m_sh2_state->pc, mem_mask, m_intevt2);
+ return m_intevt2;
+}
+
+void sh3_base_device::intevt2_w(offs_t offset, uint32_t data, uint32_t mem_mask)
+{
+ COMBINE_DATA(&m_intevt2);
+ logerror("'%s' (%08x): INTC unmapped internal write %08x & %08x (INTEVT2)\n", tag(), m_sh2_state->pc, data, mem_mask);
+}
+
+uint8_t sh3_base_device::irr0_r(offs_t offset, uint8_t mem_mask)
+{
+ logerror("'%s' (%08x): INTC unmapped internal read mask %02x (IRR0) %02x\n", tag(), m_sh2_state->pc, mem_mask, m_irr0);
+ return m_irr0;
+}
+
+void sh3_base_device::irr0_w(offs_t offset, uint8_t data, uint8_t mem_mask)
+{
+ COMBINE_DATA(&m_irr0);
+ logerror("'%s' (%08x): INTC unmapped internal write %02x & %02x (IRR0)\n", tag(), m_sh2_state->pc, data, mem_mask);
+ // not sure if this is how we should clear lines in this core...
+ if (!(data & 0x01)) execute_set_input(0, CLEAR_LINE);
+ if (!(data & 0x02)) execute_set_input(1, CLEAR_LINE);
+ if (!(data & 0x04)) execute_set_input(2, CLEAR_LINE);
+ if (!(data & 0x08)) execute_set_input(3, CLEAR_LINE);
+}
+
+uint8_t sh3_base_device::irr1_r(offs_t offset, uint8_t mem_mask)
+{
+ logerror("'%s' (%08x): INTC unmapped internal read mask %02x (IRR1) %02x\n", tag(), m_sh2_state->pc, mem_mask, m_irr1);
+ return m_irr1;
+}
+
+void sh3_base_device::irr1_w(offs_t offset, uint8_t data, uint8_t mem_mask)
+{
+ COMBINE_DATA(&m_irr1);
+ logerror("'%s' (%08x): INTC unmapped internal write %02x & %02x (IRR1)\n", tag(), m_sh2_state->pc, data, mem_mask);
+}
+
+uint8_t sh3_base_device::irr2_r(offs_t offset, uint8_t mem_mask)
+{
+ logerror("'%s' (%08x): INTC unmapped internal read mask %02x (IRR2) %02x\n", tag(), m_sh2_state->pc, mem_mask, m_irr2);
+ return m_irr2;
+}
+
+void sh3_base_device::irr2_w(offs_t offset, uint8_t data, uint8_t mem_mask)
+{
+ COMBINE_DATA(&m_irr2);
+ logerror("'%s' (%08x): INTC unmapped internal write %02x & %02x (IRR2)\n", tag(), m_sh2_state->pc, data, mem_mask);
+}
+
+uint16_t sh3_base_device::icr1_r(offs_t offset, uint16_t mem_mask)
+{
+ logerror("'%s' (%08x): INTC unmapped internal read mask %04x (ICR1) %04x\n", tag(), m_sh2_state->pc, mem_mask, m_icr1);
+ return m_icr1;
+}
+
+void sh3_base_device::icr1_w(offs_t offset, uint16_t data, uint16_t mem_mask)
+{
+ COMBINE_DATA(&m_icr1);
+ logerror("'%s' (%08x): INTC unmapped internal write %04x & %04x (ICR1)\n", tag(), m_sh2_state->pc, data, mem_mask);
+}
+
+uint16_t sh3_base_device::icr2_r(offs_t offset, uint16_t mem_mask)
+{
+ logerror("'%s' (%08x): INTC unmapped internal read mask %04x (ICR2) %04x\n", tag(), m_sh2_state->pc, mem_mask, m_icr2);
+ return m_icr2;
+}
+
+void sh3_base_device::icr2_w(offs_t offset, uint16_t data, uint16_t mem_mask)
+{
+ COMBINE_DATA(&m_icr2);
+ logerror("'%s' (%08x): INTC unmapped internal write %04x & %04x (ICR2)\n", tag(), m_sh2_state->pc, data, mem_mask);
+}
+
+uint16_t sh3_base_device::pinter_r(offs_t offset, uint16_t mem_mask)
+{
+ logerror("'%s' (%08x): INTC unmapped internal read mask %04x (PINTER) %04x\n", tag(), m_sh2_state->pc, mem_mask, m_pinter);
+ return m_pinter;
+}
+
+void sh3_base_device::pinter_w(offs_t offset, uint16_t data, uint16_t mem_mask)
+{
+ COMBINE_DATA(&m_pinter);
+ logerror("'%s' (%08x): INTC unmapped internal write %04x & %04x (PINTER)\n", tag(), m_sh2_state->pc, data, mem_mask);
+}
+
+uint16_t sh3_base_device::iprc_r(offs_t offset, uint16_t mem_mask)
+{
+ logerror("'%s' (%08x): INTC unmapped internal read mask %04x (IPRC) %04x\n", tag(), m_sh2_state->pc, mem_mask, m_iprc);
+ return m_iprc;
+}
+
+void sh3_base_device::iprc_w(offs_t offset, uint16_t data, uint16_t mem_mask)
+{
+ COMBINE_DATA(&m_iprc);
+ logerror("'%s' (%08x): INTC internal write %04x & %04x (IPRC)\n", tag(), m_sh2_state->pc, data, mem_mask);
+ m_exception_priority[SH4_INTC_IRL0] = INTPRI((m_iprc & 0x000f) >> 0, SH4_INTC_IRL0);
+ m_exception_priority[SH4_INTC_IRL1] = INTPRI((m_iprc & 0x00f0) >> 4, SH4_INTC_IRL1);
+ m_exception_priority[SH4_INTC_IRL2] = INTPRI((m_iprc & 0x0f00) >> 8, SH4_INTC_IRL2);
+ m_exception_priority[SH4_INTC_IRL3] = INTPRI((m_iprc & 0xf000) >> 12, SH4_INTC_IRL3);
+ sh4_exception_recompute();
+}
+
+uint16_t sh3_base_device::iprd_r(offs_t offset, uint16_t mem_mask)
+{
+ logerror("'%s' (%08x): INTC unmapped internal read mask %04x (IPRD) %04x\n", tag(), m_sh2_state->pc, mem_mask, m_iprd);
+ return m_iprd;
+}
+
+void sh3_base_device::iprd_w(offs_t offset, uint16_t data, uint16_t mem_mask)
+{
+ COMBINE_DATA(&m_iprd);
+ logerror("'%s' (%08x): INTC internal write %04x & %04x (IPRD)\n", tag(), m_sh2_state->pc, data, mem_mask);
+}
+
+uint16_t sh3_base_device::ipre_r(offs_t offset, uint16_t mem_mask)
+{
+ logerror("'%s' (%08x): INTC unmapped internal read mask %04x (IPRE) %04x\n", tag(), m_sh2_state->pc, mem_mask, m_ipre);
+ return m_ipre;
+}
+
+void sh3_base_device::ipre_w(offs_t offset, uint16_t data, uint16_t mem_mask)
+{
+ COMBINE_DATA(&m_ipre);
+ logerror("'%s' (%08x): INTC internal write %04x & %04x (IPRE)\n", tag(), m_sh2_state->pc, data, mem_mask);
+}
+
+// SCI
+uint8_t sh3_base_device::scsmr_r(offs_t offset, uint8_t mem_mask)
+{
+ logerror("'%s' (%08x): SCI unmapped internal read mask %02x (SCSMR) %02x\n", tag(), m_sh2_state->pc, mem_mask, m_scsmr);
+ return m_scsmr;
+}
+
+void sh3_base_device::scsmr_w(offs_t offset, uint8_t data, uint8_t mem_mask)
+{
+ COMBINE_DATA(&m_scsmr);
+ logerror("'%s' (%08x): SCI unmapped internal write %02x & %02x (SCSMR)\n", tag(), m_sh2_state->pc, data, mem_mask);
+}
+
+uint8_t sh3_base_device::scbrr_r(offs_t offset, uint8_t mem_mask)
+{
+ logerror("'%s' (%08x): SCI unmapped internal read mask %02x (SCBRR) %02x\n", tag(), m_sh2_state->pc, mem_mask, m_scbrr);
+ return m_scbrr;
+}
+
+void sh3_base_device::scbrr_w(offs_t offset, uint8_t data, uint8_t mem_mask)
+{
+ COMBINE_DATA(&m_scbrr);
+ logerror("'%s' (%08x): SCSI unmapped internal write %02x & %02x (SCBRR)\n", tag(), m_sh2_state->pc, data, mem_mask);
+}
+
+uint8_t sh3_base_device::scscr_r(offs_t offset, uint8_t mem_mask)
+{
+ logerror("'%s' (%08x): SCI unmapped internal read mask %02x (SCSCR) %02x\n", tag(), m_sh2_state->pc, mem_mask, m_scscr);
+ return m_scscr;
+}
+
+void sh3_base_device::scscr_w(offs_t offset, uint8_t data, uint8_t mem_mask)
+{
+ COMBINE_DATA(&m_scscr);
+ logerror("'%s' (%08x): SCI unmapped internal write %02x & %02x (SCSCR)\n", tag(), m_sh2_state->pc, data, mem_mask);
+}
+
+uint8_t sh3_base_device::sctdr_r(offs_t offset, uint8_t mem_mask)
+{
+ logerror("'%s' (%08x): SCI unmapped internal read mask %02x (SCTDR) %02x\n", tag(), m_sh2_state->pc, mem_mask, m_sctdr);
+ return m_sctdr;
+}
+
+void sh3_base_device::sctdr_w(offs_t offset, uint8_t data, uint8_t mem_mask)
+{
+ COMBINE_DATA(&m_sctdr);
+ logerror("'%s' (%08x): SCI unmapped internal write %02x & %02x (SCTDR)\n", tag(), m_sh2_state->pc, data, mem_mask);
+}
+
+uint8_t sh3_base_device::scssr_r(offs_t offset, uint8_t mem_mask)
+{
+ logerror("'%s' (%08x): SCI unmapped internal read mask %02x (SCSSR) %02x\n", tag(), m_sh2_state->pc, mem_mask, m_scssr);
+ return m_scssr;
+}
+
+void sh3_base_device::scssr_w(offs_t offset, uint8_t data, uint8_t mem_mask)
+{
+ m_scssr = (m_scssr | (data & 1)) & (data | 6);
+ if (!(m_scssr & 0x80))
{
- logerror("'%s' (%08x): unmapped internal write to %08x = %08x & %08x\n",
- tag(), m_sh2_state->pc & SH34_AM,
- (offset *4)+0x4000000,
- data,
- mem_mask);
+ //printf("%c", m_sctdr);
+ m_scssr |= 0x80;
}
+ logerror("'%s' (%08x): SCI unmapped internal write %02x & %02x (SCSSR)\n", tag(), m_sh2_state->pc, data, mem_mask);
+}
+
+uint8_t sh3_base_device::scrdr_r(offs_t offset, uint8_t mem_mask)
+{
+ logerror("'%s' (%08x): SCI unmapped internal read mask %02x (SCRDR) %02x\n", tag(), m_sh2_state->pc, mem_mask, m_scrdr);
+ return m_scrdr;
+}
+
+uint8_t sh3_base_device::scscmr_r(offs_t offset, uint8_t mem_mask)
+{
+ logerror("'%s' (%08x): SCI unmapped internal read mask %02x (SCSCMR) %02x\n", tag(), m_sh2_state->pc, mem_mask, m_scscmr);
+ return m_scscmr;
+}
+
+void sh3_base_device::scscmr_w(offs_t offset, uint8_t data, uint8_t mem_mask)
+{
+ COMBINE_DATA(&m_scscmr);
+ logerror("'%s' (%08x): SCI unmapped internal write %02x & %02x (SCSCMR)\n", tag(), m_sh2_state->pc, data, mem_mask);
+}
+
+// SCI 7708
+uint8_t sh3_base_device::scsptr_r(offs_t offset, uint8_t mem_mask)
+{
+ logerror("'%s' (%08x): SCI unmapped internal read mask %02x (SCSPTR) %02x\n", tag(), m_sh2_state->pc, mem_mask, m_scsptr);
+ return m_scsptr;
+}
+
+void sh3_base_device::scsptr_w(offs_t offset, uint8_t data, uint8_t mem_mask)
+{
+ COMBINE_DATA(&m_scsptr);
+ logerror("'%s' (%08x): SCI unmapped internal write %02x & %02x (SCSPTR)\n", tag(), m_sh2_state->pc, data, mem_mask);
+}
+
+// CMT 7709
+uint16_t sh3_base_device::cmstr_r(offs_t offset, uint16_t mem_mask)
+{
+ logerror("'%s' (%08x): CMT unmapped internal read mask %04x (CMSTR) %04x\n", tag(), m_sh2_state->pc, mem_mask, m_cmstr);
+ return m_cmstr;
+}
+
+void sh3_base_device::cmstr_w(offs_t offset, uint16_t data, uint16_t mem_mask)
+{
+ COMBINE_DATA(&m_cmstr);
+ logerror("'%s' (%08x): CMT unmapped internal write %04x & %04x (CMSTR)\n", tag(), m_sh2_state->pc, data, mem_mask);
+}
+
+uint16_t sh3_base_device::cmscr_r(offs_t offset, uint16_t mem_mask)
+{
+ logerror("'%s' (%08x): CMT unmapped internal read mask %04x (CMSCR) %04x\n", tag(), m_sh2_state->pc, mem_mask, m_cmscr);
+ return m_cmscr;
+}
+
+void sh3_base_device::cmscr_w(offs_t offset, uint16_t data, uint16_t mem_mask)
+{
+ COMBINE_DATA(&m_cmscr);
+ logerror("'%s' (%08x): CMT unmapped internal write %04x & %04x (CMSCR)\n", tag(), m_sh2_state->pc, data, mem_mask);
+}
+
+uint16_t sh3_base_device::cmcnt_r(offs_t offset, uint16_t mem_mask)
+{
+ logerror("'%s' (%08x): CMT unmapped internal read mask %04x (CMCNT) %04x\n", tag(), m_sh2_state->pc, mem_mask, m_cmcnt);
+ return m_cmcnt;
+}
+
+void sh3_base_device::cmcnt_w(offs_t offset, uint16_t data, uint16_t mem_mask)
+{
+ COMBINE_DATA(&m_cmcnt);
+ logerror("'%s' (%08x): CMT unmapped internal write %04x & %04x (CMCNT)\n", tag(), m_sh2_state->pc, data, mem_mask);
+}
+
+uint16_t sh3_base_device::cmcor_r(offs_t offset, uint16_t mem_mask)
+{
+ logerror("'%s' (%08x): CMT unmapped internal read mask %04x (CMCOR) %04x\n", tag(), m_sh2_state->pc, mem_mask, m_cmcor);
+ return m_cmcor;
+}
+
+void sh3_base_device::cmcor_w(offs_t offset, uint16_t data, uint16_t mem_mask)
+{
+ COMBINE_DATA(&m_cmcor);
+ logerror("'%s' (%08x): CMT unmapped internal write %04x & %04x (CMCOR)\n", tag(), m_sh2_state->pc, data, mem_mask);
+}
+
+// AD 7709
+uint8_t sh3_base_device::addrah_r(offs_t offset, uint8_t mem_mask)
+{
+ logerror("'%s' (%08x): AD unmapped internal read mask %02x (ADDRAH) %02x\n", tag(), m_sh2_state->pc, mem_mask, m_addrah);
+ return m_addrah;
+}
+
+void sh3_base_device::addrah_w(offs_t offset, uint8_t data, uint8_t mem_mask)
+{
+ COMBINE_DATA(&m_addrah);
+ logerror("'%s' (%08x): AD unmapped internal write %02x & %02x (ADDRAH)\n", tag(), m_sh2_state->pc, data, mem_mask);
+}
+
+uint8_t sh3_base_device::addral_r(offs_t offset, uint8_t mem_mask)
+{
+ logerror("'%s' (%08x): AD unmapped internal read mask %02x (ADDRAL) %02x\n", tag(), m_sh2_state->pc, mem_mask, m_addral);
+ return m_addral;
+}
+
+void sh3_base_device::addral_w(offs_t offset, uint8_t data, uint8_t mem_mask)
+{
+ COMBINE_DATA(&m_addral);
+ logerror("'%s' (%08x): AD unmapped internal write %02x & %02x (ADDRAL)\n", tag(), m_sh2_state->pc, data, mem_mask);
+}
+
+uint8_t sh3_base_device::addrbh_r(offs_t offset, uint8_t mem_mask)
+{
+ logerror("'%s' (%08x): AD unmapped internal read mask %02x (ADDRBH) %02x\n", tag(), m_sh2_state->pc, mem_mask, m_addrbh);
+ return m_addrbh;
+}
+
+void sh3_base_device::addrbh_w(offs_t offset, uint8_t data, uint8_t mem_mask)
+{
+ COMBINE_DATA(&m_addrbh);
+ logerror("'%s' (%08x): AD unmapped internal write %02x & %02x (ADDRBH)\n", tag(), m_sh2_state->pc, data, mem_mask);
+}
+
+uint8_t sh3_base_device::addrbl_r(offs_t offset, uint8_t mem_mask)
+{
+ logerror("'%s' (%08x): AD unmapped internal read mask %02x (ADDRBL) %02x\n", tag(), m_sh2_state->pc, mem_mask, m_addrbl);
+ return m_addrbl;
+}
+
+void sh3_base_device::addrbl_w(offs_t offset, uint8_t data, uint8_t mem_mask)
+{
+ COMBINE_DATA(&m_addrbl);
+ logerror("'%s' (%08x): AD unmapped internal write %02x & %02x (ADDRBL)\n", tag(), m_sh2_state->pc, data, mem_mask);
+}
+
+uint8_t sh3_base_device::addrch_r(offs_t offset, uint8_t mem_mask)
+{
+ logerror("'%s' (%08x): AD unmapped internal read mask %02x (ADDRCH) %02x\n", tag(), m_sh2_state->pc, mem_mask, m_addrch);
+ return m_addrch;
+}
+
+void sh3_base_device::addrch_w(offs_t offset, uint8_t data, uint8_t mem_mask)
+{
+ COMBINE_DATA(&m_addrch);
+ logerror("'%s' (%08x): AD unmapped internal write %02x & %02x (ADDRCH)\n", tag(), m_sh2_state->pc, data, mem_mask);
+}
+
+uint8_t sh3_base_device::addrcl_r(offs_t offset, uint8_t mem_mask)
+{
+ logerror("'%s' (%08x): AD unmapped internal read mask %02x (ADDRCL) %02x\n", tag(), m_sh2_state->pc, mem_mask, m_addrcl);
+ return m_addrcl;
+}
+
+void sh3_base_device::addrcl_w(offs_t offset, uint8_t data, uint8_t mem_mask)
+{
+ COMBINE_DATA(&m_addrcl);
+ logerror("'%s' (%08x): AD unmapped internal write %02x & %02x (ADDRCL)\n", tag(), m_sh2_state->pc, data, mem_mask);
+}
+uint8_t sh3_base_device::addrdh_r(offs_t offset, uint8_t mem_mask)
+{
+ logerror("'%s' (%08x): AD unmapped internal read mask %02x (ADDRDH) %02x\n", tag(), m_sh2_state->pc, mem_mask, m_addrdh);
+ return m_addrdh;
+}
+
+void sh3_base_device::addrdh_w(offs_t offset, uint8_t data, uint8_t mem_mask)
+{
+ COMBINE_DATA(&m_addrdh);
+ logerror("'%s' (%08x): AD unmapped internal write %02x & %02x (ADDRDH)\n", tag(), m_sh2_state->pc, data, mem_mask);
+}
+
+uint8_t sh3_base_device::addrdl_r(offs_t offset, uint8_t mem_mask)
+{
+ logerror("'%s' (%08x): AD unmapped internal read mask %02x (ADDRDL) %02x\n", tag(), m_sh2_state->pc, mem_mask, m_addrdl);
+ return m_addrdl;
+}
+
+void sh3_base_device::addrdl_w(offs_t offset, uint8_t data, uint8_t mem_mask)
+{
+ COMBINE_DATA(&m_addrdl);
+ logerror("'%s' (%08x): AD unmapped internal write %02x & %02x (ADDRDL)\n", tag(), m_sh2_state->pc, data, mem_mask);
+}
+
+uint8_t sh3_base_device::adcsr_r(offs_t offset, uint8_t mem_mask)
+{
+ logerror("'%s' (%08x): AD unmapped internal read mask %02x (ADCSR) %02x\n", tag(), m_sh2_state->pc, mem_mask, m_adcsr);
+ return m_adcsr;
+}
+
+void sh3_base_device::adcsr_w(offs_t offset, uint8_t data, uint8_t mem_mask)
+{
+ COMBINE_DATA(&m_adcsr);
+ logerror("'%s' (%08x): AD unmapped internal write %02x & %02x (ADCSR)\n", tag(), m_sh2_state->pc, data, mem_mask);
+}
+
+uint8_t sh3_base_device::adcr_r(offs_t offset, uint8_t mem_mask)
+{
+ logerror("'%s' (%08x): AD unmapped internal read mask %02x (ADCR) %02x\n", tag(), m_sh2_state->pc, mem_mask, m_adcr);
+ return m_adcr;
+}
+
+void sh3_base_device::adcr_w(offs_t offset, uint8_t data, uint8_t mem_mask)
+{
+ COMBINE_DATA(&m_adcr);
+ logerror("'%s' (%08x): AD unmapped internal write %02x & %02x (ADCR)\n", tag(), m_sh2_state->pc, data, mem_mask);
+}
+
+// DA 7709
+uint8_t sh3_base_device::dadr0_r(offs_t offset, uint8_t mem_mask)
+{
+ logerror("'%s' (%08x): DA unmapped internal read mask %02x (DADR0) %02x\n", tag(), m_sh2_state->pc, mem_mask, m_dadr0);
+ return m_dadr0;
+}
+
+void sh3_base_device::dadr0_w(offs_t offset, uint8_t data, uint8_t mem_mask)
+{
+ COMBINE_DATA(&m_dadr0);
+ logerror("'%s' (%08x): AD unmapped internal write %02x & %02x (DADR0)\n", tag(), m_sh2_state->pc, data, mem_mask);
+}
+
+uint8_t sh3_base_device::dadr1_r(offs_t offset, uint8_t mem_mask)
+{
+ logerror("'%s' (%08x): DA unmapped internal read mask %02x (DADR1) %02x\n", tag(), m_sh2_state->pc, mem_mask, m_dadr1);
+ return m_dadr1;
+}
+
+void sh3_base_device::dadr1_w(offs_t offset, uint8_t data, uint8_t mem_mask)
+{
+ COMBINE_DATA(&m_dadr1);
+ logerror("'%s' (%08x): AD unmapped internal write %02x & %02x (DADR1)\n", tag(), m_sh2_state->pc, data, mem_mask);
+}
+
+uint8_t sh3_base_device::dadcr_r(offs_t offset, uint8_t mem_mask)
+{
+ logerror("'%s' (%08x): DA unmapped internal read mask %02x (DADCR) %02x\n", tag(), m_sh2_state->pc, mem_mask, m_dadcr);
+ return m_dadcr;
+}
+
+void sh3_base_device::dadcr_w(offs_t offset, uint8_t data, uint8_t mem_mask)
+{
+ COMBINE_DATA(&m_dadcr);
+ logerror("'%s' (%08x): AD unmapped internal write %02x & %02x (DADCR)\n", tag(), m_sh2_state->pc, data, mem_mask);
+}
+
+// PORT 7709
+uint16_t sh3_base_device::pacr_r(offs_t offset, uint16_t mem_mask)
+{
+ logerror("'%s' (%08x): PORT unmapped internal read mask %04x (PACR) %04x\n", tag(), m_sh2_state->pc, mem_mask, m_pacr);
+ return m_pacr;
+}
+
+void sh3_base_device::pacr_w(offs_t offset, uint16_t data, uint16_t mem_mask)
+{
+ COMBINE_DATA(&m_pacr);
+ logerror("'%s' (%08x): PORT unmapped internal write %04x & %04x (PACR)\n", tag(), m_sh2_state->pc, data, mem_mask);
+}
+
+uint16_t sh3_base_device::pbcr_r(offs_t offset, uint16_t mem_mask)
+{
+ logerror("'%s' (%08x): PORT unmapped internal read mask %04x (PBCR) %04x\n", tag(), m_sh2_state->pc, mem_mask, m_pbcr);
+ return m_pbcr;
+}
+
+void sh3_base_device::pbcr_w(offs_t offset, uint16_t data, uint16_t mem_mask)
+{
+ COMBINE_DATA(&m_pbcr);
+ logerror("'%s' (%08x): PORT unmapped internal write %04x & %04x (PBCR)\n", tag(), m_sh2_state->pc, data, mem_mask);
+}
+
+uint16_t sh3_base_device::pccr_r(offs_t offset, uint16_t mem_mask)
+{
+ logerror("'%s' (%08x): PORT unmapped internal read mask %04x (PCCR) %04x\n", tag(), m_sh2_state->pc, mem_mask, m_pccr);
+ return m_pccr;
+}
+
+void sh3_base_device::pccr_w(offs_t offset, uint16_t data, uint16_t mem_mask)
+{
+ COMBINE_DATA(&m_pccr);
+ logerror("'%s' (%08x): PORT unmapped internal write %04x & %04x (PCCR)\n", tag(), m_sh2_state->pc, data, mem_mask);
+}
+
+uint16_t sh3_base_device::pdcr_r(offs_t offset, uint16_t mem_mask)
+{
+ logerror("'%s' (%08x): PORT unmapped internal read mask %04x (PDCR) %04x\n", tag(), m_sh2_state->pc, mem_mask, m_pdcr);
+ return m_pdcr;
+}
+
+void sh3_base_device::pdcr_w(offs_t offset, uint16_t data, uint16_t mem_mask)
+{
+ COMBINE_DATA(&m_pdcr);
+ logerror("'%s' (%08x): PORT unmapped internal write %04x & %04x (PDCR)\n", tag(), m_sh2_state->pc, data, mem_mask);
+}
+
+uint16_t sh3_base_device::pecr_r(offs_t offset, uint16_t mem_mask)
+{
+ logerror("'%s' (%08x): PORT unmapped internal read mask %04x (PECR) %04x\n", tag(), m_sh2_state->pc, mem_mask, m_pecr);
+ return m_pecr;
+}
+
+void sh3_base_device::pecr_w(offs_t offset, uint16_t data, uint16_t mem_mask)
+{
+ COMBINE_DATA(&m_pecr);
+ logerror("'%s' (%08x): PORT unmapped internal write %04x & %04x (PECR)\n", tag(), m_sh2_state->pc, data, mem_mask);
+}
+
+uint16_t sh3_base_device::pfcr_r(offs_t offset, uint16_t mem_mask)
+{
+ logerror("'%s' (%08x): PORT unmapped internal read mask %04x (PFCR) %04x\n", tag(), m_sh2_state->pc, mem_mask, m_pfcr);
+ return m_pfcr;
+}
+
+void sh3_base_device::pfcr_w(offs_t offset, uint16_t data, uint16_t mem_mask)
+{
+ COMBINE_DATA(&m_pfcr);
+ logerror("'%s' (%08x): PORT unmapped internal write %04x & %04x (PFCR)\n", tag(), m_sh2_state->pc, data, mem_mask);
+}
+
+uint16_t sh3_base_device::pgcr_r(offs_t offset, uint16_t mem_mask)
+{
+ logerror("'%s' (%08x): PORT unmapped internal read mask %04x (PGCR) %04x\n", tag(), m_sh2_state->pc, mem_mask, m_pgcr);
+ return m_pgcr;
+}
+
+void sh3_base_device::pgcr_w(offs_t offset, uint16_t data, uint16_t mem_mask)
+{
+ COMBINE_DATA(&m_pgcr);
+ logerror("'%s' (%08x): PORT unmapped internal write %04x & %04x (PGCR)\n", tag(), m_sh2_state->pc, data, mem_mask);
+}
+
+uint16_t sh3_base_device::phcr_r(offs_t offset, uint16_t mem_mask)
+{
+ logerror("'%s' (%08x): PORT unmapped internal read mask %04x (PHCR) %04x\n", tag(), m_sh2_state->pc, mem_mask, m_phcr);
+ return m_phcr;
+}
+
+void sh3_base_device::phcr_w(offs_t offset, uint16_t data, uint16_t mem_mask)
+{
+ COMBINE_DATA(&m_phcr);
+ logerror("'%s' (%08x): PORT unmapped internal write %04x & %04x (PHCR)\n", tag(), m_sh2_state->pc, data, mem_mask);
+}
+
+uint16_t sh3_base_device::pjcr_r(offs_t offset, uint16_t mem_mask)
+{
+ logerror("'%s' (%08x): PORT unmapped internal read mask %04x (PJCR) %04x\n", tag(), m_sh2_state->pc, mem_mask, m_pjcr);
+ return m_pjcr;
+}
+
+void sh3_base_device::pjcr_w(offs_t offset, uint16_t data, uint16_t mem_mask)
+{
+ COMBINE_DATA(&m_pjcr);
+ logerror("'%s' (%08x): PORT unmapped internal write %04x & %04x (PJCR)\n", tag(), m_sh2_state->pc, data, mem_mask);
+}
+
+uint16_t sh3_base_device::pkcr_r(offs_t offset, uint16_t mem_mask)
+{
+ logerror("'%s' (%08x): PORT unmapped internal read mask %04x (PKCR) %04x\n", tag(), m_sh2_state->pc, mem_mask, m_pkcr);
+ return m_pkcr;
+}
+
+void sh3_base_device::pkcr_w(offs_t offset, uint16_t data, uint16_t mem_mask)
+{
+ COMBINE_DATA(&m_pkcr);
+ logerror("'%s' (%08x): PORT unmapped internal write %04x & %04x (PKCR)\n", tag(), m_sh2_state->pc, data, mem_mask);
+}
+
+uint16_t sh3_base_device::plcr_r(offs_t offset, uint16_t mem_mask)
+{
+ logerror("'%s' (%08x): PORT unmapped internal read mask %04x (PLCR) %04x\n", tag(), m_sh2_state->pc, mem_mask, m_plcr);
+ return m_plcr;
+}
+
+void sh3_base_device::plcr_w(offs_t offset, uint16_t data, uint16_t mem_mask)
+{
+ COMBINE_DATA(&m_plcr);
+ logerror("'%s' (%08x): PORT unmapped internal write %04x & %04x (PLCR)\n", tag(), m_sh2_state->pc, data, mem_mask);
+}
+
+uint16_t sh3_base_device::scpcr_r(offs_t offset, uint16_t mem_mask)
+{
+ logerror("'%s' (%08x): PORT unmapped internal read mask %04x (SCPCR) %04x\n", tag(), m_sh2_state->pc, mem_mask, m_scpcr);
+ return m_scpcr;
+}
+
+void sh3_base_device::scpcr_w(offs_t offset, uint16_t data, uint16_t mem_mask)
+{
+ COMBINE_DATA(&m_scpcr);
+ logerror("'%s' (%08x): PORT unmapped internal write %04x & %04x (SCPCR)\n", tag(), m_sh2_state->pc, data, mem_mask);
+}
+
+uint8_t sh3_base_device::padr_r(offs_t offset, uint8_t mem_mask)
+{
+ //logerror("'%s' (%08x): PORT unmapped internal read mask %02x (PADR) %02x\n", tag(), m_sh2_state->pc, mem_mask, m_padr);
+ return m_io->read_qword(SH3_PORT_A);
+}
+
+void sh3_base_device::padr_w(offs_t offset, uint8_t data, uint8_t mem_mask)
+{
+ COMBINE_DATA(&m_padr);
+ //logerror("'%s' (%08x): PORT unmapped internal write %02x & %02x (PADR)\n", tag(), m_sh2_state->pc, data, mem_mask);
+ m_io->write_qword(SH3_PORT_A, data);
+}
+
+uint8_t sh3_base_device::pbdr_r(offs_t offset, uint8_t mem_mask)
+{
+ //logerror("'%s' (%08x): PORT unmapped internal read mask %02x (PBDR) %02x\n", tag(), m_sh2_state->pc, mem_mask, m_padr);
+ return m_io->read_qword(SH3_PORT_B);
+}
+
+void sh3_base_device::pbdr_w(offs_t offset, uint8_t data, uint8_t mem_mask)
+{
+ COMBINE_DATA(&m_pbdr);
+ //logerror("'%s' (%08x): PORT unmapped internal write %02x & %02x (PBDR)\n", tag(), m_sh2_state->pc, data, mem_mask);
+ m_io->write_qword(SH3_PORT_B, data);
+}
+
+uint8_t sh3_base_device::pcdr_r(offs_t offset, uint8_t mem_mask)
+{
+ //logerror("'%s' (%08x): PORT unmapped internal read mask %02x (PCDR) %02x\n", tag(), m_sh2_state->pc, mem_mask, m_pcdr);
+ return m_io->read_qword(SH3_PORT_C);
+}
+
+void sh3_base_device::pcdr_w(offs_t offset, uint8_t data, uint8_t mem_mask)
+{
+ COMBINE_DATA(&m_pcdr);
+ //logerror("'%s' (%08x): PORT unmapped internal write %02x & %02x (PCDR)\n", tag(), m_sh2_state->pc, data, mem_mask);
+ m_io->write_qword(SH3_PORT_C, data);
+}
+
+uint8_t sh3_base_device::pddr_r(offs_t offset, uint8_t mem_mask)
+{
+ //logerror("'%s' (%08x): PORT unmapped internal read mask %02x (PDDR) %02x\n", tag(), m_sh2_state->pc, mem_mask, m_pddr);
+ return m_io->read_qword(SH3_PORT_D);
+}
+
+void sh3_base_device::pddr_w(offs_t offset, uint8_t data, uint8_t mem_mask)
+{
+ COMBINE_DATA(&m_pddr);
+ //logerror("'%s' (%08x): PORT unmapped internal write %02x & %02x (PDDR)\n", tag(), m_sh2_state->pc, data, mem_mask);
+ m_io->write_qword(SH3_PORT_D, data);
+}
+
+uint8_t sh3_base_device::pedr_r(offs_t offset, uint8_t mem_mask)
+{
+ //logerror("'%s' (%08x): PORT unmapped internal read mask %02x (PEDR) %02x\n", tag(), m_sh2_state->pc, mem_mask, m_pedr);
+ return m_io->read_qword(SH3_PORT_E);
+}
+
+void sh3_base_device::pedr_w(offs_t offset, uint8_t data, uint8_t mem_mask)
+{
+ COMBINE_DATA(&m_pedr);
+ //logerror("'%s' (%08x): PORT unmapped internal write %02x & %02x (PEDR)\n", tag(), m_sh2_state->pc, data, mem_mask);
+ m_io->write_qword(SH3_PORT_E, data);
+}
+
+uint8_t sh3_base_device::pfdr_r(offs_t offset, uint8_t mem_mask)
+{
+ //logerror("'%s' (%08x): PORT unmapped internal read mask %02x (PFDR) %02x\n", tag(), m_sh2_state->pc, mem_mask, m_pfdr);
+ return m_io->read_qword(SH3_PORT_F);
+}
+
+void sh3_base_device::pfdr_w(offs_t offset, uint8_t data, uint8_t mem_mask)
+{
+ COMBINE_DATA(&m_pfdr);
+ //logerror("'%s' (%08x): PORT unmapped internal write %02x & %02x (PFDR)\n", tag(), m_sh2_state->pc, data, mem_mask);
+ m_io->write_qword(SH3_PORT_F, data);
+}
+
+uint8_t sh3_base_device::pgdr_r(offs_t offset, uint8_t mem_mask)
+{
+ //logerror("'%s' (%08x): PORT unmapped internal read mask %02x (PGDR) %02x\n", tag(), m_sh2_state->pc, mem_mask, m_pgdr);
+ return m_io->read_qword(SH3_PORT_G);
+}
+
+void sh3_base_device::pgdr_w(offs_t offset, uint8_t data, uint8_t mem_mask)
+{
+ COMBINE_DATA(&m_pgdr);
+ //logerror("'%s' (%08x): PORT unmapped internal write %02x & %02x (PGDR)\n", tag(), m_sh2_state->pc, data, mem_mask);
+ m_io->write_qword(SH3_PORT_G, data);
+}
+
+uint8_t sh3_base_device::phdr_r(offs_t offset, uint8_t mem_mask)
+{
+ //logerror("'%s' (%08x): PORT unmapped internal read mask %02x (PHDR) %02x\n", tag(), m_sh2_state->pc, mem_mask, m_phdr);
+ return m_io->read_qword(SH3_PORT_H);
+}
+
+void sh3_base_device::phdr_w(offs_t offset, uint8_t data, uint8_t mem_mask)
+{
+ COMBINE_DATA(&m_phdr);
+ //logerror("'%s' (%08x): PORT unmapped internal write %02x & %02x (PHDR)\n", tag(), m_sh2_state->pc, data, mem_mask);
+ m_io->write_qword(SH3_PORT_H, data);
+}
+
+uint8_t sh3_base_device::pjdr_r(offs_t offset, uint8_t mem_mask)
+{
+ //logerror("'%s' (%08x): PORT unmapped internal read mask %02x (PJDR) %02x\n", tag(), m_sh2_state->pc, mem_mask, m_pjdr);
+ return m_io->read_qword(SH3_PORT_J);
+}
+
+void sh3_base_device::pjdr_w(offs_t offset, uint8_t data, uint8_t mem_mask)
+{
+ COMBINE_DATA(&m_pjdr);
+ //logerror("'%s' (%08x): PORT unmapped internal write %02x & %02x (PJDR)\n", tag(), m_sh2_state->pc, data, mem_mask);
+ m_io->write_qword(SH3_PORT_J, data);
+}
+
+uint8_t sh3_base_device::pkdr_r(offs_t offset, uint8_t mem_mask)
+{
+ //logerror("'%s' (%08x): PORT unmapped internal read mask %02x (PKDR) %02x\n", tag(), m_sh2_state->pc, mem_mask, m_pkdr);
+ return m_io->read_qword(SH3_PORT_K);
+}
+
+void sh3_base_device::pkdr_w(offs_t offset, uint8_t data, uint8_t mem_mask)
+{
+ COMBINE_DATA(&m_pkdr);
+ //logerror("'%s' (%08x): PORT unmapped internal write %02x & %02x (PKDR)\n", tag(), m_sh2_state->pc, data, mem_mask);
+ m_io->write_qword(SH3_PORT_K, data);
+}
+
+uint8_t sh3_base_device::pldr_r(offs_t offset, uint8_t mem_mask)
+{
+ //logerror("'%s' (%08x): PORT unmapped internal read mask %02x (PLDR) %02x\n", tag(), m_sh2_state->pc, mem_mask, m_pldr);
+ return m_io->read_qword(SH3_PORT_L);
+}
+
+void sh3_base_device::pldr_w(offs_t offset, uint8_t data, uint8_t mem_mask)
+{
+ COMBINE_DATA(&m_pldr);
+ //logerror("'%s' (%08x): PORT unmapped internal write %02x & %02x (PLDR)\n", tag(), m_sh2_state->pc, data, mem_mask);
+ m_io->write_qword(SH3_PORT_L, data);
+}
+
+uint8_t sh3_base_device::scpdr_r(offs_t offset, uint8_t mem_mask)
+{
+ logerror("'%s' (%08x): PORT unmapped internal read mask %02x (SCPDR) %02x\n", tag(), m_sh2_state->pc, mem_mask, m_scpdr);
+ return m_scpdr;
+}
+
+void sh3_base_device::scpdr_w(offs_t offset, uint8_t data, uint8_t mem_mask)
+{
+ COMBINE_DATA(&m_scpdr);
+ logerror("'%s' (%08x): PORT unmapped internal write %02x & %02x (SCPDR)\n", tag(), m_sh2_state->pc, data, mem_mask);
+}
+
+// IRDA 7709
+uint8_t sh3_base_device::scsmr1_r(offs_t offset, uint8_t mem_mask)
+{
+ logerror("'%s' (%08x): IRDA unmapped internal read mask %02x (SCSMR1) %02x\n", tag(), m_sh2_state->pc, mem_mask, m_scsmr1);
+ return m_scsmr1;
+}
+
+void sh3_base_device::scsmr1_w(offs_t offset, uint8_t data, uint8_t mem_mask)
+{
+ COMBINE_DATA(&m_scsmr1);
+ logerror("'%s' (%08x): IRDA unmapped internal write %02x & %02x (SCSMR1)\n", tag(), m_sh2_state->pc, data, mem_mask);
+}
+
+uint8_t sh3_base_device::scbrr1_r(offs_t offset, uint8_t mem_mask)
+{
+ logerror("'%s' (%08x): IRDA unmapped internal read mask %02x (SCBRR1) %02x\n", tag(), m_sh2_state->pc, mem_mask, m_scbrr1);
+ return m_scbrr1;
+}
+
+void sh3_base_device::scbrr1_w(offs_t offset, uint8_t data, uint8_t mem_mask)
+{
+ COMBINE_DATA(&m_scbrr1);
+ logerror("'%s' (%08x): IRDA unmapped internal write %02x & %02x (SCBRR1)\n", tag(), m_sh2_state->pc, data, mem_mask);
+}
+
+uint8_t sh3_base_device::scscr1_r(offs_t offset, uint8_t mem_mask)
+{
+ logerror("'%s' (%08x): IRDA unmapped internal read mask %02x (SCSCR1) %02x\n", tag(), m_sh2_state->pc, mem_mask, m_scscr1);
+ return m_scscr1;
+}
+
+void sh3_base_device::scscr1_w(offs_t offset, uint8_t data, uint8_t mem_mask)
+{
+ COMBINE_DATA(&m_scscr1);
+ logerror("'%s' (%08x): IRDA unmapped internal write %02x & %02x (SCSCR1)\n", tag(), m_sh2_state->pc, data, mem_mask);
+}
+
+uint8_t sh3_base_device::scftdr1_r(offs_t offset, uint8_t mem_mask)
+{
+ logerror("'%s' (%08x): IRDA unmapped internal read mask %02x (SCFTDR1) %02x\n", tag(), m_sh2_state->pc, mem_mask, m_scftdr1);
+ return m_scftdr1;
+}
+
+void sh3_base_device::scftdr1_w(offs_t offset, uint8_t data, uint8_t mem_mask)
+{
+ COMBINE_DATA(&m_scftdr1);
+ logerror("'%s' (%08x): IRDA unmapped internal write %02x & %02x (SCFTDR1)\n", tag(), m_sh2_state->pc, data, mem_mask);
+}
+
+uint16_t sh3_base_device::scssr1_r(offs_t offset, uint16_t mem_mask)
+{
+ logerror("'%s' (%08x): IRDA unmapped internal read mask %04x (SCSSR1) %04x\n", tag(), m_sh2_state->pc, mem_mask, m_scssr1);
+ return m_scssr1;
+}
+
+void sh3_base_device::scssr1_w(offs_t offset, uint16_t data, uint16_t mem_mask)
+{
+ COMBINE_DATA(&m_scssr1);
+ logerror("'%s' (%08x): IRDA unmapped internal write %04x & %04x (SCSSR1)\n", tag(), m_sh2_state->pc, data, mem_mask);
+}
+
+uint8_t sh3_base_device::scfrdr1_r(offs_t offset, uint8_t mem_mask)
+{
+ logerror("'%s' (%08x): IRDA unmapped internal read mask %02x (SCFRDR1) %02x\n", tag(), m_sh2_state->pc, mem_mask, m_scfrdr1);
+ return m_scfrdr1;
+}
+
+void sh3_base_device::scfrdr1_w(offs_t offset, uint8_t data, uint8_t mem_mask)
+{
+ COMBINE_DATA(&m_scfrdr1);
+ logerror("'%s' (%08x): IRDA unmapped internal write %02x & %02x (SCFRDR1)\n", tag(), m_sh2_state->pc, data, mem_mask);
+}
+
+uint8_t sh3_base_device::scfcr1_r(offs_t offset, uint8_t mem_mask)
+{
+ logerror("'%s' (%08x): IRDA unmapped internal read mask %02x (SCFCR1) %02x\n", tag(), m_sh2_state->pc, mem_mask, m_scfcr1);
+ return m_scfcr1;
+}
+
+void sh3_base_device::scfcr1_w(offs_t offset, uint8_t data, uint8_t mem_mask)
+{
+ COMBINE_DATA(&m_scfcr1);
+ logerror("'%s' (%08x): IRDA unmapped internal write %02x & %02x (SCFCR1)\n", tag(), m_sh2_state->pc, data, mem_mask);
+}
+
+uint16_t sh3_base_device::scfdr1_r(offs_t offset, uint16_t mem_mask)
+{
+ logerror("'%s' (%08x): IRDA unmapped internal read mask %04x (SCFDR1) %04x\n", tag(), m_sh2_state->pc, mem_mask, m_scfdr1);
+ return m_scfdr1;
+}
+
+void sh3_base_device::scfdr1_w(offs_t offset, uint16_t data, uint16_t mem_mask)
+{
+ COMBINE_DATA(&m_scfdr1);
+ logerror("'%s' (%08x): IRDA unmapped internal write %04x & %04x (SCFDR1)\n", tag(), m_sh2_state->pc, data, mem_mask);
+}
+
+// SCIF 7709
+uint8_t sh3_base_device::scsmr2_r(offs_t offset, uint8_t mem_mask)
+{
+ logerror("'%s' (%08x): SCIF unmapped internal read mask %02x (SCSMR2) %02x\n", tag(), m_sh2_state->pc, mem_mask, m_scsmr2);
+ return m_scsmr2;
+}
+
+void sh3_base_device::scsmr2_w(offs_t offset, uint8_t data, uint8_t mem_mask)
+{
+ COMBINE_DATA(&m_scsmr2);
+ logerror("'%s' (%08x): SCIF unmapped internal write %02x & %02x (SCSMR2)\n", tag(), m_sh2_state->pc, data, mem_mask);
+}
+
+uint8_t sh3_base_device::scbrr2_r(offs_t offset, uint8_t mem_mask)
+{
+ logerror("'%s' (%08x): SCIF unmapped internal read mask %02x (SCBRR2) %02x\n", tag(), m_sh2_state->pc, mem_mask, m_scbrr2);
+ return m_scbrr2;
+}
+
+void sh3_base_device::scbrr2_w(offs_t offset, uint8_t data, uint8_t mem_mask)
+{
+ COMBINE_DATA(&m_scbrr2);
+ logerror("'%s' (%08x): SCIF unmapped internal write %02x & %02x (SCBRR2)\n", tag(), m_sh2_state->pc, data, mem_mask);
+}
+
+uint8_t sh3_base_device::scscr2_r(offs_t offset, uint8_t mem_mask)
+{
+ logerror("'%s' (%08x): SCIF unmapped internal read mask %02x (SCSCR2) %02x\n", tag(), m_sh2_state->pc, mem_mask, m_scscr2);
+ return m_scscr2;
+}
+
+void sh3_base_device::scscr2_w(offs_t offset, uint8_t data, uint8_t mem_mask)
+{
+ COMBINE_DATA(&m_scscr2);
+ logerror("'%s' (%08x): SCIF unmapped internal write %02x & %02x (SCSCR2)\n", tag(), m_sh2_state->pc, data, mem_mask);
+}
+
+uint8_t sh3_base_device::scftdr2_r(offs_t offset, uint8_t mem_mask)
+{
+ logerror("'%s' (%08x): SCIF unmapped internal read mask %02x (SCFTDR2) %02x\n", tag(), m_sh2_state->pc, mem_mask, m_scftdr2);
+ return m_scftdr2;
+}
+
+void sh3_base_device::scftdr2_w(offs_t offset, uint8_t data, uint8_t mem_mask)
+{
+ COMBINE_DATA(&m_scftdr2);
+ logerror("'%s' (%08x): SCIF unmapped internal write %02x & %02x (SCFTDR2)\n", tag(), m_sh2_state->pc, data, mem_mask);
+}
+
+uint16_t sh3_base_device::scssr2_r(offs_t offset, uint16_t mem_mask)
+{
+ logerror("'%s' (%08x): SCIF unmapped internal read mask %04x (SCSSR2) %04x\n", tag(), m_sh2_state->pc, mem_mask, m_scssr2);
+ return m_scssr2;
+}
+
+void sh3_base_device::scssr2_w(offs_t offset, uint16_t data, uint16_t mem_mask)
+{
+ COMBINE_DATA(&m_scssr2);
+ logerror("'%s' (%08x): SCIF unmapped internal write %04x & %04x (SCSSR2)\n", tag(), m_sh2_state->pc, data, mem_mask);
+}
+
+uint8_t sh3_base_device::scfrdr2_r(offs_t offset, uint8_t mem_mask)
+{
+ logerror("'%s' (%08x): SCIF unmapped internal read mask %02x (SCFRDR2) %02x\n", tag(), m_sh2_state->pc, mem_mask, m_scfrdr2);
+ return m_scfrdr2;
+}
+
+void sh3_base_device::scfrdr2_w(offs_t offset, uint8_t data, uint8_t mem_mask)
+{
+ COMBINE_DATA(&m_scfrdr2);
+ logerror("'%s' (%08x): SCIF unmapped internal write %02x & %02x (SCFRDR2)\n", tag(), m_sh2_state->pc, data, mem_mask);
+}
+
+uint8_t sh3_base_device::scfcr2_r(offs_t offset, uint8_t mem_mask)
+{
+ logerror("'%s' (%08x): SCIF unmapped internal read mask %02x (SCFCR2) %02x\n", tag(), m_sh2_state->pc, mem_mask, m_scfcr2);
+ return m_scfcr2;
+}
+
+void sh3_base_device::scfcr2_w(offs_t offset, uint8_t data, uint8_t mem_mask)
+{
+ COMBINE_DATA(&m_scfcr2);
+ logerror("'%s' (%08x): SCIF unmapped internal write %02x & %02x (SCFCR2)\n", tag(), m_sh2_state->pc, data, mem_mask);
+}
+
+uint16_t sh3_base_device::scfdr2_r(offs_t offset, uint16_t mem_mask)
+{
+ logerror("'%s' (%08x): SCIF unmapped internal read mask %04x (SCFDR2) %04x\n", tag(), m_sh2_state->pc, mem_mask, m_scfdr2);
+ return m_scfdr2;
+}
+
+void sh3_base_device::scfdr2_w(offs_t offset, uint16_t data, uint16_t mem_mask)
+{
+ COMBINE_DATA(&m_scfdr2);
+ logerror("'%s' (%08x): SCIF unmapped internal write %04x & %04x (SCFDR2)\n", tag(), m_sh2_state->pc, data, mem_mask);
+}
+
+// UDI 7709S
+uint16_t sh3_base_device::sdir_r(offs_t offset, uint16_t mem_mask)
+{
+ logerror("'%s' (%08x): UDI unmapped internal read mask %04x (SDIR) %04x\n", tag(), m_sh2_state->pc, mem_mask, m_sdir);
+ return m_sdir;
+}
+
+void sh3_base_device::sdir_w(offs_t offset, uint16_t data, uint16_t mem_mask)
+{
+ COMBINE_DATA(&m_sdir);
+ logerror("'%s' (%08x): UDI unmapped internal write %04x & %04x (SDIR)\n", tag(), m_sh2_state->pc, data, mem_mask);
}
diff --git a/src/devices/cpu/sh/sh3comn.h b/src/devices/cpu/sh/sh3comn.h
index 241035b993e..b735cdebec9 100644
--- a/src/devices/cpu/sh/sh3comn.h
+++ b/src/devices/cpu/sh/sh3comn.h
@@ -1,9 +1,9 @@
// license:BSD-3-Clause
// copyright-holders:R. Belmont
-#pragma once
+#ifndef MAME_CPU_SH_SH3COMN_H
+#define MAME_CPU_SH_SH3COMN_H
-#ifndef __SH3COMN_H__
-#define __SH3COMN_H__
+#pragma once
// actual port handling is more complex than this
@@ -22,75 +22,4 @@
#define SH3_PORT_K (0x19*8)
#define SH3_PORT_L (0x1a*8)
-/* SH3 lower area regs */
-
-#define SH3_LOWER_REGBASE (0x04000000)
-#define SH3_LOWER_REGEND (0x07ffffff)
-
-#define INTEVT2 ((0x4000000 - SH3_LOWER_REGBASE)/4)
-#define IRR0_IRR1 ((0x4000004 - SH3_LOWER_REGBASE)/4)
-#define PINTER_IPRC ((0x4000014 - SH3_LOWER_REGBASE)/4)
-
-#define SH3_SAR0_ADDR ((0x4000020 - SH3_LOWER_REGBASE)/4)
-#define SH3_DAR0_ADDR ((0x4000024 - SH3_LOWER_REGBASE)/4)
-#define SH3_DMATCR0_ADDR ((0x4000028 - SH3_LOWER_REGBASE)/4)
-#define SH3_CHCR0_ADDR ((0x400002c - SH3_LOWER_REGBASE)/4)
-#define SH3_SAR1_ADDR ((0x4000030 - SH3_LOWER_REGBASE)/4)
-#define SH3_DAR1_ADDR ((0x4000034 - SH3_LOWER_REGBASE)/4)
-#define SH3_DMATCR1_ADDR ((0x4000038 - SH3_LOWER_REGBASE)/4)
-#define SH3_CHCR1_ADDR ((0x400003c - SH3_LOWER_REGBASE)/4)
-#define SH3_SAR2_ADDR ((0x4000040 - SH3_LOWER_REGBASE)/4)
-#define SH3_DAR2_ADDR ((0x4000044 - SH3_LOWER_REGBASE)/4)
-#define SH3_DMATCR2_ADDR ((0x4000048 - SH3_LOWER_REGBASE)/4)
-#define SH3_CHCR2_ADDR ((0x400004c - SH3_LOWER_REGBASE)/4)
-#define SH3_SAR3_ADDR ((0x4000050 - SH3_LOWER_REGBASE)/4)
-#define SH3_DAR3_ADDR ((0x4000054 - SH3_LOWER_REGBASE)/4)
-#define SH3_DMATCR3_ADDR ((0x4000058 - SH3_LOWER_REGBASE)/4)
-#define SH3_CHCR3_ADDR ((0x400005c - SH3_LOWER_REGBASE)/4)
-#define SH3_DMAOR_ADDR ((0x4000060 - SH3_LOWER_REGBASE)/4)
-
-
-#define PCCR_PDCR ((0x4000104 - SH3_LOWER_REGBASE)/4)
-#define PECR_PFCR ((0x4000108 - SH3_LOWER_REGBASE)/4)
-#define PGCR_PHCR ((0x400010c - SH3_LOWER_REGBASE)/4)
-#define PJCR_PKCR ((0x4000110 - SH3_LOWER_REGBASE)/4)
-#define PLCR_SCPCR ((0x4000114 - SH3_LOWER_REGBASE)/4)
-
-#define PADR_PBDR ((0x4000120 - SH3_LOWER_REGBASE)/4)
-#define PCDR_PDDR ((0x4000124 - SH3_LOWER_REGBASE)/4)
-#define PEDR_PFDR ((0x4000128 - SH3_LOWER_REGBASE)/4)
-#define PGDR_PHDR ((0x400012c - SH3_LOWER_REGBASE)/4)
-#define PJDR_PKDR ((0x4000130 - SH3_LOWER_REGBASE)/4)
-#define PLDR_SCPDR ((0x4000134 - SH3_LOWER_REGBASE)/4)
-
-#define SCSMR2_SCBRR2 ((0x4000150 - SH3_LOWER_REGBASE)/4)
-#define SCSCR2_SCFTDR2 ((0x4000154 - SH3_LOWER_REGBASE)/4)
-#define SCSSR2_SCFRDR2 ((0x4000158 - SH3_LOWER_REGBASE)/4)
-#define SCFCR2_SCFDR2 ((0x400015c - SH3_LOWER_REGBASE)/4)
-
-
-/* SH3 upper area */
-
-
-#define SH3_UPPER_REGBASE (0xffffd000)
-#define SH3_UPPER_REGEND (0xffffffff)
-
-#define SH3_ICR0_IPRA_ADDR ((0xfffffee0 - SH3_UPPER_REGBASE)/4)
-#define SH3_IPRB_ADDR ((0xfffffee4 - SH3_UPPER_REGBASE)/4)
-
-#define SH3_TOCR_TSTR_ADDR ((0xfffffe90 - SH3_UPPER_REGBASE)/4)
-#define SH3_TCOR0_ADDR ((0xfffffe94 - SH3_UPPER_REGBASE)/4)
-#define SH3_TCNT0_ADDR ((0xfffffe98 - SH3_UPPER_REGBASE)/4)
-#define SH3_TCR0_ADDR ((0xfffffe9c - SH3_UPPER_REGBASE)/4)
-#define SH3_TCOR1_ADDR ((0xfffffea0 - SH3_UPPER_REGBASE)/4)
-#define SH3_TCNT1_ADDR ((0xfffffea4 - SH3_UPPER_REGBASE)/4)
-#define SH3_TCR1_ADDR ((0xfffffea8 - SH3_UPPER_REGBASE)/4)
-#define SH3_TCOR2_ADDR ((0xfffffeac - SH3_UPPER_REGBASE)/4)
-#define SH3_TCNT2_ADDR ((0xfffffeb0 - SH3_UPPER_REGBASE)/4)
-#define SH3_TCR2_ADDR ((0xfffffeb4 - SH3_UPPER_REGBASE)/4)
-#define SH3_TCPR2_ADDR ((0xfffffeb8 - SH3_UPPER_REGBASE)/4)
-#define SH3_TRA_ADDR ((0xffffffd0 - SH3_UPPER_REGBASE)/4)
-#define SH3_EXPEVT_ADDR ((0xffffffd4 - SH3_UPPER_REGBASE)/4)
-#define SH3_INTEVT_ADDR ((0xffffffd8 - SH3_UPPER_REGBASE)/4)
-
-#endif /* __SH3COMN_H__ */
+#endif // MAME_CPU_SH_SH3COMN_H
diff --git a/src/devices/cpu/sh/sh4.cpp b/src/devices/cpu/sh/sh4.cpp
index 636bcd05ddb..6e73b69a531 100644
--- a/src/devices/cpu/sh/sh4.cpp
+++ b/src/devices/cpu/sh/sh4.cpp
@@ -2,7 +2,7 @@
// copyright-holders:R. Belmont
/*****************************************************************************
*
- * sh4.c
+ * sh4.cpp
* Portable Hitachi SH-4 (SH7750 family) emulator
*
* By R. Belmont, based on sh2.c by Juergen Buchmueller, Mariusz Wojcieszek,
@@ -32,13 +32,19 @@
#include "sh4tmu.h"
#include "sh_dasm.h"
#include "cpu/drcumlsh.h"
-#include "debugger.h"
-DEFINE_DEVICE_TYPE(SH3LE, sh3_device, "sh3le", "Hitachi SH-3 (little)")
-DEFINE_DEVICE_TYPE(SH3BE, sh3be_device, "sh3be", "Hitachi SH-3 (big)")
-DEFINE_DEVICE_TYPE(SH4LE, sh4_device, "sh4le", "Hitachi SH-4 (little)")
-DEFINE_DEVICE_TYPE(SH4BE, sh4be_device, "sh4be", "Hitachi SH-4 (big)")
+DEFINE_DEVICE_TYPE(SH3, sh3_device, "sh3", "Hitachi SH-3 (Unidentified)")
+DEFINE_DEVICE_TYPE(SH7708S, sh7708s_device, "sh7708s", "Hitachi SH7708S")
+DEFINE_DEVICE_TYPE(SH7709, sh7709_device, "sh7709", "Hitachi SH7709")
+DEFINE_DEVICE_TYPE(SH7709S, sh7709s_device, "sh7709s", "Hitachi SH7709S")
+DEFINE_DEVICE_TYPE(SH4, sh4_device, "sh4", "Hitachi SH-4 (Unidentified)")
+DEFINE_DEVICE_TYPE(SH7091, sh7091_device, "sh7091", "Hitachi SH7091")
+DEFINE_DEVICE_TYPE(SH7750, sh7750_device, "sh7750", "Hitachi SH7750")
+DEFINE_DEVICE_TYPE(SH7750R, sh7750r_device, "sh7750r", "Hitachi SH7750R")
+DEFINE_DEVICE_TYPE(SH7750S, sh7750s_device, "sh7750s", "Hitachi SH7750S")
+DEFINE_DEVICE_TYPE(SH7751, sh7751_device, "sh7751", "Hitachi SH7751")
+DEFINE_DEVICE_TYPE(SH7751R, sh7751r_device, "sh7751r", "Hitachi SH7751R")
#if 0
@@ -48,6 +54,8 @@ void sh4_base_device::sh4_internal_map(address_map &map)
map(0x1C000000, 0x1C000FFF).ram().mirror(0x03FFD000);
map(0x1C002000, 0x1C002FFF).ram().mirror(0x03FFD000);
map(0xE0000000, 0xE000003F).ram().mirror(0x03FFFFC0);
+
+ sh4_register_map(map);
}
#endif
@@ -62,15 +70,819 @@ void sh4_base_device::sh4_internal_map(address_map &map)
map(0xF7000000, 0xF77FFFFF).rw(FUNC(sh4_base_device::sh4_utlb_data_array1_r), FUNC(sh4_base_device::sh4_utlb_data_array1_w));
map(0xF7800000, 0xF7FFFFFF).rw(FUNC(sh4_base_device::sh4_utlb_data_array2_r), FUNC(sh4_base_device::sh4_utlb_data_array2_w));
- map(0xFE000000, 0xFFFFFFFF).rw(FUNC(sh4_base_device::sh4_internal_r), FUNC(sh4_base_device::sh4_internal_w)).umask32(0xffffffff);
+ sh4_register_map(map);
+}
+
+void sh4_device::sh4_register_map(address_map &map)
+{
+ map(0xff000030, 0xff000033).lr32([] { return PVR_SH7751; }, "pvr_r");
+
+ ccn_map(map);
+ ubc_map(map);
+ bsc_map(map);
+ dmac_map(map);
+ cpg_7750r_map(map);
+ rtc_map(map);
+ intc_7750r_map(map);
+ tmu_7750r_map(map);
+ sci_map(map);
+ scif_map(map);
+ hudi_7750r_map(map);
+ pci_7751_map(map);
+}
+
+void sh7091_device::sh4_register_map(address_map& map)
+{
+ map(0xff000030, 0xff000033).lr32([] { return PVR_SH7091; }, "pvr_r");
+
+ ccn_map(map);
+ ubc_map(map);
+ bsc_map(map);
+ dmac_map(map);
+ cpg_map(map);
+ rtc_map(map);
+ intc_map(map);
+ tmu_map(map);
+ sci_map(map);
+ scif_map(map);
+ hudi_map(map);
+}
+
+void sh7750_device::sh4_register_map(address_map& map)
+{
+ map(0xff000030, 0xff000033).lr32([] { return PVR_SH7750; }, "pvr_r");
+
+ ccn_map(map);
+ ubc_map(map);
+ bsc_map(map);
+ dmac_map(map);
+ cpg_map(map);
+ rtc_map(map);
+ intc_map(map);
+ tmu_map(map);
+ sci_map(map);
+ scif_map(map);
+ hudi_map(map);
+}
+
+void sh7750s_device::sh4_register_map(address_map& map)
+{
+ map(0xff000030, 0xff000033).lr32([] { return PVR_SH7750S; }, "pvr_r");
+
+ ccn_map(map);
+ ubc_map(map);
+ bsc_map(map);
+ dmac_map(map);
+ cpg_map(map);
+ rtc_map(map);
+ intc_7750s_map(map);
+ tmu_map(map);
+ sci_map(map);
+ scif_map(map);
+ hudi_map(map);
+}
+
+void sh7750r_device::sh4_register_map(address_map& map)
+{
+ map(0xff000030, 0xff000033).lr32([] { return PVR_SH7750R; }, "pvr_r");
+ map(0xff000044, 0xff000047).lr32([] { return PRR_SH7750R; }, "prr_r");
+
+ ccn_map(map);
+ ubc_map(map);
+ bsc_7750r_map(map);
+ dmac_7750r_map(map);
+ cpg_7750r_map(map);
+ rtc_7750r_map(map);
+ intc_7750r_map(map);
+ tmu_7750r_map(map);
+ sci_map(map);
+ scif_map(map);
+ hudi_7750r_map(map);
+}
+
+void sh7751_device::sh4_register_map(address_map& map)
+{
+ map(0xff000030, 0xff000033).lr32([] { return PVR_SH7751; }, "pvr_r");
+
+ ccn_map(map);
+ ubc_map(map);
+ bsc_map(map);
+ dmac_map(map);
+ cpg_7750r_map(map);
+ rtc_map(map);
+ intc_7750r_map(map);
+ tmu_7750r_map(map);
+ sci_map(map);
+ scif_map(map);
+ hudi_7750r_map(map);
+ pci_7751_map(map);
+}
+
+void sh7751r_device::sh4_register_map(address_map& map)
+{
+ map(0xff000030, 0xff000033).lr32([] { return PVR_SH7751R; }, "pvr_r");
+ map(0xff000044, 0xff000047).lr32([] { return PRR_SH7751R; }, "prr_r");
+
+ ccn_map(map);
+ ubc_map(map);
+ bsc_7750r_map(map);
+ dmac_7750r_map(map);
+ cpg_7750r_map(map);
+ rtc_7750r_map(map);
+ intc_7750r_map(map);
+ tmu_7750r_map(map);
+ sci_map(map);
+ scif_map(map);
+ hudi_7750r_map(map);
+ pci_7751_map(map);
+}
+
+void sh4_base_device::ccn_map(address_map &map)
+{
+ map(0xff000000, 0xff000003).rw(FUNC(sh4_base_device::pteh_r), FUNC(sh4_base_device::pteh_w));
+ map(0xff000004, 0xff000007).rw(FUNC(sh4_base_device::ptel_r), FUNC(sh4_base_device::ptel_w));
+ map(0xff000008, 0xff00000b).rw(FUNC(sh4_base_device::ttb_r), FUNC(sh4_base_device::ttb_w));
+ map(0xff00000c, 0xff00000f).rw(FUNC(sh4_base_device::tea_r), FUNC(sh4_base_device::tea_w));
+ map(0xff000010, 0xff000013).rw(FUNC(sh4_base_device::mmucr_r), FUNC(sh4_base_device::mmucr_w));
+ map(0xff000014, 0xff000014).rw(FUNC(sh4_base_device::basra_r), FUNC(sh4_base_device::basra_w));
+ map(0xff000018, 0xff000018).rw(FUNC(sh4_base_device::basrb_r), FUNC(sh4_base_device::basrb_w));
+ map(0xff00001c, 0xff00001f).rw(FUNC(sh4_base_device::ccr_r), FUNC(sh4_base_device::ccr_w));
+ map(0xff000020, 0xff000023).rw(FUNC(sh4_base_device::tra_r), FUNC(sh4_base_device::tra_w));
+ map(0xff000024, 0xff000027).rw(FUNC(sh4_base_device::expevt_r), FUNC(sh4_base_device::expevt_w));
+ map(0xff000028, 0xff00002b).rw(FUNC(sh4_base_device::intevt_r), FUNC(sh4_base_device::intevt_w));
+ map(0xff000034, 0xff000037).rw(FUNC(sh4_base_device::ptea_r), FUNC(sh4_base_device::ptea_w));
+ map(0xff000038, 0xff00003b).rw(FUNC(sh4_base_device::qacr0_r), FUNC(sh4_base_device::qacr0_w));
+ map(0xff00003c, 0xff00003f).rw(FUNC(sh4_base_device::qacr1_r), FUNC(sh4_base_device::qacr1_w));
+}
+
+void sh4_base_device::ubc_map(address_map &map)
+{
+ map(0xff200000, 0xff200003).rw(FUNC(sh4_base_device::bara_r), FUNC(sh4_base_device::bara_w));
+ map(0xff200004, 0xff200004).rw(FUNC(sh4_base_device::bamra_r), FUNC(sh4_base_device::bamra_w));
+ map(0xff200008, 0xff200009).rw(FUNC(sh4_base_device::bbra_r), FUNC(sh4_base_device::bbra_w));
+ map(0xff20000c, 0xff20000f).rw(FUNC(sh4_base_device::barb_r), FUNC(sh4_base_device::barb_w));
+ map(0xff200010, 0xff200010).rw(FUNC(sh4_base_device::bamrb_r), FUNC(sh4_base_device::bamrb_w));
+ map(0xff200014, 0xff200015).rw(FUNC(sh4_base_device::bbrb_r), FUNC(sh4_base_device::bbrb_w));
+ map(0xff200018, 0xff20001b).rw(FUNC(sh4_base_device::bdrb_r), FUNC(sh4_base_device::bdrb_w));
+ map(0xff20001c, 0xff20001f).rw(FUNC(sh4_base_device::bdmrb_r), FUNC(sh4_base_device::bdmrb_w));
+ map(0xff200020, 0xff200021).rw(FUNC(sh4_base_device::brcr_r), FUNC(sh4_base_device::brcr_w));
+}
+
+void sh4_base_device::bsc_map(address_map& map)
+{
+ map(0xff800000, 0xff800003).rw(FUNC(sh4_base_device::bcr1_r), FUNC(sh4_base_device::bcr1_w));
+ map(0xff800004, 0xff800005).rw(FUNC(sh4_base_device::bcr2_r), FUNC(sh4_base_device::bcr2_w));
+ map(0xff800008, 0xff80000b).rw(FUNC(sh4_base_device::wcr1_r), FUNC(sh4_base_device::wcr1_w));
+ map(0xff80000c, 0xff80000f).rw(FUNC(sh4_base_device::wcr2_r), FUNC(sh4_base_device::wcr2_w));
+ map(0xff800010, 0xff800013).rw(FUNC(sh4_base_device::wcr3_r), FUNC(sh4_base_device::wcr3_w));
+ map(0xff800014, 0xff800017).rw(FUNC(sh4_base_device::mcr_r), FUNC(sh4_base_device::mcr_w));
+ map(0xff800018, 0xff800019).rw(FUNC(sh4_base_device::pcr_r), FUNC(sh4_base_device::pcr_w));
+ map(0xff80001c, 0xff80001d).rw(FUNC(sh4_base_device::rtcsr_r), FUNC(sh4_base_device::rtcsr_w));
+ map(0xff800020, 0xff800021).rw(FUNC(sh4_base_device::rtcnt_r), FUNC(sh4_base_device::rtcnt_w));
+ map(0xff800024, 0xff800025).rw(FUNC(sh4_base_device::rtcor_r), FUNC(sh4_base_device::rtcor_w));
+ map(0xff800028, 0xff800029).rw(FUNC(sh4_base_device::rfcr_r), FUNC(sh4_base_device::rfcr_w));
+ map(0xff80002c, 0xff80002f).rw(FUNC(sh4_base_device::pctra_r), FUNC(sh4_base_device::pctra_w));
+ map(0xff800030, 0xff800031).rw(FUNC(sh4_base_device::pdtra_r), FUNC(sh4_base_device::pdtra_w));
+ map(0xff800040, 0xff800043).rw(FUNC(sh4_base_device::pctrb_r), FUNC(sh4_base_device::pctrb_w));
+ map(0xff800044, 0xff800045).rw(FUNC(sh4_base_device::pdtrb_r), FUNC(sh4_base_device::pdtrb_w));
+ map(0xff800048, 0xff800049).rw(FUNC(sh4_base_device::gpioic_r), FUNC(sh4_base_device::gpioic_w));
+ map(0xff900000, 0xff90ffff).w(FUNC(sh4_base_device::sdmr2_w));
+ map(0xff940000, 0xff94ffff).w(FUNC(sh4_base_device::sdmr3_w));
+}
+
+void sh4_base_device::bsc_7750r_map(address_map& map)
+{
+ bsc_map(map);
+
+ map(0xff800050, 0xff800051).rw(FUNC(sh4_base_device::bcr3_r), FUNC(sh4_base_device::bcr3_w));
+ map(0xfe0a00f0, 0xfe0a00f3).rw(FUNC(sh4_base_device::bcr4_r), FUNC(sh4_base_device::bcr4_w));
+}
+
+void sh4_base_device::dmac_map(address_map& map)
+{
+ map(0xffa00000, 0xffa00003).rw(FUNC(sh4_base_device::sar0_r), FUNC(sh4_base_device::sar0_w));
+ map(0xffa00004, 0xffa00007).rw(FUNC(sh4_base_device::dar0_r), FUNC(sh4_base_device::dar0_w));
+ map(0xffa00008, 0xffa0000b).rw(FUNC(sh4_base_device::dmatcr0_r), FUNC(sh4_base_device::dmatcr0_w));
+ map(0xffa0000c, 0xffa0000f).rw(FUNC(sh4_base_device::chcr0_r), FUNC(sh4_base_device::chcr0_w));
+ map(0xffa00010, 0xffa00013).rw(FUNC(sh4_base_device::sar1_r), FUNC(sh4_base_device::sar1_w));
+ map(0xffa00014, 0xffa00017).rw(FUNC(sh4_base_device::dar1_r), FUNC(sh4_base_device::dar1_w));
+ map(0xffa00018, 0xffa0001b).rw(FUNC(sh4_base_device::dmatcr1_r), FUNC(sh4_base_device::dmatcr1_w));
+ map(0xffa0001c, 0xffa0001f).rw(FUNC(sh4_base_device::chcr1_r), FUNC(sh4_base_device::chcr1_w));
+ map(0xffa00020, 0xffa00023).rw(FUNC(sh4_base_device::sar2_r), FUNC(sh4_base_device::sar2_w));
+ map(0xffa00024, 0xffa00027).rw(FUNC(sh4_base_device::dar2_r), FUNC(sh4_base_device::dar2_w));
+ map(0xffa00028, 0xffa0002b).rw(FUNC(sh4_base_device::dmatcr2_r), FUNC(sh4_base_device::dmatcr2_w));
+ map(0xffa0002c, 0xffa0002f).rw(FUNC(sh4_base_device::chcr2_r), FUNC(sh4_base_device::chcr2_w));
+ map(0xffa00030, 0xffa00033).rw(FUNC(sh4_base_device::sar3_r), FUNC(sh4_base_device::sar3_w));
+ map(0xffa00034, 0xffa00037).rw(FUNC(sh4_base_device::dar3_r), FUNC(sh4_base_device::dar3_w));
+ map(0xffa00038, 0xffa0003b).rw(FUNC(sh4_base_device::dmatcr3_r), FUNC(sh4_base_device::dmatcr3_w));
+ map(0xffa0003c, 0xffa0003f).rw(FUNC(sh4_base_device::chcr3_r), FUNC(sh4_base_device::chcr3_w));
+ map(0xffa00040, 0xffa00043).rw(FUNC(sh4_base_device::dmaor_r), FUNC(sh4_base_device::dmaor_w));
+}
+
+void sh4_base_device::dmac_7750r_map(address_map& map)
+{
+ dmac_map(map);
+
+ map(0xffa00050, 0xffa00053).rw(FUNC(sh4_base_device::sar4_r), FUNC(sh4_base_device::sar4_w));
+ map(0xffa00054, 0xffa00057).rw(FUNC(sh4_base_device::dar4_r), FUNC(sh4_base_device::dar4_w));
+ map(0xffa00058, 0xffa0005b).rw(FUNC(sh4_base_device::dmatcr4_r), FUNC(sh4_base_device::dmatcr4_w));
+ map(0xffa0005c, 0xffa0005f).rw(FUNC(sh4_base_device::chcr4_r), FUNC(sh4_base_device::chcr4_w));
+ map(0xffa00060, 0xffa00063).rw(FUNC(sh4_base_device::sar5_r), FUNC(sh4_base_device::sar5_w));
+ map(0xffa00064, 0xffa00067).rw(FUNC(sh4_base_device::dar5_r), FUNC(sh4_base_device::dar5_w));
+ map(0xffa00068, 0xffa0006b).rw(FUNC(sh4_base_device::dmatcr5_r), FUNC(sh4_base_device::dmatcr5_w));
+ map(0xffa0006c, 0xffa0006f).rw(FUNC(sh4_base_device::chcr5_r), FUNC(sh4_base_device::chcr5_w));
+ map(0xffa00070, 0xffa00073).rw(FUNC(sh4_base_device::sar6_r), FUNC(sh4_base_device::sar6_w));
+ map(0xffa00074, 0xffa00077).rw(FUNC(sh4_base_device::dar6_r), FUNC(sh4_base_device::dar6_w));
+ map(0xffa00078, 0xffa0007b).rw(FUNC(sh4_base_device::dmatcr6_r), FUNC(sh4_base_device::dmatcr6_w));
+ map(0xffa0007c, 0xffa0007f).rw(FUNC(sh4_base_device::chcr6_r), FUNC(sh4_base_device::chcr6_w));
+ map(0xffa00080, 0xffa00083).rw(FUNC(sh4_base_device::sar7_r), FUNC(sh4_base_device::sar7_w));
+ map(0xffa00084, 0xffa00087).rw(FUNC(sh4_base_device::dar7_r), FUNC(sh4_base_device::dar7_w));
+ map(0xffa00088, 0xffa0008b).rw(FUNC(sh4_base_device::dmatcr7_r), FUNC(sh4_base_device::dmatcr7_w));
+ map(0xffa0008c, 0xffa0008f).rw(FUNC(sh4_base_device::chcr7_r), FUNC(sh4_base_device::chcr7_w));
+}
+
+void sh4_base_device::cpg_map(address_map& map)
+{
+ map(0xffc00000, 0xffc00001).rw(FUNC(sh4_base_device::frqcr_r), FUNC(sh4_base_device::frqcr_w));
+ map(0xffc00004, 0xffc00004).rw(FUNC(sh4_base_device::stbcr_r), FUNC(sh4_base_device::stbcr_w));
+ map(0xffc00008, 0xffc00008).r(FUNC(sh4_base_device::wtcnt_r));
+ map(0xffc00008, 0xffc00009).w(FUNC(sh4_base_device::wtcnt_w));
+ map(0xffc0000c, 0xffc0000c).r(FUNC(sh4_base_device::wtcsr_r));
+ map(0xffc0000c, 0xffc0000d).w(FUNC(sh4_base_device::wtcsr_w));
+ map(0xffc00010, 0xffc00010).rw(FUNC(sh4_base_device::stbcr2_r), FUNC(sh4_base_device::stbcr2_w));
+}
+
+void sh4_base_device::cpg_7750r_map(address_map& map)
+{
+ cpg_map(map);
+
+ map(0xfe0a0000, 0xfe0a0003).rw(FUNC(sh4_base_device::clkstp00_r), FUNC(sh4_base_device::clkstp00_w));
+ map(0xfe0a0008, 0xfe0a000b).w(FUNC(sh4_base_device::clkstpclr_w));
+}
+
+void sh4_base_device::rtc_map(address_map& map)
+{
+ map(0xffc80000, 0xffc80000).r(FUNC(sh4_base_device::r64cnt_r));
+ map(0xffc80004, 0xffc80004).rw(FUNC(sh4_base_device::rseccnt_r), FUNC(sh4_base_device::rseccnt_w));
+ map(0xffc80008, 0xffc80008).rw(FUNC(sh4_base_device::rmincnt_r), FUNC(sh4_base_device::rmincnt_w));
+ map(0xffc8000c, 0xffc8000c).rw(FUNC(sh4_base_device::rhrcnt_r), FUNC(sh4_base_device::rhrcnt_w));
+ map(0xffc80010, 0xffc80010).rw(FUNC(sh4_base_device::rwkcnt_r), FUNC(sh4_base_device::rwkcnt_w));
+ map(0xffc80014, 0xffc80014).rw(FUNC(sh4_base_device::rdaycnt_r), FUNC(sh4_base_device::rdaycnt_w));
+ map(0xffc80018, 0xffc80018).rw(FUNC(sh4_base_device::rmoncnt_r), FUNC(sh4_base_device::rmoncnt_w));
+ map(0xffc8001c, 0xffc8001d).rw(FUNC(sh4_base_device::ryrcnt_r), FUNC(sh4_base_device::ryrcnt_w));
+ map(0xffc80020, 0xffc80020).rw(FUNC(sh4_base_device::rsecar_r), FUNC(sh4_base_device::rsecar_w));
+ map(0xffc80024, 0xffc80024).rw(FUNC(sh4_base_device::rminar_r), FUNC(sh4_base_device::rminar_w));
+ map(0xffc80028, 0xffc80028).rw(FUNC(sh4_base_device::rhrar_r), FUNC(sh4_base_device::rhrar_w));
+ map(0xffc8002c, 0xffc8002c).rw(FUNC(sh4_base_device::rwkar_r), FUNC(sh4_base_device::rwkar_w));
+ map(0xffc80030, 0xffc80030).rw(FUNC(sh4_base_device::rdayar_r), FUNC(sh4_base_device::rdayar_w));
+ map(0xffc80034, 0xffc80034).rw(FUNC(sh4_base_device::rmonar_r), FUNC(sh4_base_device::rmonar_w));
+ map(0xffc80038, 0xffc80038).rw(FUNC(sh4_base_device::rcr1_r), FUNC(sh4_base_device::rcr1_w));
+ map(0xffc8003c, 0xffc8003c).rw(FUNC(sh4_base_device::rcr2_r), FUNC(sh4_base_device::rcr2_w));
+}
+
+void sh4_base_device::rtc_7750r_map(address_map& map)
+{
+ rtc_map(map);
+
+ map(0xffc80050, 0xffc80050).rw(FUNC(sh4_base_device::rcr3_r), FUNC(sh4_base_device::rcr3_w));
+ map(0xffc80054, 0xffc80055).rw(FUNC(sh4_base_device::ryrar_r), FUNC(sh4_base_device::ryrar_w));
+}
+
+void sh4_base_device::intc_map(address_map& map)
+{
+ map(0xffd00000, 0xffd00001).rw(FUNC(sh4_base_device::icr_r), FUNC(sh4_base_device::icr_w));
+ map(0xffd00004, 0xffd00005).rw(FUNC(sh4_base_device::ipra_r), FUNC(sh4_base_device::ipra_w));
+ map(0xffd00008, 0xffd00009).rw(FUNC(sh4_base_device::iprb_r), FUNC(sh4_base_device::iprb_w));
+ map(0xffd0000c, 0xffd0000d).rw(FUNC(sh4_base_device::iprc_r), FUNC(sh4_base_device::iprc_w));
+}
+
+void sh4_base_device::intc_7750s_map(address_map& map)
+{
+ intc_map(map);
+
+ map(0xffd00010, 0xffd00011).rw(FUNC(sh4_base_device::iprd_r), FUNC(sh4_base_device::iprd_w));
+}
+
+void sh4_base_device::intc_7750r_map(address_map& map)
+{
+ intc_7750s_map(map);
+
+ map(0xfe080000, 0xfe080003).rw(FUNC(sh4_base_device::intpri00_r), FUNC(sh4_base_device::intpri00_w));
+ map(0xfe080020, 0xfe080023).rw(FUNC(sh4_base_device::intreq00_r), FUNC(sh4_base_device::intreq00_w));
+ map(0xfe080040, 0xfe080043).rw(FUNC(sh4_base_device::intmsk00_r), FUNC(sh4_base_device::intmskclr_w));
+ map(0xfe080060, 0xfe080063).w(FUNC(sh4_base_device::intmsk00_w));
+}
+
+void sh4_base_device::tmu_map(address_map& map)
+{
+ map(0xffd80000, 0xffd80000).rw(FUNC(sh4_base_device::tocr_r), FUNC(sh4_base_device::tocr_w));
+ map(0xffd80004, 0xffd80004).rw(FUNC(sh4_base_device::tstr_r), FUNC(sh4_base_device::tstr_w));
+ map(0xffd80008, 0xffd8000b).rw(FUNC(sh4_base_device::tcor0_r), FUNC(sh4_base_device::tcor0_w));
+ map(0xffd8000c, 0xffd8000f).rw(FUNC(sh4_base_device::tcnt0_r), FUNC(sh4_base_device::tcnt0_w));
+ map(0xffd80010, 0xffd80011).rw(FUNC(sh4_base_device::tcr0_r), FUNC(sh4_base_device::tcr0_w));
+ map(0xffd80014, 0xffd80017).rw(FUNC(sh4_base_device::tcor1_r), FUNC(sh4_base_device::tcor1_w));
+ map(0xffd80018, 0xffd8001b).rw(FUNC(sh4_base_device::tcnt1_r), FUNC(sh4_base_device::tcnt1_w));
+ map(0xffd8001c, 0xffd8001d).rw(FUNC(sh4_base_device::tcr1_r), FUNC(sh4_base_device::tcr1_w));
+ map(0xffd80020, 0xffd80023).rw(FUNC(sh4_base_device::tcor2_r), FUNC(sh4_base_device::tcor2_w));
+ map(0xffd80024, 0xffd80027).rw(FUNC(sh4_base_device::tcnt2_r), FUNC(sh4_base_device::tcnt2_w));
+ map(0xffd80028, 0xffd80029).rw(FUNC(sh4_base_device::tcr2_r), FUNC(sh4_base_device::tcr2_w));
+ map(0xffd8002c, 0xffd8002f).rw(FUNC(sh4_base_device::tcpr2_r), FUNC(sh4_base_device::tcpr2_w));
+}
+
+void sh4_base_device::tmu_7750r_map(address_map& map)
+{
+ tmu_map(map);
+
+ map(0xfe100004, 0xfe100004).rw(FUNC(sh4_base_device::tstr2_r), FUNC(sh4_base_device::tstr2_w));
+ map(0xfe100008, 0xfe10000b).rw(FUNC(sh4_base_device::tcor3_r), FUNC(sh4_base_device::tcor3_w));
+ map(0xfe10000c, 0xfe10000f).rw(FUNC(sh4_base_device::tcnt3_r), FUNC(sh4_base_device::tcnt3_w));
+ map(0xfe100010, 0xfe100011).rw(FUNC(sh4_base_device::tcr3_r), FUNC(sh4_base_device::tcr3_w));
+ map(0xfe100014, 0xfe100017).rw(FUNC(sh4_base_device::tcor4_r), FUNC(sh4_base_device::tcor4_w));
+ map(0xfe100018, 0xfe10001b).rw(FUNC(sh4_base_device::tcnt4_r), FUNC(sh4_base_device::tcnt4_w));
+ map(0xfe10001c, 0xfe10001d).rw(FUNC(sh4_base_device::tcr4_r), FUNC(sh4_base_device::tcr4_w));
+}
+
+void sh4_base_device::sci_map(address_map& map)
+{
+ map(0xffe00000, 0xffe00000).rw(FUNC(sh4_base_device::scsmr1_r), FUNC(sh4_base_device::scsmr1_w));
+ map(0xffe00004, 0xffe00004).rw(FUNC(sh4_base_device::scbrr1_r), FUNC(sh4_base_device::scbrr1_w));
+ map(0xffe00008, 0xffe00008).rw(FUNC(sh4_base_device::scscr1_r), FUNC(sh4_base_device::scscr1_w));
+ map(0xffe0000c, 0xffe0000c).rw(FUNC(sh4_base_device::sctdr1_r), FUNC(sh4_base_device::sctdr1_w));
+ map(0xffe00010, 0xffe00010).rw(FUNC(sh4_base_device::scssr1_r), FUNC(sh4_base_device::scssr1_w));
+ map(0xffe00014, 0xffe00014).r(FUNC(sh4_base_device::scrdr1_r));
+ map(0xffe00018, 0xffe00018).rw(FUNC(sh4_base_device::scscmr1_r), FUNC(sh4_base_device::scscmr1_w));
+ map(0xffe0001c, 0xffe0001c).rw(FUNC(sh4_base_device::scsptr1_r), FUNC(sh4_base_device::scsptr1_w));
+}
+
+void sh4_base_device::scif_map(address_map& map)
+{
+ map(0xffe80000, 0xffe80001).rw(FUNC(sh4_base_device::scsmr2_r), FUNC(sh4_base_device::scsmr2_w));
+ map(0xffe80004, 0xffe80004).rw(FUNC(sh4_base_device::scbrr2_r), FUNC(sh4_base_device::scbrr2_w));
+ map(0xffe80008, 0xffe80009).rw(FUNC(sh4_base_device::scscr2_r), FUNC(sh4_base_device::scscr2_w));
+ map(0xffe8000c, 0xffe8000c).rw(FUNC(sh4_base_device::scftdr2_r), FUNC(sh4_base_device::scftdr2_w));
+ map(0xffe80010, 0xffe80011).rw(FUNC(sh4_base_device::scfsr2_r), FUNC(sh4_base_device::scfsr2_w));
+ map(0xffe80014, 0xffe80014).r(FUNC(sh4_base_device::scfrdr2_r));
+ map(0xffe80018, 0xffe80019).rw(FUNC(sh4_base_device::scfcr2_r), FUNC(sh4_base_device::scfcr2_w));
+ map(0xffe8001c, 0xffe8001d).r(FUNC(sh4_base_device::scfdr2_r));
+ map(0xffe80020, 0xffe80021).rw(FUNC(sh4_base_device::scsptr2_r), FUNC(sh4_base_device::scsptr2_w));
+ map(0xffe80024, 0xffe80025).rw(FUNC(sh4_base_device::sclsr2_r), FUNC(sh4_base_device::sclsr2_w));
+}
+
+void sh4_base_device::hudi_map(address_map &map)
+{
+ map(0xfff00000, 0xfff00001).rw(FUNC(sh4_base_device::sdir_r), FUNC(sh4_base_device::sdir_w));
+ map(0xfff00008, 0xfff0000b).rw(FUNC(sh4_base_device::sddr_r), FUNC(sh4_base_device::sddr_w));
+}
+
+void sh4_base_device::hudi_7750r_map(address_map& map)
+{
+ hudi_map(map);
+
+ map(0xfff00014, 0xfff00015).rw(FUNC(sh4_base_device::sdint_r), FUNC(sh4_base_device::sdint_w));
+}
+
+void sh4_base_device::pci_7751_map(address_map& map)
+{
+ // PCI
+ // 0xfd000000, 0xfdffffff PCIMEM
+
+ // PCIC
+ map(0xfe200000, 0xfe200003).r(FUNC(sh4_base_device::pciconf0_r));
+ map(0xfe200004, 0xfe200007).rw(FUNC(sh4_base_device::pciconf1_r), FUNC(sh4_base_device::pciconf1_w));
+ map(0xfe200008, 0xfe20000b).rw(FUNC(sh4_base_device::pciconf2_r), FUNC(sh4_base_device::pciconf2_w));
+ map(0xfe20000c, 0xfe20000f).rw(FUNC(sh4_base_device::pciconf3_r), FUNC(sh4_base_device::pciconf3_w));
+ map(0xfe200010, 0xfe200013).rw(FUNC(sh4_base_device::pciconf4_r), FUNC(sh4_base_device::pciconf4_w));
+ map(0xfe200014, 0xfe200017).rw(FUNC(sh4_base_device::pciconf5_r), FUNC(sh4_base_device::pciconf5_w));
+ map(0xfe200018, 0xfe20001b).rw(FUNC(sh4_base_device::pciconf6_r), FUNC(sh4_base_device::pciconf6_w));
+ map(0xfe20001c, 0xfe20001f).r(FUNC(sh4_base_device::pciconf7_r));
+ map(0xfe200020, 0xfe200023).r(FUNC(sh4_base_device::pciconf8_r));
+ map(0xfe200024, 0xfe200027).r(FUNC(sh4_base_device::pciconf9_r));
+ map(0xfe200028, 0xfe20002b).r(FUNC(sh4_base_device::pciconf10_r));
+ map(0xfe20002c, 0xfe20002f).rw(FUNC(sh4_base_device::pciconf11_r), FUNC(sh4_base_device::pciconf11_w));
+ map(0xfe200030, 0xfe200033).r(FUNC(sh4_base_device::pciconf12_r));
+ map(0xfe200034, 0xfe200037).r(FUNC(sh4_base_device::pciconf13_r));
+ map(0xfe200038, 0xfe20003b).r(FUNC(sh4_base_device::pciconf14_r));
+ map(0xfe20003c, 0xfe20003f).rw(FUNC(sh4_base_device::pciconf15_r), FUNC(sh4_base_device::pciconf15_w));
+ map(0xfe200040, 0xfe200043).rw(FUNC(sh4_base_device::pciconf16_r), FUNC(sh4_base_device::pciconf16_w));
+ map(0xfe200044, 0xfe200047).rw(FUNC(sh4_base_device::pciconf17_r), FUNC(sh4_base_device::pciconf17_w));
+ map(0xfe200100, 0xfe200103).rw(FUNC(sh4_base_device::pcicr_r), FUNC(sh4_base_device::pcicr_w));
+ map(0xfe200104, 0xfe200107).rw(FUNC(sh4_base_device::pcilsr0_r), FUNC(sh4_base_device::pcilsr0_w));
+ map(0xfe200108, 0xfe20010b).rw(FUNC(sh4_base_device::pcilsr1_r), FUNC(sh4_base_device::pcilsr1_w));
+ map(0xfe20010c, 0xfe20010f).rw(FUNC(sh4_base_device::pcilar0_r), FUNC(sh4_base_device::pcilar0_w));
+ map(0xfe200110, 0xfe200113).rw(FUNC(sh4_base_device::pcilar1_r), FUNC(sh4_base_device::pcilar1_w));
+ map(0xfe200114, 0xfe200117).rw(FUNC(sh4_base_device::pciint_r), FUNC(sh4_base_device::pciint_w));
+ map(0xfe200118, 0xfe20011b).rw(FUNC(sh4_base_device::pciintm_r), FUNC(sh4_base_device::pciintm_w));
+ map(0xfe20011c, 0xfe20011f).rw(FUNC(sh4_base_device::pcialr_r), FUNC(sh4_base_device::pcialr_w));
+ map(0xfe200120, 0xfe200123).rw(FUNC(sh4_base_device::pciclr_r), FUNC(sh4_base_device::pciclr_w));
+ map(0xfe200130, 0xfe200133).rw(FUNC(sh4_base_device::pciaint_r), FUNC(sh4_base_device::pciaint_w));
+ map(0xfe200134, 0xfe200137).rw(FUNC(sh4_base_device::pciaintm_r), FUNC(sh4_base_device::pciaintm_w));
+ map(0xfe200138, 0xfe20013b).rw(FUNC(sh4_base_device::pcibllr_r), FUNC(sh4_base_device::pcibllr_w));
+ map(0xfe200140, 0xfe200143).rw(FUNC(sh4_base_device::pcidmabt_r), FUNC(sh4_base_device::pcidmabt_w));
+ map(0xfe200180, 0xfe200183).rw(FUNC(sh4_base_device::pcidpa0_r), FUNC(sh4_base_device::pcidpa0_w));
+ map(0xfe200184, 0xfe200187).rw(FUNC(sh4_base_device::pcidla0_r), FUNC(sh4_base_device::pcidla0_w));
+ map(0xfe200188, 0xfe20018b).rw(FUNC(sh4_base_device::pcidtc0_r), FUNC(sh4_base_device::pcidtc0_w));
+ map(0xfe20018c, 0xfe20018f).rw(FUNC(sh4_base_device::pcidcr0_r), FUNC(sh4_base_device::pcidcr0_w));
+ map(0xfe200190, 0xfe200193).rw(FUNC(sh4_base_device::pcidpa1_r), FUNC(sh4_base_device::pcidpa1_w));
+ map(0xfe200194, 0xfe200197).rw(FUNC(sh4_base_device::pcidla1_r), FUNC(sh4_base_device::pcidla1_w));
+ map(0xfe200198, 0xfe20019b).rw(FUNC(sh4_base_device::pcidtc1_r), FUNC(sh4_base_device::pcidtc1_w));
+ map(0xfe20019c, 0xfe20019f).rw(FUNC(sh4_base_device::pcidcr1_r), FUNC(sh4_base_device::pcidcr1_w));
+ map(0xfe2001a0, 0xfe2001a3).rw(FUNC(sh4_base_device::pcidpa2_r), FUNC(sh4_base_device::pcidpa2_w));
+ map(0xfe2001a4, 0xfe2001a7).rw(FUNC(sh4_base_device::pcidla2_r), FUNC(sh4_base_device::pcidla2_w));
+ map(0xfe2001a8, 0xfe2001ab).rw(FUNC(sh4_base_device::pcidtc2_r), FUNC(sh4_base_device::pcidtc2_w));
+ map(0xfe2001ac, 0xfe2001af).rw(FUNC(sh4_base_device::pcidcr2_r), FUNC(sh4_base_device::pcidcr2_w));
+ map(0xfe2001b0, 0xfe2001b3).rw(FUNC(sh4_base_device::pcidpa3_r), FUNC(sh4_base_device::pcidpa3_w));
+ map(0xfe2001b4, 0xfe2001b7).rw(FUNC(sh4_base_device::pcidla3_r), FUNC(sh4_base_device::pcidla3_w));
+ map(0xfe2001b8, 0xfe2001bb).rw(FUNC(sh4_base_device::pcidtc3_r), FUNC(sh4_base_device::pcidtc3_w));
+ map(0xfe2001bc, 0xfe2001bf).rw(FUNC(sh4_base_device::pcidcr3_r), FUNC(sh4_base_device::pcidcr3_w));
+ map(0xfe2001c0, 0xfe2001c3).rw(FUNC(sh4_base_device::pcipar_r), FUNC(sh4_base_device::pcipar_w));
+ map(0xfe2001c4, 0xfe2001c7).rw(FUNC(sh4_base_device::pcimbr_r), FUNC(sh4_base_device::pcimbr_w));
+ map(0xfe2001c8, 0xfe2001cb).rw(FUNC(sh4_base_device::pciiobr_r), FUNC(sh4_base_device::pciiobr_w));
+ map(0xfe2001cc, 0xfe2001cf).rw(FUNC(sh4_base_device::pcipint_r), FUNC(sh4_base_device::pcipint_w));
+ map(0xfe2001d0, 0xfe2001d3).rw(FUNC(sh4_base_device::pcipintm_r), FUNC(sh4_base_device::pcipintm_w));
+ map(0xfe2001d4, 0xfe2001d7).rw(FUNC(sh4_base_device::pciclkr_r), FUNC(sh4_base_device::pciclkr_w));
+ map(0xfe2001e0, 0xfe2001e3).rw(FUNC(sh4_base_device::pcibcr1_r), FUNC(sh4_base_device::pcibcr1_w));
+ map(0xfe2001e4, 0xfe2001e7).rw(FUNC(sh4_base_device::pcibcr2_r), FUNC(sh4_base_device::pcibcr2_w));
+ map(0xfe2001f8, 0xfe2001fb).rw(FUNC(sh4_base_device::pcibcr3_r), FUNC(sh4_base_device::pcibcr3_w));
+ map(0xfe2001e8, 0xfe2001eb).rw(FUNC(sh4_base_device::pciwcr1_r), FUNC(sh4_base_device::pciwcr1_w));
+ map(0xfe2001ec, 0xfe2001ef).rw(FUNC(sh4_base_device::pciwcr2_r), FUNC(sh4_base_device::pciwcr2_w));
+ map(0xfe2001f0, 0xfe2001f3).rw(FUNC(sh4_base_device::pciwcr3_r), FUNC(sh4_base_device::pciwcr3_w));
+ map(0xfe2001f4, 0xfe2001f7).rw(FUNC(sh4_base_device::pcimcr_r), FUNC(sh4_base_device::pcimcr_w));
+ map(0xfe200200, 0xfe200203).rw(FUNC(sh4_base_device::pcipctr_r), FUNC(sh4_base_device::pcipctr_w));
+ map(0xfe200204, 0xfe200207).rw(FUNC(sh4_base_device::pcipdtr_r), FUNC(sh4_base_device::pcipdtr_w));
+ map(0xfe200220, 0xfe200223).rw(FUNC(sh4_base_device::pcipdr_r), FUNC(sh4_base_device::pcipdr_w));
+
+ // PCIIO
+ // 0xfe240000, 0xfe27ffff
}
void sh3_base_device::sh3_internal_map(address_map &map)
{
- map(SH3_LOWER_REGBASE, SH3_LOWER_REGEND).rw(FUNC(sh3_base_device::sh3_internal_r), FUNC(sh3_base_device::sh3_internal_w));
- map(SH3_UPPER_REGBASE, SH3_UPPER_REGEND).rw(FUNC(sh3_base_device::sh3_internal_high_r), FUNC(sh3_base_device::sh3_internal_high_w));
+ sh3_register_map(map);
+}
+
+void sh3_device::sh3_register_map(address_map& map)
+{
+ ccn_7709s_map(map);
+ ubc_7709s_map(map);
+ cpg_7709_map(map);
+ bsc_7709s_map(map);
+ rtc_map(map);
+ intc_7709_map(map);
+ dmac_7709_map(map);
+ tmu_map(map);
+ sci_7709_map(map);
+ cmt_7709_map(map);
+ ad_7709_map(map);
+ da_7709_map(map);
+ port_7709_map(map);
+ irda_7709_map(map);
+ scif_7709_map(map);
+ udi_7709s_map(map);
+}
+
+void sh7708s_device::sh3_register_map(address_map& map)
+{
+ ccn_map(map);
+ ubc_map(map);
+ cpg_map(map);
+ bsc_7708_map(map);
+ rtc_map(map);
+ intc_map(map);
+ tmu_map(map);
+ sci_7708_map(map);
+}
+
+void sh7709_device::sh3_register_map(address_map& map)
+{
+ ccn_map(map);
+ ubc_map(map);
+ cpg_7709_map(map);
+ bsc_7709_map(map);
+ rtc_map(map);
+ intc_7709_map(map);
+ dmac_7709_map(map);
+ tmu_map(map);
+ sci_7709_map(map);
+ cmt_7709_map(map);
+ ad_7709_map(map);
+ da_7709_map(map);
+ port_7709_map(map);
+ irda_7709_map(map);
+ scif_7709_map(map);
+}
+
+void sh7709s_device::sh3_register_map(address_map& map)
+{
+ ccn_7709s_map(map);
+ ubc_7709s_map(map);
+ cpg_7709_map(map);
+ bsc_7709s_map(map);
+ rtc_map(map);
+ intc_7709_map(map);
+ dmac_7709_map(map);
+ tmu_map(map);
+ sci_7709_map(map);
+ cmt_7709_map(map);
+ ad_7709_map(map);
+ da_7709_map(map);
+ port_7709_map(map);
+ irda_7709_map(map);
+ scif_7709_map(map);
+ udi_7709s_map(map);
+}
+
+void sh3_base_device::ccn_map(address_map& map)
+{
+ map(0xfffffff0, 0xfffffff3).rw(FUNC(sh3_base_device::pteh_r), FUNC(sh3_base_device::pteh_w));
+ map(0xfffffff4, 0xfffffff7).rw(FUNC(sh3_base_device::ptel_r), FUNC(sh3_base_device::ptel_w));
+ map(0xfffffff8, 0xfffffffb).rw(FUNC(sh3_base_device::ttb_r), FUNC(sh3_base_device::ttb_w));
+ map(0xfffffffc, 0xffffffff).rw(FUNC(sh3_base_device::tea_r), FUNC(sh3_base_device::tea_w));
+ map(0xffffffe0, 0xffffffe3).rw(FUNC(sh3_base_device::mmucr_r), FUNC(sh3_base_device::mmucr_w));
+ map(0xffffffe4, 0xffffffe4).rw(FUNC(sh3_base_device::basra_r), FUNC(sh3_base_device::basra_w));
+ map(0xffffffe8, 0xffffffe8).rw(FUNC(sh3_base_device::basrb_r), FUNC(sh3_base_device::basrb_w));
+ map(0xffffffec, 0xffffffef).rw(FUNC(sh3_base_device::ccr_r), FUNC(sh3_base_device::ccr_w));
+ map(0xffffffd0, 0xffffffd3).rw(FUNC(sh3_base_device::tra_r), FUNC(sh3_base_device::tra_w));
+ map(0xffffffd4, 0xffffffd7).rw(FUNC(sh3_base_device::expevt_r), FUNC(sh3_base_device::expevt_w));
+ map(0xffffffd8, 0xffffffdb).rw(FUNC(sh3_base_device::intevt_r), FUNC(sh3_base_device::intevt_w));
+}
+
+void sh3_base_device::ccn_7709s_map(address_map& map)
+{
+ ccn_map(map);
+
+ map(0x400000b0, 0x400000b3).rw(FUNC(sh3_base_device::ccr2_r), FUNC(sh3_base_device::ccr2_w));
+}
+
+void sh3_base_device::ubc_map(address_map& map)
+{
+ map(0xffffffb0, 0xffffffb3).rw(FUNC(sh3_base_device::bara_r), FUNC(sh3_base_device::bara_w));
+ map(0xffffffb4, 0xffffffb4).rw(FUNC(sh3_base_device::bamra_r), FUNC(sh3_base_device::bamra_w));
+ map(0xffffffb8, 0xffffffb9).rw(FUNC(sh3_base_device::bbra_r), FUNC(sh3_base_device::bbra_w));
+ map(0xffffffa0, 0xffffffa3).rw(FUNC(sh3_base_device::barb_r), FUNC(sh3_base_device::barb_w));
+ map(0xffffffa4, 0xffffffa4).rw(FUNC(sh3_base_device::bamrb_r), FUNC(sh3_base_device::bamrb_w));
+ map(0xffffffa8, 0xffffffa9).rw(FUNC(sh3_base_device::bbrb_r), FUNC(sh3_base_device::bbrb_w));
+ map(0xffffff90, 0xffffff93).rw(FUNC(sh3_base_device::bdrb_r), FUNC(sh3_base_device::bdrb_w));
+ map(0xffffff94, 0xffffff97).rw(FUNC(sh3_base_device::bdmrb_r), FUNC(sh3_base_device::bdmrb_w));
+ map(0xffffff98, 0xffffff99).rw(FUNC(sh3_base_device::brcr_r), FUNC(sh3_base_device::brcr_w));
+}
+
+void sh3_base_device::ubc_7709s_map(address_map& map)
+{
+ ubc_map(map);
+
+ map(0xffffff9c, 0xffffff9d).rw(FUNC(sh3_base_device::betr_r), FUNC(sh3_base_device::betr_w));
+ map(0xffffffac, 0xffffffaf).rw(FUNC(sh3_base_device::brsr_r), FUNC(sh3_base_device::brsr_w));
+ map(0xffffffbc, 0xffffffbf).rw(FUNC(sh3_base_device::brdr_r), FUNC(sh3_base_device::brdr_w));
+}
+
+void sh3_base_device::cpg_map(address_map& map)
+{
+ map(0xffffff80, 0xffffff81).rw(FUNC(sh3_base_device::frqcr_r), FUNC(sh3_base_device::frqcr_w));
+ map(0xffffff82, 0xffffff83).rw(FUNC(sh3_base_device::stbcr_r), FUNC(sh3_base_device::stbcr_w));
+ map(0xffffff84, 0xffffff84).r(FUNC(sh3_base_device::wtcnt_r));
+ map(0xffffff84, 0xffffff85).w(FUNC(sh3_base_device::wtcnt_w));
+ map(0xffffff86, 0xffffff86).r(FUNC(sh3_base_device::wtcsr_r));
+ map(0xffffff86, 0xffffff87).w(FUNC(sh3_base_device::wtcsr_w));
+}
+
+void sh3_base_device::cpg_7709_map(address_map& map)
+{
+ cpg_map(map);
+
+ map(0xffffff88, 0xffffff88).rw(FUNC(sh3_base_device::stbcr2_r), FUNC(sh3_base_device::stbcr2_w));
+}
+
+void sh3_base_device::bsc_map(address_map& map)
+{
+ map(0xffffff60, 0xffffff61).rw(FUNC(sh3_base_device::bcr1_r), FUNC(sh3_base_device::bcr1_w));
+ map(0xffffff62, 0xffffff63).rw(FUNC(sh3_base_device::bcr2_r), FUNC(sh3_base_device::bcr2_w));
+ map(0xffffff64, 0xffffff65).rw(FUNC(sh3_base_device::wcr1_r), FUNC(sh3_base_device::wcr1_w));
+ map(0xffffff66, 0xffffff67).rw(FUNC(sh3_base_device::wcr2_r), FUNC(sh3_base_device::wcr2_w));
+ map(0xffffff68, 0xffffff69).rw(FUNC(sh3_base_device::mcr_r), FUNC(sh3_base_device::mcr_w));
+ map(0xffffff6c, 0xffffff6d).rw(FUNC(sh3_base_device::pcr_r), FUNC(sh3_base_device::pcr_w));
+ map(0xffffff6e, 0xffffff6f).rw(FUNC(sh3_base_device::rtcsr_r), FUNC(sh3_base_device::rtcsr_w));
+ map(0xffffff70, 0xffffff71).rw(FUNC(sh3_base_device::rtcnt_r), FUNC(sh3_base_device::rtcnt_w));
+ map(0xffffff72, 0xffffff73).rw(FUNC(sh3_base_device::rtcor_r), FUNC(sh3_base_device::rtcor_w));
+ map(0xffffff74, 0xffffff75).rw(FUNC(sh3_base_device::rfcr_r), FUNC(sh3_base_device::rfcr_w));
+ map(0xfffd0000, 0xffffeffe).rw(FUNC(sh3_base_device::sdmr_r), FUNC(sh3_base_device::sdmr_w));
+}
+
+void sh3_base_device::bsc_7708_map(address_map& map)
+{
+ bsc_map(map);
+
+ map(0xffffff6a, 0xffffff6b).rw(FUNC(sh3_base_device::dcr_r), FUNC(sh3_base_device::dcr_w));
+ map(0xffffff76, 0xffffff77).rw(FUNC(sh3_base_device::pctr_r), FUNC(sh3_base_device::pctr_w));
+ map(0xffffff78, 0xffffff79).rw(FUNC(sh3_base_device::pdtr_r), FUNC(sh3_base_device::pdtr_w));
+}
+
+void sh3_base_device::bsc_7709_map(address_map& map)
+{
+ bsc_map(map);
+
+ map(0xffffff6a, 0xffffff6b).rw(FUNC(sh3_base_device::dcr_r), FUNC(sh3_base_device::dcr_w));
+ map(0xffffff7e, 0xffffff7f).rw(FUNC(sh3_base_device::bcr3_r), FUNC(sh3_base_device::bcr3_w));
+}
+
+void sh3_base_device::bsc_7709s_map(address_map& map)
+{
+ bsc_map(map);
+
+ map(0xffffff50, 0xffffff51).rw(FUNC(sh3_base_device::mcscr0_r), FUNC(sh3_base_device::mcscr0_w));
+ map(0xffffff52, 0xffffff53).rw(FUNC(sh3_base_device::mcscr1_r), FUNC(sh3_base_device::mcscr1_w));
+ map(0xffffff54, 0xffffff55).rw(FUNC(sh3_base_device::mcscr2_r), FUNC(sh3_base_device::mcscr2_w));
+ map(0xffffff56, 0xffffff57).rw(FUNC(sh3_base_device::mcscr3_r), FUNC(sh3_base_device::mcscr3_w));
+ map(0xffffff58, 0xffffff59).rw(FUNC(sh3_base_device::mcscr4_r), FUNC(sh3_base_device::mcscr4_w));
+ map(0xffffff5a, 0xffffff5b).rw(FUNC(sh3_base_device::mcscr5_r), FUNC(sh3_base_device::mcscr5_w));
+ map(0xffffff5c, 0xffffff5d).rw(FUNC(sh3_base_device::mcscr6_r), FUNC(sh3_base_device::mcscr6_w));
+ map(0xffffff5e, 0xffffff5f).rw(FUNC(sh3_base_device::mcscr7_r), FUNC(sh3_base_device::mcscr7_w));
+}
+
+void sh3_base_device::rtc_map(address_map& map)
+{
+ map(0xfffffec0, 0xfffffec0).r(FUNC(sh3_base_device::r64cnt_r));
+ map(0xfffffec2, 0xfffffec2).rw(FUNC(sh3_base_device::rseccnt_r), FUNC(sh3_base_device::rseccnt_w));
+ map(0xfffffec4, 0xfffffec4).rw(FUNC(sh3_base_device::rmincnt_r), FUNC(sh3_base_device::rmincnt_w));
+ map(0xfffffec6, 0xfffffec6).rw(FUNC(sh3_base_device::rhrcnt_r), FUNC(sh3_base_device::rhrcnt_w));
+ map(0xfffffec8, 0xfffffec8).rw(FUNC(sh3_base_device::rwkcnt_r), FUNC(sh3_base_device::rwkcnt_w));
+ map(0xfffffeca, 0xfffffeca).rw(FUNC(sh3_base_device::rdaycnt_r), FUNC(sh3_base_device::rdaycnt_w));
+ map(0xfffffecc, 0xfffffecc).rw(FUNC(sh3_base_device::rmoncnt_r), FUNC(sh3_base_device::rmoncnt_w));
+ map(0xfffffece, 0xfffffece).rw(FUNC(sh3_base_device::ryrcnt_r), FUNC(sh3_base_device::ryrcnt_w));
+ map(0xfffffec0, 0xfffffec0).rw(FUNC(sh3_base_device::rsecar_r), FUNC(sh3_base_device::rsecar_w));
+ map(0xfffffed2, 0xfffffed2).rw(FUNC(sh3_base_device::rminar_r), FUNC(sh3_base_device::rminar_w));
+ map(0xfffffed4, 0xfffffed4).rw(FUNC(sh3_base_device::rhrar_r), FUNC(sh3_base_device::rhrar_w));
+ map(0xfffffed6, 0xfffffed6).rw(FUNC(sh3_base_device::rwkar_r), FUNC(sh3_base_device::rwkar_w));
+ map(0xfffffed8, 0xfffffed8).rw(FUNC(sh3_base_device::rdayar_r), FUNC(sh3_base_device::rdayar_w));
+ map(0xfffffeda, 0xfffffeda).rw(FUNC(sh3_base_device::rmonar_r), FUNC(sh3_base_device::rmonar_w));
+ map(0xfffffedc, 0xfffffedc).rw(FUNC(sh3_base_device::rcr1_r), FUNC(sh3_base_device::rcr1_w));
+ map(0xfffffede, 0xfffffede).rw(FUNC(sh3_base_device::rcr2_r), FUNC(sh3_base_device::rcr2_w));
+}
+
+void sh3_base_device::intc_map(address_map& map)
+{
+ map(0xfffffee0, 0xfffffee1).rw(FUNC(sh3_base_device::icr0_r), FUNC(sh3_base_device::icr0_w));
+ map(0xfffffee2, 0xfffffee3).rw(FUNC(sh3_base_device::ipra_r), FUNC(sh3_base_device::ipra_w));
+ map(0xfffffee4, 0xfffffee5).rw(FUNC(sh3_base_device::iprb_r), FUNC(sh3_base_device::iprb_w));
+}
+
+void sh3_base_device::intc_7709_map(address_map& map)
+{
+ intc_map(map);
+
+ map(0x04000000, 0x04000003).rw(FUNC(sh3_base_device::intevt2_r), FUNC(sh3_base_device::intevt2_w));
+ map(0x04000004, 0x04000004).rw(FUNC(sh3_base_device::irr0_r), FUNC(sh3_base_device::irr0_w));
+ map(0x04000006, 0x04000006).rw(FUNC(sh3_base_device::irr1_r), FUNC(sh3_base_device::irr1_w));
+ map(0x04000008, 0x04000008).rw(FUNC(sh3_base_device::irr2_r), FUNC(sh3_base_device::irr2_w));
+ map(0x04000010, 0x04000011).rw(FUNC(sh3_base_device::icr1_r), FUNC(sh3_base_device::icr1_w));
+ map(0x04000012, 0x04000013).rw(FUNC(sh3_base_device::icr2_r), FUNC(sh3_base_device::icr2_w));
+ map(0x04000014, 0x04000015).rw(FUNC(sh3_base_device::pinter_r), FUNC(sh3_base_device::pinter_w));
+ map(0x04000016, 0x04000017).rw(FUNC(sh3_base_device::iprc_r), FUNC(sh3_base_device::iprc_w));
+ map(0x04000018, 0x04000019).rw(FUNC(sh3_base_device::iprd_r), FUNC(sh3_base_device::iprd_w));
+ map(0x0400001a, 0x0400001b).rw(FUNC(sh3_base_device::ipre_r), FUNC(sh3_base_device::ipre_w));
+}
+
+void sh3_base_device::dmac_7709_map(address_map& map)
+{
+ map(0x04000020, 0x04000023).rw(FUNC(sh3_base_device::sar0_r), FUNC(sh3_base_device::sar0_w));
+ map(0x04000024, 0x04000027).rw(FUNC(sh3_base_device::dar0_r), FUNC(sh3_base_device::dar0_w));
+ map(0x04000028, 0x0400002b).rw(FUNC(sh3_base_device::dmatcr0_r), FUNC(sh3_base_device::dmatcr0_w));
+ map(0x0400002c, 0x0400002f).rw(FUNC(sh3_base_device::chcr0_r), FUNC(sh3_base_device::chcr0_w));
+ map(0x04000030, 0x04000033).rw(FUNC(sh3_base_device::sar1_r), FUNC(sh3_base_device::sar1_w));
+ map(0x04000034, 0x04000037).rw(FUNC(sh3_base_device::dar1_r), FUNC(sh3_base_device::dar1_w));
+ map(0x04000038, 0x0400003b).rw(FUNC(sh3_base_device::dmatcr1_r), FUNC(sh3_base_device::dmatcr1_w));
+ map(0x0400003c, 0x0400003f).rw(FUNC(sh3_base_device::chcr1_r), FUNC(sh3_base_device::chcr1_w));
+ map(0x04000040, 0x04000043).rw(FUNC(sh3_base_device::sar2_r), FUNC(sh3_base_device::sar2_w));
+ map(0x04000044, 0x04000047).rw(FUNC(sh3_base_device::dar2_r), FUNC(sh3_base_device::dar2_w));
+ map(0x04000048, 0x0400004b).rw(FUNC(sh3_base_device::dmatcr2_r), FUNC(sh3_base_device::dmatcr2_w));
+ map(0x0400004c, 0x0400004f).rw(FUNC(sh3_base_device::chcr2_r), FUNC(sh3_base_device::chcr2_w));
+ map(0x04000050, 0x04000053).rw(FUNC(sh3_base_device::sar3_r), FUNC(sh3_base_device::sar3_w));
+ map(0x04000054, 0x04000057).rw(FUNC(sh3_base_device::dar3_r), FUNC(sh3_base_device::dar3_w));
+ map(0x04000058, 0x0400005b).rw(FUNC(sh3_base_device::dmatcr3_r), FUNC(sh3_base_device::dmatcr3_w));
+ map(0x0400005c, 0x0400005f).rw(FUNC(sh3_base_device::chcr3_r), FUNC(sh3_base_device::chcr3_w));
+ map(0x04000060, 0x04000061).lrw16(
+ [this](offs_t offset, uint16_t mem_mask) { return dmaor_r(offset, mem_mask); }, "sh3_base_device::dmaor_r",
+ [this](offs_t offset, uint16_t data, uint16_t mem_mask) { dmaor_w(offset, data, mem_mask); }, "sh3_base_device::dmaor_w");
+}
+
+void sh3_base_device::tmu_map(address_map& map)
+{
+ map(0xfffffe90, 0xfffffe90).rw(FUNC(sh3_base_device::tocr_r), FUNC(sh3_base_device::tocr_w));
+ map(0xfffffe92, 0xfffffe92).rw(FUNC(sh3_base_device::tstr_r), FUNC(sh3_base_device::tstr_w));
+ map(0xfffffe94, 0xfffffe97).rw(FUNC(sh3_base_device::tcor0_r), FUNC(sh3_base_device::tcor0_w));
+ map(0xfffffe98, 0xfffffe9b).rw(FUNC(sh3_base_device::tcnt0_r), FUNC(sh3_base_device::tcnt0_w));
+ map(0xfffffe9c, 0xfffffe9d).rw(FUNC(sh3_base_device::tcr0_r), FUNC(sh3_base_device::tcr0_w));
+ map(0xfffffea0, 0xfffffea3).rw(FUNC(sh3_base_device::tcor1_r), FUNC(sh3_base_device::tcor1_w));
+ map(0xfffffea4, 0xfffffea7).rw(FUNC(sh3_base_device::tcnt1_r), FUNC(sh3_base_device::tcnt1_w));
+ map(0xfffffea8, 0xfffffea9).rw(FUNC(sh3_base_device::tcr1_r), FUNC(sh3_base_device::tcr1_w));
+ map(0xfffffeac, 0xfffffeaf).rw(FUNC(sh3_base_device::tcor2_r), FUNC(sh3_base_device::tcor2_w));
+ map(0xfffffeb0, 0xfffffeb3).rw(FUNC(sh3_base_device::tcnt2_r), FUNC(sh3_base_device::tcnt2_w));
+ map(0xfffffeb4, 0xfffffeb5).rw(FUNC(sh3_base_device::tcr2_r), FUNC(sh3_base_device::tcr2_w));
+ map(0xfffffeb8, 0xfffffebb).rw(FUNC(sh3_base_device::tcpr2_r), FUNC(sh3_base_device::tcpr2_w));
+}
+
+void sh3_base_device::sci_7708_map(address_map& map)
+{
+ sci_7709_map(map);
+
+ map(0xffffff7c, 0xffffff7c).rw(FUNC(sh3_base_device::scsptr_r), FUNC(sh3_base_device::scsptr_w));
+}
+
+void sh3_base_device::sci_7709_map(address_map& map)
+{
+ map(0xfffffe80, 0xfffffe80).rw(FUNC(sh3_base_device::scsmr_r), FUNC(sh3_base_device::scsmr_w));
+ map(0xfffffe82, 0xfffffe82).rw(FUNC(sh3_base_device::scbrr_r), FUNC(sh3_base_device::scbrr_w));
+ map(0xfffffe84, 0xfffffe84).rw(FUNC(sh3_base_device::scscr_r), FUNC(sh3_base_device::scscr_w));
+ map(0xfffffe86, 0xfffffe86).rw(FUNC(sh3_base_device::sctdr_r), FUNC(sh3_base_device::sctdr_w));
+ map(0xfffffe88, 0xfffffe88).rw(FUNC(sh3_base_device::scssr_r), FUNC(sh3_base_device::scssr_w));
+ map(0xfffffe8a, 0xfffffe8a).r(FUNC(sh3_base_device::scrdr_r));
+ map(0xfffffe8c, 0xfffffe8c).rw(FUNC(sh3_base_device::scscmr_r), FUNC(sh3_base_device::scscmr_w));
+}
+
+void sh3_base_device::cmt_7709_map(address_map& map)
+{
+ map(0x04000070, 0x04000071).rw(FUNC(sh3_base_device::cmstr_r), FUNC(sh3_base_device::cmstr_w));
+ map(0x04000072, 0x04000073).rw(FUNC(sh3_base_device::cmscr_r), FUNC(sh3_base_device::cmscr_w));
+ map(0x04000074, 0x04000075).rw(FUNC(sh3_base_device::cmcnt_r), FUNC(sh3_base_device::cmcnt_w));
+ map(0x04000076, 0x04000077).rw(FUNC(sh3_base_device::cmcor_r), FUNC(sh3_base_device::cmcor_w));
+}
+
+void sh3_base_device::ad_7709_map(address_map& map)
+{
+ map(0x04000080, 0x04000080).rw(FUNC(sh3_base_device::addrah_r), FUNC(sh3_base_device::addrah_w));
+ map(0x04000082, 0x04000082).rw(FUNC(sh3_base_device::addral_r), FUNC(sh3_base_device::addral_w));
+ map(0x04000084, 0x04000084).rw(FUNC(sh3_base_device::addrbh_r), FUNC(sh3_base_device::addrbh_w));
+ map(0x04000086, 0x04000086).rw(FUNC(sh3_base_device::addrbl_r), FUNC(sh3_base_device::addrbl_w));
+ map(0x04000088, 0x04000088).rw(FUNC(sh3_base_device::addrch_r), FUNC(sh3_base_device::addrch_w));
+ map(0x0400008a, 0x0400008a).rw(FUNC(sh3_base_device::addrcl_r), FUNC(sh3_base_device::addrcl_w));
+ map(0x0400008c, 0x0400008c).rw(FUNC(sh3_base_device::addrdh_r), FUNC(sh3_base_device::addrdh_w));
+ map(0x0400008e, 0x0400008e).rw(FUNC(sh3_base_device::addrdl_r), FUNC(sh3_base_device::addrdl_w));
+ map(0x04000090, 0x04000090).rw(FUNC(sh3_base_device::adcsr_r), FUNC(sh3_base_device::adcsr_w));
+ map(0x04000092, 0x04000092).rw(FUNC(sh3_base_device::adcr_r), FUNC(sh3_base_device::adcr_w));
+}
+
+void sh3_base_device::da_7709_map(address_map& map)
+{
+ map(0x040000a0, 0x040000a0).rw(FUNC(sh3_base_device::dadr0_r), FUNC(sh3_base_device::dadr0_w));
+ map(0x040000a2, 0x040000a2).rw(FUNC(sh3_base_device::dadr1_r), FUNC(sh3_base_device::dadr1_w));
+ map(0x040000a4, 0x040000a4).rw(FUNC(sh3_base_device::dadcr_r), FUNC(sh3_base_device::dadcr_w));
+}
+
+void sh3_base_device::port_7709_map(address_map& map)
+{
+ map(0x04000100, 0x04000101).rw(FUNC(sh3_base_device::pacr_r), FUNC(sh3_base_device::pacr_w));
+ map(0x04000102, 0x04000103).rw(FUNC(sh3_base_device::pbcr_r), FUNC(sh3_base_device::pbcr_w));
+ map(0x04000104, 0x04000105).rw(FUNC(sh3_base_device::pccr_r), FUNC(sh3_base_device::pccr_w));
+ map(0x04000106, 0x04000107).rw(FUNC(sh3_base_device::pdcr_r), FUNC(sh3_base_device::pdcr_w));
+ map(0x04000108, 0x04000109).rw(FUNC(sh3_base_device::pecr_r), FUNC(sh3_base_device::pecr_w));
+ map(0x0400010a, 0x0400010b).rw(FUNC(sh3_base_device::pfcr_r), FUNC(sh3_base_device::pfcr_w));
+ map(0x0400010c, 0x0400010d).rw(FUNC(sh3_base_device::pgcr_r), FUNC(sh3_base_device::pgcr_w));
+ map(0x0400010e, 0x0400010f).rw(FUNC(sh3_base_device::phcr_r), FUNC(sh3_base_device::phcr_w));
+ map(0x04000110, 0x04000111).rw(FUNC(sh3_base_device::pjcr_r), FUNC(sh3_base_device::pjcr_w));
+ map(0x04000112, 0x04000113).rw(FUNC(sh3_base_device::pkcr_r), FUNC(sh3_base_device::pkcr_w));
+ map(0x04000114, 0x04000115).rw(FUNC(sh3_base_device::plcr_r), FUNC(sh3_base_device::plcr_w));
+ map(0x04000116, 0x04000117).rw(FUNC(sh3_base_device::scpcr_r), FUNC(sh3_base_device::scpcr_w));
+ map(0x04000120, 0x04000120).rw(FUNC(sh3_base_device::padr_r), FUNC(sh3_base_device::padr_w));
+ map(0x04000122, 0x04000122).rw(FUNC(sh3_base_device::pbdr_r), FUNC(sh3_base_device::pbdr_w));
+ map(0x04000124, 0x04000124).rw(FUNC(sh3_base_device::pcdr_r), FUNC(sh3_base_device::pcdr_w));
+ map(0x04000126, 0x04000126).rw(FUNC(sh3_base_device::pddr_r), FUNC(sh3_base_device::pddr_w));
+ map(0x04000128, 0x04000128).rw(FUNC(sh3_base_device::pedr_r), FUNC(sh3_base_device::pedr_w));
+ map(0x0400012a, 0x0400012a).rw(FUNC(sh3_base_device::pfdr_r), FUNC(sh3_base_device::pfdr_w));
+ map(0x0400012c, 0x0400012c).rw(FUNC(sh3_base_device::pgdr_r), FUNC(sh3_base_device::pgdr_w));
+ map(0x0400012e, 0x0400012e).rw(FUNC(sh3_base_device::phdr_r), FUNC(sh3_base_device::phdr_w));
+ map(0x04000130, 0x04000130).rw(FUNC(sh3_base_device::pjdr_r), FUNC(sh3_base_device::pjdr_w));
+ map(0x04000132, 0x04000132).rw(FUNC(sh3_base_device::pkdr_r), FUNC(sh3_base_device::pkdr_w));
+ map(0x04000134, 0x04000134).rw(FUNC(sh3_base_device::pldr_r), FUNC(sh3_base_device::pldr_w));
+ map(0x04000136, 0x04000136).rw(FUNC(sh3_base_device::scpdr_r), FUNC(sh3_base_device::scpdr_w));
+}
+
+void sh3_base_device::irda_7709_map(address_map& map)
+{
+ map(0x04000140, 0x04000140).rw(FUNC(sh3_base_device::scsmr1_r), FUNC(sh3_base_device::scsmr1_w));
+ map(0x04000142, 0x04000142).rw(FUNC(sh3_base_device::scbrr1_r), FUNC(sh3_base_device::scbrr1_w));
+ map(0x04000144, 0x04000144).rw(FUNC(sh3_base_device::scscr1_r), FUNC(sh3_base_device::scscr1_w));
+ map(0x04000146, 0x04000146).rw(FUNC(sh3_base_device::scftdr1_r), FUNC(sh3_base_device::scftdr1_w));
+ map(0x04000148, 0x04000149).rw(FUNC(sh3_base_device::scssr1_r), FUNC(sh3_base_device::scssr1_w));
+ map(0x0400014a, 0x0400014a).rw(FUNC(sh3_base_device::scfrdr1_r), FUNC(sh3_base_device::scfrdr1_w));
+ map(0x0400014c, 0x0400014c).rw(FUNC(sh3_base_device::scfcr1_r), FUNC(sh3_base_device::scfcr1_w));
+ map(0x0400014e, 0x0400014f).rw(FUNC(sh3_base_device::scfdr1_r), FUNC(sh3_base_device::scfdr1_w));
+}
+
+void sh3_base_device::scif_7709_map(address_map& map)
+{
+ map(0x04000150, 0x04000150).rw(FUNC(sh3_base_device::scsmr2_r), FUNC(sh3_base_device::scsmr2_w));
+ map(0x04000152, 0x04000152).rw(FUNC(sh3_base_device::scbrr2_r), FUNC(sh3_base_device::scbrr2_w));
+ map(0x04000154, 0x04000154).rw(FUNC(sh3_base_device::scscr2_r), FUNC(sh3_base_device::scscr2_w));
+ map(0x04000156, 0x04000156).rw(FUNC(sh3_base_device::scftdr2_r), FUNC(sh3_base_device::scftdr2_w));
+ map(0x04000158, 0x04000159).rw(FUNC(sh3_base_device::scssr2_r), FUNC(sh3_base_device::scssr2_w));
+ map(0x0400015a, 0x0400015a).rw(FUNC(sh3_base_device::scfrdr2_r), FUNC(sh3_base_device::scfrdr2_w));
+ map(0x0400015c, 0x0400015c).rw(FUNC(sh3_base_device::scfcr2_r), FUNC(sh3_base_device::scfcr2_w));
+ map(0x0400015e, 0x0400015f).rw(FUNC(sh3_base_device::scfdr2_r), FUNC(sh3_base_device::scfdr2_w));
}
+void sh3_base_device::udi_7709s_map(address_map& map)
+{
+ map(0x4000200, 0x4000201).rw(FUNC(sh3_base_device::sdir_r), FUNC(sh3_base_device::sdir_w));
+}
sh34_base_device::sh34_base_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock, endianness_t endianness, address_map_constructor internal)
: sh_common_execution(mconfig, type, tag, owner, clock, endianness, internal)
@@ -84,12 +896,39 @@ sh34_base_device::sh34_base_device(const machine_config &mconfig, device_type ty
device_memory_interface::space_config_vector sh34_base_device::memory_space_config() const
{
- return space_config_vector {
+ return space_config_vector
+ {
std::make_pair(AS_PROGRAM, &m_program_config),
std::make_pair(AS_IO, &m_io_config)
};
}
+bool sh34_base_device::memory_translate(int spacenum, int intention, offs_t& address, address_space*& target_space)
+{
+ target_space = &space(spacenum);
+
+ if (address >= 0xe0000000)
+ return true;
+
+ if (address >= 0x80000000) // P1/P2/P3 region
+ {
+ address &= SH34_AM;
+ return true;
+ }
+ else // P0 region
+ {
+ if (!m_sh4_mmu_enabled)
+ {
+ address &= SH34_AM;
+ return true;
+ }
+ else
+ {
+ address = get_remap(address & SH34_AM);
+ return true;
+ }
+ }
+}
sh3_base_device::sh3_base_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock, endianness_t endianness)
: sh34_base_device(mconfig, type, tag, owner, clock, endianness, address_map_constructor(FUNC(sh3_base_device::sh3_internal_map), this))
@@ -107,29 +946,63 @@ sh4_base_device::sh4_base_device(const machine_config &mconfig, device_type type
}
-sh3_device::sh3_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : sh3_base_device(mconfig, SH3LE, tag, owner, clock, ENDIANNESS_LITTLE)
+sh3_device::sh3_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock, endianness_t endianness)
+ : sh3_base_device(mconfig, SH3, tag, owner, clock, endianness)
+{
+}
+
+sh7708s_device::sh7708s_device(const machine_config& mconfig, const char* tag, device_t* owner, uint32_t clock, endianness_t endianness)
+ : sh3_base_device(mconfig, SH7708S, tag, owner, clock, endianness)
{
}
+sh7709_device::sh7709_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock, endianness_t endianness)
+ : sh3_base_device(mconfig, SH7709, tag, owner, clock, endianness)
+{
+}
-sh3be_device::sh3be_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : sh3_base_device(mconfig, SH3BE, tag, owner, clock, ENDIANNESS_BIG)
+sh7709s_device::sh7709s_device(const machine_config& mconfig, const char* tag, device_t* owner, uint32_t clock, endianness_t endianness)
+ : sh3_base_device(mconfig, SH7709S, tag, owner, clock, endianness)
{
}
-sh4_device::sh4_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : sh4_base_device(mconfig, SH4LE, tag, owner, clock, ENDIANNESS_LITTLE)
+sh4_device::sh4_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock, endianness_t endianness)
+ : sh4_base_device(mconfig, SH4, tag, owner, clock, endianness)
{
}
+sh7091_device::sh7091_device(const machine_config& mconfig, const char* tag, device_t* owner, uint32_t clock, endianness_t endianness)
+ : sh4_base_device(mconfig, SH7091, tag, owner, clock, endianness)
+{
+}
-sh4be_device::sh4be_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : sh4_base_device(mconfig, SH4BE, tag, owner, clock, ENDIANNESS_BIG)
+sh7750_device::sh7750_device(const machine_config& mconfig, const char* tag, device_t* owner, uint32_t clock, endianness_t endianness)
+ : sh4_base_device(mconfig, SH7750, tag, owner, clock, endianness)
{
}
+sh7750s_device::sh7750s_device(const machine_config& mconfig, const char* tag, device_t* owner, uint32_t clock, endianness_t endianness)
+ : sh4_base_device(mconfig, SH7750S, tag, owner, clock, endianness)
+{
+}
+
+sh7750r_device::sh7750r_device(const machine_config& mconfig, const char* tag, device_t* owner, uint32_t clock, endianness_t endianness)
+ : sh4_base_device(mconfig, SH7750R, tag, owner, clock, endianness)
+{
+}
+
+sh7751_device::sh7751_device(const machine_config& mconfig, const char* tag, device_t* owner, uint32_t clock, endianness_t endianness)
+ : sh4_base_device(mconfig, SH7751, tag, owner, clock, endianness)
+{
+ m_pciconf0 = 0x35051054;
+}
+
+sh7751r_device::sh7751r_device(const machine_config& mconfig, const char* tag, device_t* owner, uint32_t clock, endianness_t endianness)
+ : sh4_base_device(mconfig, SH7751R, tag, owner, clock, endianness)
+{
+ m_pciconf0 = 0x350e1054;
+}
std::unique_ptr<util::disasm_interface> sh34_base_device::create_disassembler()
{
@@ -149,28 +1022,28 @@ void sh34_base_device::LDTLB(const uint16_t opcode)
void sh4_base_device::LDTLB(const uint16_t opcode)
{
- int replace = (m_m[MMUCR] & 0x0000fc00) >> 10;
+ int replace = (m_mmucr & 0x0000fc00) >> 10;
logerror("using LDTLB to replace UTLB entry %02x\n", replace);
// these come from PTEH
- m_utlb[replace].VPN = (m_m[PTEH] & 0xfffffc00) >> 10;
- // m_utlb[replace].D = (m_m[PTEH] & 0x00000200) >> 9; // from PTEL
- // m_utlb[replace].V = (m_m[PTEH] & 0x00000100) >> 8; // from PTEL
- m_utlb[replace].ASID = (m_m[PTEH] & 0x000000ff) >> 0;
+ m_utlb[replace].VPN = (m_pteh & 0xfffffc00) >> 10;
+ // m_utlb[replace].D = (m_pteh & 0x00000200) >> 9; // from PTEL
+ // m_utlb[replace].V = (m_pteh & 0x00000100) >> 8; // from PTEL
+ m_utlb[replace].ASID = (m_pteh & 0x000000ff) >> 0;
// these come from PTEL
- m_utlb[replace].PPN = (m_m[PTEL] & 0x1ffffc00) >> 10;
- m_utlb[replace].V = (m_m[PTEL] & 0x00000100) >> 8;
- m_utlb[replace].PSZ = (m_m[PTEL] & 0x00000080) >> 6;
- m_utlb[replace].PSZ |= (m_m[PTEL] & 0x00000010) >> 4;
- m_utlb[replace].PPR = (m_m[PTEL] & 0x00000060) >> 5;
- m_utlb[replace].C = (m_m[PTEL] & 0x00000008) >> 3;
- m_utlb[replace].D = (m_m[PTEL] & 0x00000004) >> 2;
- m_utlb[replace].SH = (m_m[PTEL] & 0x00000002) >> 1;
- m_utlb[replace].WT = (m_m[PTEL] & 0x00000001) >> 0;
+ m_utlb[replace].PPN = (m_ptel & 0x1ffffc00) >> 10;
+ m_utlb[replace].V = (m_ptel & 0x00000100) >> 8;
+ m_utlb[replace].PSZ = (m_ptel & 0x00000080) >> 6;
+ m_utlb[replace].PSZ |= (m_ptel & 0x00000010) >> 4;
+ m_utlb[replace].PPR = (m_ptel & 0x00000060) >> 5;
+ m_utlb[replace].C = (m_ptel & 0x00000008) >> 3;
+ m_utlb[replace].D = (m_ptel & 0x00000004) >> 2;
+ m_utlb[replace].SH = (m_ptel & 0x00000002) >> 1;
+ m_utlb[replace].WT = (m_ptel & 0x00000001) >> 0;
// these come from PTEA
- m_utlb[replace].TC = (m_m[PTEA] & 0x00000008) >> 3;
- m_utlb[replace].SA = (m_m[PTEA] & 0x00000007) >> 0;
+ m_utlb[replace].TC = (m_ptea & 0x00000008) >> 3;
+ m_utlb[replace].SA = (m_ptea & 0x00000007) >> 0;
}
#if 0
@@ -194,14 +1067,19 @@ int data_type_of(int n)
uint32_t abs;
abs = m_sh2_state->m_fr[n] & 0x7fffffff;
- if ((m_sh2_state->m_fpscr & PR) == 0) { /* Single-precision */
- if (abs < 0x00800000) {
- if (((m_sh2_state->m_fpscr & DN) == 1) || (abs == 0x00000000)) {
- if (sign_of(n) == 0) {
+ if ((m_sh2_state->m_fpscr & PR) == 0) /* Single-precision */
+ {
+ if (abs < 0x00800000)
+ {
+ if (((m_sh2_state->m_fpscr & DN) == 1) || (abs == 0x00000000))
+ {
+ if (sign_of(n) == 0)
+ {
zero(n, 0);
return(SH4_FPU_PZERO);
}
- else {
+ else
+ {
zero(n, 1);
return(SH4_FPU_NZERO);
}
@@ -213,7 +1091,8 @@ int data_type_of(int n)
if (abs < 0x7f800000)
return(SH4_FPU_NORM);
else
- if (abs == 0x7f800000) {
+ if (abs == 0x7f800000)
+ {
if (sign_of(n) == 0)
return(SH4_FPU_PINF);
else
@@ -225,14 +1104,19 @@ int data_type_of(int n)
else
return(SH4_FPU_sNaN);
}
- else { /* Double-precision */
- if (abs < 0x00100000) {
- if (((m_sh2_state->m_fpscr & DN) == 1) || ((abs == 0x00000000) && (m_sh2_state->m_fr[n + 1] == 0x00000000))) {
- if (sign_of(n) == 0) {
+ else /* Double-precision */
+ {
+ if (abs < 0x00100000)
+ {
+ if (((m_sh2_state->m_fpscr & DN) == 1) || ((abs == 0x00000000) && (m_sh2_state->m_fr[n + 1] == 0x00000000)))
+ {
+ if (sign_of(n) == 0)
+ {
zero(n, 0);
return(SH4_FPU_PZERO);
}
- else {
+ else
+ {
zero(n, 1);
return(SH4_FPU_NZERO);
}
@@ -244,7 +1128,8 @@ int data_type_of(int n)
if (abs < 0x7ff00000)
return(SH4_FPU_NORM);
else
- if ((abs == 0x7ff00000) && (m_sh2_state->m_fr[n + 1] == 0x00000000)) {
+ if ((abs == 0x7ff00000) && (m_sh2_state->m_fr[n + 1] == 0x00000000))
+ {
if (sign_of(n) == 0)
return(SH4_FPU_PINF);
else
@@ -260,149 +1145,154 @@ int data_type_of(int n)
}
#endif
-inline uint8_t sh34_base_device::RB(offs_t A)
+inline uint8_t sh34_base_device::read_byte(offs_t offset)
{
- if (A >= 0xe0000000)
- return m_program->read_byte(A);
+ if (offset >= 0xe0000000)
+ return m_program->read_byte(offset);
- if (A >= 0x80000000) // P1/P2/P3 region
+ if (offset >= 0x80000000) // P1/P2/P3 region
{
- return m_program->read_byte(A & SH34_AM);
+ return m_program->read_byte(offset & SH34_AM);
}
else // P0 region
{
if (!m_sh4_mmu_enabled)
{
- return m_program->read_byte(A & SH34_AM);
+ return m_program->read_byte(offset & SH34_AM);
}
else
{
- A = get_remap(A & SH34_AM);
- return m_program->read_byte(A);
+ offset = get_remap(offset & SH34_AM);
+ return m_program->read_byte(offset);
}
}
}
-inline uint16_t sh34_base_device::RW(offs_t A)
+inline uint16_t sh34_base_device::read_word(offs_t offset)
{
- if (A >= 0xe0000000)
- return m_program->read_word(A);
+ if (offset >= 0xe0000000)
+ return m_program->read_word(offset);
- if (A >= 0x80000000) // P1/P2/P3 region
+ if (offset >= 0x80000000) // P1/P2/P3 region
{
- return m_program->read_word(A & SH34_AM);
+ return m_program->read_word(offset & SH34_AM);
}
else
{
if (!m_sh4_mmu_enabled)
{
- return m_program->read_word(A & SH34_AM);
+ return m_program->read_word(offset & SH34_AM);
}
else
{
- A = get_remap(A & SH34_AM);
- return m_program->read_word(A);
+ offset = get_remap(offset & SH34_AM);
+ return m_program->read_word(offset);
}
}
}
-inline uint32_t sh34_base_device::RL(offs_t A)
+inline uint16_t sh34_base_device::decrypted_read_word(offs_t offset)
{
- if (A >= 0xe0000000)
- return m_program->read_dword(A);
+ return read_word(offset);
+}
- if (A >= 0x80000000) // P1/P2/P3 region
+inline uint32_t sh34_base_device::read_long(offs_t offset)
+{
+ if (offset >= 0xe0000000)
+ return m_program->read_dword(offset);
+
+ if (offset >= 0x80000000) // P1/P2/P3 region
{
- return m_program->read_dword(A & SH34_AM);
+ return m_program->read_dword(offset & SH34_AM);
}
else
{
if (!m_sh4_mmu_enabled)
{
- return m_program->read_dword(A & SH34_AM);
+ return m_program->read_dword(offset & SH34_AM);
}
else
{
- A = get_remap(A & SH34_AM);
- return m_program->read_dword(A);
+ offset = get_remap(offset & SH34_AM);
+ return m_program->read_dword(offset);
}
}
}
-inline void sh34_base_device::WB(offs_t A, uint8_t V)
+inline void sh34_base_device::write_byte(offs_t offset, uint8_t data)
{
- if (A >= 0xe0000000)
+ if (offset >= 0xe0000000)
{
- m_program->write_byte(A, V);
+ m_program->write_byte(offset, data);
return;
}
- if (A >= 0x80000000) // P1/P2/P3 region
+ if (offset >= 0x80000000) // P1/P2/P3 region
{
- m_program->write_byte(A & SH34_AM, V);
+ m_program->write_byte(offset & SH34_AM, data);
}
else
{
if (!m_sh4_mmu_enabled)
{
- m_program->write_byte(A & SH34_AM, V);
+ m_program->write_byte(offset & SH34_AM, data);
}
else
{
- A = get_remap(A & SH34_AM);
- m_program->write_byte(A, V);
+ offset = get_remap(offset & SH34_AM);
+ m_program->write_byte(offset, data);
}
}
}
-inline void sh34_base_device::WW(offs_t A, uint16_t V)
+inline void sh34_base_device::write_word(offs_t offset, uint16_t data)
{
- if (A >= 0xe0000000)
+ if (offset >= 0xe0000000)
{
- m_program->write_word(A, V);
+ m_program->write_word(offset, data);
return;
}
- if (A >= 0x80000000) // P1/P2/P3 region
+ if (offset >= 0x80000000) // P1/P2/P3 region
{
- m_program->write_word(A & SH34_AM, V);
+ m_program->write_word(offset & SH34_AM, data);
}
else
{
if (!m_sh4_mmu_enabled)
{
- m_program->write_word(A & SH34_AM, V);
+ m_program->write_word(offset & SH34_AM, data);
}
else
{
- A = get_remap(A & SH34_AM);
- m_program->write_word(A, V);
+ offset = get_remap(offset & SH34_AM);
+ m_program->write_word(offset, data);
}
}
}
-inline void sh34_base_device::WL(offs_t A, uint32_t V)
+inline void sh34_base_device::write_long(offs_t offset, uint32_t data)
{
- if (A >= 0xe0000000)
+ if (offset >= 0xe0000000)
{
- m_program->write_dword(A, V);
+ m_program->write_dword(offset, data);
return;
}
- if (A >= 0x80000000) // P1/P2/P3 region
+ if (offset >= 0x80000000) // P1/P2/P3 region
{
- m_program->write_dword(A & SH34_AM, V);
+ m_program->write_dword(offset & SH34_AM, data);
}
else
{
if (!m_sh4_mmu_enabled)
{
- m_program->write_dword(A & SH34_AM, V);
+ m_program->write_dword(offset & SH34_AM, data);
}
else
{
- A = get_remap(A & SH34_AM);
- m_program->write_dword(A, V);
+ offset = get_remap(offset & SH34_AM);
+ m_program->write_dword(offset, data);
}
}
}
@@ -415,8 +1305,8 @@ inline void sh34_base_device::ILLEGAL()
/* MOVCA.L R0,@Rn */
inline void sh34_base_device::MOVCAL(const uint16_t opcode)
{
- m_sh2_state->ea = m_sh2_state->r[Rn];
- WL(m_sh2_state->ea, m_sh2_state->r[0]);
+ m_sh2_state->ea = m_sh2_state->r[REG_N];
+ write_long(m_sh2_state->ea, m_sh2_state->r[0]);
}
inline void sh34_base_device::CLRS(const uint16_t opcode)
@@ -433,13 +1323,13 @@ inline void sh34_base_device::SETS(const uint16_t opcode)
inline void sh34_base_device::LDCSR(const uint16_t opcode)
{
// important to store the value now so that it doesn't get affected by the bank change
- uint32_t reg = m_sh2_state->r[Rn];
+ uint32_t reg = m_sh2_state->r[REG_N];
- if ((machine().debug_flags & DEBUG_FLAG_ENABLED) != 0)
+ if (debugger_enabled())
sh4_syncronize_register_bank((m_sh2_state->sr & sRB) >> 29);
- if ((m_sh2_state->r[Rn] & sRB) != (m_sh2_state->sr & sRB))
- sh4_change_register_bank(m_sh2_state->r[Rn] & sRB ? 1 : 0);
+ if ((m_sh2_state->r[REG_N] & sRB) != (m_sh2_state->sr & sRB))
+ sh4_change_register_bank(m_sh2_state->r[REG_N] & sRB ? 1 : 0);
m_sh2_state->sr = reg & SH34_FLAGS;
sh4_exception_recompute();
@@ -448,16 +1338,14 @@ inline void sh34_base_device::LDCSR(const uint16_t opcode)
/* LDC.L @Rm+,SR */
inline void sh34_base_device::LDCMSR(const uint16_t opcode)
{
- uint32_t old;
-
- old = m_sh2_state->sr;
- m_sh2_state->ea = m_sh2_state->r[Rn];
- m_sh2_state->sr = RL(m_sh2_state->ea) & SH34_FLAGS;
- if ((machine().debug_flags & DEBUG_FLAG_ENABLED) != 0)
+ uint32_t old = m_sh2_state->sr;
+ m_sh2_state->ea = m_sh2_state->r[REG_N];
+ m_sh2_state->sr = read_long(m_sh2_state->ea) & SH34_FLAGS;
+ if (debugger_enabled())
sh4_syncronize_register_bank((old & sRB) >> 29);
if ((old & sRB) != (m_sh2_state->sr & sRB))
sh4_change_register_bank(m_sh2_state->sr & sRB ? 1 : 0);
- m_sh2_state->r[Rn] += 4;
+ m_sh2_state->r[REG_N] += 4;
m_sh2_state->icount -= 2;
sh4_exception_recompute();
}
@@ -467,7 +1355,7 @@ inline void sh34_base_device::RTE()
{
m_sh2_state->m_delay = m_sh2_state->ea = m_sh2_state->m_spc;
- if ((machine().debug_flags & DEBUG_FLAG_ENABLED) != 0)
+ if (debugger_enabled())
sh4_syncronize_register_bank((m_sh2_state->sr & sRB) >> 29);
if ((m_sh2_state->m_ssr & sRB) != (m_sh2_state->sr & sRB))
sh4_change_register_bank(m_sh2_state->m_ssr & sRB ? 1 : 0);
@@ -484,11 +1372,11 @@ inline void sh34_base_device::TRAPA(uint32_t i)
if (m_cpu_type == CPU_TYPE_SH4)
{
- m_m[TRA] = imm << 2;
+ m_tra = imm << 2;
}
else /* SH3 */
{
- m_sh3internal_upper[SH3_TRA_ADDR] = imm << 2;
+ m_tra = imm << 2;
}
m_sh2_state->m_ssr = m_sh2_state->sr;
@@ -497,7 +1385,7 @@ inline void sh34_base_device::TRAPA(uint32_t i)
m_sh2_state->m_sgr = m_sh2_state->r[15];
m_sh2_state->sr |= MD;
- if ((machine().debug_flags & DEBUG_FLAG_ENABLED) != 0)
+ if (debugger_enabled())
sh4_syncronize_register_bank((m_sh2_state->sr & sRB) >> 29);
if (!(m_sh2_state->sr & sRB))
sh4_change_register_bank(1);
@@ -507,11 +1395,11 @@ inline void sh34_base_device::TRAPA(uint32_t i)
if (m_cpu_type == CPU_TYPE_SH4)
{
- m_m[EXPEVT] = 0x00000160;
+ m_expevt = 0x00000160;
}
else /* SH3 */
{
- m_sh3internal_upper[SH3_EXPEVT_ADDR] = 0x00000160;
+ m_expevt = 0x00000160;
}
m_sh2_state->pc = m_sh2_state->vbr + 0x00000100;
@@ -522,100 +1410,99 @@ inline void sh34_base_device::TRAPA(uint32_t i)
/* STCRBANK Rm_BANK,Rn */
inline void sh34_base_device::STCRBANK(const uint16_t opcode)
{
- uint32_t m = Rm;
+ uint32_t m = REG_M;
- m_sh2_state->r[Rn] = m_sh2_state->m_rbnk[m_sh2_state->sr&sRB ? 0 : 1][m & 7];
+ m_sh2_state->r[REG_N] = m_sh2_state->m_rbnk[m_sh2_state->sr&sRB ? 0 : 1][m & 7];
}
/* STCMRBANK Rm_BANK,@-Rn */
inline void sh34_base_device::STCMRBANK(const uint16_t opcode)
{
- uint32_t m = Rm; uint32_t n = Rn;
+ uint32_t m = REG_M;
+ uint32_t n = REG_N;
m_sh2_state->r[n] -= 4;
m_sh2_state->ea = m_sh2_state->r[n];
- WL(m_sh2_state->ea, m_sh2_state->m_rbnk[m_sh2_state->sr&sRB ? 0 : 1][m & 7]);
+ write_long(m_sh2_state->ea, m_sh2_state->m_rbnk[m_sh2_state->sr&sRB ? 0 : 1][m & 7]);
m_sh2_state->icount--;
}
/* STS.L SGR,@-Rn */
inline void sh34_base_device::STCMSGR(const uint16_t opcode)
{
- uint32_t n = Rn;
+ uint32_t n = REG_N;
m_sh2_state->r[n] -= 4;
m_sh2_state->ea = m_sh2_state->r[n];
- WL(m_sh2_state->ea, m_sh2_state->m_sgr);
+ write_long(m_sh2_state->ea, m_sh2_state->m_sgr);
}
/* STS.L FPUL,@-Rn */
inline void sh34_base_device::STSMFPUL(const uint16_t opcode)
{
- uint32_t n = Rn;
+ uint32_t n = REG_N;
m_sh2_state->r[n] -= 4;
m_sh2_state->ea = m_sh2_state->r[n];
- WL(m_sh2_state->ea, m_sh2_state->m_fpul);
+ write_long(m_sh2_state->ea, m_sh2_state->m_fpul);
}
/* STS.L FPSCR,@-Rn */
inline void sh34_base_device::STSMFPSCR(const uint16_t opcode)
{
- uint32_t n = Rn;
+ uint32_t n = REG_N;
m_sh2_state->r[n] -= 4;
m_sh2_state->ea = m_sh2_state->r[n];
- WL(m_sh2_state->ea, m_sh2_state->m_fpscr & 0x003FFFFF);
+ write_long(m_sh2_state->ea, m_sh2_state->m_fpscr & 0x003FFFFF);
}
/* STC.L DBR,@-Rn */
inline void sh34_base_device::STCMDBR(const uint16_t opcode)
{
- uint32_t n = Rn;
+ uint32_t n = REG_N;
m_sh2_state->r[n] -= 4;
m_sh2_state->ea = m_sh2_state->r[n];
- WL(m_sh2_state->ea, m_sh2_state->m_dbr);
+ write_long(m_sh2_state->ea, m_sh2_state->m_dbr);
}
/* STC.L SSR,@-Rn */
inline void sh34_base_device::STCMSSR(const uint16_t opcode)
{
- uint32_t n = Rn;
+ uint32_t n = REG_N;
m_sh2_state->r[n] -= 4;
m_sh2_state->ea = m_sh2_state->r[n];
- WL(m_sh2_state->ea, m_sh2_state->m_ssr);
+ write_long(m_sh2_state->ea, m_sh2_state->m_ssr);
}
/* STC.L SPC,@-Rn */
inline void sh34_base_device::STCMSPC(const uint16_t opcode)
{
- uint32_t n = Rn;
+ uint32_t n = REG_N;
m_sh2_state->r[n] -= 4;
m_sh2_state->ea = m_sh2_state->r[n];
- WL(m_sh2_state->ea, m_sh2_state->m_spc);
+ write_long(m_sh2_state->ea, m_sh2_state->m_spc);
}
/* LDS.L @Rm+,FPUL */
inline void sh34_base_device::LDSMFPUL(const uint16_t opcode)
{
- m_sh2_state->ea = m_sh2_state->r[Rn];
- m_sh2_state->m_fpul = RL(m_sh2_state->ea);
- m_sh2_state->r[Rn] += 4;
+ m_sh2_state->ea = m_sh2_state->r[REG_N];
+ m_sh2_state->m_fpul = read_long(m_sh2_state->ea);
+ m_sh2_state->r[REG_N] += 4;
}
/* LDS.L @Rm+,FPSCR */
inline void sh34_base_device::LDSMFPSCR(const uint16_t opcode)
{
- uint32_t s;
-
- s = m_sh2_state->m_fpscr;
- m_sh2_state->ea = m_sh2_state->r[Rn];
- m_sh2_state->m_fpscr = RL(m_sh2_state->ea);
+ uint32_t s = m_sh2_state->m_fpscr;
+ m_sh2_state->ea = m_sh2_state->r[REG_N];
+ m_sh2_state->m_fpscr = read_long(m_sh2_state->ea);
m_sh2_state->m_fpscr &= 0x003FFFFF;
- m_sh2_state->r[Rn] += 4;
+ m_sh2_state->r[REG_N] += 4;
if ((s & FR) != (m_sh2_state->m_fpscr & FR))
sh4_swap_fp_registers();
#ifdef LSB_FIRST
@@ -629,50 +1516,49 @@ inline void sh34_base_device::LDSMFPSCR(const uint16_t opcode)
/* LDC.L @Rm+,DBR */
inline void sh34_base_device::LDCMDBR(const uint16_t opcode)
{
- m_sh2_state->ea = m_sh2_state->r[Rn];
- m_sh2_state->m_dbr = RL(m_sh2_state->ea);
- m_sh2_state->r[Rn] += 4;
+ m_sh2_state->ea = m_sh2_state->r[REG_N];
+ m_sh2_state->m_dbr = read_long(m_sh2_state->ea);
+ m_sh2_state->r[REG_N] += 4;
}
/* LDC.L @Rn+,Rm_BANK */
inline void sh34_base_device::LDCMRBANK(const uint16_t opcode)
{
- uint32_t m = Rm; uint32_t n = Rn;
+ uint32_t m = REG_M;
+ uint32_t n = REG_N;
m_sh2_state->ea = m_sh2_state->r[n];
- m_sh2_state->m_rbnk[m_sh2_state->sr&sRB ? 0 : 1][m & 7] = RL(m_sh2_state->ea);
+ m_sh2_state->m_rbnk[m_sh2_state->sr&sRB ? 0 : 1][m & 7] = read_long(m_sh2_state->ea);
m_sh2_state->r[n] += 4;
}
/* LDC.L @Rm+,SSR */
inline void sh34_base_device::LDCMSSR(const uint16_t opcode)
{
- m_sh2_state->ea = m_sh2_state->r[Rn];
- m_sh2_state->m_ssr = RL(m_sh2_state->ea);
- m_sh2_state->r[Rn] += 4;
+ m_sh2_state->ea = m_sh2_state->r[REG_N];
+ m_sh2_state->m_ssr = read_long(m_sh2_state->ea);
+ m_sh2_state->r[REG_N] += 4;
}
/* LDC.L @Rm+,SPC */
inline void sh34_base_device::LDCMSPC(const uint16_t opcode)
{
- m_sh2_state->ea = m_sh2_state->r[Rn];
- m_sh2_state->m_spc = RL(m_sh2_state->ea);
- m_sh2_state->r[Rn] += 4;
+ m_sh2_state->ea = m_sh2_state->r[REG_N];
+ m_sh2_state->m_spc = read_long(m_sh2_state->ea);
+ m_sh2_state->r[REG_N] += 4;
}
/* LDS Rm,FPUL */
inline void sh34_base_device::LDSFPUL(const uint16_t opcode)
{
- m_sh2_state->m_fpul = m_sh2_state->r[Rn];
+ m_sh2_state->m_fpul = m_sh2_state->r[REG_N];
}
/* LDS Rm,FPSCR */
inline void sh34_base_device::LDSFPSCR(const uint16_t opcode)
{
- uint32_t s;
-
- s = m_sh2_state->m_fpscr;
- m_sh2_state->m_fpscr = m_sh2_state->r[Rn] & 0x003FFFFF;
+ uint32_t s = m_sh2_state->m_fpscr;
+ m_sh2_state->m_fpscr = m_sh2_state->r[REG_N] & 0x003FFFFF;
if ((s & FR) != (m_sh2_state->m_fpscr & FR))
sh4_swap_fp_registers();
#ifdef LSB_FIRST
@@ -686,54 +1572,56 @@ inline void sh34_base_device::LDSFPSCR(const uint16_t opcode)
/* LDC Rm,DBR */
inline void sh34_base_device::LDCDBR(const uint16_t opcode)
{
- m_sh2_state->m_dbr = m_sh2_state->r[Rn];
+ m_sh2_state->m_dbr = m_sh2_state->r[REG_N];
}
/* STC SSR,Rn */
inline void sh34_base_device::STCSSR(const uint16_t opcode)
{
- m_sh2_state->r[Rn] = m_sh2_state->m_ssr;
+ m_sh2_state->r[REG_N] = m_sh2_state->m_ssr;
}
/* STC SPC,Rn */
inline void sh34_base_device::STCSPC(const uint16_t opcode)
{
- m_sh2_state->r[Rn] = m_sh2_state->m_spc;
+ m_sh2_state->r[REG_N] = m_sh2_state->m_spc;
}
/* STC SGR,Rn */
inline void sh34_base_device::STCSGR(const uint16_t opcode)
{
- m_sh2_state->r[Rn] = m_sh2_state->m_sgr;
+ m_sh2_state->r[REG_N] = m_sh2_state->m_sgr;
}
/* STS FPUL,Rn */
inline void sh34_base_device::STSFPUL(const uint16_t opcode)
{
- m_sh2_state->r[Rn] = m_sh2_state->m_fpul;
+ m_sh2_state->r[REG_N] = m_sh2_state->m_fpul;
}
/* STS FPSCR,Rn */
inline void sh34_base_device::STSFPSCR(const uint16_t opcode)
{
- m_sh2_state->r[Rn] = m_sh2_state->m_fpscr & 0x003FFFFF;
+ m_sh2_state->r[REG_N] = m_sh2_state->m_fpscr & 0x003FFFFF;
}
/* STC DBR,Rn */
inline void sh34_base_device::STCDBR(const uint16_t opcode)
{
- m_sh2_state->r[Rn] = m_sh2_state->m_dbr;
+ m_sh2_state->r[REG_N] = m_sh2_state->m_dbr;
}
/* SHAD Rm,Rn */
inline void sh34_base_device::SHAD(const uint16_t opcode)
{
- uint32_t m = Rm; uint32_t n = Rn;
+ uint32_t m = REG_M;
+ uint32_t n = REG_N;
if ((m_sh2_state->r[m] & 0x80000000) == 0)
m_sh2_state->r[n] = m_sh2_state->r[n] << (m_sh2_state->r[m] & 0x1F);
- else if ((m_sh2_state->r[m] & 0x1F) == 0) {
+ else if ((m_sh2_state->r[m] & 0x1F) == 0)
+ {
if ((m_sh2_state->r[n] & 0x80000000) == 0)
m_sh2_state->r[n] = 0;
else
@@ -746,7 +1634,8 @@ inline void sh34_base_device::SHAD(const uint16_t opcode)
/* SHLD Rm,Rn */
inline void sh34_base_device::SHLD(const uint16_t opcode)
{
- uint32_t m = Rm; uint32_t n = Rn;
+ uint32_t m = REG_M;
+ uint32_t n = REG_N;
if ((m_sh2_state->r[m] & 0x80000000) == 0)
m_sh2_state->r[n] = m_sh2_state->r[n] << (m_sh2_state->r[m] & 0x1F);
@@ -759,47 +1648,45 @@ inline void sh34_base_device::SHLD(const uint16_t opcode)
/* LDCRBANK Rn,Rm_BANK */
inline void sh34_base_device::LDCRBANK(const uint16_t opcode)
{
- uint32_t m = Rm;
+ uint32_t m = REG_M;
- m_sh2_state->m_rbnk[m_sh2_state->sr&sRB ? 0 : 1][m & 7] = m_sh2_state->r[Rn];
+ m_sh2_state->m_rbnk[m_sh2_state->sr&sRB ? 0 : 1][m & 7] = m_sh2_state->r[REG_N];
}
/* LDC Rm,SSR */
inline void sh34_base_device::LDCSSR(const uint16_t opcode)
{
- m_sh2_state->m_ssr = m_sh2_state->r[Rn];
+ m_sh2_state->m_ssr = m_sh2_state->r[REG_N];
}
/* LDC Rm,SPC */
inline void sh34_base_device::LDCSPC(const uint16_t opcode)
{
- m_sh2_state->m_spc = m_sh2_state->r[Rn];
+ m_sh2_state->m_spc = m_sh2_state->r[REG_N];
}
/* PREF @Rn */
inline void sh34_base_device::PREFM(const uint16_t opcode)
{
- int a;
- uint32_t addr, dest, sq;
-
- addr = m_sh2_state->r[Rn]; // address
+ uint32_t addr = m_sh2_state->r[REG_N]; // address
if ((addr >= 0xE0000000) && (addr <= 0xE3FFFFFF))
{
+ uint32_t dest;
if (m_sh4_mmu_enabled)
{
addr = addr & 0xFFFFFFE0;
- dest = sh4_getsqremap(addr); // good enough for naomi-gd rom, probably not much else
-
+ // good enough for NAOMI GD-ROM, not much else
+ dest = sh4_getsqremap(addr);
}
else
{
- sq = (addr & 0x20) >> 5;
+ uint32_t sq = (addr & 0x20) >> 5;
dest = addr & 0x03FFFFE0;
if (sq == 0)
{
if (m_cpu_type == CPU_TYPE_SH4)
{
- dest |= (m_m[QACR0] & 0x1C) << 24;
+ dest |= (m_qacr0 & 0x1C) << 24;
}
else
{
@@ -810,7 +1697,7 @@ inline void sh34_base_device::PREFM(const uint16_t opcode)
{
if (m_cpu_type == CPU_TYPE_SH4)
{
- dest |= (m_m[QACR1] & 0x1C) << 24;
+ dest |= (m_qacr1 & 0x1C) << 24;
}
else
{
@@ -821,7 +1708,7 @@ inline void sh34_base_device::PREFM(const uint16_t opcode)
addr = addr & 0xFFFFFFE0;
}
- for (a = 0;a < 4;a++)
+ for (int a = 0; a < 4; a++)
{
// shouldn't be causing a memory read, should store sq writes in registers.
m_program->write_qword(dest, m_program->read_qword(addr));
@@ -843,37 +1730,42 @@ inline void sh34_base_device::PREFM(const uint16_t opcode)
/* FMOV @Rm+,XDn PR=1 1111nnn1mmmm1001 */
inline void sh34_base_device::FMOVMRIFR(const uint16_t opcode)
{
- uint32_t m = Rm; uint32_t n = Rn;
+ uint32_t m = REG_M;
+ uint32_t n = REG_N;
- if (m_sh2_state->m_fpu_sz) { /* SZ = 1 */
- if (n & 1) {
+ if (m_sh2_state->m_fpu_sz) /* SZ = 1 */
+ {
+ if (n & 1)
+ {
n &= 14;
#ifdef LSB_FIRST
n ^= m_sh2_state->m_fpu_pr;
#endif
m_sh2_state->ea = m_sh2_state->r[m];
- m_sh2_state->m_xf[n] = RL(m_sh2_state->ea);
+ m_sh2_state->m_xf[n] = read_long(m_sh2_state->ea);
m_sh2_state->r[m] += 4;
- m_sh2_state->m_xf[n ^ 1] = RL(m_sh2_state->ea + 4);
+ m_sh2_state->m_xf[n ^ 1] = read_long(m_sh2_state->ea + 4);
m_sh2_state->r[m] += 4;
}
- else {
+ else
+ {
#ifdef LSB_FIRST
n ^= m_sh2_state->m_fpu_pr;
#endif
m_sh2_state->ea = m_sh2_state->r[m];
- m_sh2_state->m_fr[n] = RL(m_sh2_state->ea);
+ m_sh2_state->m_fr[n] = read_long(m_sh2_state->ea);
m_sh2_state->r[m] += 4;
- m_sh2_state->m_fr[n ^ 1] = RL(m_sh2_state->ea + 4);
+ m_sh2_state->m_fr[n ^ 1] = read_long(m_sh2_state->ea + 4);
m_sh2_state->r[m] += 4;
}
}
- else { /* SZ = 0 */
+ else /* SZ = 0 */
+ {
m_sh2_state->ea = m_sh2_state->r[m];
#ifdef LSB_FIRST
n ^= m_sh2_state->m_fpu_pr;
#endif
- m_sh2_state->m_fr[n] = RL(m_sh2_state->ea);
+ m_sh2_state->m_fr[n] = read_long(m_sh2_state->ea);
m_sh2_state->r[m] += 4;
}
}
@@ -884,33 +1776,38 @@ inline void sh34_base_device::FMOVMRIFR(const uint16_t opcode)
/* FMOV XDm,@Rn PR=1 1111nnnnmmm11010 */
inline void sh34_base_device::FMOVFRMR(const uint16_t opcode)
{
- uint32_t m = Rm; uint32_t n = Rn;
+ uint32_t m = REG_M;
+ uint32_t n = REG_N;
- if (m_sh2_state->m_fpu_sz) { /* SZ = 1 */
- if (m & 1) {
+ if (m_sh2_state->m_fpu_sz) /* SZ = 1 */
+ {
+ if (m & 1)
+ {
m &= 14;
#ifdef LSB_FIRST
m ^= m_sh2_state->m_fpu_pr;
#endif
m_sh2_state->ea = m_sh2_state->r[n];
- WL(m_sh2_state->ea, m_sh2_state->m_xf[m]);
- WL(m_sh2_state->ea + 4, m_sh2_state->m_xf[m ^ 1]);
+ write_long(m_sh2_state->ea, m_sh2_state->m_xf[m]);
+ write_long(m_sh2_state->ea + 4, m_sh2_state->m_xf[m ^ 1]);
}
- else {
+ else
+ {
#ifdef LSB_FIRST
m ^= m_sh2_state->m_fpu_pr;
#endif
m_sh2_state->ea = m_sh2_state->r[n];
- WL(m_sh2_state->ea, m_sh2_state->m_fr[m]);
- WL(m_sh2_state->ea + 4, m_sh2_state->m_fr[m ^ 1]);
+ write_long(m_sh2_state->ea, m_sh2_state->m_fr[m]);
+ write_long(m_sh2_state->ea + 4, m_sh2_state->m_fr[m ^ 1]);
}
}
- else { /* SZ = 0 */
+ else /* SZ = 0 */
+ {
m_sh2_state->ea = m_sh2_state->r[n];
#ifdef LSB_FIRST
m ^= m_sh2_state->m_fpu_pr;
#endif
- WL(m_sh2_state->ea, m_sh2_state->m_fr[m]);
+ write_long(m_sh2_state->ea, m_sh2_state->m_fr[m]);
}
}
@@ -920,36 +1817,41 @@ inline void sh34_base_device::FMOVFRMR(const uint16_t opcode)
/* FMOV XDm,@-Rn PR=1 1111nnnnmmm11011 */
inline void sh34_base_device::FMOVFRMDR(const uint16_t opcode)
{
- uint32_t m = Rm; uint32_t n = Rn;
+ uint32_t m = REG_M;
+ uint32_t n = REG_N;
- if (m_sh2_state->m_fpu_sz) { /* SZ = 1 */
- if (m & 1) {
+ if (m_sh2_state->m_fpu_sz) /* SZ = 1 */
+ {
+ if (m & 1)
+ {
m &= 14;
#ifdef LSB_FIRST
m ^= m_sh2_state->m_fpu_pr;
#endif
m_sh2_state->r[n] -= 8;
m_sh2_state->ea = m_sh2_state->r[n];
- WL(m_sh2_state->ea, m_sh2_state->m_xf[m]);
- WL(m_sh2_state->ea + 4, m_sh2_state->m_xf[m ^ 1]);
+ write_long(m_sh2_state->ea, m_sh2_state->m_xf[m]);
+ write_long(m_sh2_state->ea + 4, m_sh2_state->m_xf[m ^ 1]);
}
- else {
+ else
+ {
#ifdef LSB_FIRST
m ^= m_sh2_state->m_fpu_pr;
#endif
m_sh2_state->r[n] -= 8;
m_sh2_state->ea = m_sh2_state->r[n];
- WL(m_sh2_state->ea, m_sh2_state->m_fr[m]);
- WL(m_sh2_state->ea + 4, m_sh2_state->m_fr[m ^ 1]);
+ write_long(m_sh2_state->ea, m_sh2_state->m_fr[m]);
+ write_long(m_sh2_state->ea + 4, m_sh2_state->m_fr[m ^ 1]);
}
}
- else { /* SZ = 0 */
+ else /* SZ = 0 */
+ {
m_sh2_state->r[n] -= 4;
m_sh2_state->ea = m_sh2_state->r[n];
#ifdef LSB_FIRST
m ^= m_sh2_state->m_fpu_pr;
#endif
- WL(m_sh2_state->ea, m_sh2_state->m_fr[m]);
+ write_long(m_sh2_state->ea, m_sh2_state->m_fr[m]);
}
}
@@ -959,33 +1861,38 @@ inline void sh34_base_device::FMOVFRMDR(const uint16_t opcode)
/* FMOV XDm,@(R0,Rn) PR=1 1111nnnnmmm10111 */
inline void sh34_base_device::FMOVFRS0(const uint16_t opcode)
{
- uint32_t m = Rm; uint32_t n = Rn;
+ uint32_t m = REG_M;
+ uint32_t n = REG_N;
- if (m_sh2_state->m_fpu_sz) { /* SZ = 1 */
- if (m & 1) {
+ if (m_sh2_state->m_fpu_sz) /* SZ = 1 */
+ {
+ if (m & 1)
+ {
m &= 14;
#ifdef LSB_FIRST
m ^= m_sh2_state->m_fpu_pr;
#endif
m_sh2_state->ea = m_sh2_state->r[0] + m_sh2_state->r[n];
- WL(m_sh2_state->ea, m_sh2_state->m_xf[m]);
- WL(m_sh2_state->ea + 4, m_sh2_state->m_xf[m ^ 1]);
+ write_long(m_sh2_state->ea, m_sh2_state->m_xf[m]);
+ write_long(m_sh2_state->ea + 4, m_sh2_state->m_xf[m ^ 1]);
}
- else {
+ else
+ {
#ifdef LSB_FIRST
m ^= m_sh2_state->m_fpu_pr;
#endif
m_sh2_state->ea = m_sh2_state->r[0] + m_sh2_state->r[n];
- WL(m_sh2_state->ea, m_sh2_state->m_fr[m]);
- WL(m_sh2_state->ea + 4, m_sh2_state->m_fr[m ^ 1]);
+ write_long(m_sh2_state->ea, m_sh2_state->m_fr[m]);
+ write_long(m_sh2_state->ea + 4, m_sh2_state->m_fr[m ^ 1]);
}
}
- else { /* SZ = 0 */
+ else /* SZ = 0 */
+ {
m_sh2_state->ea = m_sh2_state->r[0] + m_sh2_state->r[n];
#ifdef LSB_FIRST
m ^= m_sh2_state->m_fpu_pr;
#endif
- WL(m_sh2_state->ea, m_sh2_state->m_fr[m]);
+ write_long(m_sh2_state->ea, m_sh2_state->m_fr[m]);
}
}
@@ -995,33 +1902,38 @@ inline void sh34_base_device::FMOVFRS0(const uint16_t opcode)
/* FMOV @(R0,Rm),XDn PR=1 1111nnn1mmmm0110 */
inline void sh34_base_device::FMOVS0FR(const uint16_t opcode)
{
- uint32_t m = Rm; uint32_t n = Rn;
+ uint32_t m = REG_M;
+ uint32_t n = REG_N;
- if (m_sh2_state->m_fpu_sz) { /* SZ = 1 */
- if (n & 1) {
+ if (m_sh2_state->m_fpu_sz) /* SZ = 1 */
+ {
+ if (n & 1)
+ {
n &= 14;
#ifdef LSB_FIRST
n ^= m_sh2_state->m_fpu_pr;
#endif
m_sh2_state->ea = m_sh2_state->r[0] + m_sh2_state->r[m];
- m_sh2_state->m_xf[n] = RL(m_sh2_state->ea);
- m_sh2_state->m_xf[n ^ 1] = RL(m_sh2_state->ea + 4);
+ m_sh2_state->m_xf[n] = read_long(m_sh2_state->ea);
+ m_sh2_state->m_xf[n ^ 1] = read_long(m_sh2_state->ea + 4);
}
- else {
+ else
+ {
#ifdef LSB_FIRST
n ^= m_sh2_state->m_fpu_pr;
#endif
m_sh2_state->ea = m_sh2_state->r[0] + m_sh2_state->r[m];
- m_sh2_state->m_fr[n] = RL(m_sh2_state->ea);
- m_sh2_state->m_fr[n ^ 1] = RL(m_sh2_state->ea + 4);
+ m_sh2_state->m_fr[n] = read_long(m_sh2_state->ea);
+ m_sh2_state->m_fr[n ^ 1] = read_long(m_sh2_state->ea + 4);
}
}
- else { /* SZ = 0 */
+ else /* SZ = 0 */
+ {
m_sh2_state->ea = m_sh2_state->r[0] + m_sh2_state->r[m];
#ifdef LSB_FIRST
n ^= m_sh2_state->m_fpu_pr;
#endif
- m_sh2_state->m_fr[n] = RL(m_sh2_state->ea);
+ m_sh2_state->m_fr[n] = read_long(m_sh2_state->ea);
}
}
@@ -1032,33 +1944,38 @@ inline void sh34_base_device::FMOVS0FR(const uint16_t opcode)
/* FMOV @Rm,DRn PR=1 1111nnn0mmmm1000 */
inline void sh34_base_device::FMOVMRFR(const uint16_t opcode)
{
- uint32_t m = Rm; uint32_t n = Rn;
+ uint32_t m = REG_M;
+ uint32_t n = REG_N;
- if (m_sh2_state->m_fpu_sz) { /* SZ = 1 */
- if (n & 1) {
+ if (m_sh2_state->m_fpu_sz) /* SZ = 1 */
+ {
+ if (n & 1)
+ {
n &= 14;
#ifdef LSB_FIRST
n ^= m_sh2_state->m_fpu_pr;
#endif
m_sh2_state->ea = m_sh2_state->r[m];
- m_sh2_state->m_xf[n] = RL(m_sh2_state->ea);
- m_sh2_state->m_xf[n ^ 1] = RL(m_sh2_state->ea + 4);
+ m_sh2_state->m_xf[n] = read_long(m_sh2_state->ea);
+ m_sh2_state->m_xf[n ^ 1] = read_long(m_sh2_state->ea + 4);
}
- else {
+ else
+ {
#ifdef LSB_FIRST
n ^= m_sh2_state->m_fpu_pr;
#endif
m_sh2_state->ea = m_sh2_state->r[m];
- m_sh2_state->m_fr[n] = RL(m_sh2_state->ea);
- m_sh2_state->m_fr[n ^ 1] = RL(m_sh2_state->ea + 4);
+ m_sh2_state->m_fr[n] = read_long(m_sh2_state->ea);
+ m_sh2_state->m_fr[n ^ 1] = read_long(m_sh2_state->ea + 4);
}
}
- else { /* SZ = 0 */
+ else /* SZ = 0 */
+ {
m_sh2_state->ea = m_sh2_state->r[m];
#ifdef LSB_FIRST
n ^= m_sh2_state->m_fpu_pr;
#endif
- m_sh2_state->m_fr[n] = RL(m_sh2_state->ea);
+ m_sh2_state->m_fr[n] = read_long(m_sh2_state->ea);
}
}
@@ -1069,32 +1986,41 @@ inline void sh34_base_device::FMOVMRFR(const uint16_t opcode)
/* FMOV XDm,XDn PR=1 XDm -> XDn 1111nnn1mmm11100 */
inline void sh34_base_device::FMOVFR(const uint16_t opcode)
{
- uint32_t m = Rm; uint32_t n = Rn;
+ uint32_t m = REG_M;
+ uint32_t n = REG_N;
- if (m_sh2_state->m_fpu_sz == 0) { /* SZ = 0 */
+ if (m_sh2_state->m_fpu_sz == 0) /* SZ = 0 */
+ {
#ifdef LSB_FIRST
n ^= m_sh2_state->m_fpu_pr;
m ^= m_sh2_state->m_fpu_pr;
#endif
m_sh2_state->m_fr[n] = m_sh2_state->m_fr[m];
}
- else { /* SZ = 1 */
- if (m & 1) {
- if (n & 1) {
+ else /* SZ = 1 */
+ {
+ if (m & 1)
+ {
+ if (n & 1)
+ {
m_sh2_state->m_xf[n & 14] = m_sh2_state->m_xf[m & 14];
m_sh2_state->m_xf[n | 1] = m_sh2_state->m_xf[m | 1];
}
- else {
+ else
+ {
m_sh2_state->m_fr[n] = m_sh2_state->m_xf[m & 14];
m_sh2_state->m_fr[n | 1] = m_sh2_state->m_xf[m | 1];
}
}
- else {
- if (n & 1) {
+ else
+ {
+ if (n & 1)
+ {
m_sh2_state->m_xf[n & 14] = m_sh2_state->m_fr[m];
m_sh2_state->m_xf[n | 1] = m_sh2_state->m_fr[m | 1]; // (a&14)+1 -> a|1
}
- else {
+ else
+ {
m_sh2_state->m_fr[n] = m_sh2_state->m_fr[m];
m_sh2_state->m_fr[n | 1] = m_sh2_state->m_fr[m | 1];
}
@@ -1106,9 +2032,9 @@ inline void sh34_base_device::FMOVFR(const uint16_t opcode)
inline void sh34_base_device::FLDI1(const uint16_t opcode)
{
#ifdef LSB_FIRST
- m_sh2_state->m_fr[Rn ^ m_sh2_state->m_fpu_pr] = 0x3F800000;
+ m_sh2_state->m_fr[REG_N ^ m_sh2_state->m_fpu_pr] = 0x3F800000;
#else
- m_sh2_state->m_fr[Rn] = 0x3F800000;
+ m_sh2_state->m_fr[REG_N] = 0x3F800000;
#endif
}
@@ -1116,9 +2042,9 @@ inline void sh34_base_device::FLDI1(const uint16_t opcode)
inline void sh34_base_device::FLDI0(const uint16_t opcode)
{
#ifdef LSB_FIRST
- m_sh2_state->m_fr[Rn ^ m_sh2_state->m_fpu_pr] = 0;
+ m_sh2_state->m_fr[REG_N ^ m_sh2_state->m_fpu_pr] = 0;
#else
- m_sh2_state->m_fr[Rn] = 0;
+ m_sh2_state->m_fr[REG_N] = 0;
#endif
}
@@ -1126,9 +2052,9 @@ inline void sh34_base_device::FLDI0(const uint16_t opcode)
inline void sh34_base_device::FLDS(const uint16_t opcode)
{
#ifdef LSB_FIRST
- m_sh2_state->m_fpul = m_sh2_state->m_fr[Rn ^ m_sh2_state->m_fpu_pr];
+ m_sh2_state->m_fpul = m_sh2_state->m_fr[REG_N ^ m_sh2_state->m_fpu_pr];
#else
- m_sh2_state->m_fpul = m_sh2_state->m_fr[Rn];
+ m_sh2_state->m_fpul = m_sh2_state->m_fr[REG_N];
#endif
}
@@ -1136,9 +2062,9 @@ inline void sh34_base_device::FLDS(const uint16_t opcode)
inline void sh34_base_device::FSTS(const uint16_t opcode)
{
#ifdef LSB_FIRST
- m_sh2_state->m_fr[Rn ^ m_sh2_state->m_fpu_pr] = m_sh2_state->m_fpul;
+ m_sh2_state->m_fr[REG_N ^ m_sh2_state->m_fpu_pr] = m_sh2_state->m_fpul;
#else
- m_sh2_state->m_fr[Rn] = m_sh2_state->m_fpul;
+ m_sh2_state->m_fr[REG_N] = m_sh2_state->m_fpul;
#endif
}
@@ -1160,17 +2086,19 @@ void sh34_base_device::FSCHG()
/* FTRC DRm,FPUL PR=1 1111mmm000111101 */
inline void sh34_base_device::FTRC(const uint16_t opcode)
{
- uint32_t n = Rn;
+ uint32_t n = REG_N;
- if (m_sh2_state->m_fpu_pr) { /* PR = 1 */
+ if (m_sh2_state->m_fpu_pr) /* PR = 1 */
+ {
if (n & 1)
fatalerror("SH-4: FTRC opcode used with n %d", n);
n = n & 14;
*((int32_t *)&m_sh2_state->m_fpul) = (int32_t)FP_RFD(n);
}
- else { /* PR = 0 */
- /* read m_sh2_state->m_fr[n] as float -> truncate -> fpul(32) */
+ else /* PR = 0 */
+ {
+ /* read m_sh2_state->m_fr[n] as float -> truncate -> fpul(32) */
*((int32_t *)&m_sh2_state->m_fpul) = (int32_t)FP_RFS(n);
}
}
@@ -1179,16 +2107,18 @@ inline void sh34_base_device::FTRC(const uint16_t opcode)
/* FLOAT FPUL,DRn PR=1 1111nnn000101101 */
inline void sh34_base_device::FLOAT(const uint16_t opcode)
{
- uint32_t n = Rn;
+ uint32_t n = REG_N;
- if (m_sh2_state->m_fpu_pr) { /* PR = 1 */
+ if (m_sh2_state->m_fpu_pr) /* PR = 1 */
+ {
if (n & 1)
fatalerror("SH-4: FLOAT opcode used with n %d", n);
n = n & 14;
FP_RFD(n) = (double)*((int32_t *)&m_sh2_state->m_fpul);
}
- else { /* PR = 0 */
+ else /* PR = 0 */
+ {
FP_RFS(n) = (float)*((int32_t *)&m_sh2_state->m_fpul);
}
}
@@ -1197,12 +2127,14 @@ inline void sh34_base_device::FLOAT(const uint16_t opcode)
/* FNEG DRn PR=1 1111nnn001001101 */
inline void sh34_base_device::FNEG(const uint16_t opcode)
{
- uint32_t n = Rn;
+ uint32_t n = REG_N;
- if (m_sh2_state->m_fpu_pr) { /* PR = 1 */
+ if (m_sh2_state->m_fpu_pr) /* PR = 1 */
+ {
FP_RFD(n) = -FP_RFD(n);
}
- else { /* PR = 0 */
+ else /* PR = 0 */
+ {
FP_RFS(n) = -FP_RFS(n);
}
}
@@ -1211,9 +2143,10 @@ inline void sh34_base_device::FNEG(const uint16_t opcode)
/* FABS DRn PR=1 1111nnn001011101 */
inline void sh34_base_device::FABS(const uint16_t opcode)
{
- uint32_t n = Rn;
+ uint32_t n = REG_N;
- if (m_sh2_state->m_fpu_pr) { /* PR = 1 */
+ if (m_sh2_state->m_fpu_pr) /* PR = 1 */
+ {
#ifdef LSB_FIRST
n = n | 1; // n & 14 + 1
m_sh2_state->m_fr[n] = m_sh2_state->m_fr[n] & 0x7fffffff;
@@ -1222,7 +2155,8 @@ inline void sh34_base_device::FABS(const uint16_t opcode)
m_sh2_state->m_fr[n] = m_sh2_state->m_fr[n] & 0x7fffffff;
#endif
}
- else { /* PR = 0 */
+ else /* PR = 0 */
+ {
m_sh2_state->m_fr[n] = m_sh2_state->m_fr[n] & 0x7fffffff;
}
}
@@ -1231,9 +2165,11 @@ inline void sh34_base_device::FABS(const uint16_t opcode)
/* FCMP/EQ DRm,DRn PR=1 1111nnn0mmm00100 */
inline void sh34_base_device::FCMP_EQ(const uint16_t opcode)
{
- uint32_t m = Rm; uint32_t n = Rn;
+ uint32_t m = REG_M;
+ uint32_t n = REG_N;
- if (m_sh2_state->m_fpu_pr) { /* PR = 1 */
+ if (m_sh2_state->m_fpu_pr) /* PR = 1 */
+ {
n = n & 14;
m = m & 14;
if (FP_RFD(n) == FP_RFD(m))
@@ -1241,7 +2177,8 @@ inline void sh34_base_device::FCMP_EQ(const uint16_t opcode)
else
m_sh2_state->sr &= ~SH_T;
}
- else { /* PR = 0 */
+ else /* PR = 0 */
+ {
if (FP_RFS(n) == FP_RFS(m))
m_sh2_state->sr |= SH_T;
else
@@ -1253,9 +2190,11 @@ inline void sh34_base_device::FCMP_EQ(const uint16_t opcode)
/* FCMP/GT DRm,DRn PR=1 1111nnn0mmm00101 */
inline void sh34_base_device::FCMP_GT(const uint16_t opcode)
{
- uint32_t m = Rm; uint32_t n = Rn;
+ uint32_t m = REG_M;
+ uint32_t n = REG_N;
- if (m_sh2_state->m_fpu_pr) { /* PR = 1 */
+ if (m_sh2_state->m_fpu_pr) /* PR = 1 */
+ {
n = n & 14;
m = m & 14;
if (FP_RFD(n) > FP_RFD(m))
@@ -1263,7 +2202,8 @@ inline void sh34_base_device::FCMP_GT(const uint16_t opcode)
else
m_sh2_state->sr &= ~SH_T;
}
- else { /* PR = 0 */
+ else /* PR = 0 */
+ {
if (FP_RFS(n) > FP_RFS(m))
m_sh2_state->sr |= SH_T;
else
@@ -1274,9 +2214,10 @@ inline void sh34_base_device::FCMP_GT(const uint16_t opcode)
/* FCNVDS DRm,FPUL PR=1 1111mmm010111101 */
inline void sh34_base_device::FCNVDS(const uint16_t opcode)
{
- uint32_t n = Rn;
+ uint32_t n = REG_N;
- if (m_sh2_state->m_fpu_pr) { /* PR = 1 */
+ if (m_sh2_state->m_fpu_pr) /* PR = 1 */
+ {
n = n & 14;
if (m_sh2_state->m_fpscr & RM)
m_sh2_state->m_fr[n | NATIVE_ENDIAN_VALUE_LE_BE(0, 1)] &= 0xe0000000; /* round toward zero*/
@@ -1287,9 +2228,10 @@ inline void sh34_base_device::FCNVDS(const uint16_t opcode)
/* FCNVSD FPUL, DRn PR=1 1111nnn010101101 */
inline void sh34_base_device::FCNVSD(const uint16_t opcode)
{
- uint32_t n = Rn;
+ uint32_t n = REG_N;
- if (m_sh2_state->m_fpu_pr) { /* PR = 1 */
+ if (m_sh2_state->m_fpu_pr) /* PR = 1 */
+ {
n = n & 14;
FP_RFD(n) = (double)*((float *)&m_sh2_state->m_fpul);
}
@@ -1299,14 +2241,17 @@ inline void sh34_base_device::FCNVSD(const uint16_t opcode)
/* FADD DRm,DRn PR=1 1111nnn0mmm00000 */
inline void sh34_base_device::FADD(const uint16_t opcode)
{
- uint32_t m = Rm; uint32_t n = Rn;
+ uint32_t m = REG_M;
+ uint32_t n = REG_N;
- if (m_sh2_state->m_fpu_pr) { /* PR = 1 */
+ if (m_sh2_state->m_fpu_pr) /* PR = 1 */
+ {
n = n & 14;
m = m & 14;
FP_RFD(n) = FP_RFD(n) + FP_RFD(m);
}
- else { /* PR = 0 */
+ else /* PR = 0 */
+ {
FP_RFS(n) = FP_RFS(n) + FP_RFS(m);
}
}
@@ -1315,14 +2260,17 @@ inline void sh34_base_device::FADD(const uint16_t opcode)
/* FSUB DRm,DRn PR=1 1111nnn0mmm00001 */
inline void sh34_base_device::FSUB(const uint16_t opcode)
{
- uint32_t m = Rm; uint32_t n = Rn;
+ uint32_t m = REG_M;
+ uint32_t n = REG_N;
- if (m_sh2_state->m_fpu_pr) { /* PR = 1 */
+ if (m_sh2_state->m_fpu_pr) /* PR = 1 */
+ {
n = n & 14;
m = m & 14;
FP_RFD(n) = FP_RFD(n) - FP_RFD(m);
}
- else { /* PR = 0 */
+ else /* PR = 0 */
+ {
FP_RFS(n) = FP_RFS(n) - FP_RFS(m);
}
}
@@ -1332,14 +2280,17 @@ inline void sh34_base_device::FSUB(const uint16_t opcode)
/* FMUL DRm,DRn PR=1 1111nnn0mmm00010 */
inline void sh34_base_device::FMUL(const uint16_t opcode)
{
- uint32_t m = Rm; uint32_t n = Rn;
+ uint32_t m = REG_M;
+ uint32_t n = REG_N;
- if (m_sh2_state->m_fpu_pr) { /* PR = 1 */
+ if (m_sh2_state->m_fpu_pr) /* PR = 1 */
+ {
n = n & 14;
m = m & 14;
FP_RFD(n) = FP_RFD(n) * FP_RFD(m);
}
- else { /* PR = 0 */
+ else /* PR = 0 */
+ {
FP_RFS(n) = FP_RFS(n) * FP_RFS(m);
}
}
@@ -1348,16 +2299,19 @@ inline void sh34_base_device::FMUL(const uint16_t opcode)
/* FDIV DRm,DRn PR=1 1111nnn0mmm00011 */
inline void sh34_base_device::FDIV(const uint16_t opcode)
{
- uint32_t m = Rm; uint32_t n = Rn;
+ uint32_t m = REG_M;
+ uint32_t n = REG_N;
- if (m_sh2_state->m_fpu_pr) { /* PR = 1 */
+ if (m_sh2_state->m_fpu_pr) /* PR = 1 */
+ {
n = n & 14;
m = m & 14;
if (FP_RFD(m) == 0)
return;
FP_RFD(n) = FP_RFD(n) / FP_RFD(m);
}
- else { /* PR = 0 */
+ else /* PR = 0 */
+ {
if (FP_RFS(m) == 0)
return;
FP_RFS(n) = FP_RFS(n) / FP_RFS(m);
@@ -1367,9 +2321,11 @@ inline void sh34_base_device::FDIV(const uint16_t opcode)
/* FMAC FR0,FRm,FRn PR=0 1111nnnnmmmm1110 */
inline void sh34_base_device::FMAC(const uint16_t opcode)
{
- uint32_t m = Rm; uint32_t n = Rn;
+ uint32_t m = REG_M;
+ uint32_t n = REG_N;
- if (m_sh2_state->m_fpu_pr == 0) { /* PR = 0 */
+ if (m_sh2_state->m_fpu_pr == 0) /* PR = 0 */
+ {
FP_RFS(n) = (FP_RFS(0) * FP_RFS(m)) + FP_RFS(n);
}
}
@@ -1378,15 +2334,17 @@ inline void sh34_base_device::FMAC(const uint16_t opcode)
/* FSQRT DRn PR=1 1111nnnn01101101 */
inline void sh34_base_device::FSQRT(const uint16_t opcode)
{
- uint32_t n = Rn;
+ uint32_t n = REG_N;
- if (m_sh2_state->m_fpu_pr) { /* PR = 1 */
+ if (m_sh2_state->m_fpu_pr) /* PR = 1 */
+ {
n = n & 14;
if (FP_RFD(n) < 0)
return;
FP_RFD(n) = sqrtf(FP_RFD(n));
}
- else { /* PR = 0 */
+ else /* PR = 0 */
+ {
if (FP_RFS(n) < 0)
return;
FP_RFS(n) = sqrtf(FP_RFS(n));
@@ -1396,7 +2354,7 @@ inline void sh34_base_device::FSQRT(const uint16_t opcode)
/* FSRRA FRn PR=0 1111nnnn01111101 */
inline void sh34_base_device::FSRRA(const uint16_t opcode)
{
- uint32_t n = Rn;
+ uint32_t n = REG_N;
if (FP_RFS(n) < 0)
return;
@@ -1406,11 +2364,9 @@ inline void sh34_base_device::FSRRA(const uint16_t opcode)
/* FSSCA FPUL,FRn PR=0 1111nnn011111101 */
void sh34_base_device::FSSCA(const uint16_t opcode)
{
- uint32_t n = Rn;
+ uint32_t n = REG_N;
- float angle;
-
- angle = (((float)(m_sh2_state->m_fpul & 0xFFFF)) / 65536.0f) * 2.0f * (float)M_PI;
+ float angle = (((float)(m_sh2_state->m_fpul & 0xFFFF)) / 65536.0f) * 2.0f * (float)M_PI;
FP_RFS(n) = sinf(angle);
FP_RFS(n + 1) = cosf(angle);
}
@@ -1418,15 +2374,12 @@ void sh34_base_device::FSSCA(const uint16_t opcode)
/* FIPR FVm,FVn PR=0 1111nnmm11101101 */
inline void sh34_base_device::FIPR(const uint16_t opcode)
{
- uint32_t n = Rn;
+ uint32_t n = REG_N;
+ uint32_t m = (n & 3) << 2;
+ n = n & 12;
- uint32_t m;
float ml[4];
- int a;
-
- m = (n & 3) << 2;
- n = n & 12;
- for (a = 0;a < 4;a++)
+ for (int a = 0; a < 4; a++)
ml[a] = FP_RFS(n + a) * FP_RFS(m + a);
FP_RFS(n + 3) = ml[0] + ml[1] + ml[2] + ml[3];
}
@@ -1434,25 +2387,26 @@ inline void sh34_base_device::FIPR(const uint16_t opcode)
/* FTRV XMTRX,FVn PR=0 1111nn0111111101 */
void sh34_base_device::FTRV(const uint16_t opcode)
{
- uint32_t n = Rn;
+ uint32_t n = REG_N;
+ n = n & 12;
- int i, j;
float sum[4];
-
- n = n & 12;
- for (i = 0;i < 4;i++) {
+ for (int i = 0; i < 4; i++)
+ {
sum[i] = 0;
- for (j = 0;j < 4;j++)
+ for (int j = 0; j < 4; j++)
sum[i] += FP_XFS((j << 2) + i)*FP_RFS(n + j);
}
- for (i = 0;i < 4;i++)
+ for (int i = 0; i < 4; i++)
FP_RFS(n + i) = sum[i];
}
inline void sh34_base_device::op1111_0xf13(const uint16_t opcode)
{
- if (opcode & 0x100) {
- if (opcode & 0x200) {
+ if (opcode & 0x100)
+ {
+ if (opcode & 0x200)
+ {
switch (opcode & 0xC00)
{
case 0x000:
@@ -1466,11 +2420,13 @@ inline void sh34_base_device::op1111_0xf13(const uint16_t opcode)
break;
}
}
- else {
+ else
+ {
FTRV(opcode);
}
}
- else {
+ else
+ {
FSSCA(opcode);
}
}
@@ -1531,45 +2487,80 @@ void sh34_base_device::device_reset()
m_sh2_state->m_test_irq = 0;
memset(m_exception_priority, 0, sizeof(m_exception_priority));
memset(m_exception_requesting, 0, sizeof(m_exception_requesting));
- memset(m_m, 0, sizeof(m_m));
- memset(m_sh3internal_upper, 0, sizeof(m_sh3internal_upper));
- memset(m_sh3internal_lower, 0, sizeof(m_sh3internal_lower));
memset(m_irq_line_state, 0, sizeof(m_irq_line_state));
- m_SH4_TSTR = 0;
- m_SH4_TCNT0 = 0;
- m_SH4_TCNT1 = 0;
- m_SH4_TCNT2 = 0;
- m_SH4_TCR0 = 0;
- m_SH4_TCR1 = 0;
- m_SH4_TCR2 = 0;
- m_SH4_TCOR0 = 0;
- m_SH4_TCOR1 = 0;
- m_SH4_TCOR2 = 0;
- m_SH4_TOCR = 0;
- m_SH4_TCPR2 = 0;
- m_SH4_IPRA = 0;
- m_SH4_IPRC = 0;
- m_SH4_SAR0 = 0;
- m_SH4_SAR1 = 0;
- m_SH4_SAR2 = 0;
- m_SH4_SAR3 = 0;
- m_SH4_DAR0 = 0;
- m_SH4_DAR1 = 0;
- m_SH4_DAR2 = 0;
- m_SH4_DAR3 = 0;
- m_SH4_CHCR0 = 0;
- m_SH4_CHCR1 = 0;
- m_SH4_CHCR2 = 0;
- m_SH4_CHCR3 = 0;
- m_SH4_DMATCR0 = 0;
- m_SH4_DMATCR1 = 0;
- m_SH4_DMATCR2 = 0;
- m_SH4_DMATCR3 = 0;
- m_SH4_DMAOR = 0;
+
+ // CCN
+ m_pteh = 0;
+ m_ptel = 0;
+ m_ttb = 0;
+ m_mmucr = 0;
+ m_ccr = 0;
+ m_tra = 0;
+ m_expevt = 0;
+ m_intevt = 0;
+
+ // CCN 7709S
+ m_ccr2 = 0;
+
+ // CCN 7091
+ m_ptea = 0;
+ m_qacr0 = 0;
+ m_qacr1 = 0;
+
+ // TMU
+ m_tocr = 0;
+ m_tstr = 0;
+ m_tcor0 = 0xffffffff;
+ m_tcnt0 = 0xffffffff;
+ m_tcr0 = 0;
+ m_tcor1 = 0xffffffff;
+ m_tcnt1 = 0xffffffff;
+ m_tcr1 = 0;
+ m_tcor2 = 0xffffffff;
+ m_tcnt2 = 0xffffffff;
+ m_tcr2 = 0;
+ m_tcpr2 = 0;
+
+ // INTC
+ m_icr = 0;
+ m_ipra = 0;
+ m_iprc = 0;
+
+ // INTC 7709
+ m_intevt2 = 0;
+
+ // DMAC
+ m_sar0 = 0;
+ m_sar1 = 0;
+ m_sar2 = 0;
+ m_sar3 = 0;
+ m_dar0 = 0;
+ m_dar1 = 0;
+ m_dar2 = 0;
+ m_dar3 = 0;
+ m_chcr0 = 0;
+ m_chcr1 = 0;
+ m_chcr2 = 0;
+ m_chcr3 = 0;
+ m_dmatcr0 = 0;
+ m_dmatcr1 = 0;
+ m_dmatcr2 = 0;
+ m_dmatcr3 = 0;
+ m_dmaor = 0;
+
m_nmi_line_state = 0;
m_sh2_state->m_frt_input = 0;
m_internal_irq_vector = 0;
- m_refresh_timer_base = 0;
+ for (int i = 0; i < 3; i++)
+ {
+ if (m_timer[i])
+ m_timer[i]->adjust(attotime::never, i);
+ }
+ for (int i = 0; i < 4; i++)
+ {
+ if (m_dma_timer[i])
+ m_dma_timer[i]->adjust(attotime::never, i);
+ }
memset(m_dma_timer_active, 0, sizeof(m_dma_timer_active));
memset(m_dma_source, 0, sizeof(m_dma_source));
memset(m_dma_destination, 0, sizeof(m_dma_destination));
@@ -1585,11 +2576,9 @@ void sh34_base_device::device_reset()
sh4_default_exception_priorities();
- m_rtc_timer->adjust(attotime::from_hz(128));
-
m_sh2_state->pc = 0xa0000000;
- m_sh2_state->m_ppc = m_sh2_state->pc & SH34_AM;
- m_sh2_state->r[15] = RL(4);
+ m_sh2_state->m_ppc = m_sh2_state->pc;
+ m_sh2_state->r[15] = read_long(4);
m_sh2_state->sr = 0x700000f0;
m_sh2_state->m_fpscr = 0x00040001;
m_sh2_state->m_fpu_sz = (m_sh2_state->m_fpscr & SZ) ? 1 : 0;
@@ -1601,7 +2590,7 @@ void sh34_base_device::device_reset()
m_irln = 15;
m_sh2_state->sleep_mode = 0;
- m_sh4_mmu_enabled = 0;
+ m_sh4_mmu_enabled = false;
m_cache_dirty = true;
}
@@ -1613,25 +2602,158 @@ void sh3_base_device::device_reset()
{
sh34_base_device::device_reset();
- m_SH4_TCOR0 = 0xffffffff;
- m_SH4_TCNT0 = 0xffffffff;
- m_SH4_TCOR1 = 0xffffffff;
- m_SH4_TCNT1 = 0xffffffff;
- m_SH4_TCOR2 = 0xffffffff;
- m_SH4_TCNT2 = 0xffffffff;
+ // INTC
+ m_icr0 &= 0x8000;
+ m_iprb = 0;
+
+ // INTC 7709
+ m_irr0 = 0;
+ m_irr1 = 0;
+ m_irr2 = 0;
+ m_icr1 = 0;
+ m_icr2 = 0;
+ m_pinter = 0;
+ m_iprd = 0;
+ m_ipre = 0;
+
+ // SCI
+ m_scsmr = 0;
+ m_scbrr = 0xff;
+ m_scscr = 0;
+ m_sctdr = 0xff;
+ m_scssr = 0x84;
+ m_scrdr = 0;
+ m_scscmr = 0;
+
+ // SCI 7709
+ m_scsptr = 0;
+
+ // CMT 7709
+ m_cmstr = 0;
+ m_cmscr = 0;
+ m_cmcnt = 0;
+ m_cmcor = 0xffff;
+
+ // AD 7709
+ m_addrah = 0;
+ m_addral = 0;
+ m_addrbh = 0;
+ m_addrbl = 0;
+ m_addrch = 0;
+ m_addrcl = 0;
+ m_addrdh = 0;
+ m_addrdl = 0;
+ m_adcsr = 0;
+ m_adcr = 0x07;
+
+ // DA 7709
+ m_dadr0 = 0;
+ m_dadr1 = 0;
+ m_dadcr = 0x1f;
+
+ // PORT 7709
+ m_pacr = 0;
+ m_pbcr = 0;
+ m_pccr = 0xaaaa;
+ m_pdcr = 0xaa8a;
+ m_pecr = 0xaaaa; // asemd0=0x2aa8
+ m_pfcr = 0xaaaa; // asemd0=0x00aa
+ m_pgcr = 0xaaaa; // asemd0=0xa200
+ m_phcr = 0xaaaa; // asemd0=0x8aaa
+ m_pjcr = 0;
+ m_pkcr = 0;
+ m_plcr = 0;
+ m_scpcr = 0xa888;
+ m_padr = 0;
+ m_pbdr = 0;
+ m_pcdr = 0;
+ m_pddr = 0;
+ m_pedr = 0;
+ m_pfdr = 0;
+ m_pgdr = 0;
+ m_phdr = 0;
+ m_pjdr = 0;
+ m_pkdr = 0;
+ m_pldr = 0;
+ m_scpdr = 0;
+
+ // IRDA 7709
+ m_scsmr1 = 0;
+ m_scbrr1 = 0xff;
+ m_scscr1 = 0;
+ m_scftdr1 = 0;
+ m_scssr1 = 0x60;
+ m_scfrdr1 = 0;
+ m_scfcr1 = 0;
+ m_scfdr1 = 0;
+
+ // SCIF 7709
+ m_scsmr2 = 0;
+ m_scbrr2 = 0xff;
+ m_scscr2 = 0;
+ m_scftdr2 = 0;
+ m_scssr2 = 0x60;
+ m_scfrdr2 = 0;
+ m_scfcr2 = 0;
+ m_scfdr2 = 0;
+
+ // UDI 7709S
+ m_sdir = 0xffff;
}
void sh4_base_device::device_reset()
{
sh34_base_device::device_reset();
- m_m[RCR2] = 0x09;
- m_SH4_TCOR0 = 0xffffffff;
- m_SH4_TCNT0 = 0xffffffff;
- m_SH4_TCOR1 = 0xffffffff;
- m_SH4_TCNT1 = 0xffffffff;
- m_SH4_TCOR2 = 0xffffffff;
- m_SH4_TCNT2 = 0xffffffff;
+ m_rtc_timer->adjust(attotime::from_hz(128));
+ m_refresh_timer->adjust(attotime::never);
+ m_refresh_timer_base = 0;
+
+ // DMAC 7750R
+ m_sar4 = 0;
+ m_dar4 = 0;
+ m_sar5 = 0;
+ m_dar5 = 0;
+ m_sar6 = 0;
+ m_dar6 = 0;
+ m_sar7 = 0;
+ m_dar7 = 0;
+ m_chcr4 = 0;
+ m_chcr5 = 0;
+ m_chcr6 = 0;
+ m_chcr7 = 0;
+ m_dmatcr4 = 0;
+ m_dmatcr5 = 0;
+ m_dmatcr6 = 0;
+ m_dmatcr7 = 0;
+
+ // INTC
+ m_iprb = 0;
+
+ // INTC 7750S
+ m_iprd = 0xda74;
+
+ // SCI
+ m_scsmr1 = 0;
+ m_scbrr1 = 0xff;
+ m_scscr1 = 0;
+ m_sctdr1 = 0xff;
+ m_scssr1 = 0x84;
+ m_scrdr1 = 0x00;
+ m_scscmr1 = 0x00;
+ m_scsptr1 = 0;
+
+ // SCIF
+ m_scsmr2 = 0;
+ m_scbrr2 = 0xff;
+ m_scscr2 = 0;
+ m_scftdr2 = 0;
+ m_scfsr2 = 0x60;
+ m_scfrdr2 = 0;
+ m_scfcr2 = 0;
+ m_scfdr2 = 0;
+ m_scsptr2 = 0;
+ m_sclsr2 = 0;
}
inline void sh34_base_device::execute_one_0000(const uint16_t opcode)
@@ -1855,7 +2977,7 @@ inline void sh34_base_device::execute_one_f000(const uint16_t opcode)
/* Execute cycles - returns number of cycles actually run */
void sh34_base_device::execute_run()
{
- if ( m_isdrc )
+ if (m_isdrc)
{
execute_run_drc();
return;
@@ -1863,19 +2985,20 @@ void sh34_base_device::execute_run()
if (m_sh2_state->m_cpu_off)
{
+ debugger_wait_hook();
m_sh2_state->icount = 0;
return;
}
do
{
- m_sh2_state->m_ppc = m_sh2_state->pc & SH34_AM;
- debugger_instruction_hook(m_sh2_state->pc & SH34_AM);
+ m_sh2_state->m_ppc = m_sh2_state->pc;
+ debugger_instruction_hook(m_sh2_state->pc);
uint16_t opcode;
if (!m_sh4_mmu_enabled) opcode = m_pr16(m_sh2_state->pc & SH34_AM);
- else opcode = RW(m_sh2_state->pc); // should probably use a different function as this needs to go through the ITLB
+ else opcode = read_word(m_sh2_state->pc); // should probably use a different function as this needs to go through the ITLB
if (m_sh2_state->m_delay)
{
@@ -1896,90 +3019,265 @@ void sh34_base_device::execute_run()
} while (m_sh2_state->icount > 0);
}
-void sh3be_device::execute_run()
+void sh3_base_device::device_start()
{
- if ( m_isdrc )
- {
- execute_run_drc();
- return;
- }
-
- if (m_sh2_state->m_cpu_off)
- {
- m_sh2_state->icount = 0;
- return;
- }
-
- do
- {
- m_sh2_state->m_ppc = m_sh2_state->pc & SH34_AM;
- debugger_instruction_hook(m_sh2_state->pc & SH34_AM);
-
- const uint16_t opcode = m_pr16(m_sh2_state->pc & SH34_AM);
-
- if (m_sh2_state->m_delay)
- {
- m_sh2_state->pc = m_sh2_state->m_delay;
- m_sh2_state->m_delay = 0;
- }
- else
- m_sh2_state->pc += 2;
-
- execute_one(opcode);
-
- if (m_sh2_state->m_test_irq && !m_sh2_state->m_delay)
- {
- sh4_check_pending_irq("mame_sh4_execute");
- }
-
- m_sh2_state->icount--;
- } while (m_sh2_state->icount > 0);
-}
-
-void sh4be_device::execute_run()
-{
- if ( m_isdrc )
- {
- execute_run_drc();
- return;
- }
-
- if (m_sh2_state->m_cpu_off)
- {
- m_sh2_state->icount = 0;
- return;
- }
-
- do
- {
- m_sh2_state->m_ppc = m_sh2_state->pc & SH34_AM;
- debugger_instruction_hook(m_sh2_state->pc & SH34_AM);
-
- const uint16_t opcode = m_pr16(m_sh2_state->pc & SH34_AM);
-
- if (m_sh2_state->m_delay)
- {
- m_sh2_state->pc = m_sh2_state->m_delay;
- m_sh2_state->m_delay = 0;
- }
- else
- m_sh2_state->pc += 2;
-
- execute_one(opcode);
-
- if (m_sh2_state->m_test_irq && !m_sh2_state->m_delay)
- {
- sh4_check_pending_irq("mame_sh4_execute");
- }
+ sh34_base_device::device_start();
- m_sh2_state->icount--;
- } while (m_sh2_state->icount > 0);
+ // UBC
+ m_bara = 0;
+ m_bamra = 0;
+ m_bbra = 0;
+ m_barb = 0;
+ m_bamrb = 0;
+ m_bbrb = 0;
+ m_bdrb = 0;
+ m_bdmrb = 0;
+ m_brcr = 0;
+
+ // UBC 7709S
+ m_betr = 0;
+ m_brsr = 0;
+ m_brdr = 0;
+
+ // CPG
+ m_frqcr = 0x0102;
+ m_wtcnt = 0;
+ m_wtcsr = 0;
+ m_stbcr = 0;
+
+ // CPG 7709
+ m_stbcr2 = 0;
+
+ // BSC
+ m_bcr1 = 0;
+ m_bcr2 = 0x3ff0;
+ m_wcr1 = 0x3ff3;
+ m_wcr2 = 0xffff;
+ m_mcr = 0;
+ m_pcr = 0;
+ m_rtcsr = 0;
+ m_rtcnt = 0;
+ m_rtcor = 0;
+ m_rfcr = 0;
+
+ // BSC 7708
+ m_dcr = 0;
+ m_pctr = 0;
+ m_pdtr = 0;
+
+ // BSC 7709
+ m_bcr3 = 0;
+
+ // BSC 7709S
+ m_mcscr0 = 0;
+ m_mcscr1 = 0;
+ m_mcscr2 = 0;
+ m_mcscr3 = 0;
+ m_mcscr4 = 0;
+ m_mcscr5 = 0;
+ m_mcscr6 = 0;
+ m_mcscr7 = 0;
+
+ // RTC
+ m_r64cnt = 0;
+ m_rseccnt = 0;
+ m_rmincnt = 0;
+ m_rhrcnt = 0;
+ m_rwkcnt = 0;
+ m_rmoncnt = 0;
+ m_rdaycnt = 0;
+ m_ryrcnt = 0;
+ m_rsecar = 0;
+ m_rminar = 0;
+ m_rhrar = 0;
+ m_rwkar = 0;
+ m_rdayar = 0;
+ m_rmonar = 0;
+ m_rcr1 = 0;
+ m_rcr2 = 0x09;
+
+ // INTC
+ m_icr0 = 0;
+
+ // UBC
+ save_item(NAME(m_bara));
+ save_item(NAME(m_bamra));
+ save_item(NAME(m_bbra));
+ save_item(NAME(m_barb));
+ save_item(NAME(m_bamrb));
+ save_item(NAME(m_bbrb));
+ save_item(NAME(m_bdrb));
+ save_item(NAME(m_bdmrb));
+ save_item(NAME(m_brcr));
+
+ // UBC 7709S
+ save_item(NAME(m_betr));
+ save_item(NAME(m_brsr));
+ save_item(NAME(m_brdr));
+
+ // CPG
+ save_item(NAME(m_frqcr));
+ save_item(NAME(m_stbcr));
+ save_item(NAME(m_wtcnt));
+ save_item(NAME(m_wtcsr));
+
+ // CPG 7709
+ save_item(NAME(m_stbcr2));
+
+ // BSC
+ save_item(NAME(m_bcr1));
+ save_item(NAME(m_bcr2));
+ save_item(NAME(m_wcr1));
+ save_item(NAME(m_wcr2));
+ save_item(NAME(m_mcr));
+ save_item(NAME(m_pcr));
+ save_item(NAME(m_rtcsr));
+ save_item(NAME(m_rtcnt));
+ save_item(NAME(m_rtcor));
+ save_item(NAME(m_rfcr));
+
+ // BSC 7708
+ save_item(NAME(m_dcr));
+ save_item(NAME(m_pctr));
+ save_item(NAME(m_pdtr));
+
+ // BSC 7709
+ save_item(NAME(m_bcr3));
+
+ // BSC 7709S
+ save_item(NAME(m_mcscr0));
+ save_item(NAME(m_mcscr1));
+ save_item(NAME(m_mcscr2));
+ save_item(NAME(m_mcscr3));
+ save_item(NAME(m_mcscr4));
+ save_item(NAME(m_mcscr5));
+ save_item(NAME(m_mcscr6));
+ save_item(NAME(m_mcscr7));
+
+ // RTC
+ save_item(NAME(m_r64cnt));
+ save_item(NAME(m_rseccnt));
+ save_item(NAME(m_rmincnt));
+ save_item(NAME(m_rhrcnt));
+ save_item(NAME(m_rwkcnt));
+ save_item(NAME(m_rmoncnt));
+ save_item(NAME(m_rdaycnt));
+ save_item(NAME(m_ryrcnt));
+ save_item(NAME(m_rsecar));
+ save_item(NAME(m_rminar));
+ save_item(NAME(m_rhrar));
+ save_item(NAME(m_rwkar));
+ save_item(NAME(m_rdayar));
+ save_item(NAME(m_rmonar));
+ save_item(NAME(m_rcr1));
+ save_item(NAME(m_rcr2));
+
+ // INTC
+ save_item(NAME(m_icr0));
+ save_item(NAME(m_iprb));
+
+ // INTC 7709
+ save_item(NAME(m_irr0));
+ save_item(NAME(m_irr1));
+ save_item(NAME(m_irr2));
+ save_item(NAME(m_icr1));
+ save_item(NAME(m_icr2));
+ save_item(NAME(m_pinter));
+ save_item(NAME(m_iprd));
+ save_item(NAME(m_ipre));
+
+ // SCI
+ save_item(NAME(m_scsmr));
+ save_item(NAME(m_scbrr));
+ save_item(NAME(m_scscr));
+ save_item(NAME(m_sctdr));
+ save_item(NAME(m_scssr));
+ save_item(NAME(m_scrdr));
+ save_item(NAME(m_scscmr));
+
+ // SCI 7709
+ save_item(NAME(m_scsptr));
+
+ // CMT 7709
+ save_item(NAME(m_cmstr));
+ save_item(NAME(m_cmscr));
+ save_item(NAME(m_cmcnt));
+ save_item(NAME(m_cmcor));
+
+ // AD 7709
+ save_item(NAME(m_addrah));
+ save_item(NAME(m_addral));
+ save_item(NAME(m_addrbh));
+ save_item(NAME(m_addrbl));
+ save_item(NAME(m_addrch));
+ save_item(NAME(m_addrcl));
+ save_item(NAME(m_addrdh));
+ save_item(NAME(m_addrdl));
+ save_item(NAME(m_adcsr));
+ save_item(NAME(m_adcr));
+
+ // DA 7709
+ save_item(NAME(m_dadr0));
+ save_item(NAME(m_dadr1));
+ save_item(NAME(m_dadcr));
+
+ // PORT 7709
+ save_item(NAME(m_pacr));
+ save_item(NAME(m_pbcr));
+ save_item(NAME(m_pccr));
+ save_item(NAME(m_pdcr));
+ save_item(NAME(m_pecr));
+ save_item(NAME(m_pfcr));
+ save_item(NAME(m_pgcr));
+ save_item(NAME(m_phcr));
+ save_item(NAME(m_pjcr));
+ save_item(NAME(m_pkcr));
+ save_item(NAME(m_plcr));
+ save_item(NAME(m_scpcr));
+ save_item(NAME(m_padr));
+ save_item(NAME(m_pbdr));
+ save_item(NAME(m_pcdr));
+ save_item(NAME(m_pddr));
+ save_item(NAME(m_pedr));
+ save_item(NAME(m_pfdr));
+ save_item(NAME(m_pgdr));
+ save_item(NAME(m_phdr));
+ save_item(NAME(m_pjdr));
+ save_item(NAME(m_pkdr));
+ save_item(NAME(m_pldr));
+ save_item(NAME(m_scpdr));
+
+ // IRDA 7709
+ save_item(NAME(m_scsmr1));
+ save_item(NAME(m_scbrr1));
+ save_item(NAME(m_scscr1));
+ save_item(NAME(m_scftdr1));
+ save_item(NAME(m_scssr1));
+ save_item(NAME(m_scfrdr1));
+ save_item(NAME(m_scfcr1));
+ save_item(NAME(m_scfdr1));
+
+ // SCIF 7709
+ save_item(NAME(m_scsmr2));
+ save_item(NAME(m_scbrr2));
+ save_item(NAME(m_scscr2));
+ save_item(NAME(m_scftdr2));
+ save_item(NAME(m_scssr2));
+ save_item(NAME(m_scfrdr2));
+ save_item(NAME(m_scfcr2));
+ save_item(NAME(m_scfdr2));
+
+ // UDI 7709S
+ save_item(NAME(m_sdir));
}
void sh4_base_device::device_start()
{
sh34_base_device::device_start();
+ m_rtc_timer = timer_alloc(FUNC(sh4_base_device::sh4_rtc_timer_callback), this);
+ m_refresh_timer = timer_alloc(FUNC(sh4_base_device::sh4_refresh_timer_callback), this);
+
int i;
for (i = 0;i < 64;i++)
{
@@ -1997,6 +3295,156 @@ void sh4_base_device::device_start()
m_utlb[i].TC = 0;
}
+ // UBC
+ m_bara = 0;
+ m_bamra = 0;
+ m_bbra = 0;
+ m_barb = 0;
+ m_bamrb = 0;
+ m_bbrb = 0;
+ m_bdrb = 0;
+ m_bdmrb = 0;
+ m_brcr = 0;
+
+ // BSC
+ m_bcr1 = 0;
+ m_bcr2 = 0;
+ m_wcr1 = 0;
+ m_wcr2 = 0;
+ m_wcr3 = 0;
+ m_mcr = 0;
+ m_pcr = 0;
+ m_rtcsr = 0;
+ m_rtcnt = 0;
+ m_rtcor = 0;
+ m_rfcr = 0;
+ m_pctra = 0;
+ m_pdtra = 0;
+ m_pctrb = 0;
+ m_pdtrb = 0;
+ m_gpioic = 0;
+
+ // BSC 7750R
+ m_bcr3 = 0;
+ m_bcr4 = 0;
+
+ // CPG
+ m_frqcr = 0;
+ m_stbcr = 0;
+ m_wtcnt = 0;
+ m_wtcsr = 0;
+ m_stbcr2 = 0;
+
+ // RTC
+ m_r64cnt = 0;
+ m_rseccnt = 0;
+ m_rmincnt = 0;
+ m_rhrcnt = 0;
+ m_rwkcnt = 0;
+ m_rmoncnt = 0;
+ m_rdaycnt = 0;
+ m_ryrcnt = 0;
+ m_rsecar = 0;
+ m_rminar = 0;
+ m_rhrar = 0;
+ m_rwkar = 0;
+ m_rdayar = 0;
+ m_rmonar = 0;
+ m_rcr1 = 0;
+ m_rcr2 = 0x09;
+
+ // RTC 7750R
+ m_rcr3 = 0;
+ m_ryrar = 0;
+
+ // INTC 7750R
+ m_intpri00 = 0;
+ m_intreq00 = 0;
+ m_intmsk00 = 0x000003ff;
+
+ // CPG 7750R
+ m_clkstp00 = 0;
+
+ // TMU 7750R
+ m_tstr2 = 0;
+ m_tcor3 = 0xffffffff;
+ m_tcnt3 = 0xffffffff;
+ m_tcr3 = 0;
+ m_tcor4 = 0xffffffff;
+ m_tcnt4 = 0xffffffff;
+ m_tcr4 = 0;
+
+ // PCI 7751
+ m_pciconf1 = 0x02900080;
+ m_pciconf2 = 0;
+ m_pciconf3 = 0;
+ m_pciconf4 = 1;
+ m_pciconf5 = 0;
+ m_pciconf6 = 0;
+ m_pciconf7 = 0;
+ m_pciconf8 = 0;
+ m_pciconf9 = 0;
+ m_pciconf10 = 0;
+ m_pciconf11 = 0;
+ m_pciconf12 = 0;
+ m_pciconf13 = 0x00000040;
+ m_pciconf14 = 0;
+ m_pciconf15 = 0x00000100;
+ m_pciconf16 = 0x00010001;
+ m_pciconf17 = 0;
+ m_pcicr = 0;
+ m_pcilsr0 = 0;
+ m_pcilsr1 = 0;
+ m_pcilar0 = 0;
+ m_pcilar1 = 0;
+ m_pciint = 0;
+ m_pciintm = 0;
+ m_pcialr = 0;
+ m_pciclr = 0;
+ m_pciaint = 0;
+ m_pciaintm = 0;
+ m_pcibllr = 0;
+ m_pcidmabt = 0;
+ m_pcidpa0 = 0;
+ m_pcidla0 = 0;
+ m_pcidtc0 = 0;
+ m_pcidcr0 = 0;
+ m_pcidpa1 = 0;
+ m_pcidla1 = 0;
+ m_pcidtc1 = 0;
+ m_pcidcr1 = 0;
+ m_pcidpa2 = 0;
+ m_pcidla2 = 0;
+ m_pcidtc2 = 0;
+ m_pcidcr2 = 0;
+ m_pcidpa3 = 0;
+ m_pcidla3 = 0;
+ m_pcidtc3 = 0;
+ m_pcidcr3 = 0;
+ m_pcipar = 0;
+ m_pcimbr = 0;
+ m_pciiobr = 0;
+ m_pcipint = 0;
+ m_pcipintm = 0;
+ m_pciclkr = 0;
+ m_pcibcr1 = 0;
+ m_pcibcr2 = 0x00003ffc;
+ m_pcibcr3 = 1;
+ m_pciwcr1 = 0x77777777;
+ m_pciwcr2 = 0xfffeefff;
+ m_pciwcr3 = 0x07777777;
+ m_pcimcr = 0;
+ m_pcipctr = 0;
+ m_pcipdtr = 0;
+ m_pcipdr = 0;
+
+ // H-UDI
+ m_sdir = 0xffff;
+ m_sddr = 0;
+ m_sdint = 0;
+
+ save_item(NAME(m_refresh_timer_base));
+
for (i = 0;i < 64;i++)
{
save_item(NAME(m_utlb[i].ASID), i);
@@ -2012,6 +3460,201 @@ void sh4_base_device::device_start()
save_item(NAME(m_utlb[i].SA), i);
save_item(NAME(m_utlb[i].TC), i);
}
+
+ // UBC
+ save_item(NAME(m_bara));
+ save_item(NAME(m_bamra));
+ save_item(NAME(m_bbra));
+ save_item(NAME(m_barb));
+ save_item(NAME(m_bamrb));
+ save_item(NAME(m_bbrb));
+ save_item(NAME(m_bdrb));
+ save_item(NAME(m_bdmrb));
+ save_item(NAME(m_brcr));
+
+ // BSC
+ save_item(NAME(m_bcr1));
+ save_item(NAME(m_bcr2));
+ save_item(NAME(m_wcr1));
+ save_item(NAME(m_wcr2));
+ save_item(NAME(m_wcr3));
+ save_item(NAME(m_mcr));
+ save_item(NAME(m_pcr));
+ save_item(NAME(m_rtcsr));
+ save_item(NAME(m_rtcnt));
+ save_item(NAME(m_rtcor));
+ save_item(NAME(m_rfcr));
+ save_item(NAME(m_pctra));
+ save_item(NAME(m_pdtra));
+ save_item(NAME(m_pctrb));
+ save_item(NAME(m_pdtrb));
+ save_item(NAME(m_gpioic));
+
+ // BSC 7750R
+ save_item(NAME(m_bcr3));
+ save_item(NAME(m_bcr4));
+
+ // DMAC 7750R
+ save_item(NAME(m_sar4));
+ save_item(NAME(m_dar4));
+ save_item(NAME(m_dmatcr4));
+ save_item(NAME(m_chcr4));
+ save_item(NAME(m_sar5));
+ save_item(NAME(m_dar5));
+ save_item(NAME(m_dmatcr5));
+ save_item(NAME(m_chcr5));
+ save_item(NAME(m_sar6));
+ save_item(NAME(m_dar6));
+ save_item(NAME(m_dmatcr6));
+ save_item(NAME(m_chcr6));
+ save_item(NAME(m_sar7));
+ save_item(NAME(m_dar7));
+ save_item(NAME(m_dmatcr7));
+ save_item(NAME(m_chcr7));
+
+ // CPG
+ save_item(NAME(m_frqcr));
+ save_item(NAME(m_stbcr));
+ save_item(NAME(m_wtcnt));
+ save_item(NAME(m_wtcsr));
+ save_item(NAME(m_stbcr2));
+
+ // CPG 7750R
+ save_item(NAME(m_clkstp00));
+
+ // RTC
+ save_item(NAME(m_r64cnt));
+ save_item(NAME(m_rseccnt));
+ save_item(NAME(m_rmincnt));
+ save_item(NAME(m_rhrcnt));
+ save_item(NAME(m_rwkcnt));
+ save_item(NAME(m_rmoncnt));
+ save_item(NAME(m_rdaycnt));
+ save_item(NAME(m_ryrcnt));
+ save_item(NAME(m_rsecar));
+ save_item(NAME(m_rminar));
+ save_item(NAME(m_rhrar));
+ save_item(NAME(m_rwkar));
+ save_item(NAME(m_rdayar));
+ save_item(NAME(m_rmonar));
+ save_item(NAME(m_rcr1));
+ save_item(NAME(m_rcr2));
+
+ // INTC
+ save_item(NAME(m_iprb));
+
+ // INTC 7750S
+ save_item(NAME(m_iprd));
+
+ // INTC 7750R
+ save_item(NAME(m_intpri00));
+ save_item(NAME(m_intreq00));
+ save_item(NAME(m_intmsk00));
+
+ // TMU 7750R
+ save_item(NAME(m_tstr2));
+ save_item(NAME(m_tcor3));
+ save_item(NAME(m_tcnt3));
+ save_item(NAME(m_tcr3));
+ save_item(NAME(m_tcor4));
+ save_item(NAME(m_tcnt4));
+ save_item(NAME(m_tcr4));
+
+ // RTC 7750R
+ save_item(NAME(m_rcr3));
+ save_item(NAME(m_ryrar));
+
+ // SCI
+ save_item(NAME(m_scsmr1));
+ save_item(NAME(m_scbrr1));
+ save_item(NAME(m_scscr1));
+ save_item(NAME(m_sctdr1));
+ save_item(NAME(m_scssr1));
+ save_item(NAME(m_scrdr1));
+ save_item(NAME(m_scscmr1));
+ save_item(NAME(m_scsptr1));
+
+ // SCIF
+ save_item(NAME(m_scsmr2));
+ save_item(NAME(m_scbrr2));
+ save_item(NAME(m_scscr2));
+ save_item(NAME(m_scftdr2));
+ save_item(NAME(m_scfsr2));
+ save_item(NAME(m_scfrdr2));
+ save_item(NAME(m_scfcr2));
+ save_item(NAME(m_scfdr2));
+ save_item(NAME(m_scsptr2));
+ save_item(NAME(m_sclsr2));
+
+ // H-UDI
+ save_item(NAME(m_sdir));
+ save_item(NAME(m_sddr));
+ save_item(NAME(m_sdint));
+
+ // PCI 7751
+ save_item(NAME(m_pciconf0));
+ save_item(NAME(m_pciconf1));
+ save_item(NAME(m_pciconf2));
+ save_item(NAME(m_pciconf3));
+ save_item(NAME(m_pciconf4));
+ save_item(NAME(m_pciconf5));
+ save_item(NAME(m_pciconf6));
+ save_item(NAME(m_pciconf7));
+ save_item(NAME(m_pciconf8));
+ save_item(NAME(m_pciconf9));
+ save_item(NAME(m_pciconf10));
+ save_item(NAME(m_pciconf11));
+ save_item(NAME(m_pciconf12));
+ save_item(NAME(m_pciconf13));
+ save_item(NAME(m_pciconf14));
+ save_item(NAME(m_pciconf15));
+ save_item(NAME(m_pciconf16));
+ save_item(NAME(m_pciconf17));
+ save_item(NAME(m_pcicr));
+ save_item(NAME(m_pcilsr0));
+ save_item(NAME(m_pcilsr1));
+ save_item(NAME(m_pcilar0));
+ save_item(NAME(m_pcilar1));
+ save_item(NAME(m_pciint));
+ save_item(NAME(m_pciintm));
+ save_item(NAME(m_pcialr));
+ save_item(NAME(m_pciclr));
+ save_item(NAME(m_pciaint));
+ save_item(NAME(m_pciaintm));
+ save_item(NAME(m_pcibllr));
+ save_item(NAME(m_pcidmabt));
+ save_item(NAME(m_pcidpa0));
+ save_item(NAME(m_pcidla0));
+ save_item(NAME(m_pcidtc0));
+ save_item(NAME(m_pcidcr0));
+ save_item(NAME(m_pcidpa1));
+ save_item(NAME(m_pcidla1));
+ save_item(NAME(m_pcidtc1));
+ save_item(NAME(m_pcidcr1));
+ save_item(NAME(m_pcidpa2));
+ save_item(NAME(m_pcidla2));
+ save_item(NAME(m_pcidtc2));
+ save_item(NAME(m_pcidcr2));
+ save_item(NAME(m_pcidpa3));
+ save_item(NAME(m_pcidla3));
+ save_item(NAME(m_pcidtc3));
+ save_item(NAME(m_pcidcr3));
+ save_item(NAME(m_pcipar));
+ save_item(NAME(m_pcimbr));
+ save_item(NAME(m_pciiobr));
+ save_item(NAME(m_pcipint));
+ save_item(NAME(m_pcipintm));
+ save_item(NAME(m_pciclkr));
+ save_item(NAME(m_pcibcr1));
+ save_item(NAME(m_pcibcr2));
+ save_item(NAME(m_pcibcr3));
+ save_item(NAME(m_pciwcr1));
+ save_item(NAME(m_pciwcr2));
+ save_item(NAME(m_pciwcr3));
+ save_item(NAME(m_pcimcr));
+ save_item(NAME(m_pcipctr));
+ save_item(NAME(m_pcipdtr));
+ save_item(NAME(m_pcipdr));
}
@@ -2024,23 +3667,16 @@ void sh34_base_device::device_start()
for (int i = 0; i < 3; i++)
{
- m_timer[i] = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(sh34_base_device::sh4_timer_callback), this));
+ m_timer[i] = timer_alloc(FUNC(sh34_base_device::sh4_timer_callback), this);
m_timer[i]->adjust(attotime::never, i);
}
for (int i = 0; i < 4; i++)
{
- m_dma_timer[i] = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(sh34_base_device::sh4_dmac_callback), this));
+ m_dma_timer[i] = timer_alloc(FUNC(sh34_base_device::sh4_dmac_callback), this);
m_dma_timer[i]->adjust(attotime::never, i);
}
- m_refresh_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(sh34_base_device::sh4_refresh_timer_callback), this));
- m_refresh_timer->adjust(attotime::never);
- m_refresh_timer_base = 0;
-
- m_rtc_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(sh34_base_device::sh4_rtc_timer_callback), this));
- m_rtc_timer->adjust(attotime::never);
-
sh4_parse_configuration();
m_internal = &space(AS_PROGRAM);
@@ -2048,34 +3684,34 @@ void sh34_base_device::device_start()
m_io = &space(AS_IO);
if (m_program->endianness() == ENDIANNESS_LITTLE)
{
- auto cache = m_program->cache<3, 0, ENDIANNESS_LITTLE>();
- m_pr16 = [cache](offs_t address) -> u16 { return cache->read_word(address); };
+ m_program->cache(m_cache64le);
+ m_pr16 = [this](offs_t address) -> u16 { return m_cache64le.read_word(address); };
if (ENDIANNESS_NATIVE != ENDIANNESS_LITTLE)
- m_prptr = [cache](offs_t address) -> const void * {
- const u16 *ptr = static_cast<u16 *>(cache->read_ptr(address & ~7));
+ m_prptr = [this](offs_t address) -> const void * {
+ const u16 *ptr = static_cast<u16 *>(m_cache64le.read_ptr(address & ~7));
ptr += (~address >> 1) & 3;
return ptr;
};
else
- m_prptr = [cache](offs_t address) -> const void * {
- const u16 *ptr = static_cast<u16 *>(cache->read_ptr(address & ~7));
+ m_prptr = [this](offs_t address) -> const void * {
+ const u16 *ptr = static_cast<u16 *>(m_cache64le.read_ptr(address & ~7));
ptr += (address >> 1) & 3;
return ptr;
};
}
else
{
- auto cache = m_program->cache<3, 0, ENDIANNESS_BIG>();
- m_pr16 = [cache](offs_t address) -> u16 { return cache->read_word(address); };
+ m_program->cache(m_cache64be);
+ m_pr16 = [this](offs_t address) -> u16 { return m_cache64be.read_word(address); };
if (ENDIANNESS_NATIVE != ENDIANNESS_BIG)
- m_prptr = [cache](offs_t address) -> const void * {
- const u16 *ptr = static_cast<u16 *>(cache->read_ptr(address & ~7));
+ m_prptr = [this](offs_t address) -> const void * {
+ const u16 *ptr = static_cast<u16 *>(m_cache64be.read_ptr(address & ~7));
ptr += (~address >> 1) & 3;
return ptr;
};
else
- m_prptr = [cache](offs_t address) -> const void * {
- const u16 *ptr = static_cast<u16 *>(cache->read_ptr(address & ~7));
+ m_prptr = [this](offs_t address) -> const void * {
+ const u16 *ptr = static_cast<u16 *>(m_cache64be.read_ptr(address & ~7));
ptr += (address >> 1) & 3;
return ptr;
};
@@ -2102,41 +3738,80 @@ void sh34_base_device::device_start()
save_item(NAME(m_exception_priority));
save_item(NAME(m_exception_requesting));
save_item(NAME(m_irq_line_state));
- save_item(NAME(m_m));
- save_item(NAME(m_SH4_TSTR));
- save_item(NAME(m_SH4_TCNT0));
- save_item(NAME(m_SH4_TCNT1));
- save_item(NAME(m_SH4_TCNT2));
- save_item(NAME(m_SH4_TCR0));
- save_item(NAME(m_SH4_TCR1));
- save_item(NAME(m_SH4_TCR2));
- save_item(NAME(m_SH4_TCOR0));
- save_item(NAME(m_SH4_TCOR1));
- save_item(NAME(m_SH4_TCOR2));
- save_item(NAME(m_SH4_TOCR));
- save_item(NAME(m_SH4_TCPR2));
- save_item(NAME(m_SH4_IPRA));
- save_item(NAME(m_SH4_IPRC));
- save_item(NAME(m_SH4_DAR0));
- save_item(NAME(m_SH4_DAR1));
- save_item(NAME(m_SH4_DAR2));
- save_item(NAME(m_SH4_DAR3));
- save_item(NAME(m_SH4_CHCR0));
- save_item(NAME(m_SH4_CHCR1));
- save_item(NAME(m_SH4_CHCR2));
- save_item(NAME(m_SH4_CHCR3));
- save_item(NAME(m_SH4_DMATCR0));
- save_item(NAME(m_SH4_DMATCR1));
- save_item(NAME(m_SH4_DMATCR2));
- save_item(NAME(m_SH4_DMATCR3));
- save_item(NAME(m_SH4_DMAOR));
+
+ // CCN
+ m_tea = 0;
+ m_basra = 0;
+ m_basrb = 0;
+
+ // CCN
+ save_item(NAME(m_pteh));
+ save_item(NAME(m_ptel));
+ save_item(NAME(m_ttb));
+ save_item(NAME(m_tea));
+ save_item(NAME(m_mmucr));
+ save_item(NAME(m_basra));
+ save_item(NAME(m_basrb));
+ save_item(NAME(m_ccr));
+ save_item(NAME(m_tra));
+ save_item(NAME(m_expevt));
+ save_item(NAME(m_intevt));
+
+ // CCN 7709S
+ save_item(NAME(m_ccr2));
+
+ // CCN 7091
+ save_item(NAME(m_ptea));
+ save_item(NAME(m_qacr0));
+ save_item(NAME(m_qacr1));
+
+ // TMU
+ save_item(NAME(m_tocr));
+ save_item(NAME(m_tstr));
+ save_item(NAME(m_tcor0));
+ save_item(NAME(m_tcnt0));
+ save_item(NAME(m_tcr0));
+ save_item(NAME(m_tcor1));
+ save_item(NAME(m_tcnt1));
+ save_item(NAME(m_tcr1));
+ save_item(NAME(m_tcor2));
+ save_item(NAME(m_tcnt2));
+ save_item(NAME(m_tcr2));
+ save_item(NAME(m_tcpr2));
+
+ // INTC
+ save_item(NAME(m_icr));
+ save_item(NAME(m_ipra));
+ save_item(NAME(m_iprc));
+
+ // INTC 7709
+ save_item(NAME(m_intevt2));
+
+ // DMAC
+ save_item(NAME(m_sar0));
+ save_item(NAME(m_sar1));
+ save_item(NAME(m_sar2));
+ save_item(NAME(m_sar3));
+ save_item(NAME(m_dar0));
+ save_item(NAME(m_dar1));
+ save_item(NAME(m_dar2));
+ save_item(NAME(m_dar3));
+ save_item(NAME(m_chcr0));
+ save_item(NAME(m_chcr1));
+ save_item(NAME(m_chcr2));
+ save_item(NAME(m_chcr3));
+ save_item(NAME(m_dmatcr0));
+ save_item(NAME(m_dmatcr1));
+ save_item(NAME(m_dmatcr2));
+ save_item(NAME(m_dmatcr3));
+ save_item(NAME(m_dmaor));
+
save_item(NAME(m_nmi_line_state));
save_item(NAME(m_sh2_state->m_frt_input));
save_item(NAME(m_irln));
save_item(NAME(m_internal_irq_level));
save_item(NAME(m_internal_irq_vector));
- save_item(NAME(m_refresh_timer_base));
save_item(NAME(m_dma_timer_active));
save_item(NAME(m_dma_source));
save_item(NAME(m_dma_destination));
@@ -2154,8 +3829,6 @@ void sh34_base_device::device_start()
save_item(NAME(m_ioport4_pullup));
save_item(NAME(m_ioport4_direction));
save_item(NAME(m_sh4_mmu_enabled));
- save_item(NAME(m_sh3internal_upper));
- save_item(NAME(m_sh3internal_lower));
// Debugger state
@@ -2219,7 +3892,7 @@ void sh34_base_device::device_start()
state_add(STATE_GENPC, "GENPC", m_debugger_temp).callimport().callexport().noshow();
//state_add(STATE_GENPCBASE, "CURPC", m_sh2_state->m_ppc).noshow();
- state_add( STATE_GENPCBASE, "CURPC", m_sh2_state->pc ).callimport().noshow();
+ state_add(STATE_GENPCBASE, "CURPC", m_sh2_state->pc).callimport().noshow();
for (int regnum = 0; regnum < 16; regnum++)
{
@@ -2246,6 +3919,7 @@ void sh34_base_device::state_import(const device_state_entry &entry)
{
case STATE_GENPC:
m_sh2_state->pc = m_debugger_temp;
+ [[fallthrough]];
case SH4_PC:
m_sh2_state->m_delay = 0;
break;
@@ -2390,7 +4064,7 @@ void sh34_base_device::state_export(const device_state_entry &entry)
switch (entry.index())
{
case STATE_GENPC:
- m_debugger_temp = (m_sh2_state->pc & SH34_AM);
+ m_debugger_temp = m_sh2_state->pc;
break;
}
}
@@ -2556,43 +4230,23 @@ void sh34_base_device::sh4_set_ftcsr_callback(sh4_ftcsr_callback callback)
}
*/
-const opcode_desc* sh4be_device::get_desclist(offs_t pc)
-{
- return m_drcfe->describe_code(pc);
-}
-
-void sh4be_device::init_drc_frontend()
-{
- m_drcfe = std::make_unique<sh4be_frontend>(this, COMPILE_BACKWARDS_BYTES, COMPILE_FORWARDS_BYTES, SINGLE_INSTRUCTION_MODE ? 1 : COMPILE_MAX_SEQUENCE);
-}
-
-const opcode_desc* sh4_device::get_desclist(offs_t pc)
+const opcode_desc* sh4_base_device::get_desclist(offs_t pc)
{
return m_drcfe->describe_code(pc);
}
-void sh4_device::init_drc_frontend()
+void sh4_base_device::init_drc_frontend()
{
m_drcfe = std::make_unique<sh4_frontend>(this, COMPILE_BACKWARDS_BYTES, COMPILE_FORWARDS_BYTES, SINGLE_INSTRUCTION_MODE ? 1 : COMPILE_MAX_SEQUENCE);
}
-const opcode_desc* sh3be_device::get_desclist(offs_t pc)
+const opcode_desc* sh3_base_device::get_desclist(offs_t pc)
{
return m_drcfe->describe_code(pc);
}
-void sh3be_device::init_drc_frontend()
-{
- m_drcfe = std::make_unique<sh4be_frontend>(this, COMPILE_BACKWARDS_BYTES, COMPILE_FORWARDS_BYTES, SINGLE_INSTRUCTION_MODE ? 1 : COMPILE_MAX_SEQUENCE);
-}
-
-const opcode_desc* sh3_device::get_desclist(offs_t pc)
-{
- return m_drcfe->describe_code(pc);
-}
-
-void sh3_device::init_drc_frontend()
+void sh3_base_device::init_drc_frontend()
{
m_drcfe = std::make_unique<sh4_frontend>(this, COMPILE_BACKWARDS_BYTES, COMPILE_FORWARDS_BYTES, SINGLE_INSTRUCTION_MODE ? 1 : COMPILE_MAX_SEQUENCE);
}
@@ -2713,7 +4367,7 @@ void sh34_base_device::static_generate_memory_accessor(int size, int iswrite, co
UML_LABEL(block, label++); // label:
- if ((machine().debug_flags & DEBUG_FLAG_ENABLED) == 0)
+ if (!debugger_enabled())
{
for (auto & elem : m_fastram)
{
@@ -2902,13 +4556,13 @@ bool sh34_base_device::generate_group_0_STCRBANK(drcuml_block &block, compiler_s
bool sh34_base_device::generate_group_0_STCSSR(drcuml_block &block, compiler_state &compiler, const opcode_desc *desc, uint16_t opcode, int in_delay_slot, uint32_t ovrpc)
{
- UML_MOV(block, R32(Rn), mem(&m_sh2_state->m_ssr));
+ UML_MOV(block, R32(REG_N), mem(&m_sh2_state->m_ssr));
return true;
}
bool sh34_base_device::generate_group_0_STCSPC(drcuml_block &block, compiler_state &compiler, const opcode_desc *desc, uint16_t opcode, int in_delay_slot, uint32_t ovrpc)
{
- UML_MOV(block, R32(Rn), mem(&m_sh2_state->m_spc));
+ UML_MOV(block, R32(REG_N), mem(&m_sh2_state->m_spc));
return true;
}
@@ -2926,7 +4580,7 @@ bool sh34_base_device::generate_group_0_PREFM(drcuml_block &block, compiler_stat
bool sh34_base_device::generate_group_0_MOVCAL(drcuml_block &block, compiler_state &compiler, const opcode_desc *desc, uint16_t opcode, int in_delay_slot, uint32_t ovrpc)
{
- UML_MOV(block, I0, R32(Rn))
+ UML_MOV(block, I0, R32(REG_N))
SETEA(0);
UML_MOV(block, I1, R32(0));
UML_CALLH(block, *m_write32);
@@ -2971,27 +4625,27 @@ bool sh34_base_device::generate_group_0_SETS(drcuml_block &block, compiler_state
bool sh34_base_device::generate_group_0_STCSGR(drcuml_block &block, compiler_state &compiler, const opcode_desc *desc, uint16_t opcode, int in_delay_slot, uint32_t ovrpc)
{
- UML_MOV(block, R32(Rn), mem(&m_sh2_state->m_sgr));
+ UML_MOV(block, R32(REG_N), mem(&m_sh2_state->m_sgr));
return true;
}
bool sh34_base_device::generate_group_0_STSFPUL(drcuml_block &block, compiler_state &compiler, const opcode_desc *desc, uint16_t opcode, int in_delay_slot, uint32_t ovrpc)
{
- UML_MOV(block, R32(Rn), mem(&m_sh2_state->m_fpul));
+ UML_MOV(block, R32(REG_N), mem(&m_sh2_state->m_fpul));
return true;
}
bool sh34_base_device::generate_group_0_STSFPSCR(drcuml_block &block, compiler_state &compiler, const opcode_desc *desc, uint16_t opcode, int in_delay_slot, uint32_t ovrpc)
{
UML_AND(block, I0, 0x003FFFFF, mem(&m_sh2_state->m_fpscr));
- UML_MOV(block, R32(Rn), I0);
+ UML_MOV(block, R32(REG_N), I0);
return true;
}
bool sh34_base_device::generate_group_0_STCDBR(drcuml_block &block, compiler_state &compiler, const opcode_desc *desc, uint16_t opcode, int in_delay_slot, uint32_t ovrpc)
{
- UML_MOV(block, R32(Rn), mem(&m_sh2_state->m_dbr));
+ UML_MOV(block, R32(REG_N), mem(&m_sh2_state->m_dbr));
return true;
}
@@ -3281,7 +4935,7 @@ bool sh34_base_device::generate_group_4_LDCMSSR(drcuml_block &block, compiler_st
bool sh34_base_device::generate_group_4_LDCSSR(drcuml_block &block, compiler_state &compiler, const opcode_desc *desc, uint16_t opcode, int in_delay_slot, uint32_t ovrpc)
{
- UML_MOV(block, mem(&m_sh2_state->m_ssr), R32(Rn));
+ UML_MOV(block, mem(&m_sh2_state->m_ssr), R32(REG_N));
return true;
}
@@ -3311,7 +4965,7 @@ bool sh34_base_device::generate_group_4_LDCMSPC(drcuml_block &block, compiler_st
bool sh34_base_device::generate_group_4_LDCSPC(drcuml_block &block, compiler_state &compiler, const opcode_desc *desc, uint16_t opcode, int in_delay_slot, uint32_t ovrpc)
{
- UML_MOV(block, mem(&m_sh2_state->m_spc), R32(Rn));
+ UML_MOV(block, mem(&m_sh2_state->m_spc), R32(REG_N));
return true;
}
@@ -3341,7 +4995,7 @@ bool sh34_base_device::generate_group_4_LDSMFPUL(drcuml_block &block, compiler_s
bool sh34_base_device::generate_group_4_LDSFPUL(drcuml_block &block, compiler_state &compiler, const opcode_desc *desc, uint16_t opcode, int in_delay_slot, uint32_t ovrpc)
{
- UML_MOV(block, mem(&m_sh2_state->m_fpul), R32(Rn));
+ UML_MOV(block, mem(&m_sh2_state->m_fpul), R32(REG_N));
return true;
}
@@ -3450,11 +5104,11 @@ bool sh34_base_device::generate_group_15_FADD(drcuml_block &block, compiler_stat
UML_TEST(block, mem(&m_sh2_state->m_fpu_pr), 0);
UML_JMPc(block, COND_Z, compiler.labelnum);
- UML_FDADD(block, FPD32(Rn), FPD32(Rn), FPD32(Rm));
+ UML_FDADD(block, FPD32(REG_N), FPD32(REG_N), FPD32(REG_M));
UML_JMP(block, compiler.labelnum+1);
UML_LABEL(block, compiler.labelnum++); // labelnum:
- UML_FSADD(block, FPS32(Rn), FPS32(Rn), FPS32(Rm));
+ UML_FSADD(block, FPS32(REG_N), FPS32(REG_N), FPS32(REG_M));
UML_LABEL(block, compiler.labelnum++); // labelnum+1:
@@ -3466,11 +5120,11 @@ bool sh34_base_device::generate_group_15_FSUB(drcuml_block &block, compiler_stat
UML_TEST(block, mem(&m_sh2_state->m_fpu_pr), 0);
UML_JMPc(block, COND_Z, compiler.labelnum);
- UML_FDSUB(block, FPD32(Rn), FPD32(Rn), FPD32(Rm));
+ UML_FDSUB(block, FPD32(REG_N), FPD32(REG_N), FPD32(REG_M));
UML_JMP(block, compiler.labelnum+1);
UML_LABEL(block, compiler.labelnum++); // labelnum:
- UML_FSSUB(block, FPS32(Rn), FPS32(Rn), FPS32(Rm));
+ UML_FSSUB(block, FPS32(REG_N), FPS32(REG_N), FPS32(REG_M));
UML_LABEL(block, compiler.labelnum++); // labelnum+1:
@@ -3482,11 +5136,11 @@ bool sh34_base_device::generate_group_15_FMUL(drcuml_block &block, compiler_stat
UML_TEST(block, mem(&m_sh2_state->m_fpu_pr), 0);
UML_JMPc(block, COND_Z, compiler.labelnum);
- UML_FDMUL(block, FPD32(Rn), FPD32(Rn), FPD32(Rm));
+ UML_FDMUL(block, FPD32(REG_N), FPD32(REG_N), FPD32(REG_M));
UML_JMP(block, compiler.labelnum+1);
UML_LABEL(block, compiler.labelnum++); // labelnum:
- UML_FSMUL(block, FPS32(Rn), FPS32(Rn), FPS32(Rm));
+ UML_FSMUL(block, FPS32(REG_N), FPS32(REG_N), FPS32(REG_M));
UML_LABEL(block, compiler.labelnum++); // labelnum+1:
@@ -3498,11 +5152,11 @@ bool sh34_base_device::generate_group_15_FDIV(drcuml_block &block, compiler_stat
UML_TEST(block, mem(&m_sh2_state->m_fpu_pr), 0);
UML_JMPc(block, COND_Z, compiler.labelnum);
- UML_FDDIV(block, FPD32(Rn), FPD32(Rn), FPD32(Rm));
+ UML_FDDIV(block, FPD32(REG_N), FPD32(REG_N), FPD32(REG_M));
UML_JMP(block, compiler.labelnum+1);
UML_LABEL(block, compiler.labelnum++); // labelnum:
- UML_FSDIV(block, FPS32(Rn), FPS32(Rn), FPS32(Rm));
+ UML_FSDIV(block, FPS32(REG_N), FPS32(REG_N), FPS32(REG_M));
UML_LABEL(block, compiler.labelnum++); // labelnum+1:
@@ -3514,7 +5168,7 @@ bool sh34_base_device::generate_group_15_FCMP_EQ(drcuml_block &block, compiler_s
UML_TEST(block, uml::mem(&m_sh2_state->m_fpu_pr), 0);
UML_JMPc(block, COND_Z, compiler.labelnum);
- UML_FDCMP(block, FPD32(Rm & 14), FPD32(Rn & 14));
+ UML_FDCMP(block, FPD32(REG_M & 14), FPD32(REG_N & 14));
UML_SETc(block, COND_Z, I0);
UML_ROLINS(block, uml::mem(&m_sh2_state->sr), I0, T_SHIFT, SH_T);
@@ -3522,7 +5176,7 @@ bool sh34_base_device::generate_group_15_FCMP_EQ(drcuml_block &block, compiler_s
UML_LABEL(block, compiler.labelnum++); // labelnum:
- UML_FSCMP(block, FPS32(Rm), FPS32(Rn));
+ UML_FSCMP(block, FPS32(REG_M), FPS32(REG_N));
UML_SETc(block, COND_Z, I0);
UML_ROLINS(block, uml::mem(&m_sh2_state->sr), I0, T_SHIFT, SH_T);
@@ -3535,7 +5189,7 @@ bool sh34_base_device::generate_group_15_FCMP_GT(drcuml_block &block, compiler_s
UML_TEST(block, uml::mem(&m_sh2_state->m_fpu_pr), 0);
UML_JMPc(block, COND_Z, compiler.labelnum);
- UML_FDCMP(block, FPD32(Rm & 14), FPD32(Rn & 14));
+ UML_FDCMP(block, FPD32(REG_M & 14), FPD32(REG_N & 14));
UML_SETc(block, COND_C, I0);
UML_ROLINS(block, uml::mem(&m_sh2_state->sr), I0, T_SHIFT, SH_T);
@@ -3543,7 +5197,7 @@ bool sh34_base_device::generate_group_15_FCMP_GT(drcuml_block &block, compiler_s
UML_LABEL(block, compiler.labelnum++); // labelnum:
- UML_FSCMP(block, FPS32(Rm), FPS32(Rn));
+ UML_FSCMP(block, FPS32(REG_M), FPS32(REG_N));
UML_SETc(block, COND_C, I0);
UML_ROLINS(block, uml::mem(&m_sh2_state->sr), I0, T_SHIFT, SH_T);
@@ -3640,8 +5294,8 @@ bool sh34_base_device::generate_group_15_FMAC(drcuml_block &block, compiler_stat
UML_TEST(block, mem(&m_sh2_state->m_fpu_pr), 0);
UML_JMPc(block, COND_NZ, compiler.labelnum);
- UML_FSMUL(block, F0, FPS32(0), FPS32(Rm));
- UML_FSADD(block, FPS32(Rn), F0, FPS32(Rn));
+ UML_FSMUL(block, F0, FPS32(0), FPS32(REG_M));
+ UML_FSADD(block, FPS32(REG_N), F0, FPS32(REG_N));
UML_LABEL(block, compiler.labelnum++);
return true;
@@ -3674,10 +5328,10 @@ bool sh34_base_device::generate_group_15_op1111_0x13(drcuml_block &block, compil
bool sh34_base_device::generate_group_15_op1111_0x13_FSTS(drcuml_block &block, compiler_state &compiler, const opcode_desc *desc, uint16_t opcode, int in_delay_slot, uint32_t ovrpc)
{
#ifdef LSB_FIRST
- UML_XOR(block, I0, Rn, uml::mem(&m_sh2_state->m_fpu_pr));
+ UML_XOR(block, I0, REG_N, uml::mem(&m_sh2_state->m_fpu_pr));
UML_STORE(block, m_sh2_state->m_fr, I0, uml::mem(&m_sh2_state->m_fpul), SIZE_DWORD, SCALE_x4);
#else
- UML_MOV(block, FPS32(Rn), uml::mem(&m_sh2_state->m_fpul));
+ UML_MOV(block, FPS32(REG_N), uml::mem(&m_sh2_state->m_fpul));
#endif
return true;
}
@@ -3699,12 +5353,12 @@ bool sh34_base_device::generate_group_15_op1111_0x13_FLOAT(drcuml_block &block,
UML_TEST(block, uml::mem(&m_sh2_state->m_fpu_pr), 0);
UML_JMPc(block, COND_Z, compiler.labelnum);
- UML_FDFRINT(block, FPD32(Rn & 14), uml::mem(&m_sh2_state->m_fpul), SIZE_DWORD);
+ UML_FDFRINT(block, FPD32(REG_N & 14), uml::mem(&m_sh2_state->m_fpul), SIZE_DWORD);
UML_JMP(block, compiler.labelnum+1);
UML_LABEL(block, compiler.labelnum++); // labelnum:
- UML_FSFRINT(block, FPS32(Rn), uml::mem(&m_sh2_state->m_fpul), SIZE_DWORD);
+ UML_FSFRINT(block, FPS32(REG_N), uml::mem(&m_sh2_state->m_fpul), SIZE_DWORD);
UML_LABEL(block, compiler.labelnum++); // labelnum+1:
@@ -3716,12 +5370,12 @@ bool sh34_base_device::generate_group_15_op1111_0x13_FTRC(drcuml_block &block, c
UML_TEST(block, uml::mem(&m_sh2_state->m_fpu_pr), 0);
UML_JMPc(block, COND_Z, compiler.labelnum);
- UML_FDTOINT(block, uml::mem(&m_sh2_state->m_fpul), FPD32(Rn & 14), SIZE_DWORD, ROUND_TRUNC);
+ UML_FDTOINT(block, uml::mem(&m_sh2_state->m_fpul), FPD32(REG_N & 14), SIZE_DWORD, ROUND_TRUNC);
UML_JMP(block, compiler.labelnum+1);
UML_LABEL(block, compiler.labelnum++); // labelnum:
- UML_FSTOINT(block, uml::mem(&m_sh2_state->m_fpul), FPS32(Rn), SIZE_DWORD, ROUND_TRUNC);
+ UML_FSTOINT(block, uml::mem(&m_sh2_state->m_fpul), FPS32(REG_N), SIZE_DWORD, ROUND_TRUNC);
UML_LABEL(block, compiler.labelnum++); // labelnum+1:
return true;
@@ -3735,14 +5389,14 @@ bool sh34_base_device::generate_group_15_op1111_0x13_FNEG(drcuml_block &block, c
UML_JMPc(block, COND_Z, compiler.labelnum);
UML_FDFRINT(block, F1, I0, SIZE_DWORD);
- UML_FDSUB(block, FPD32(Rn), F1, FPD32(Rn));
+ UML_FDSUB(block, FPD32(REG_N), F1, FPD32(REG_N));
UML_JMP(block, compiler.labelnum+1);
UML_LABEL(block, compiler.labelnum++); // labelnum:
UML_FSFRINT(block, F1, I0, SIZE_DWORD);
- UML_FSSUB(block, FPS32(Rn), F1, FPS32(Rn));
+ UML_FSSUB(block, FPS32(REG_N), F1, FPS32(REG_N));
UML_LABEL(block, compiler.labelnum++); // labelnum+1:
return true;
@@ -3754,16 +5408,16 @@ bool sh34_base_device::generate_group_15_op1111_0x13_FABS(drcuml_block &block, c
UML_JMPc(block, COND_Z, compiler.labelnum);
#ifdef LSB_FIRST
- UML_AND(block, FPS32(((Rn&14)|1)), FPS32(((Rn&14)|1)), 0x7fffffff);
+ UML_AND(block, FPS32(((REG_N & 14) | 1)), FPS32(((REG_N & 14) | 1)), 0x7fffffff);
#else
- UML_AND(block, FPS32(Rn&14), FPS32(Rn&14), 0x7fffffff);
+ UML_AND(block, FPS32(REG_N & 14), FPS32(REG_N & 14), 0x7fffffff);
#endif
- UML_JMP(block, compiler.labelnum+1);
+ UML_JMP(block, compiler.labelnum + 1);
UML_LABEL(block, compiler.labelnum++); // labelnum:
- UML_AND(block, FPS32(Rn), FPS32(Rn), 0x7fffffff);
+ UML_AND(block, FPS32(REG_N), FPS32(REG_N), 0x7fffffff);
UML_LABEL(block, compiler.labelnum++); // labelnum+1:
return true;
@@ -3796,11 +5450,11 @@ bool sh34_base_device::generate_group_15_op1111_0x13_FSRRA(drcuml_block &block,
bool sh34_base_device::generate_group_15_op1111_0x13_FLDI0(drcuml_block &block, compiler_state &compiler, const opcode_desc *desc, uint16_t opcode, int in_delay_slot, uint32_t ovrpc)
{
#ifdef LSB_FIRST
- UML_MOV(block, I0, Rn);
+ UML_MOV(block, I0, REG_N);
UML_XOR(block, I0, I0, uml::mem(&m_sh2_state->m_fpu_pr));
UML_STORE(block, m_sh2_state->m_fr, I0, 0, SIZE_DWORD, SCALE_x4);
#else
- UML_MOV(block, FP_RFS(Rn), 0);
+ UML_MOV(block, FP_RFS(REG_N), 0);
#endif
return true;
}
@@ -3808,11 +5462,11 @@ bool sh34_base_device::generate_group_15_op1111_0x13_FLDI0(drcuml_block &block,
bool sh34_base_device::generate_group_15_op1111_0x13_FLDI1(drcuml_block &block, compiler_state &compiler, const opcode_desc *desc, uint16_t opcode, int in_delay_slot, uint32_t ovrpc)
{
#ifdef LSB_FIRST
- UML_MOV(block, I0, Rn);
+ UML_MOV(block, I0, REG_N);
UML_XOR(block, I0, I0, uml::mem(&m_sh2_state->m_fpu_pr));
UML_STORE(block, m_sh2_state->m_fr, I0, 0x3F800000, SIZE_DWORD, SCALE_x4);
#else
- UML_MOV(block, FP_RFS(Rn), 0x3F800000);
+ UML_MOV(block, FP_RFS(REG_N), 0x3F800000);
#endif
return true;
}
@@ -3855,8 +5509,10 @@ bool sh34_base_device::generate_group_15_op1111_0x13_FIPR(drcuml_block &block, c
bool sh34_base_device::generate_group_15_op1111_0x13_op1111_0xf13(drcuml_block &block, compiler_state &compiler, const opcode_desc *desc, uint16_t opcode, int in_delay_slot, uint32_t ovrpc)
{
- if (opcode & 0x100) {
- if (opcode & 0x200) {
+ if (opcode & 0x100)
+ {
+ if (opcode & 0x200)
+ {
switch (opcode & 0xC00)
{
case 0x000:
@@ -3870,11 +5526,13 @@ bool sh34_base_device::generate_group_15_op1111_0x13_op1111_0xf13(drcuml_block &
break;
}
}
- else {
+ else
+ {
return generate_group_15_op1111_0x13_op1111_0xf13_FTRV(block, compiler, desc, opcode, in_delay_slot, ovrpc); // FTRV(opcode);
}
}
- else {
+ else
+ {
return generate_group_15_op1111_0x13_op1111_0xf13_FSSCA(block, compiler, desc, opcode, in_delay_slot, ovrpc); // FSSCA(opcode);
}
return false;
diff --git a/src/devices/cpu/sh/sh4.h b/src/devices/cpu/sh/sh4.h
index df11767d95d..c4fc1c0cd1c 100644
--- a/src/devices/cpu/sh/sh4.h
+++ b/src/devices/cpu/sh/sh4.h
@@ -2,7 +2,7 @@
// copyright-holders:R. Belmont
/*****************************************************************************
*
- * sh4->h
+ * sh4.h
* Portable Hitachi SH-4 (SH7750 family) emulator interface
*
* By R. Belmont, based on sh2.c by Juergen Buchmueller, Mariusz Wojcieszek,
@@ -10,8 +10,8 @@
*
*****************************************************************************/
-#ifndef MAME_CPU_SH4_SH4_H
-#define MAME_CPU_SH4_SH4_H
+#ifndef MAME_CPU_SH_SH4_H
+#define MAME_CPU_SH_SH4_H
#pragma once
@@ -156,7 +156,6 @@ struct sh4_utlb
typedef void (*sh4_ftcsr_callback)(uint32_t);
class sh4_frontend;
-class sh4be_frontend;
class sh34_base_device : public sh_common_execution
{
@@ -168,10 +167,8 @@ public:
void set_mmu_hacktype(int hacktype) { m_mmuhack = hacktype; }
- TIMER_CALLBACK_MEMBER( sh4_refresh_timer_callback );
- TIMER_CALLBACK_MEMBER( sh4_rtc_timer_callback );
- TIMER_CALLBACK_MEMBER( sh4_timer_callback );
- TIMER_CALLBACK_MEMBER( sh4_dmac_callback );
+ TIMER_CALLBACK_MEMBER(sh4_timer_callback);
+ TIMER_CALLBACK_MEMBER(sh4_dmac_callback);
virtual void set_frt_input(int state) override;
void sh4_set_irln_input(int value);
@@ -257,19 +254,19 @@ protected:
sh34_base_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock, endianness_t endianness, address_map_constructor internal);
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
// device_execute_interface overrides
- virtual uint32_t execute_min_cycles() const override { return 1; }
- virtual uint32_t execute_max_cycles() const override { return 4; }
- virtual uint32_t execute_input_lines() const override { return 5; }
+ virtual uint32_t execute_min_cycles() const noexcept override { return 1; }
+ virtual uint32_t execute_max_cycles() const noexcept override { return 4; }
virtual void execute_run() override;
virtual void execute_set_input(int inputnum, int state) override;
- virtual bool execute_input_edge_triggered(int inputnum) const override { return inputnum == INPUT_LINE_NMI; }
+ virtual bool execute_input_edge_triggered(int inputnum) const noexcept override { return inputnum == INPUT_LINE_NMI; }
// device_memory_interface overrides
virtual space_config_vector memory_space_config() const override;
+ virtual bool memory_translate(int spacenum, int intention, offs_t& address, address_space*& target_space) override;
// device_state_interface overrides
virtual void state_import(const device_state_entry &entry) override;
@@ -288,7 +285,7 @@ protected:
int m_md[9];
int m_clock;
- // hack 1 = Naomi hack, hack 2 = Work in Progress implementation
+ // hack 1 = Naomi hack, hack 2 = WIP implementation
int m_mmuhack;
uint32_t m_exception_priority[128];
@@ -299,50 +296,67 @@ protected:
address_space *m_program;
address_space *m_io;
- // sh4 internal
- uint32_t m_m[16384];
-
- // timer regs handled manually for reuse
- uint32_t m_SH4_TSTR;
- uint32_t m_SH4_TCNT0;
- uint32_t m_SH4_TCNT1;
- uint32_t m_SH4_TCNT2;
- uint32_t m_SH4_TCR0;
- uint32_t m_SH4_TCR1;
- uint32_t m_SH4_TCR2;
- uint32_t m_SH4_TCOR0;
- uint32_t m_SH4_TCOR1;
- uint32_t m_SH4_TCOR2;
- uint32_t m_SH4_TOCR;
- uint32_t m_SH4_TCPR2;
-
- // INTC regs
- uint32_t m_SH4_IPRA;
-
- uint32_t m_SH4_IPRC;
-
- // DMAC regs
- uint32_t m_SH4_SAR0;
- uint32_t m_SH4_SAR1;
- uint32_t m_SH4_SAR2;
- uint32_t m_SH4_SAR3;
-
- uint32_t m_SH4_DAR0;
- uint32_t m_SH4_DAR1;
- uint32_t m_SH4_DAR2;
- uint32_t m_SH4_DAR3;
-
- uint32_t m_SH4_CHCR0;
- uint32_t m_SH4_CHCR1;
- uint32_t m_SH4_CHCR2;
- uint32_t m_SH4_CHCR3;
-
- uint32_t m_SH4_DMATCR0;
- uint32_t m_SH4_DMATCR1;
- uint32_t m_SH4_DMATCR2;
- uint32_t m_SH4_DMATCR3;
-
- uint32_t m_SH4_DMAOR;
+ // CCN
+ uint32_t m_pteh;
+ uint32_t m_ptel;
+ uint32_t m_ttb;
+ uint32_t m_tea;
+ uint32_t m_mmucr;
+ uint8_t m_basra;
+ uint8_t m_basrb;
+ uint32_t m_ccr;
+ uint32_t m_tra;
+ uint32_t m_expevt;
+ uint32_t m_intevt;
+
+ // CCN 7709S
+ uint32_t m_ccr2;
+
+ // CCN 7091
+ uint32_t m_ptea;
+ uint32_t m_qacr0;
+ uint32_t m_qacr1;
+
+ // TMU
+ uint8_t m_tocr;
+ uint8_t m_tstr;
+ uint32_t m_tcor0;
+ uint32_t m_tcnt0;
+ uint16_t m_tcr0;
+ uint32_t m_tcor1;
+ uint32_t m_tcnt1;
+ uint16_t m_tcr1;
+ uint32_t m_tcor2;
+ uint32_t m_tcnt2;
+ uint16_t m_tcr2;
+ uint32_t m_tcpr2;
+
+ // INTC
+ uint16_t m_icr;
+ uint16_t m_ipra;
+ uint16_t m_iprc;
+
+ // INTC 7709
+ uint32_t m_intevt2;
+
+ // DMAC
+ uint32_t m_sar0;
+ uint32_t m_dar0;
+ uint32_t m_dmatcr0;
+ uint32_t m_chcr0;
+ uint32_t m_sar1;
+ uint32_t m_dar1;
+ uint32_t m_dmatcr1;
+ uint32_t m_chcr1;
+ uint32_t m_sar2;
+ uint32_t m_dar2;
+ uint32_t m_dmatcr2;
+ uint32_t m_chcr2;
+ uint32_t m_sar3;
+ uint32_t m_dar3;
+ uint32_t m_dmatcr3;
+ uint32_t m_chcr3;
+ uint32_t m_dmaor;
int8_t m_nmi_line_state;
@@ -351,10 +365,7 @@ protected:
int m_internal_irq_vector;
emu_timer *m_dma_timer[4];
- emu_timer *m_refresh_timer;
- emu_timer *m_rtc_timer;
emu_timer *m_timer[3];
- uint32_t m_refresh_timer_base;
int m_dma_timer_active[4];
uint32_t m_dma_source[4];
uint32_t m_dma_destination[4];
@@ -377,24 +388,17 @@ protected:
//void (*m_ftcsr_read_callback)(uint32_t data);
- /* This MMU simulation is good for the simple remap used on Naomi GD-ROM SQ access *ONLY* */
- uint8_t m_sh4_mmu_enabled;
-
- // sh3 internal
- uint32_t m_sh3internal_upper[0x3000/4];
- uint32_t m_sh3internal_lower[0x1000];
+ bool m_sh4_mmu_enabled;
uint64_t m_debugger_temp;
inline void sh4_check_pending_irq(const char *message) // look for highest priority active exception and handle it
{
- int a,irq,z;
-
m_willjump = 0; // for the DRC
- irq = 0;
- z = -1;
- for (a=0;a <= SH4_INTC_ROVI;a++)
+ int irq = 0;
+ int z = -1;
+ for (int a = 0; a <= SH4_INTC_ROVI; a++)
{
if (m_exception_requesting[a])
{
@@ -422,84 +426,83 @@ protected:
void sh4_exception_checkunrequest(int exception);
void sh4_exception_process(int exception, uint32_t vector);
void sh4_exception(const char *message, int exception);
- uint32_t compute_ticks_refresh_timer(emu_timer *timer, int hertz, int base, int divisor);
- void sh4_refresh_timer_recompute();
- void increment_rtc_time(int mode);
void sh4_dmac_nmi();
- void sh4_handler_ipra_w(uint32_t data, uint32_t mem_mask);
+ uint16_t ipra_r(offs_t offset, uint16_t mem_mask);
+ void ipra_w(offs_t offset, uint16_t data, uint16_t mem_mask);
virtual uint32_t get_remap(uint32_t address);
virtual uint32_t sh4_getsqremap(uint32_t address);
void sh4_parse_configuration();
void sh4_timer_recompute(int which);
- uint32_t sh4_handle_tcnt0_addr_r(uint32_t mem_mask);
- uint32_t sh4_handle_tcnt1_addr_r(uint32_t mem_mask);
- uint32_t sh4_handle_tcnt2_addr_r(uint32_t mem_mask);
- uint32_t sh4_handle_tcor0_addr_r(uint32_t mem_mask);
- uint32_t sh4_handle_tcor1_addr_r(uint32_t mem_mask);
- uint32_t sh4_handle_tcor2_addr_r(uint32_t mem_mask);
- uint32_t sh4_handle_tcr0_addr_r(uint32_t mem_mask);
- uint32_t sh4_handle_tcr1_addr_r(uint32_t mem_mask);
- uint32_t sh4_handle_tcr2_addr_r(uint32_t mem_mask);
- uint32_t sh4_handle_tstr_addr_r(uint32_t mem_mask);
- uint32_t sh4_handle_tocr_addr_r(uint32_t mem_mask);
- uint32_t sh4_handle_tcpr2_addr_r(uint32_t mem_mask);
- void sh4_handle_tstr_addr_w(uint32_t data, uint32_t mem_mask);
- void sh4_handle_tcr0_addr_w(uint32_t data, uint32_t mem_mask);
- void sh4_handle_tcr1_addr_w(uint32_t data, uint32_t mem_mask);
- void sh4_handle_tcr2_addr_w(uint32_t data, uint32_t mem_mask);
- void sh4_handle_tcor0_addr_w(uint32_t data, uint32_t mem_mask);
- void sh4_handle_tcor1_addr_w(uint32_t data, uint32_t mem_mask);
- void sh4_handle_tcor2_addr_w(uint32_t data, uint32_t mem_mask);
- void sh4_handle_tcnt0_addr_w(uint32_t data, uint32_t mem_mask);
- void sh4_handle_tcnt1_addr_w(uint32_t data, uint32_t mem_mask);
- void sh4_handle_tcnt2_addr_w(uint32_t data, uint32_t mem_mask);
- void sh4_handle_tocr_addr_w(uint32_t data, uint32_t mem_mask);
- void sh4_handle_tcpr2_addr_w(uint32_t data, uint32_t mem_mask);
+ uint8_t tocr_r(offs_t offset, uint8_t mem_mask);
+ void tocr_w(offs_t offset, uint8_t data, uint8_t mem_mask);
+ uint8_t tstr_r(offs_t offset, uint8_t mem_mask);
+ void tstr_w(offs_t offset, uint8_t data, uint8_t mem_mask);
+ uint32_t tcor0_r(offs_t offset, uint32_t mem_mask);
+ void tcor0_w(offs_t offset, uint32_t data, uint32_t mem_mask);
+ uint32_t tcnt0_r(offs_t offset, uint32_t mem_mask);
+ void tcnt0_w(offs_t offset, uint32_t data, uint32_t mem_mask);
+ uint16_t tcr0_r(offs_t offset, uint16_t mem_mask);
+ void tcr0_w(offs_t offset, uint16_t data, uint16_t mem_mask);
+ uint32_t tcor1_r(offs_t offset, uint32_t mem_mask);
+ void tcor1_w(offs_t offset, uint32_t data, uint32_t mem_mask);
+ uint32_t tcnt1_r(offs_t offset, uint32_t mem_mask);
+ void tcnt1_w(offs_t offset, uint32_t data, uint32_t mem_mask);
+ uint16_t tcr1_r(offs_t offset, uint16_t mem_mask);
+ void tcr1_w(offs_t offset, uint16_t data, uint16_t mem_mask);
+ uint32_t tcor2_r(offs_t offset, uint32_t mem_mask);
+ void tcor2_w(offs_t offset, uint32_t data, uint32_t mem_mask);
+ uint32_t tcnt2_r(offs_t offset, uint32_t mem_mask);
+ void tcnt2_w(offs_t offset, uint32_t data, uint32_t mem_mask);
+ uint16_t tcr2_r(offs_t offset, uint16_t mem_mask);
+ void tcr2_w(offs_t offset, uint16_t data, uint16_t mem_mask);
+ uint32_t tcpr2_r(offs_t offset, uint32_t mem_mask);
+ void tcpr2_w(offs_t offset, uint32_t data, uint32_t mem_mask);
int sh4_dma_transfer(int channel, int timermode, uint32_t chcr, uint32_t *sar, uint32_t *dar, uint32_t *dmatcr);
int sh4_dma_transfer_device(int channel, uint32_t chcr, uint32_t *sar, uint32_t *dar, uint32_t *dmatcr);
void sh4_dmac_check(int channel);
- void sh4_handle_sar0_addr_w(uint32_t data, uint32_t mem_mask);
- void sh4_handle_sar1_addr_w(uint32_t data, uint32_t mem_mask);
- void sh4_handle_sar2_addr_w(uint32_t data, uint32_t mem_mask);
- void sh4_handle_sar3_addr_w(uint32_t data, uint32_t mem_mask);
- void sh4_handle_dar0_addr_w(uint32_t data, uint32_t mem_mask);
- void sh4_handle_dar1_addr_w(uint32_t data, uint32_t mem_mask);
- void sh4_handle_dar2_addr_w(uint32_t data, uint32_t mem_mask);
- void sh4_handle_dar3_addr_w(uint32_t data, uint32_t mem_mask);
- void sh4_handle_dmatcr0_addr_w(uint32_t data, uint32_t mem_mask);
- void sh4_handle_dmatcr1_addr_w(uint32_t data, uint32_t mem_mask);
- void sh4_handle_dmatcr2_addr_w(uint32_t data, uint32_t mem_mask);
- void sh4_handle_dmatcr3_addr_w(uint32_t data, uint32_t mem_mask);
- void sh4_handle_chcr0_addr_w(uint32_t data, uint32_t mem_mask);
- void sh4_handle_chcr1_addr_w(uint32_t data, uint32_t mem_mask);
- void sh4_handle_chcr2_addr_w(uint32_t data, uint32_t mem_mask);
- void sh4_handle_chcr3_addr_w(uint32_t data, uint32_t mem_mask);
- void sh4_handle_dmaor_addr_w(uint32_t data, uint32_t mem_mask);
- uint32_t sh4_handle_sar0_addr_r(uint32_t mem_mask) { return m_SH4_SAR0; }
- uint32_t sh4_handle_sar1_addr_r(uint32_t mem_mask) { return m_SH4_SAR1; }
- uint32_t sh4_handle_sar2_addr_r(uint32_t mem_mask) { return m_SH4_SAR2; }
- uint32_t sh4_handle_sar3_addr_r(uint32_t mem_mask) { return m_SH4_SAR3; }
- uint32_t sh4_handle_dar0_addr_r(uint32_t mem_mask) { return m_SH4_DAR0; }
- uint32_t sh4_handle_dar1_addr_r(uint32_t mem_mask) { return m_SH4_DAR1; }
- uint32_t sh4_handle_dar2_addr_r(uint32_t mem_mask) { return m_SH4_DAR2; }
- uint32_t sh4_handle_dar3_addr_r(uint32_t mem_mask) { return m_SH4_DAR3; }
- uint32_t sh4_handle_dmatcr0_addr_r(uint32_t mem_mask) { return m_SH4_DMATCR0; }
- uint32_t sh4_handle_dmatcr1_addr_r(uint32_t mem_mask) { return m_SH4_DMATCR1; }
- uint32_t sh4_handle_dmatcr2_addr_r(uint32_t mem_mask) { return m_SH4_DMATCR2; }
- uint32_t sh4_handle_dmatcr3_addr_r(uint32_t mem_mask) { return m_SH4_DMATCR3; }
- uint32_t sh4_handle_chcr0_addr_r(uint32_t mem_mask) { return m_SH4_CHCR0; }
- uint32_t sh4_handle_chcr1_addr_r(uint32_t mem_mask) { return m_SH4_CHCR1; }
- uint32_t sh4_handle_chcr2_addr_r(uint32_t mem_mask) { return m_SH4_CHCR2; }
- uint32_t sh4_handle_chcr3_addr_r(uint32_t mem_mask) { return m_SH4_CHCR3; }
- uint32_t sh4_handle_dmaor_addr_r(uint32_t mem_mask) { return m_SH4_DMAOR; }
+ uint32_t sar0_r(offs_t offset, uint32_t mem_mask);
+ void sar0_w(offs_t offset, uint32_t data, uint32_t mem_mask);
+ uint32_t dar0_r(offs_t offset, uint32_t mem_mask);
+ void dar0_w(offs_t offset, uint32_t data, uint32_t mem_mask);
+ uint32_t dmatcr0_r(offs_t offset, uint32_t mem_mask);
+ void dmatcr0_w(offs_t offset, uint32_t data, uint32_t mem_mask);
+ uint32_t chcr0_r(offs_t offset, uint32_t mem_mask);
+ void chcr0_w(offs_t offset, uint32_t data, uint32_t mem_mask);
+ uint32_t sar1_r(offs_t offset, uint32_t mem_mask);
+ void sar1_w(offs_t offset, uint32_t data, uint32_t mem_mask);
+ uint32_t dar1_r(offs_t offset, uint32_t mem_mask);
+ void dar1_w(offs_t offset, uint32_t data, uint32_t mem_mask);
+ uint32_t dmatcr1_r(offs_t offset, uint32_t mem_mask);
+ void dmatcr1_w(offs_t offset, uint32_t data, uint32_t mem_mask);
+ uint32_t chcr1_r(offs_t offset, uint32_t mem_mask);
+ void chcr1_w(offs_t offset, uint32_t data, uint32_t mem_mask);
+ uint32_t sar2_r(offs_t offset, uint32_t mem_mask);
+ void sar2_w(offs_t offset, uint32_t data, uint32_t mem_mask);
+ uint32_t dar2_r(offs_t offset, uint32_t mem_mask);
+ void dar2_w(offs_t offset, uint32_t data, uint32_t mem_mask);
+ uint32_t dmatcr2_r(offs_t offset, uint32_t mem_mask);
+ void dmatcr2_w(offs_t offset, uint32_t data, uint32_t mem_mask);
+ uint32_t chcr2_r(offs_t offset, uint32_t mem_mask);
+ void chcr2_w(offs_t offset, uint32_t data, uint32_t mem_mask);
+ uint32_t sar3_r(offs_t offset, uint32_t mem_mask);
+ void sar3_w(offs_t offset, uint32_t data, uint32_t mem_mask);
+ uint32_t dar3_r(offs_t offset, uint32_t mem_mask);
+ void dar3_w(offs_t offset, uint32_t data, uint32_t mem_mask);
+ uint32_t dmatcr3_r(offs_t offset, uint32_t mem_mask);
+ void dmatcr3_w(offs_t offset, uint32_t data, uint32_t mem_mask);
+ uint32_t chcr3_r(offs_t offset, uint32_t mem_mask);
+ void chcr3_w(offs_t offset, uint32_t data, uint32_t mem_mask);
+ uint32_t dmaor_r(offs_t offset, uint32_t mem_mask);
+ void dmaor_w(offs_t offset, uint32_t data, uint32_t mem_mask);
// memory handlers
- virtual uint8_t RB(offs_t A) override;
- virtual uint16_t RW(offs_t A) override;
- virtual uint32_t RL(offs_t A) override;
- virtual void WB(offs_t A, uint8_t V) override;
- virtual void WW(offs_t A, uint16_t V) override;
- virtual void WL(offs_t A, uint32_t V) override;
+ virtual uint8_t read_byte(offs_t offset) override;
+ virtual uint16_t read_word(offs_t offset) override;
+ virtual uint32_t read_long(offs_t offset) override;
+ virtual uint16_t decrypted_read_word(offs_t offset) override;
+ virtual void write_byte(offs_t offset, uint8_t data) override;
+ virtual void write_word(offs_t offset, uint16_t data) override;
+ virtual void write_long(offs_t offset, uint32_t data) override;
// regular handlers for opcodes which need to differ on sh3/4 due to different interrupt / exception handling and register banking
virtual void LDCSR(const uint16_t opcode) override;
@@ -681,102 +684,1292 @@ private:
class sh3_base_device : public sh34_base_device
{
-public:
- DECLARE_WRITE32_MEMBER( sh3_internal_w );
- DECLARE_READ32_MEMBER( sh3_internal_r );
-
- DECLARE_WRITE32_MEMBER( sh3_internal_high_w );
- DECLARE_READ32_MEMBER( sh3_internal_high_r );
+ friend class sh4_frontend;
- void sh3_internal_map(address_map &map);
protected:
// construction/destruction
sh3_base_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock, endianness_t endianness);
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+
+ void sh3_internal_map(address_map &map) ATTR_COLD;
+ virtual void sh3_register_map(address_map& map) ATTR_COLD {}
+
+ void ccn_map(address_map& map) ATTR_COLD;
+ void ccn_7709s_map(address_map& map) ATTR_COLD;
+ void ubc_map(address_map& map) ATTR_COLD;
+ void ubc_7709s_map(address_map& map) ATTR_COLD;
+ void cpg_map(address_map& map) ATTR_COLD;
+ void cpg_7709_map(address_map& map) ATTR_COLD;
+ void bsc_map(address_map& map) ATTR_COLD;
+ void bsc_7708_map(address_map& map) ATTR_COLD;
+ void bsc_7709_map(address_map& map) ATTR_COLD;
+ void bsc_7709s_map(address_map& map) ATTR_COLD;
+ void rtc_map(address_map& map) ATTR_COLD;
+ void intc_map(address_map& map) ATTR_COLD;
+ void intc_7709_map(address_map& map) ATTR_COLD;
+ void dmac_7709_map(address_map& map) ATTR_COLD;
+ void tmu_map(address_map& map) ATTR_COLD;
+ void sci_7708_map(address_map& map) ATTR_COLD;
+ void sci_7709_map(address_map& map) ATTR_COLD;
+ void cmt_7709_map(address_map& map) ATTR_COLD;
+ void ad_7709_map(address_map& map) ATTR_COLD;
+ void da_7709_map(address_map& map) ATTR_COLD;
+ void port_7709_map(address_map& map) ATTR_COLD;
+ void irda_7709_map(address_map& map) ATTR_COLD;
+ void scif_7709_map(address_map& map) ATTR_COLD;
+ void udi_7709s_map(address_map& map) ATTR_COLD;
+
+ // CCN
+ uint32_t pteh_r(offs_t offset, uint32_t mem_mask);
+ void pteh_w(offs_t offset, uint32_t data, uint32_t mem_mask);
+ uint32_t ptel_r(offs_t offset, uint32_t mem_mask);
+ void ptel_w(offs_t offset, uint32_t data, uint32_t mem_mask);
+ uint32_t ttb_r(offs_t offset, uint32_t mem_mask);
+ void ttb_w(offs_t offset, uint32_t data, uint32_t mem_mask);
+ uint32_t tea_r(offs_t offset, uint32_t mem_mask);
+ void tea_w(offs_t offset, uint32_t data, uint32_t mem_mask);
+ uint32_t mmucr_r(offs_t offset, uint32_t mem_mask);
+ void mmucr_w(offs_t offset, uint32_t data, uint32_t mem_mask);
+ uint8_t basra_r(offs_t offset, uint8_t mem_mask);
+ void basra_w(offs_t offset, uint8_t data, uint8_t mem_mask);
+ uint8_t basrb_r(offs_t offset, uint8_t mem_mask);
+ void basrb_w(offs_t offset, uint8_t data, uint8_t mem_mask);
+ uint32_t ccr_r(offs_t offset, uint32_t mem_mask);
+ void ccr_w(offs_t offset, uint32_t data, uint32_t mem_mask);
+ uint32_t tra_r(offs_t offset, uint32_t mem_mask);
+ void tra_w(offs_t offset, uint32_t data, uint32_t mem_mask);
+ uint32_t expevt_r(offs_t offset, uint32_t mem_mask);
+ void expevt_w(offs_t offset, uint32_t data, uint32_t mem_mask);
+ uint32_t intevt_r(offs_t offset, uint32_t mem_mask);
+ void intevt_w(offs_t offset, uint32_t data, uint32_t mem_mask);
+
+ // CCN 7709S
+ uint32_t ccr2_r(offs_t offset, uint32_t mem_mask);
+ void ccr2_w(offs_t offset, uint32_t data, uint32_t mem_mask);
+
+ // UBC
+ uint32_t bara_r(offs_t offset, uint32_t mem_mask);
+ void bara_w(offs_t offset, uint32_t data, uint32_t mem_mask);
+ uint8_t bamra_r(offs_t offset, uint8_t mem_mask);
+ void bamra_w(offs_t offset, uint8_t data, uint8_t mem_mask);
+ uint16_t bbra_r(offs_t offset, uint16_t mem_mask);
+ void bbra_w(offs_t offset, uint16_t data, uint16_t mem_mask);
+ uint32_t barb_r(offs_t offset, uint32_t mem_mask);
+ void barb_w(offs_t offset, uint32_t data, uint32_t mem_mask);
+ uint8_t bamrb_r(offs_t offset, uint8_t mem_mask);
+ void bamrb_w(offs_t offset, uint8_t data, uint8_t mem_mask);
+ uint16_t bbrb_r(offs_t offset, uint16_t mem_mask);
+ void bbrb_w(offs_t offset, uint16_t data, uint16_t mem_mask);
+ uint32_t bdrb_r(offs_t offset, uint32_t mem_mask);
+ void bdrb_w(offs_t offset, uint32_t data, uint32_t mem_mask);
+ uint32_t bdmrb_r(offs_t offset, uint32_t mem_mask);
+ void bdmrb_w(offs_t offset, uint32_t data, uint32_t mem_mask);
+ uint16_t brcr_r(offs_t offset, uint16_t mem_mask);
+ void brcr_w(offs_t offset, uint16_t data, uint16_t mem_mask);
+
+ // UBC 7709S
+ uint16_t betr_r(offs_t offset, uint16_t mem_mask);
+ void betr_w(offs_t offset, uint16_t data, uint16_t mem_mask);
+ uint32_t brsr_r(offs_t offset, uint32_t mem_mask);
+ void brsr_w(offs_t offset, uint32_t data, uint32_t mem_mask);
+ uint32_t brdr_r(offs_t offset, uint32_t mem_mask);
+ void brdr_w(offs_t offset, uint32_t data, uint32_t mem_mask);
+
+ // CPG
+ uint16_t frqcr_r(offs_t offset, uint16_t mem_mask);
+ void frqcr_w(offs_t offset, uint16_t data, uint16_t mem_mask);
+ uint8_t stbcr_r(offs_t offset, uint8_t mem_mask);
+ void stbcr_w(offs_t offset, uint8_t data, uint8_t mem_mask);
+ uint8_t wtcnt_r(offs_t offset, uint8_t mem_mask);
+ void wtcnt_w(offs_t offset, uint16_t data, uint16_t mem_mask);
+ uint8_t wtcsr_r(offs_t offset, uint8_t mem_mask);
+ void wtcsr_w(offs_t offset, uint16_t data, uint16_t mem_mask);
+
+ // CPG 7709
+ uint8_t stbcr2_r(offs_t offset, uint8_t mem_mask);
+ void stbcr2_w(offs_t offset, uint8_t data, uint8_t mem_mask);
+
+ // BSC
+ uint16_t bcr1_r(offs_t offset, uint16_t mem_mask);
+ void bcr1_w(offs_t offset, uint16_t data, uint16_t mem_mask);
+ uint16_t bcr2_r(offs_t offset, uint16_t mem_mask);
+ void bcr2_w(offs_t offset, uint16_t data, uint16_t mem_mask);
+ uint16_t wcr1_r(offs_t offset, uint16_t mem_mask);
+ void wcr1_w(offs_t offset, uint16_t data, uint16_t mem_mask);
+ uint16_t wcr2_r(offs_t offset, uint16_t mem_mask);
+ void wcr2_w(offs_t offset, uint16_t data, uint16_t mem_mask);
+ uint16_t mcr_r(offs_t offset, uint16_t mem_mask);
+ void mcr_w(offs_t offset, uint16_t data, uint16_t mem_mask);
+ uint16_t pcr_r(offs_t offset, uint16_t mem_mask);
+ void pcr_w(offs_t offset, uint16_t data, uint16_t mem_mask);
+ uint16_t rtcsr_r(offs_t offset, uint16_t mem_mask);
+ void rtcsr_w(offs_t offset, uint16_t data, uint16_t mem_mask);
+ uint16_t rtcnt_r(offs_t offset, uint16_t mem_mask);
+ void rtcnt_w(offs_t offset, uint16_t data, uint16_t mem_mask);
+ uint16_t rtcor_r(offs_t offset, uint16_t mem_mask);
+ void rtcor_w(offs_t offset, uint16_t data, uint16_t mem_mask);
+ uint16_t rfcr_r(offs_t offset, uint16_t mem_mask);
+ void rfcr_w(offs_t offset, uint16_t data, uint16_t mem_mask);
+ uint8_t sdmr_r(offs_t offset, uint8_t mem_mask);
+ void sdmr_w(offs_t offset, uint8_t data, uint8_t mem_mask);
+
+ // BSC 7708
+ uint16_t dcr_r(offs_t offset, uint16_t mem_mask);
+ void dcr_w(offs_t offset, uint16_t data, uint16_t mem_mask);
+ uint16_t pctr_r(offs_t offset, uint16_t mem_mask);
+ void pctr_w(offs_t offset, uint16_t data, uint16_t mem_mask);
+ uint16_t pdtr_r(offs_t offset, uint16_t mem_mask);
+ void pdtr_w(offs_t offset, uint16_t data, uint16_t mem_mask);
+
+ // BSC 7709
+ uint16_t bcr3_r(offs_t offset, uint16_t mem_mask);
+ void bcr3_w(offs_t offset, uint16_t data, uint16_t mem_mask);
+
+ // BSC 7709S
+ uint16_t mcscr0_r(offs_t offset, uint16_t mem_mask);
+ void mcscr0_w(offs_t offset, uint16_t data, uint16_t mem_mask);
+ uint16_t mcscr1_r(offs_t offset, uint16_t mem_mask);
+ void mcscr1_w(offs_t offset, uint16_t data, uint16_t mem_mask);
+ uint16_t mcscr2_r(offs_t offset, uint16_t mem_mask);
+ void mcscr2_w(offs_t offset, uint16_t data, uint16_t mem_mask);
+ uint16_t mcscr3_r(offs_t offset, uint16_t mem_mask);
+ void mcscr3_w(offs_t offset, uint16_t data, uint16_t mem_mask);
+ uint16_t mcscr4_r(offs_t offset, uint16_t mem_mask);
+ void mcscr4_w(offs_t offset, uint16_t data, uint16_t mem_mask);
+ uint16_t mcscr5_r(offs_t offset, uint16_t mem_mask);
+ void mcscr5_w(offs_t offset, uint16_t data, uint16_t mem_mask);
+ uint16_t mcscr6_r(offs_t offset, uint16_t mem_mask);
+ void mcscr6_w(offs_t offset, uint16_t data, uint16_t mem_mask);
+ uint16_t mcscr7_r(offs_t offset, uint16_t mem_mask);
+ void mcscr7_w(offs_t offset, uint16_t data, uint16_t mem_mask);
+
+ // RTC
+ uint8_t r64cnt_r(offs_t offset, uint8_t mem_mask);
+ uint8_t rseccnt_r(offs_t offset, uint8_t mem_mask);
+ void rseccnt_w(offs_t offset, uint8_t data, uint8_t mem_mask);
+ uint8_t rmincnt_r(offs_t offset, uint8_t mem_mask);
+ void rmincnt_w(offs_t offset, uint8_t data, uint8_t mem_mask);
+ uint8_t rhrcnt_r(offs_t offset, uint8_t mem_mask);
+ void rhrcnt_w(offs_t offset, uint8_t data, uint8_t mem_mask);
+ uint8_t rwkcnt_r(offs_t offset, uint8_t mem_mask);
+ void rwkcnt_w(offs_t offset, uint8_t data, uint8_t mem_mask);
+ uint8_t rdaycnt_r(offs_t offset, uint8_t mem_mask);
+ void rdaycnt_w(offs_t offset, uint8_t data, uint8_t mem_mask);
+ uint8_t rmoncnt_r(offs_t offset, uint8_t mem_mask);
+ void rmoncnt_w(offs_t offset, uint8_t data, uint8_t mem_mask);
+ uint8_t ryrcnt_r(offs_t offset, uint8_t mem_mask);
+ void ryrcnt_w(offs_t offset, uint8_t data, uint8_t mem_mask);
+ uint8_t rsecar_r(offs_t offset, uint8_t mem_mask);
+ void rsecar_w(offs_t offset, uint8_t data, uint8_t mem_mask);
+ uint8_t rminar_r(offs_t offset, uint8_t mem_mask);
+ void rminar_w(offs_t offset, uint8_t data, uint8_t mem_mask);
+ uint8_t rhrar_r(offs_t offset, uint8_t mem_mask);
+ void rhrar_w(offs_t offset, uint8_t data, uint8_t mem_mask);
+ uint8_t rwkar_r(offs_t offset, uint8_t mem_mask);
+ void rwkar_w(offs_t offset, uint8_t data, uint8_t mem_mask);
+ uint8_t rdayar_r(offs_t offset, uint8_t mem_mask);
+ void rdayar_w(offs_t offset, uint8_t data, uint8_t mem_mask);
+ uint8_t rmonar_r(offs_t offset, uint8_t mem_mask);
+ void rmonar_w(offs_t offset, uint8_t data, uint8_t mem_mask);
+ uint8_t rcr1_r(offs_t offset, uint8_t mem_mask);
+ void rcr1_w(offs_t offset, uint8_t data, uint8_t mem_mask);
+ uint8_t rcr2_r(offs_t offset, uint8_t mem_mask);
+ void rcr2_w(offs_t offset, uint8_t data, uint8_t mem_mask);
+
+ // INTC
+ uint16_t icr0_r(offs_t offset, uint16_t mem_mask);
+ void icr0_w(offs_t offset, uint16_t data, uint16_t mem_mask);
+ uint16_t iprb_r(offs_t offset, uint16_t mem_mask);
+ void iprb_w(offs_t offset, uint16_t data, uint16_t mem_mask);
+
+ // INTC 7709
+ uint32_t intevt2_r(offs_t offset, uint32_t mem_mask);
+ void intevt2_w(offs_t offset, uint32_t data, uint32_t mem_mask);
+ uint8_t irr0_r(offs_t offset, uint8_t mem_mask);
+ void irr0_w(offs_t offset, uint8_t data, uint8_t mem_mask);
+ uint8_t irr1_r(offs_t offset, uint8_t mem_mask);
+ void irr1_w(offs_t offset, uint8_t data, uint8_t mem_mask);
+ uint8_t irr2_r(offs_t offset, uint8_t mem_mask);
+ void irr2_w(offs_t offset, uint8_t data, uint8_t mem_mask);
+ uint16_t icr1_r(offs_t offset, uint16_t mem_mask);
+ void icr1_w(offs_t offset, uint16_t data, uint16_t mem_mask);
+ uint16_t icr2_r(offs_t offset, uint16_t mem_mask);
+ void icr2_w(offs_t offset, uint16_t data, uint16_t mem_mask);
+ uint16_t pinter_r(offs_t offset, uint16_t mem_mask);
+ void pinter_w(offs_t offset, uint16_t data, uint16_t mem_mask);
+ uint16_t iprc_r(offs_t offset, uint16_t mem_mask);
+ void iprc_w(offs_t offset, uint16_t data, uint16_t mem_mask);
+ uint16_t iprd_r(offs_t offset, uint16_t mem_mask);
+ void iprd_w(offs_t offset, uint16_t data, uint16_t mem_mask);
+ uint16_t ipre_r(offs_t offset, uint16_t mem_mask);
+ void ipre_w(offs_t offset, uint16_t data, uint16_t mem_mask);
+
+ // SCI
+ uint8_t scsmr_r(offs_t offset, uint8_t mem_mask);
+ void scsmr_w(offs_t offset, uint8_t data, uint8_t mem_mask);
+ uint8_t scbrr_r(offs_t offset, uint8_t mem_mask);
+ void scbrr_w(offs_t offset, uint8_t data, uint8_t mem_mask);
+ uint8_t scscr_r(offs_t offset, uint8_t mem_mask);
+ void scscr_w(offs_t offset, uint8_t data, uint8_t mem_mask);
+ uint8_t sctdr_r(offs_t offset, uint8_t mem_mask);
+ void sctdr_w(offs_t offset, uint8_t data, uint8_t mem_mask);
+ uint8_t scssr_r(offs_t offset, uint8_t mem_mask);
+ void scssr_w(offs_t offset, uint8_t data, uint8_t mem_mask);
+ uint8_t scrdr_r(offs_t offset, uint8_t mem_mask);
+ void scscmr_w(offs_t offset, uint8_t data, uint8_t mem_mask);
+ uint8_t scscmr_r(offs_t offset, uint8_t mem_mask);
+
+ // SCI 7708
+ uint8_t scsptr_r(offs_t offset, uint8_t mem_mask);
+ void scsptr_w(offs_t offset, uint8_t data, uint8_t mem_mask);
+
+ // CMT 7709
+ uint16_t cmstr_r(offs_t offset, uint16_t mem_mask);
+ void cmstr_w(offs_t offset, uint16_t data, uint16_t mem_mask);
+ uint16_t cmscr_r(offs_t offset, uint16_t mem_mask);
+ void cmscr_w(offs_t offset, uint16_t data, uint16_t mem_mask);
+ uint16_t cmcnt_r(offs_t offset, uint16_t mem_mask);
+ void cmcnt_w(offs_t offset, uint16_t data, uint16_t mem_mask);
+ uint16_t cmcor_r(offs_t offset, uint16_t mem_mask);
+ void cmcor_w(offs_t offset, uint16_t data, uint16_t mem_mask);
+
+ // AD 7709
+ uint8_t addrah_r(offs_t offset, uint8_t mem_mask);
+ void addrah_w(offs_t offset, uint8_t data, uint8_t mem_mask);
+ uint8_t addral_r(offs_t offset, uint8_t mem_mask);
+ void addral_w(offs_t offset, uint8_t data, uint8_t mem_mask);
+ uint8_t addrbh_r(offs_t offset, uint8_t mem_mask);
+ void addrbh_w(offs_t offset, uint8_t data, uint8_t mem_mask);
+ uint8_t addrbl_r(offs_t offset, uint8_t mem_mask);
+ void addrbl_w(offs_t offset, uint8_t data, uint8_t mem_mask);
+ uint8_t addrch_r(offs_t offset, uint8_t mem_mask);
+ void addrch_w(offs_t offset, uint8_t data, uint8_t mem_mask);
+ uint8_t addrcl_r(offs_t offset, uint8_t mem_mask);
+ void addrcl_w(offs_t offset, uint8_t data, uint8_t mem_mask);
+ uint8_t addrdh_r(offs_t offset, uint8_t mem_mask);
+ void addrdh_w(offs_t offset, uint8_t data, uint8_t mem_mask);
+ uint8_t addrdl_r(offs_t offset, uint8_t mem_mask);
+ void addrdl_w(offs_t offset, uint8_t data, uint8_t mem_mask);
+ uint8_t adcsr_r(offs_t offset, uint8_t mem_mask);
+ void adcsr_w(offs_t offset, uint8_t data, uint8_t mem_mask);
+ uint8_t adcr_r(offs_t offset, uint8_t mem_mask);
+ void adcr_w(offs_t offset, uint8_t data, uint8_t mem_mask);
+
+ // DA 7709
+ uint8_t dadr0_r(offs_t offset, uint8_t mem_mask);
+ void dadr0_w(offs_t offset, uint8_t data, uint8_t mem_mask);
+ uint8_t dadr1_r(offs_t offset, uint8_t mem_mask);
+ void dadr1_w(offs_t offset, uint8_t data, uint8_t mem_mask);
+ uint8_t dadcr_r(offs_t offset, uint8_t mem_mask);
+ void dadcr_w(offs_t offset, uint8_t data, uint8_t mem_mask);
+
+ // PORT 7709
+ uint16_t pacr_r(offs_t offset, uint16_t mem_mask);
+ void pacr_w(offs_t offset, uint16_t data, uint16_t mem_mask);
+ uint16_t pbcr_r(offs_t offset, uint16_t mem_mask);
+ void pbcr_w(offs_t offset, uint16_t data, uint16_t mem_mask);
+ uint16_t pccr_r(offs_t offset, uint16_t mem_mask);
+ void pccr_w(offs_t offset, uint16_t data, uint16_t mem_mask);
+ uint16_t pdcr_r(offs_t offset, uint16_t mem_mask);
+ void pdcr_w(offs_t offset, uint16_t data, uint16_t mem_mask);
+ uint16_t pecr_r(offs_t offset, uint16_t mem_mask);
+ void pecr_w(offs_t offset, uint16_t data, uint16_t mem_mask);
+ uint16_t pfcr_r(offs_t offset, uint16_t mem_mask);
+ void pfcr_w(offs_t offset, uint16_t data, uint16_t mem_mask);
+ uint16_t pgcr_r(offs_t offset, uint16_t mem_mask);
+ void pgcr_w(offs_t offset, uint16_t data, uint16_t mem_mask);
+ uint16_t phcr_r(offs_t offset, uint16_t mem_mask);
+ void phcr_w(offs_t offset, uint16_t data, uint16_t mem_mask);
+ uint16_t pjcr_r(offs_t offset, uint16_t mem_mask);
+ void pjcr_w(offs_t offset, uint16_t data, uint16_t mem_mask);
+ uint16_t pkcr_r(offs_t offset, uint16_t mem_mask);
+ void pkcr_w(offs_t offset, uint16_t data, uint16_t mem_mask);
+ uint16_t plcr_r(offs_t offset, uint16_t mem_mask);
+ void plcr_w(offs_t offset, uint16_t data, uint16_t mem_mask);
+ uint16_t scpcr_r(offs_t offset, uint16_t mem_mask);
+ void scpcr_w(offs_t offset, uint16_t data, uint16_t mem_mask);
+ uint8_t padr_r(offs_t offset, uint8_t mem_mask);
+ void padr_w(offs_t offset, uint8_t data, uint8_t mem_mask);
+ uint8_t pbdr_r(offs_t offset, uint8_t mem_mask);
+ void pbdr_w(offs_t offset, uint8_t data, uint8_t mem_mask);
+ uint8_t pcdr_r(offs_t offset, uint8_t mem_mask);
+ void pcdr_w(offs_t offset, uint8_t data, uint8_t mem_mask);
+ uint8_t pddr_r(offs_t offset, uint8_t mem_mask);
+ void pddr_w(offs_t offset, uint8_t data, uint8_t mem_mask);
+ uint8_t pedr_r(offs_t offset, uint8_t mem_mask);
+ void pedr_w(offs_t offset, uint8_t data, uint8_t mem_mask);
+ uint8_t pfdr_r(offs_t offset, uint8_t mem_mask);
+ void pfdr_w(offs_t offset, uint8_t data, uint8_t mem_mask);
+ uint8_t pgdr_r(offs_t offset, uint8_t mem_mask);
+ void pgdr_w(offs_t offset, uint8_t data, uint8_t mem_mask);
+ uint8_t phdr_r(offs_t offset, uint8_t mem_mask);
+ void phdr_w(offs_t offset, uint8_t data, uint8_t mem_mask);
+ uint8_t pjdr_r(offs_t offset, uint8_t mem_mask);
+ void pjdr_w(offs_t offset, uint8_t data, uint8_t mem_mask);
+ uint8_t pkdr_r(offs_t offset, uint8_t mem_mask);
+ void pkdr_w(offs_t offset, uint8_t data, uint8_t mem_mask);
+ uint8_t pldr_r(offs_t offset, uint8_t mem_mask);
+ void pldr_w(offs_t offset, uint8_t data, uint8_t mem_mask);
+ uint8_t scpdr_r(offs_t offset, uint8_t mem_mask);
+ void scpdr_w(offs_t offset, uint8_t data, uint8_t mem_mask);
+
+ // IRDA 7709
+ uint8_t scsmr1_r(offs_t offset, uint8_t mem_mask);
+ void scsmr1_w(offs_t offset, uint8_t data, uint8_t mem_mask);
+ uint8_t scbrr1_r(offs_t offset, uint8_t mem_mask);
+ void scbrr1_w(offs_t offset, uint8_t data, uint8_t mem_mask);
+ uint8_t scscr1_r(offs_t offset, uint8_t mem_mask);
+ void scscr1_w(offs_t offset, uint8_t data, uint8_t mem_mask);
+ uint8_t scftdr1_r(offs_t offset, uint8_t mem_mask);
+ void scftdr1_w(offs_t offset, uint8_t data, uint8_t mem_mask);
+ uint16_t scssr1_r(offs_t offset, uint16_t mem_mask);
+ void scssr1_w(offs_t offset, uint16_t data, uint16_t mem_mask);
+ uint8_t scfrdr1_r(offs_t offset, uint8_t mem_mask);
+ void scfrdr1_w(offs_t offset, uint8_t data, uint8_t mem_mask);
+ uint8_t scfcr1_r(offs_t offset, uint8_t mem_mask);
+ void scfcr1_w(offs_t offset, uint8_t data, uint8_t mem_mask);
+ uint16_t scfdr1_r(offs_t offset, uint16_t mem_mask);
+ void scfdr1_w(offs_t offset, uint16_t data, uint16_t mem_mask);
+
+ // SCIF 7709
+ uint8_t scsmr2_r(offs_t offset, uint8_t mem_mask);
+ void scsmr2_w(offs_t offset, uint8_t data, uint8_t mem_mask);
+ uint8_t scbrr2_r(offs_t offset, uint8_t mem_mask);
+ void scbrr2_w(offs_t offset, uint8_t data, uint8_t mem_mask);
+ uint8_t scscr2_r(offs_t offset, uint8_t mem_mask);
+ void scscr2_w(offs_t offset, uint8_t data, uint8_t mem_mask);
+ uint8_t scftdr2_r(offs_t offset, uint8_t mem_mask);
+ void scftdr2_w(offs_t offset, uint8_t data, uint8_t mem_mask);
+ uint16_t scssr2_r(offs_t offset, uint16_t mem_mask);
+ void scssr2_w(offs_t offset, uint16_t data, uint16_t mem_mask);
+ uint8_t scfrdr2_r(offs_t offset, uint8_t mem_mask);
+ void scfrdr2_w(offs_t offset, uint8_t data, uint8_t mem_mask);
+ uint8_t scfcr2_r(offs_t offset, uint8_t mem_mask);
+ void scfcr2_w(offs_t offset, uint8_t data, uint8_t mem_mask);
+ uint16_t scfdr2_r(offs_t offset, uint16_t mem_mask);
+ void scfdr2_w(offs_t offset, uint16_t data, uint16_t mem_mask);
+
+ // UDI 7709S
+ uint16_t sdir_r(offs_t offset, uint16_t mem_mask);
+ void sdir_w(offs_t offset, uint16_t data, uint16_t mem_mask);
+
+ std::unique_ptr<sh4_frontend> m_drcfe; /* pointer to the DRC front-end state */
+ virtual const opcode_desc* get_desclist(offs_t pc) override;
+ virtual void init_drc_frontend() override;
+
+ // UBC
+ uint32_t m_bara;
+ uint8_t m_bamra;
+ uint16_t m_bbra;
+ uint32_t m_barb;
+ uint8_t m_bamrb;
+ uint16_t m_bbrb;
+ uint32_t m_bdrb;
+ uint32_t m_bdmrb;
+ uint16_t m_brcr;
+
+ // UBC 7709S
+ uint16_t m_betr;
+ uint32_t m_brsr;
+ uint32_t m_brdr;
+
+ // CPG
+ uint16_t m_frqcr;
+ uint8_t m_stbcr;
+ uint16_t m_wtcnt;
+ uint16_t m_wtcsr;
+
+ // CPG 7709
+ uint8_t m_stbcr2;
+
+ // BSC
+ uint16_t m_bcr1;
+ uint16_t m_bcr2;
+ uint16_t m_wcr1;
+ uint16_t m_wcr2;
+ uint16_t m_mcr;
+ uint16_t m_pcr;
+ uint16_t m_rtcsr;
+ uint16_t m_rtcnt;
+ uint16_t m_rtcor;
+ uint16_t m_rfcr;
+
+ // BSC 7708
+ uint16_t m_dcr;
+ uint16_t m_pctr;
+ uint16_t m_pdtr;
+
+ // BSC 7709
+ uint16_t m_bcr3;
+
+ // BSC 7709S
+ uint16_t m_mcscr0;
+ uint16_t m_mcscr1;
+ uint16_t m_mcscr2;
+ uint16_t m_mcscr3;
+ uint16_t m_mcscr4;
+ uint16_t m_mcscr5;
+ uint16_t m_mcscr6;
+ uint16_t m_mcscr7;
+
+ // RTC
+ uint8_t m_r64cnt;
+ uint8_t m_rseccnt;
+ uint8_t m_rmincnt;
+ uint8_t m_rhrcnt;
+ uint8_t m_rwkcnt;
+ uint8_t m_rmoncnt;
+ uint8_t m_rdaycnt;
+ uint8_t m_ryrcnt;
+ uint8_t m_rsecar;
+ uint8_t m_rminar;
+ uint8_t m_rhrar;
+ uint8_t m_rwkar;
+ uint8_t m_rdayar;
+ uint8_t m_rmonar;
+ uint8_t m_rcr1;
+ uint8_t m_rcr2;
+
+ // INTC
+ uint16_t m_icr0;
+ uint16_t m_iprb;
+
+ // INTC 7709
+ uint8_t m_irr0;
+ uint8_t m_irr1;
+ uint8_t m_irr2;
+ uint16_t m_icr1;
+ uint16_t m_icr2;
+ uint16_t m_pinter;
+ uint16_t m_iprd;
+ uint16_t m_ipre;
+
+ // SCI
+ uint8_t m_scsmr;
+ uint8_t m_scbrr;
+ uint8_t m_scscr;
+ uint8_t m_sctdr;
+ uint8_t m_scssr;
+ uint8_t m_scrdr;
+ uint8_t m_scscmr;
+
+ // SCI 7709
+ uint8_t m_scsptr;
+
+ // CMT 7709
+ uint16_t m_cmstr;
+ uint16_t m_cmscr;
+ uint16_t m_cmcnt;
+ uint16_t m_cmcor;
+
+ // AD 7709
+ uint8_t m_addrah;
+ uint8_t m_addral;
+ uint8_t m_addrbh;
+ uint8_t m_addrbl;
+ uint8_t m_addrch;
+ uint8_t m_addrcl;
+ uint8_t m_addrdh;
+ uint8_t m_addrdl;
+ uint8_t m_adcsr;
+ uint8_t m_adcr;
+
+ // DA 7709
+ uint8_t m_dadr0;
+ uint8_t m_dadr1;
+ uint8_t m_dadcr;
+
+ // PORT 7709
+ uint16_t m_pacr;
+ uint16_t m_pbcr;
+ uint16_t m_pccr;
+ uint16_t m_pdcr;
+ uint16_t m_pecr;
+ uint16_t m_pfcr;
+ uint16_t m_pgcr;
+ uint16_t m_phcr;
+ uint16_t m_pjcr;
+ uint16_t m_pkcr;
+ uint16_t m_plcr;
+ uint16_t m_scpcr;
+ uint8_t m_padr;
+ uint8_t m_pbdr;
+ uint8_t m_pcdr;
+ uint8_t m_pddr;
+ uint8_t m_pedr;
+ uint8_t m_pfdr;
+ uint8_t m_pgdr;
+ uint8_t m_phdr;
+ uint8_t m_pjdr;
+ uint8_t m_pkdr;
+ uint8_t m_pldr;
+ uint8_t m_scpdr;
+
+ // IRDA 7709
+ uint8_t m_scsmr1;
+ uint8_t m_scbrr1;
+ uint8_t m_scscr1;
+ uint8_t m_scftdr1;
+ uint16_t m_scssr1;
+ uint8_t m_scfrdr1;
+ uint8_t m_scfcr1;
+ uint16_t m_scfdr1;
+
+ // SCIF 7709
+ uint8_t m_scsmr2;
+ uint8_t m_scbrr2;
+ uint8_t m_scscr2;
+ uint8_t m_scftdr2;
+ uint16_t m_scssr2;
+ uint16_t m_scfrdr2;
+ uint8_t m_scfcr2;
+ uint8_t m_scfdr2;
+
+ // UDI 7709S
+ uint16_t m_sdir;
};
class sh4_base_device : public sh34_base_device
{
-public:
- DECLARE_WRITE32_MEMBER( sh4_internal_w );
- DECLARE_READ32_MEMBER( sh4_internal_r );
+protected:
+ friend class sh4_frontend;
- DECLARE_READ64_MEMBER( sh4_utlb_address_array_r );
- DECLARE_WRITE64_MEMBER( sh4_utlb_address_array_w );
- DECLARE_READ64_MEMBER( sh4_utlb_data_array1_r );
- DECLARE_WRITE64_MEMBER( sh4_utlb_data_array1_w );
- DECLARE_READ64_MEMBER( sh4_utlb_data_array2_r );
- DECLARE_WRITE64_MEMBER( sh4_utlb_data_array2_w );
+ // construction/destruction
+ sh4_base_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock, endianness_t endianness);
+
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+
+ virtual void init_drc_frontend() override;
+ std::unique_ptr<sh4_frontend> m_drcfe; /* pointer to the DRC front-end state */
+ virtual const opcode_desc* get_desclist(offs_t pc) override;
+ void sh4_internal_map(address_map& map) ATTR_COLD;
+ virtual void sh4_register_map(address_map& map) ATTR_COLD {}
+
+ void ccn_map(address_map &map) ATTR_COLD;
+ void ubc_map(address_map& map) ATTR_COLD;
+ void bsc_map(address_map& map) ATTR_COLD;
+ void bsc_7750r_map(address_map& map) ATTR_COLD;
+ void dmac_map(address_map& map) ATTR_COLD;
+ void dmac_7750r_map(address_map& map) ATTR_COLD;
+ void cpg_map(address_map& map) ATTR_COLD;
+ void cpg_7750r_map(address_map& map) ATTR_COLD;
+ void rtc_map(address_map& map) ATTR_COLD;
+ void rtc_7750r_map(address_map& map) ATTR_COLD;
+ void intc_map(address_map& map) ATTR_COLD;
+ void intc_7750s_map(address_map& map) ATTR_COLD;
+ void intc_7750r_map(address_map& map) ATTR_COLD;
+ void tmu_map(address_map& map) ATTR_COLD;
+ void tmu_7750r_map(address_map& map) ATTR_COLD;
+ void sci_map(address_map &map) ATTR_COLD;
+ void scif_map(address_map &map) ATTR_COLD;
+ void hudi_map(address_map& map) ATTR_COLD;
+ void hudi_7750r_map(address_map& map) ATTR_COLD;
+ void pci_7751_map(address_map& map) ATTR_COLD;
+
+ uint64_t sh4_utlb_address_array_r(offs_t offset);
+ void sh4_utlb_address_array_w(offs_t offset, uint64_t data);
+ uint64_t sh4_utlb_data_array1_r(offs_t offset);
+ void sh4_utlb_data_array1_w(offs_t offset, uint64_t data);
+ uint64_t sh4_utlb_data_array2_r(offs_t offset);
+ void sh4_utlb_data_array2_w(offs_t offset, uint64_t data);
+
+ // CCN
+ uint32_t pteh_r(offs_t offset, uint32_t mem_mask);
+ void pteh_w(offs_t offset, uint32_t data, uint32_t mem_mask);
+ uint32_t ptel_r(offs_t offset, uint32_t mem_mask);
+ void ptel_w(offs_t offset, uint32_t data, uint32_t mem_mask);
+ uint32_t ttb_r(offs_t offset, uint32_t mem_mask);
+ void ttb_w(offs_t offset, uint32_t data, uint32_t mem_mask);
+ uint32_t tea_r(offs_t offset, uint32_t mem_mask);
+ void tea_w(offs_t offset, uint32_t data, uint32_t mem_mask);
+ uint32_t mmucr_r(offs_t offset, uint32_t mem_mask);
+ void mmucr_w(offs_t offset, uint32_t data, uint32_t mem_mask);
+ uint8_t basra_r(offs_t offset, uint8_t mem_mask);
+ void basra_w(offs_t offset, uint8_t data, uint8_t mem_mask);
+ uint8_t basrb_r(offs_t offset, uint8_t mem_mask);
+ void basrb_w(offs_t offset, uint8_t data, uint8_t mem_mask);
+ uint32_t ccr_r(offs_t offset, uint32_t mem_mask);
+ void ccr_w(offs_t offset, uint32_t data, uint32_t mem_mask);
+ uint32_t tra_r(offs_t offset, uint32_t mem_mask);
+ void tra_w(offs_t offset, uint32_t data, uint32_t mem_mask);
+ uint32_t expevt_r(offs_t offset, uint32_t mem_mask);
+ void expevt_w(offs_t offset, uint32_t data, uint32_t mem_mask);
+ uint32_t intevt_r(offs_t offset, uint32_t mem_mask);
+ void intevt_w(offs_t offset, uint32_t data, uint32_t mem_mask);
+ uint32_t ptea_r(offs_t offset, uint32_t mem_mask);
+ void ptea_w(offs_t offset, uint32_t data, uint32_t mem_mask);
+ uint32_t qacr0_r(offs_t offset, uint32_t mem_mask);
+ void qacr0_w(offs_t offset, uint32_t data, uint32_t mem_mask);
+ uint32_t qacr1_r(offs_t offset, uint32_t mem_mask);
+ void qacr1_w(offs_t offset, uint32_t data, uint32_t mem_mask);
+
+ // UBC
+ uint32_t bara_r(offs_t offset, uint32_t mem_mask);
+ void bara_w(offs_t offset, uint32_t data, uint32_t mem_mask);
+ uint8_t bamra_r(offs_t offset, uint8_t mem_mask);
+ void bamra_w(offs_t offset, uint8_t data, uint8_t mem_mask);
+ uint16_t bbra_r(offs_t offset, uint16_t mem_mask);
+ void bbra_w(offs_t offset, uint16_t data, uint16_t mem_mask);
+ uint32_t barb_r(offs_t offset, uint32_t mem_mask);
+ void barb_w(offs_t offset, uint32_t data, uint32_t mem_mask);
+ uint8_t bamrb_r(offs_t offset, uint8_t mem_mask);
+ void bamrb_w(offs_t offset, uint8_t data, uint8_t mem_mask);
+ uint16_t bbrb_r(offs_t offset, uint16_t mem_mask);
+ void bbrb_w(offs_t offset, uint16_t data, uint16_t mem_mask);
+ uint32_t bdrb_r(offs_t offset, uint32_t mem_mask);
+ void bdrb_w(offs_t offset, uint32_t data, uint32_t mem_mask);
+ uint32_t bdmrb_r(offs_t offset, uint32_t mem_mask);
+ void bdmrb_w(offs_t offset, uint32_t data, uint32_t mem_mask);
+ uint16_t brcr_r(offs_t offset, uint16_t mem_mask);
+ void brcr_w(offs_t offset, uint16_t data, uint16_t mem_mask);
+
+ // BSC
+ uint32_t bcr1_r(offs_t offset, uint32_t mem_mask);
+ void bcr1_w(offs_t offset, uint32_t data, uint32_t mem_mask);
+ uint16_t bcr2_r(offs_t offset, uint16_t mem_mask);
+ void bcr2_w(offs_t offset, uint16_t data, uint16_t mem_mask);
+ uint32_t wcr1_r(offs_t offset, uint32_t mem_mask);
+ void wcr1_w(offs_t offset, uint32_t data, uint32_t mem_mask);
+ uint32_t wcr2_r(offs_t offset, uint32_t mem_mask);
+ void wcr2_w(offs_t offset, uint32_t data, uint32_t mem_mask);
+ uint32_t wcr3_r(offs_t offset, uint32_t mem_mask);
+ void wcr3_w(offs_t offset, uint32_t data, uint32_t mem_mask);
+ uint32_t mcr_r(offs_t offset, uint32_t mem_mask);
+ void mcr_w(offs_t offset, uint32_t data, uint32_t mem_mask);
+ uint16_t pcr_r(offs_t offset, uint16_t mem_mask);
+ void pcr_w(offs_t offset, uint16_t data, uint16_t mem_mask);
+ uint16_t rtcsr_r(offs_t offset, uint16_t mem_mask);
+ void rtcsr_w(offs_t offset, uint16_t data, uint16_t mem_mask);
+ uint16_t rtcnt_r(offs_t offset, uint16_t mem_mask);
+ void rtcnt_w(offs_t offset, uint16_t data, uint16_t mem_mask);
+ uint16_t rtcor_r(offs_t offset, uint16_t mem_mask);
+ void rtcor_w(offs_t offset, uint16_t data, uint16_t mem_mask);
+ uint16_t rfcr_r(offs_t offset, uint16_t mem_mask);
+ void rfcr_w(offs_t offset, uint16_t data, uint16_t mem_mask);
+ uint32_t pctra_r(offs_t offset, uint32_t mem_mask);
+ void pctra_w(offs_t offset, uint32_t data, uint32_t mem_mask);
+ uint16_t pdtra_r(offs_t offset, uint16_t mem_mask);
+ void pdtra_w(offs_t offset, uint16_t data, uint16_t mem_mask);
+ uint32_t pctrb_r(offs_t offset, uint32_t mem_mask);
+ void pctrb_w(offs_t offset, uint32_t data, uint32_t mem_mask);
+ uint16_t pdtrb_r(offs_t offset, uint16_t mem_mask);
+ void pdtrb_w(offs_t offset, uint16_t data, uint16_t mem_mask);
+ uint16_t gpioic_r(offs_t offset, uint16_t mem_mask);
+ void gpioic_w(offs_t offset, uint16_t data, uint16_t mem_mask);
+ void sdmr2_w(offs_t offset, uint8_t data, uint8_t mem_mask);
+ void sdmr3_w(offs_t offset, uint8_t data, uint8_t mem_mask);
+
+ // BSC 7750R
+ uint16_t bcr3_r(offs_t offset, uint16_t mem_mask);
+ void bcr3_w(offs_t offset, uint16_t data, uint16_t mem_mask);
+ uint32_t bcr4_r(offs_t offset, uint32_t mem_mask);
+ void bcr4_w(offs_t offset, uint32_t data, uint32_t mem_mask);
+
+ // DMAC 7750R
+ uint32_t sar4_r(offs_t offset, uint32_t mem_mask);
+ void sar4_w(offs_t offset, uint32_t data, uint32_t mem_mask);
+ uint32_t dar4_r(offs_t offset, uint32_t mem_mask);
+ void dar4_w(offs_t offset, uint32_t data, uint32_t mem_mask);
+ uint32_t dmatcr4_r(offs_t offset, uint32_t mem_mask);
+ void dmatcr4_w(offs_t offset, uint32_t data, uint32_t mem_mask);
+ uint32_t chcr4_r(offs_t offset, uint32_t mem_mask);
+ void chcr4_w(offs_t offset, uint32_t data, uint32_t mem_mask);
+ uint32_t sar5_r(offs_t offset, uint32_t mem_mask);
+ void sar5_w(offs_t offset, uint32_t data, uint32_t mem_mask);
+ uint32_t dar5_r(offs_t offset, uint32_t mem_mask);
+ void dar5_w(offs_t offset, uint32_t data, uint32_t mem_mask);
+ uint32_t dmatcr5_r(offs_t offset, uint32_t mem_mask);
+ void dmatcr5_w(offs_t offset, uint32_t data, uint32_t mem_mask);
+ uint32_t chcr5_r(offs_t offset, uint32_t mem_mask);
+ void chcr5_w(offs_t offset, uint32_t data, uint32_t mem_mask);
+ uint32_t sar6_r(offs_t offset, uint32_t mem_mask);
+ void sar6_w(offs_t offset, uint32_t data, uint32_t mem_mask);
+ uint32_t dar6_r(offs_t offset, uint32_t mem_mask);
+ void dar6_w(offs_t offset, uint32_t data, uint32_t mem_mask);
+ uint32_t dmatcr6_r(offs_t offset, uint32_t mem_mask);
+ void dmatcr6_w(offs_t offset, uint32_t data, uint32_t mem_mask);
+ uint32_t chcr6_r(offs_t offset, uint32_t mem_mask);
+ void chcr6_w(offs_t offset, uint32_t data, uint32_t mem_mask);
+ uint32_t sar7_r(offs_t offset, uint32_t mem_mask);
+ void sar7_w(offs_t offset, uint32_t data, uint32_t mem_mask);
+ uint32_t dar7_r(offs_t offset, uint32_t mem_mask);
+ void dar7_w(offs_t offset, uint32_t data, uint32_t mem_mask);
+ uint32_t dmatcr7_r(offs_t offset, uint32_t mem_mask);
+ void dmatcr7_w(offs_t offset, uint32_t data, uint32_t mem_mask);
+ uint32_t chcr7_r(offs_t offset, uint32_t mem_mask);
+ void chcr7_w(offs_t offset, uint32_t data, uint32_t mem_mask);
+
+ // CPG
+ uint16_t frqcr_r(offs_t offset, uint16_t mem_mask);
+ void frqcr_w(offs_t offset, uint16_t data, uint16_t mem_mask);
+ uint8_t stbcr_r(offs_t offset, uint8_t mem_mask);
+ void stbcr_w(offs_t offset, uint8_t data, uint8_t mem_mask);
+ uint8_t wtcnt_r(offs_t offset, uint8_t mem_mask);
+ void wtcnt_w(offs_t offset, uint16_t data, uint16_t mem_mask);
+ uint8_t wtcsr_r(offs_t offset, uint8_t mem_mask);
+ void wtcsr_w(offs_t offset, uint16_t data, uint16_t mem_mask);
+ uint8_t stbcr2_r(offs_t offset, uint8_t mem_mask);
+ void stbcr2_w(offs_t offset, uint8_t data, uint8_t mem_mask);
+
+ // CPG 7750R
+ uint32_t clkstp00_r(offs_t offset, uint32_t mem_mask);
+ void clkstp00_w(offs_t offset, uint32_t data, uint32_t mem_mask);
+ void clkstpclr_w(offs_t offset, uint32_t data, uint32_t mem_mask);
+
+ // RTC
+ uint8_t r64cnt_r(offs_t offset, uint8_t mem_mask);
+ uint8_t rseccnt_r(offs_t offset, uint8_t mem_mask);
+ void rseccnt_w(offs_t offset, uint8_t data, uint8_t mem_mask);
+ uint8_t rmincnt_r(offs_t offset, uint8_t mem_mask);
+ void rmincnt_w(offs_t offset, uint8_t data, uint8_t mem_mask);
+ uint8_t rhrcnt_r(offs_t offset, uint8_t mem_mask);
+ void rhrcnt_w(offs_t offset, uint8_t data, uint8_t mem_mask);
+ uint8_t rwkcnt_r(offs_t offset, uint8_t mem_mask);
+ void rwkcnt_w(offs_t offset, uint8_t data, uint8_t mem_mask);
+ uint8_t rdaycnt_r(offs_t offset, uint8_t mem_mask);
+ void rdaycnt_w(offs_t offset, uint8_t data, uint8_t mem_mask);
+ uint8_t rmoncnt_r(offs_t offset, uint8_t mem_mask);
+ void rmoncnt_w(offs_t offset, uint8_t data, uint8_t mem_mask);
+ uint16_t ryrcnt_r(offs_t offset, uint16_t mem_mask);
+ void ryrcnt_w(offs_t offset, uint16_t data, uint16_t mem_mask);
+ uint8_t rsecar_r(offs_t offset, uint8_t mem_mask);
+ void rsecar_w(offs_t offset, uint8_t data, uint8_t mem_mask);
+ uint8_t rminar_r(offs_t offset, uint8_t mem_mask);
+ void rminar_w(offs_t offset, uint8_t data, uint8_t mem_mask);
+ uint8_t rhrar_r(offs_t offset, uint8_t mem_mask);
+ void rhrar_w(offs_t offset, uint8_t data, uint8_t mem_mask);
+ uint8_t rwkar_r(offs_t offset, uint8_t mem_mask);
+ void rwkar_w(offs_t offset, uint8_t data, uint8_t mem_mask);
+ uint8_t rdayar_r(offs_t offset, uint8_t mem_mask);
+ void rdayar_w(offs_t offset, uint8_t data, uint8_t mem_mask);
+ uint8_t rmonar_r(offs_t offset, uint8_t mem_mask);
+ void rmonar_w(offs_t offset, uint8_t data, uint8_t mem_mask);
+ uint8_t rcr1_r(offs_t offset, uint8_t mem_mask);
+ void rcr1_w(offs_t offset, uint8_t data, uint8_t mem_mask);
+ uint8_t rcr2_r(offs_t offset, uint8_t mem_mask);
+ void rcr2_w(offs_t offset, uint8_t data, uint8_t mem_mask);
+
+ // RTC 7750R
+ uint8_t rcr3_r(offs_t offset, uint8_t mem_mask);
+ void rcr3_w(offs_t offset, uint8_t data, uint8_t mem_mask);
+ uint16_t ryrar_r(offs_t offset, uint16_t mem_mask);
+ void ryrar_w(offs_t offset, uint16_t data, uint16_t mem_mask);
+
+ // INTC
+ uint16_t icr_r(offs_t offset, uint16_t mem_mask);
+ void icr_w(offs_t offset, uint16_t data, uint16_t mem_mask);
+ uint16_t iprb_r(offs_t offset, uint16_t mem_mask);
+ void iprb_w(offs_t offset, uint16_t data, uint16_t mem_mask);
+ uint16_t iprc_r(offs_t offset, uint16_t mem_mask);
+ void iprc_w(offs_t offset, uint16_t data, uint16_t mem_mask);
+
+ // INTC 7750S
+ uint16_t iprd_r(offs_t offset, uint16_t mem_mask);
+ void iprd_w(offs_t offset, uint16_t data, uint16_t mem_mask);
+
+ // INTC 7750R
+ uint32_t intpri00_r(offs_t offset, uint32_t mem_mask);
+ void intpri00_w(offs_t offset, uint32_t data, uint32_t mem_mask);
+ uint32_t intreq00_r(offs_t offset, uint32_t mem_mask);
+ void intreq00_w(offs_t offset, uint32_t data, uint32_t mem_mask);
+ uint32_t intmsk00_r(offs_t offset, uint32_t mem_mask);
+ void intmsk00_w(offs_t offset, uint32_t data, uint32_t mem_mask);
+ void intmskclr_w(offs_t offset, uint32_t data, uint32_t mem_mask);
+
+ // TMU 7750R
+ uint8_t tstr2_r(offs_t offset, uint8_t mem_mask);
+ void tstr2_w(offs_t offset, uint8_t data, uint8_t mem_mask);
+ uint32_t tcor3_r(offs_t offset, uint32_t mem_mask);
+ void tcor3_w(offs_t offset, uint32_t data, uint32_t mem_mask);
+ uint32_t tcnt3_r(offs_t offset, uint32_t mem_mask);
+ void tcnt3_w(offs_t offset, uint32_t data, uint32_t mem_mask);
+ uint16_t tcr3_r(offs_t offset, uint16_t mem_mask);
+ void tcr3_w(offs_t offset, uint16_t data, uint16_t mem_mask);
+ uint32_t tcor4_r(offs_t offset, uint32_t mem_mask);
+ void tcor4_w(offs_t offset, uint32_t data, uint32_t mem_mask);
+ uint32_t tcnt4_r(offs_t offset, uint32_t mem_mask);
+ void tcnt4_w(offs_t offset, uint32_t data, uint32_t mem_mask);
+ uint16_t tcr4_r(offs_t offset, uint16_t mem_mask);
+ void tcr4_w(offs_t offset, uint16_t data, uint16_t mem_mask);
+
+ // SCI
+ uint8_t scsmr1_r(offs_t offset, uint8_t mem_mask);
+ void scsmr1_w(offs_t offset, uint8_t data, uint8_t mem_mask);
+ uint8_t scbrr1_r(offs_t offset, uint8_t mem_mask);
+ void scbrr1_w(offs_t offset, uint8_t data, uint8_t mem_mask);
+ uint8_t scscr1_r(offs_t offset, uint8_t mem_mask);
+ void scscr1_w(offs_t offset, uint8_t data, uint8_t mem_mask);
+ uint8_t sctdr1_r(offs_t offset, uint8_t mem_mask);
+ void sctdr1_w(offs_t offset, uint8_t data, uint8_t mem_mask);
+ uint8_t scssr1_r(offs_t offset, uint8_t mem_mask);
+ void scssr1_w(offs_t offset, uint8_t data, uint8_t mem_mask);
+ uint8_t scrdr1_r(offs_t offset, uint8_t mem_mask);
+ void scscmr1_w(offs_t offset, uint8_t data, uint8_t mem_mask);
+ uint8_t scscmr1_r(offs_t offset, uint8_t mem_mask);
+ uint8_t scsptr1_r(offs_t offset, uint8_t mem_mask);
+ void scsptr1_w(offs_t offset, uint8_t data, uint8_t mem_mask);
+
+ // SCIF
+ uint16_t scsmr2_r(offs_t offset, uint16_t mem_mask);
+ void scsmr2_w(offs_t offset, uint16_t data, uint16_t mem_mask);
+ uint8_t scbrr2_r(offs_t offset, uint8_t mem_mask);
+ void scbrr2_w(offs_t offset, uint8_t data, uint8_t mem_mask);
+ uint16_t scscr2_r(offs_t offset, uint16_t mem_mask);
+ void scscr2_w(offs_t offset, uint16_t data, uint16_t mem_mask);
+ uint8_t scftdr2_r(offs_t offset, uint8_t mem_mask);
+ void scftdr2_w(offs_t offset, uint8_t data, uint8_t mem_mask);
+ uint16_t scfsr2_r(offs_t offset, uint16_t mem_mask);
+ void scfsr2_w(offs_t offset, uint16_t data, uint16_t mem_mask);
+ uint8_t scfrdr2_r(offs_t offset, uint8_t mem_mask);
+ uint16_t scfcr2_r(offs_t offset, uint16_t mem_mask);
+ void scfcr2_w(offs_t offset, uint16_t data, uint16_t mem_mask);
+ uint16_t scfdr2_r(offs_t offset, uint16_t mem_mask);
+ uint16_t scsptr2_r(offs_t offset, uint16_t mem_mask);
+ void scsptr2_w(offs_t offset, uint16_t data, uint16_t mem_mask);
+ uint16_t sclsr2_r(offs_t offset, uint16_t mem_mask);
+ void sclsr2_w(offs_t offset, uint16_t data, uint16_t mem_mask);
+
+ // H-UDI
+ uint16_t sdir_r(offs_t offset, uint16_t mem_mask);
+ void sdir_w(offs_t offset, uint16_t data, uint16_t mem_mask);
+ uint32_t sddr_r(offs_t offset, uint32_t mem_mask);
+ void sddr_w(offs_t offset, uint32_t data, uint32_t mem_mask);
+
+ // H-UDI 7750R
+ uint16_t sdint_r(offs_t offset, uint16_t mem_mask);
+ void sdint_w(offs_t offset, uint16_t data, uint16_t mem_mask);
+
+ // PCI 7751
+ uint32_t pciconf0_r(offs_t offset, uint32_t mem_mask);
+ uint32_t pciconf1_r(offs_t offset, uint32_t mem_mask);
+ void pciconf1_w(offs_t offset, uint32_t data, uint32_t mem_mask);
+ uint32_t pciconf2_r(offs_t offset, uint32_t mem_mask);
+ void pciconf2_w(offs_t offset, uint32_t data, uint32_t mem_mask);
+ uint32_t pciconf3_r(offs_t offset, uint32_t mem_mask);
+ void pciconf3_w(offs_t offset, uint32_t data, uint32_t mem_mask);
+ uint32_t pciconf4_r(offs_t offset, uint32_t mem_mask);
+ void pciconf4_w(offs_t offset, uint32_t data, uint32_t mem_mask);
+ uint32_t pciconf5_r(offs_t offset, uint32_t mem_mask);
+ void pciconf5_w(offs_t offset, uint32_t data, uint32_t mem_mask);
+ uint32_t pciconf6_r(offs_t offset, uint32_t mem_mask);
+ void pciconf6_w(offs_t offset, uint32_t data, uint32_t mem_mask);
+ uint32_t pciconf7_r(offs_t offset, uint32_t mem_mask);
+ uint32_t pciconf8_r(offs_t offset, uint32_t mem_mask);
+ uint32_t pciconf9_r(offs_t offset, uint32_t mem_mask);
+ uint32_t pciconf10_r(offs_t offset, uint32_t mem_mask);
+ uint32_t pciconf11_r(offs_t offset, uint32_t mem_mask);
+ void pciconf11_w(offs_t offset, uint32_t data, uint32_t mem_mask);
+ uint32_t pciconf12_r(offs_t offset, uint32_t mem_mask);
+ uint32_t pciconf13_r(offs_t offset, uint32_t mem_mask);
+ uint32_t pciconf14_r(offs_t offset, uint32_t mem_mask);
+ uint32_t pciconf15_r(offs_t offset, uint32_t mem_mask);
+ void pciconf15_w(offs_t offset, uint32_t data, uint32_t mem_mask);
+ uint32_t pciconf16_r(offs_t offset, uint32_t mem_mask);
+ void pciconf16_w(offs_t offset, uint32_t data, uint32_t mem_mask);
+ uint32_t pciconf17_r(offs_t offset, uint32_t mem_mask);
+ void pciconf17_w(offs_t offset, uint32_t data, uint32_t mem_mask);
+ uint32_t pcicr_r(offs_t offset, uint32_t mem_mask);
+ void pcicr_w(offs_t offset, uint32_t data, uint32_t mem_mask);
+ uint32_t pcilsr0_r(offs_t offset, uint32_t mem_mask);
+ void pcilsr0_w(offs_t offset, uint32_t data, uint32_t mem_mask);
+ uint32_t pcilsr1_r(offs_t offset, uint32_t mem_mask);
+ void pcilsr1_w(offs_t offset, uint32_t data, uint32_t mem_mask);
+ uint32_t pcilar0_r(offs_t offset, uint32_t mem_mask);
+ void pcilar0_w(offs_t offset, uint32_t data, uint32_t mem_mask);
+ uint32_t pcilar1_r(offs_t offset, uint32_t mem_mask);
+ void pcilar1_w(offs_t offset, uint32_t data, uint32_t mem_mask);
+ uint32_t pciint_r(offs_t offset, uint32_t mem_mask);
+ void pciint_w(offs_t offset, uint32_t data, uint32_t mem_mask);
+ uint32_t pciintm_r(offs_t offset, uint32_t mem_mask);
+ void pciintm_w(offs_t offset, uint32_t data, uint32_t mem_mask);
+ uint32_t pcialr_r(offs_t offset, uint32_t mem_mask);
+ void pcialr_w(offs_t offset, uint32_t data, uint32_t mem_mask);
+ uint32_t pciclr_r(offs_t offset, uint32_t mem_mask);
+ void pciclr_w(offs_t offset, uint32_t data, uint32_t mem_mask);
+ uint32_t pciaint_r(offs_t offset, uint32_t mem_mask);
+ void pciaint_w(offs_t offset, uint32_t data, uint32_t mem_mask);
+ uint32_t pciaintm_r(offs_t offset, uint32_t mem_mask);
+ void pciaintm_w(offs_t offset, uint32_t data, uint32_t mem_mask);
+ uint32_t pcibllr_r(offs_t offset, uint32_t mem_mask);
+ void pcibllr_w(offs_t offset, uint32_t data, uint32_t mem_mask);
+ uint32_t pcidmabt_r(offs_t offset, uint32_t mem_mask);
+ void pcidmabt_w(offs_t offset, uint32_t data, uint32_t mem_mask);
+ uint32_t pcidpa0_r(offs_t offset, uint32_t mem_mask);
+ void pcidpa0_w(offs_t offset, uint32_t data, uint32_t mem_mask);
+ uint32_t pcidla0_r(offs_t offset, uint32_t mem_mask);
+ void pcidla0_w(offs_t offset, uint32_t data, uint32_t mem_mask);
+ uint32_t pcidtc0_r(offs_t offset, uint32_t mem_mask);
+ void pcidtc0_w(offs_t offset, uint32_t data, uint32_t mem_mask);
+ uint32_t pcidcr0_r(offs_t offset, uint32_t mem_mask);
+ void pcidcr0_w(offs_t offset, uint32_t data, uint32_t mem_mask);
+ uint32_t pcidpa1_r(offs_t offset, uint32_t mem_mask);
+ void pcidpa1_w(offs_t offset, uint32_t data, uint32_t mem_mask);
+ uint32_t pcidla1_r(offs_t offset, uint32_t mem_mask);
+ void pcidla1_w(offs_t offset, uint32_t data, uint32_t mem_mask);
+ uint32_t pcidtc1_r(offs_t offset, uint32_t mem_mask);
+ void pcidtc1_w(offs_t offset, uint32_t data, uint32_t mem_mask);
+ uint32_t pcidcr1_r(offs_t offset, uint32_t mem_mask);
+ void pcidcr1_w(offs_t offset, uint32_t data, uint32_t mem_mask);
+ uint32_t pcidpa2_r(offs_t offset, uint32_t mem_mask);
+ void pcidpa2_w(offs_t offset, uint32_t data, uint32_t mem_mask);
+ uint32_t pcidla2_r(offs_t offset, uint32_t mem_mask);
+ void pcidla2_w(offs_t offset, uint32_t data, uint32_t mem_mask);
+ uint32_t pcidtc2_r(offs_t offset, uint32_t mem_mask);
+ void pcidtc2_w(offs_t offset, uint32_t data, uint32_t mem_mask);
+ uint32_t pcidcr2_r(offs_t offset, uint32_t mem_mask);
+ void pcidcr2_w(offs_t offset, uint32_t data, uint32_t mem_mask);
+ uint32_t pcidpa3_r(offs_t offset, uint32_t mem_mask);
+ void pcidpa3_w(offs_t offset, uint32_t data, uint32_t mem_mask);
+ uint32_t pcidla3_r(offs_t offset, uint32_t mem_mask);
+ void pcidla3_w(offs_t offset, uint32_t data, uint32_t mem_mask);
+ uint32_t pcidtc3_r(offs_t offset, uint32_t mem_mask);
+ void pcidtc3_w(offs_t offset, uint32_t data, uint32_t mem_mask);
+ uint32_t pcidcr3_r(offs_t offset, uint32_t mem_mask);
+ void pcidcr3_w(offs_t offset, uint32_t data, uint32_t mem_mask);
+ uint32_t pcipar_r(offs_t offset, uint32_t mem_mask);
+ void pcipar_w(offs_t offset, uint32_t data, uint32_t mem_mask);
+ uint32_t pcimbr_r(offs_t offset, uint32_t mem_mask);
+ void pcimbr_w(offs_t offset, uint32_t data, uint32_t mem_mask);
+ uint32_t pciiobr_r(offs_t offset, uint32_t mem_mask);
+ void pciiobr_w(offs_t offset, uint32_t data, uint32_t mem_mask);
+ uint32_t pcipint_r(offs_t offset, uint32_t mem_mask);
+ void pcipint_w(offs_t offset, uint32_t data, uint32_t mem_mask);
+ uint32_t pcipintm_r(offs_t offset, uint32_t mem_mask);
+ void pcipintm_w(offs_t offset, uint32_t data, uint32_t mem_mask);
+ uint32_t pciclkr_r(offs_t offset, uint32_t mem_mask);
+ void pciclkr_w(offs_t offset, uint32_t data, uint32_t mem_mask);
+ uint32_t pcibcr1_r(offs_t offset, uint32_t mem_mask);
+ void pcibcr1_w(offs_t offset, uint32_t data, uint32_t mem_mask);
+ uint32_t pcibcr2_r(offs_t offset, uint32_t mem_mask);
+ void pcibcr2_w(offs_t offset, uint32_t data, uint32_t mem_mask);
+ uint32_t pcibcr3_r(offs_t offset, uint32_t mem_mask);
+ void pcibcr3_w(offs_t offset, uint32_t data, uint32_t mem_mask);
+ uint32_t pciwcr1_r(offs_t offset, uint32_t mem_mask);
+ void pciwcr1_w(offs_t offset, uint32_t data, uint32_t mem_mask);
+ uint32_t pciwcr2_r(offs_t offset, uint32_t mem_mask);
+ void pciwcr2_w(offs_t offset, uint32_t data, uint32_t mem_mask);
+ uint32_t pciwcr3_r(offs_t offset, uint32_t mem_mask);
+ void pciwcr3_w(offs_t offset, uint32_t data, uint32_t mem_mask);
+ uint32_t pcimcr_r(offs_t offset, uint32_t mem_mask);
+ void pcimcr_w(offs_t offset, uint32_t data, uint32_t mem_mask);
+ uint32_t pcipctr_r(offs_t offset, uint32_t mem_mask);
+ void pcipctr_w(offs_t offset, uint32_t data, uint32_t mem_mask);
+ uint32_t pcipdtr_r(offs_t offset, uint32_t mem_mask);
+ void pcipdtr_w(offs_t offset, uint32_t data, uint32_t mem_mask);
+ uint32_t pcipdr_r(offs_t offset, uint32_t mem_mask);
+ void pcipdr_w(offs_t offset, uint32_t data, uint32_t mem_mask);
+
+ TIMER_CALLBACK_MEMBER(sh4_rtc_timer_callback);
+ TIMER_CALLBACK_MEMBER(sh4_refresh_timer_callback);
+ void increment_rtc_time(int mode);
+ uint32_t compute_ticks_refresh_timer(emu_timer* timer, int hertz, int base, int divisor);
+ void sh4_refresh_timer_recompute();
virtual void LDTLB(const uint16_t opcode) override;
virtual uint32_t get_remap(uint32_t address) override;
virtual uint32_t sh4_getsqremap(uint32_t address) override;
- sh4_utlb m_utlb[64];
- void sh4_internal_map(address_map &map);
-protected:
- // construction/destruction
- sh4_base_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock, endianness_t endianness);
+ emu_timer* m_rtc_timer;
+ emu_timer* m_refresh_timer;
+ uint32_t m_refresh_timer_base;
+ sh4_utlb m_utlb[64];
- virtual void device_start() override;
- virtual void device_reset() override;
+ // UBC
+ uint32_t m_bara;
+ uint8_t m_bamra;
+ uint16_t m_bbra;
+ uint32_t m_barb;
+ uint8_t m_bamrb;
+ uint16_t m_bbrb;
+ uint32_t m_bdrb;
+ uint32_t m_bdmrb;
+ uint16_t m_brcr;
+
+ // BSC
+ uint32_t m_bcr1;
+ uint16_t m_bcr2;
+ uint32_t m_wcr1;
+ uint32_t m_wcr2;
+ uint32_t m_wcr3;
+ uint32_t m_mcr;
+ uint16_t m_pcr;
+ uint16_t m_rtcsr;
+ uint16_t m_rtcnt;
+ uint16_t m_rtcor;
+ uint16_t m_rfcr;
+ uint32_t m_pctra;
+ uint16_t m_pdtra;
+ uint32_t m_pctrb;
+ uint16_t m_pdtrb;
+ uint16_t m_gpioic;
+
+ // BSC 7750R
+ uint32_t m_bcr3;
+ uint32_t m_bcr4;
+
+ // DMAC 7750R
+ uint32_t m_sar4;
+ uint32_t m_dar4;
+ uint32_t m_dmatcr4;
+ uint32_t m_chcr4;
+ uint32_t m_sar5;
+ uint32_t m_dar5;
+ uint32_t m_dmatcr5;
+ uint32_t m_chcr5;
+ uint32_t m_sar6;
+ uint32_t m_dar6;
+ uint32_t m_dmatcr6;
+ uint32_t m_chcr6;
+ uint32_t m_sar7;
+ uint32_t m_dar7;
+ uint32_t m_dmatcr7;
+ uint32_t m_chcr7;
+
+ // CPG
+ uint16_t m_frqcr;
+ uint8_t m_stbcr;
+ uint16_t m_wtcnt;
+ uint16_t m_wtcsr;
+ uint8_t m_stbcr2;
+
+ // CPG 7750R
+ uint32_t m_clkstp00;
+
+ // RTC
+ uint8_t m_r64cnt;
+ uint8_t m_rseccnt;
+ uint8_t m_rmincnt;
+ uint8_t m_rhrcnt;
+ uint8_t m_rwkcnt;
+ uint8_t m_rmoncnt;
+ uint8_t m_rdaycnt;
+ uint16_t m_ryrcnt;
+ uint8_t m_rsecar;
+ uint8_t m_rminar;
+ uint8_t m_rhrar;
+ uint8_t m_rwkar;
+ uint8_t m_rdayar;
+ uint8_t m_rmonar;
+ uint8_t m_rcr1;
+ uint8_t m_rcr2;
+
+ // RTC 7750R
+ uint8_t m_rcr3;
+ uint16_t m_ryrar;
+
+ // INTC
+ uint16_t m_iprb;
+
+ // INTC 7750S
+ uint16_t m_iprd;
+
+ // INTC 7750R
+ uint32_t m_intpri00;
+ uint32_t m_intreq00;
+ uint32_t m_intmsk00;
+
+ // TMU 7750R
+ uint8_t m_tstr2;
+ uint32_t m_tcor3;
+ uint32_t m_tcnt3;
+ uint16_t m_tcr3;
+ uint32_t m_tcor4;
+ uint32_t m_tcnt4;
+ uint16_t m_tcr4;
+
+ // SCI
+ uint8_t m_scsmr1;
+ uint8_t m_scbrr1;
+ uint8_t m_scscr1;
+ uint8_t m_sctdr1;
+ uint8_t m_scssr1;
+ uint8_t m_scrdr1;
+ uint8_t m_scscmr1;
+ uint8_t m_scsptr1;
+
+ // SCIF
+ uint16_t m_scsmr2;
+ uint8_t m_scbrr2;
+ uint16_t m_scscr2;
+ uint8_t m_scftdr2;
+ uint16_t m_scfsr2;
+ uint8_t m_scfrdr2;
+ uint16_t m_scfcr2;
+ uint16_t m_scfdr2;
+ uint16_t m_scsptr2;
+ uint16_t m_sclsr2;
+
+ // H-UDI
+ uint16_t m_sdir;
+ uint32_t m_sddr;
+ uint16_t m_sdint;
+
+ // PCI 7751
+ uint32_t m_pciconf0;
+ uint32_t m_pciconf1;
+ uint32_t m_pciconf2;
+ uint32_t m_pciconf3;
+ uint32_t m_pciconf4;
+ uint32_t m_pciconf5;
+ uint32_t m_pciconf6;
+ uint32_t m_pciconf7;
+ uint32_t m_pciconf8;
+ uint32_t m_pciconf9;
+ uint32_t m_pciconf10;
+ uint32_t m_pciconf11;
+ uint32_t m_pciconf12;
+ uint32_t m_pciconf13;
+ uint32_t m_pciconf14;
+ uint32_t m_pciconf15;
+ uint32_t m_pciconf16;
+ uint32_t m_pciconf17;
+ uint32_t m_pcicr;
+ uint32_t m_pcilsr0;
+ uint32_t m_pcilsr1;
+ uint32_t m_pcilar0;
+ uint32_t m_pcilar1;
+ uint32_t m_pciint;
+ uint32_t m_pciintm;
+ uint32_t m_pcialr;
+ uint32_t m_pciclr;
+ uint32_t m_pciaint;
+ uint32_t m_pciaintm;
+ uint32_t m_pcibllr;
+ uint32_t m_pcidmabt;
+ uint32_t m_pcidpa0;
+ uint32_t m_pcidla0;
+ uint32_t m_pcidtc0;
+ uint32_t m_pcidcr0;
+ uint32_t m_pcidpa1;
+ uint32_t m_pcidla1;
+ uint32_t m_pcidtc1;
+ uint32_t m_pcidcr1;
+ uint32_t m_pcidpa2;
+ uint32_t m_pcidla2;
+ uint32_t m_pcidtc2;
+ uint32_t m_pcidcr2;
+ uint32_t m_pcidpa3;
+ uint32_t m_pcidla3;
+ uint32_t m_pcidtc3;
+ uint32_t m_pcidcr3;
+ uint32_t m_pcipar;
+ uint32_t m_pcimbr;
+ uint32_t m_pciiobr;
+ uint32_t m_pcipint;
+ uint32_t m_pcipintm;
+ uint32_t m_pciclkr;
+ uint32_t m_pcibcr1;
+ uint32_t m_pcibcr2;
+ uint32_t m_pcibcr3;
+ uint32_t m_pciwcr1;
+ uint32_t m_pciwcr2;
+ uint32_t m_pciwcr3;
+ uint32_t m_pcimcr;
+ uint32_t m_pcipctr;
+ uint32_t m_pcipdtr;
+ uint32_t m_pcipdr;
};
class sh3_device : public sh3_base_device
{
- friend class sh4_frontend;
public:
- sh3_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- std::unique_ptr<sh4_frontend> m_drcfe; /* pointer to the DRC front-end state */
- virtual const opcode_desc* get_desclist(offs_t pc) override;
- virtual void init_drc_frontend() override;
+ sh3_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock, endianness_t endianness = ENDIANNESS_LITTLE);
+
+ virtual void sh3_register_map(address_map& map) override ATTR_COLD;
};
+class sh7708s_device : public sh3_base_device
+{
+public:
+ sh7708s_device(const machine_config& mconfig, const char* tag, device_t* owner, uint32_t clock, endianness_t endianness = ENDIANNESS_LITTLE);
+
+ virtual void sh3_register_map(address_map& map) override ATTR_COLD;
+};
-class sh3be_device : public sh3_base_device
+class sh7709_device : public sh3_base_device
{
- friend class sh4be_frontend;
+public:
+ sh7709_device(const machine_config& mconfig, const char* tag, device_t* owner, uint32_t clock, endianness_t endianness = ENDIANNESS_LITTLE);
+ virtual void sh3_register_map(address_map& map) override ATTR_COLD;
+};
+
+class sh7709s_device : public sh3_base_device
+{
public:
- sh3be_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- std::unique_ptr<sh4be_frontend> m_drcfe; /* pointer to the DRC front-end state */
- virtual const opcode_desc* get_desclist(offs_t pc) override;
- virtual void init_drc_frontend() override;
+ sh7709s_device(const machine_config& mconfig, const char* tag, device_t* owner, uint32_t clock, endianness_t endianness = ENDIANNESS_LITTLE);
-protected:
- virtual void execute_run() override;
+ virtual void sh3_register_map(address_map& map) override ATTR_COLD;
};
class sh4_device : public sh4_base_device
{
- friend class sh4_frontend;
+public:
+ sh4_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock, endianness_t endianness = ENDIANNESS_LITTLE);
+
+protected:
+ virtual void sh4_register_map(address_map& map) override ATTR_COLD;
+};
+class sh7091_device : public sh4_base_device
+{
public:
- sh4_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- std::unique_ptr<sh4_frontend> m_drcfe; /* pointer to the DRC front-end state */
- virtual const opcode_desc* get_desclist(offs_t pc) override;
- virtual void init_drc_frontend() override;
+ sh7091_device(const machine_config& mconfig, const char* tag, device_t* owner, uint32_t clock, endianness_t endianness = ENDIANNESS_LITTLE);
+protected:
+ virtual void sh4_register_map(address_map& map) override ATTR_COLD;
};
+class sh7750_device : public sh4_base_device
+{
+public:
+ sh7750_device(const machine_config& mconfig, const char* tag, device_t* owner, uint32_t clock, endianness_t endianness = ENDIANNESS_LITTLE);
+
+protected:
+ virtual void sh4_register_map(address_map& map) override ATTR_COLD;
+};
-class sh4be_device : public sh4_base_device
+class sh7750s_device : public sh4_base_device
{
- friend class sh4be_frontend;
+public:
+ sh7750s_device(const machine_config& mconfig, const char* tag, device_t* owner, uint32_t clock, endianness_t endianness = ENDIANNESS_LITTLE);
+protected:
+ virtual void sh4_register_map(address_map& map) override ATTR_COLD;
+};
+
+class sh7750r_device : public sh4_base_device
+{
public:
- sh4be_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- std::unique_ptr<sh4be_frontend> m_drcfe; /* pointer to the DRC front-end state */
- virtual const opcode_desc* get_desclist(offs_t pc) override;
- virtual void init_drc_frontend() override;
+ sh7750r_device(const machine_config& mconfig, const char* tag, device_t* owner, uint32_t clock, endianness_t endianness = ENDIANNESS_LITTLE);
protected:
- virtual void execute_run() override;
+ virtual void sh4_register_map(address_map& map) override ATTR_COLD;
+};
+
+class sh7751_device : public sh4_base_device
+{
+public:
+ sh7751_device(const machine_config& mconfig, const char* tag, device_t* owner, uint32_t clock, endianness_t endianness = ENDIANNESS_LITTLE);
+
+protected:
+ virtual void sh4_register_map(address_map& map) override ATTR_COLD;
+};
+
+class sh7751r_device : public sh4_base_device
+{
+public:
+ sh7751r_device(const machine_config& mconfig, const char* tag, device_t* owner, uint32_t clock, endianness_t endianness = ENDIANNESS_LITTLE);
+
+protected:
+ virtual void sh4_register_map(address_map& map) override ATTR_COLD;
};
class sh4_frontend : public sh_frontend
@@ -795,20 +1988,16 @@ private:
bool describe_op1111_0xf13(opcode_desc &desc, const opcode_desc *prev, uint16_t opcode);
};
-class sh4be_frontend : public sh4_frontend
-{
-public:
- sh4be_frontend(sh_common_execution *device, uint32_t window_start, uint32_t window_end, uint32_t max_sequence) :
- sh4_frontend(device, window_start, window_end, max_sequence)
- {}
-protected:
- virtual uint16_t read_word(opcode_desc &desc) override;
-};
-
-DECLARE_DEVICE_TYPE(SH3LE, sh3_device)
-DECLARE_DEVICE_TYPE(SH3BE, sh3be_device)
-DECLARE_DEVICE_TYPE(SH4LE, sh4_device)
-DECLARE_DEVICE_TYPE(SH4BE, sh4be_device)
-
-
-#endif // MAME_CPU_SH4_SH4_H
+DECLARE_DEVICE_TYPE(SH3, sh3_device)
+DECLARE_DEVICE_TYPE(SH7708S, sh7708s_device)
+DECLARE_DEVICE_TYPE(SH7709, sh7709_device)
+DECLARE_DEVICE_TYPE(SH7709S, sh7709s_device)
+DECLARE_DEVICE_TYPE(SH4, sh4_device)
+DECLARE_DEVICE_TYPE(SH7091, sh7091_device)
+DECLARE_DEVICE_TYPE(SH7750, sh7750_device)
+DECLARE_DEVICE_TYPE(SH7750R, sh7750r_device)
+DECLARE_DEVICE_TYPE(SH7750S, sh7750s_device)
+DECLARE_DEVICE_TYPE(SH7751, sh7751_device)
+DECLARE_DEVICE_TYPE(SH7751R, sh7751r_device)
+
+#endif // MAME_CPU_SH_SH4_H
diff --git a/src/devices/cpu/sh/sh4comn.cpp b/src/devices/cpu/sh/sh4comn.cpp
index 8c3e8cbc82c..313230b70a6 100644
--- a/src/devices/cpu/sh/sh4comn.cpp
+++ b/src/devices/cpu/sh/sh4comn.cpp
@@ -2,14 +2,13 @@
// copyright-holders:R. Belmont
/*****************************************************************************
*
- * sh4comn.c
+ * sh4comn.cpp
*
* SH-4 non-specific components
*
*****************************************************************************/
#include "emu.h"
-#include "debugger.h"
#include "sh4.h"
#include "sh4regs.h"
#include "sh4comn.h"
@@ -23,33 +22,33 @@ static const int daysmonth[12] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 3
static const uint32_t exception_priority_default[] = {
- EXPPRI(1,1,0,0), /* Power-on Reset */
- EXPPRI(1,2,0,1), /* Manual Reset */
- EXPPRI(1,1,0,2), /* H-UDI Reset */
- EXPPRI(1,3,0,3), /* Inst TLB Multiple Hit */
- EXPPRI(1,4,0,4), /* Data TLB Multiple Hit */
-
- EXPPRI(2,0,0,5), /* User break Before Instruction */
- EXPPRI(2,1,0,6), /* Inst Address Error */
- EXPPRI(2,2,0,7), /* Inst TLB Miss */
- EXPPRI(2,3,0,8), /* Inst TLB Protection Violation */
- EXPPRI(2,4,0,9), /* Illegal Instruction */
- EXPPRI(2,4,0,10), /* Slot Illegal Instruction */
- EXPPRI(2,4,0,11), /* FPU Disable */
- EXPPRI(2,4,0,12), /* Slot FPU Disable */
- EXPPRI(2,5,0,13), /* Data Address Error (Read) */
- EXPPRI(2,5,0,14), /* Data Address Error (Write) */
- EXPPRI(2,6,0,15), /* Data TBL Miss Read */
- EXPPRI(2,6,0,16), /* Data TBL Miss Write */
- EXPPRI(2,7,0,17), /* Data TBL Protection Violation Read */
- EXPPRI(2,7,0,18), /* Data TBL Protection Violation Write */
- EXPPRI(2,8,0,19), /* FPU Exception */
- EXPPRI(2,9,0,20), /* Initial Page Write exception */
-
- EXPPRI(2,4,0,21), /* Unconditional TRAP */
- EXPPRI(2,10,0,22), /* User break After Instruction */
-
- EXPPRI(3,0,16,SH4_INTC_NMI) /* NMI */
+ EXPPRI(1, 1, 0, 0), /* Power-on Reset */
+ EXPPRI(1, 2, 0, 1), /* Manual Reset */
+ EXPPRI(1, 1, 0, 2), /* H-UDI Reset */
+ EXPPRI(1, 3, 0, 3), /* Inst TLB Multiple Hit */
+ EXPPRI(1, 4, 0, 4), /* Data TLB Multiple Hit */
+
+ EXPPRI(2, 0, 0, 5), /* User break Before Instruction */
+ EXPPRI(2, 1, 0, 6), /* Inst Address Error */
+ EXPPRI(2, 2, 0, 7), /* Inst TLB Miss */
+ EXPPRI(2, 3, 0, 8), /* Inst TLB Protection Violation */
+ EXPPRI(2, 4, 0, 9), /* Illegal Instruction */
+ EXPPRI(2, 4, 0, 10), /* Slot Illegal Instruction */
+ EXPPRI(2, 4, 0, 11), /* FPU Disable */
+ EXPPRI(2, 4, 0, 12), /* Slot FPU Disable */
+ EXPPRI(2, 5, 0, 13), /* Data Address Error (Read) */
+ EXPPRI(2, 5, 0, 14), /* Data Address Error (Write) */
+ EXPPRI(2, 6, 0, 15), /* Data TBL Miss Read */
+ EXPPRI(2, 6, 0, 16), /* Data TBL Miss Write */
+ EXPPRI(2, 7, 0, 17), /* Data TBL Protection Violation Read */
+ EXPPRI(2, 7, 0, 18), /* Data TBL Protection Violation Write */
+ EXPPRI(2, 8, 0, 19), /* FPU Exception */
+ EXPPRI(2, 9, 0, 20), /* Initial Page Write exception */
+
+ EXPPRI(2, 4, 0, 21), /* Unconditional TRAP */
+ EXPPRI(2, 10, 0, 22), /* User break After Instruction */
+
+ EXPPRI(3, 0, 16, SH4_INTC_NMI) /* NMI */
/* This is copied to a table, and the IRQ priorities filled in later */
};
@@ -147,7 +146,7 @@ static const int exception_codes[] =
static const int sh3_intevt2_exception_codes[] =
{ 0x000, /* Power-on Reset */
- -1, /* Manual Reset */
+ 0x020, /* Manual Reset */
-1, /* H-UDI Reset */
-1, /* Inst TLB Multiple Hit */
-1, /* Data TLB Multiple Hit */
@@ -169,26 +168,26 @@ static const int sh3_intevt2_exception_codes[] =
-1, /* FPU Exception */
-1, /* Initial Page Write exception */
- -1, /* Unconditional TRAP */
+ 0x160, /* Unconditional TRAP */
-1, /* User break After Instruction */
- -1, /* NMI */ /* SH4_INTC_NMI=23 represents this location in this list.. */
-
- -1, /* EX Irq 0 */
- -1, /* 1 */
- -1, /* 2 */
- -1, /* 3 */
- -1, /* 4 */
- -1, /* 5 */
- -1, /* 6 */
- -1, /* 7 */
- -1, /* 8 */
- -1, /* 9 */
- -1, /* A */
- -1, /* B */
- -1, /* C */
- -1, /* D */
- -1, /* E */
+ 0x1C0, /* NMI */ /* SH4_INTC_NMI=23 represents this location in this list.. */
+
+ 0x200, /* EX Irq 0 */
+ 0x220, /* 1 */
+ 0x240, /* 2 */
+ 0x260, /* 3 */
+ 0x280, /* 4 */
+ 0x2A0, /* 5 */
+ 0x2C0, /* 6 */
+ 0x2E0, /* 7 */
+ 0x300, /* 8 */
+ 0x320, /* 9 */
+ 0x340, /* A */
+ 0x360, /* B */
+ 0x380, /* C */
+ 0x3A0, /* D */
+ 0x3C0, /* E */
0x600, /* SH4_INTC_IRL0 */
0x620, /* SH4_INTC_IRL1 */
@@ -198,10 +197,10 @@ static const int sh3_intevt2_exception_codes[] =
-1, /* HUDI */
-1, /* SH4_INTC_GPOI */
- -1, /* SH4_INTC_DMTE0 */
- -1, /* SH4_INTC_DMTE1 */
- -1, /* SH4_INTC_DMTE2 */
- -1, /* SH4_INTC_DMTE3 */
+ 0x800, /* SH4_INTC_DMTE0 */
+ 0x820, /* SH4_INTC_DMTE1 */
+ 0x840, /* SH4_INTC_DMTE2 */
+ 0x860, /* SH4_INTC_DMTE3 */
-1, /* SH4_INTC_DMTE4 */
-1, /* SH4_INTC_DMTE5 */
@@ -235,12 +234,9 @@ static const int sh3_intevt2_exception_codes[] =
void sh34_base_device::sh4_swap_fp_registers()
{
- int s;
- uint32_t z;
-
- for (s = 0;s <= 15;s++)
+ for (int s = 0; s <= 15; s++)
{
- z = m_sh2_state->m_fr[s];
+ uint32_t z = m_sh2_state->m_fr[s];
m_sh2_state->m_fr[s] = m_sh2_state->m_xf[s];
m_sh2_state->m_xf[s] = z;
}
@@ -248,14 +244,12 @@ void sh34_base_device::sh4_swap_fp_registers()
void sh34_base_device::sh4_swap_fp_couples()
{
- int s;
- uint32_t z;
-
- for (s = 0;s <= 15;s = s+2)
+ for (int s = 0; s <= 15; s += 2)
{
- z = m_sh2_state->m_fr[s];
+ uint32_t z = m_sh2_state->m_fr[s];
m_sh2_state->m_fr[s] = m_sh2_state->m_fr[s + 1];
m_sh2_state->m_fr[s + 1] = z;
+
z = m_sh2_state->m_xf[s];
m_sh2_state->m_xf[s] = m_sh2_state->m_xf[s + 1];
m_sh2_state->m_xf[s + 1] = z;
@@ -265,11 +259,9 @@ void sh34_base_device::sh4_swap_fp_couples()
void sh34_base_device::sh4_change_register_bank(int to)
{
- int s;
-
if (to) // 0 -> 1
{
- for (s = 0;s < 8;s++)
+ for (int s = 0; s < 8; s++)
{
m_sh2_state->m_rbnk[0][s] = m_sh2_state->r[s];
m_sh2_state->r[s] = m_sh2_state->m_rbnk[1][s];
@@ -277,7 +269,7 @@ void sh34_base_device::sh4_change_register_bank(int to)
}
else // 1 -> 0
{
- for (s = 0;s < 8;s++)
+ for (int s = 0; s < 8; s++)
{
m_sh2_state->m_rbnk[1][s] = m_sh2_state->r[s];
m_sh2_state->r[s] = m_sh2_state->m_rbnk[0][s];
@@ -287,9 +279,7 @@ void sh34_base_device::sh4_change_register_bank(int to)
void sh34_base_device::sh4_syncronize_register_bank(int to)
{
- int s;
-
- for (s = 0;s < 8;s++)
+ for (int s = 0; s < 8; s++)
{
m_sh2_state->m_rbnk[to][s] = m_sh2_state->r[s];
}
@@ -297,34 +287,30 @@ void sh34_base_device::sh4_syncronize_register_bank(int to)
void sh34_base_device::sh4_default_exception_priorities() // setup default priorities for exceptions
{
- int a;
-
- for (a=0;a <= SH4_INTC_NMI;a++)
+ for (int a = 0; a <= SH4_INTC_NMI; a++)
m_exception_priority[a] = exception_priority_default[a];
- for (a=SH4_INTC_IRLn0;a <= SH4_INTC_IRLnE;a++)
- m_exception_priority[a] = INTPRI(15-(a-SH4_INTC_IRLn0), a);
+ for (int a = SH4_INTC_IRLn0; a <= SH4_INTC_IRLnE; a++)
+ m_exception_priority[a] = INTPRI(15-(a - SH4_INTC_IRLn0), a);
m_exception_priority[SH4_INTC_IRL0] = INTPRI(13, SH4_INTC_IRL0);
m_exception_priority[SH4_INTC_IRL1] = INTPRI(10, SH4_INTC_IRL1);
m_exception_priority[SH4_INTC_IRL2] = INTPRI(7, SH4_INTC_IRL2);
m_exception_priority[SH4_INTC_IRL3] = INTPRI(4, SH4_INTC_IRL3);
- for (a=SH4_INTC_HUDI;a <= SH4_INTC_ROVI;a++)
+ for (int a = SH4_INTC_HUDI; a <= SH4_INTC_ROVI; a++)
m_exception_priority[a] = INTPRI(0, a);
}
void sh34_base_device::sh4_exception_recompute() // checks if there is any interrupt with high enough priority
{
- int a,z;
-
m_sh2_state->m_test_irq = 0;
- if ((!m_sh2_state->m_pending_irq) || ((m_sh2_state->sr & BL) && (m_exception_requesting[SH4_INTC_NMI] == 0)))
+ if (!m_sh2_state->m_pending_irq || ((m_sh2_state->sr & BL) && m_exception_requesting[SH4_INTC_NMI] == 0))
return;
- z = (m_sh2_state->sr >> 4) & 15;
- for (a=0;a <= SH4_INTC_ROVI;a++)
+ int z = (m_sh2_state->sr >> 4) & 15;
+ for (int a = 0; a <= SH4_INTC_ROVI; a++)
{
if (m_exception_requesting[a])
{
- int pri = (((int)m_exception_priority[a] >> 8) & 255);
- //logerror("pri is %02x z is %02x\n",pri,z);
+ int pri = ((int)m_exception_priority[a] >> 8) & 255;
+ //logerror("pri is %02x z is %02x\n", pri, z);
if (pri > z)
{
//logerror("will test\n");
@@ -361,8 +347,7 @@ void sh34_base_device::sh4_exception_checkunrequest(int exception)
{
if (exception == SH4_INTC_NMI)
sh4_exception_unrequest(exception);
- if ((exception == SH4_INTC_DMTE0) || (exception == SH4_INTC_DMTE1) ||
- (exception == SH4_INTC_DMTE2) || (exception == SH4_INTC_DMTE3))
+ if (exception == SH4_INTC_DMTE0 || exception == SH4_INTC_DMTE1 || exception == SH4_INTC_DMTE2 || exception == SH4_INTC_DMTE3)
sh4_exception_unrequest(exception);
}
@@ -378,7 +363,7 @@ void sh34_base_device::sh4_exception_process(int exception, uint32_t vector)
//printf("stored m_spc %08x m_ssr %08x m_sgr %08x\n", m_spc, m_ssr, m_sgr);
m_sh2_state->sr |= MD;
- if ((machine().debug_flags & DEBUG_FLAG_ENABLED) != 0)
+ if (debugger_enabled())
sh4_syncronize_register_bank((m_sh2_state->sr & sRB) >> 29);
if (!(m_sh2_state->sr & sRB))
sh4_change_register_bank(1);
@@ -390,7 +375,10 @@ void sh34_base_device::sh4_exception_process(int exception, uint32_t vector)
m_sh2_state->pc = m_sh2_state->vbr + vector;
m_willjump = 1; // for DRC
/* wake up if a sleep opcode is triggered */
- if(m_sh2_state->sleep_mode == 1) { m_sh2_state->sleep_mode = 2; }
+ if (m_sh2_state->sleep_mode == 1)
+ {
+ m_sh2_state->sleep_mode = 2;
+ }
}
void sh34_base_device::sh4_exception(const char *message, int exception) // handle exception
@@ -401,31 +389,34 @@ void sh34_base_device::sh4_exception(const char *message, int exception) // hand
{
if (exception < SH4_INTC_NMI)
return; // Not yet supported
- if (exception == SH4_INTC_NMI) {
- if ((m_sh2_state->sr & BL) && (!(m_m[ICR] & 0x200)))
- return;
- m_m[ICR] &= ~0x200;
- m_m[INTEVT] = 0x1c0;
+ if (exception == SH4_INTC_NMI)
+ {
+ if ((m_sh2_state->sr & BL) && !(m_icr & 0x200))
+ return;
+ m_icr &= ~0x200;
+ m_intevt = 0x1c0;
vector = 0x600;
- standard_irq_callback(INPUT_LINE_NMI);
- LOG(("SH-4 '%s' nmi exception after [%s]\n", tag(), message));
- } else {
- // if ((m_m[ICR] & 0x4000) && (m_nmi_line_state == ASSERT_LINE))
+ standard_irq_callback(INPUT_LINE_NMI, m_sh2_state->pc);
+ LOG("SH-4 '%s' nmi exception after [%s]\n", tag(), message);
+ }
+ else
+ {
+ // if ((m_icr & 0x4000) && (m_nmi_line_state == ASSERT_LINE))
// return;
if (m_sh2_state->sr & BL)
return;
if (((m_exception_priority[exception] >> 8) & 255) <= ((m_sh2_state->sr >> 4) & 15))
return;
- m_m[INTEVT] = exception_codes[exception];
+ m_intevt = exception_codes[exception];
vector = 0x600;
- if ((exception >= SH4_INTC_IRL0) && (exception <= SH4_INTC_IRL3))
- standard_irq_callback((exception-SH4_INTC_IRL0)+SH4_IRL0);
+ if (exception >= SH4_INTC_IRL0 && exception <= SH4_INTC_IRL3)
+ standard_irq_callback((exception - SH4_INTC_IRL0) + SH4_IRL0, m_sh2_state->pc);
else
- standard_irq_callback(SH4_IRL3+1);
- LOG(("SH-4 '%s' interrupt exception #%d after [%s]\n", tag(), exception, message));
+ standard_irq_callback(SH4_IRL3 + 1, m_sh2_state->pc);
+ LOG("SH-4 '%s' interrupt exception #%d after [%s]\n", tag(), exception, message);
}
}
else /* SH3 exceptions */
@@ -445,92 +436,83 @@ void sh34_base_device::sh4_exception(const char *message, int exception) // hand
if (((m_exception_priority[exception] >> 8) & 255) <= ((m_sh2_state->sr >> 4) & 15))
return;
-
vector = 0x600;
- if ((exception >= SH4_INTC_IRL0) && (exception <= SH4_INTC_IRL3))
- standard_irq_callback((exception-SH4_INTC_IRL0)+SH4_IRL0);
+ if (exception >= SH4_INTC_IRL0 && exception <= SH4_INTC_IRL3)
+ standard_irq_callback((exception - SH4_INTC_IRL0) + SH4_IRL0, m_sh2_state->pc);
else
- standard_irq_callback(SH4_IRL3+1);
+ standard_irq_callback(SH4_IRL3 + 1, m_sh2_state->pc);
- if (sh3_intevt2_exception_codes[exception]==-1)
+ if (sh3_intevt2_exception_codes[exception] == -1)
fatalerror("sh3_intevt2_exception_codes unpopulated for exception %02x\n", exception);
- m_sh3internal_lower[INTEVT2] = sh3_intevt2_exception_codes[exception];
- m_sh3internal_upper[SH3_EXPEVT_ADDR] = exception_codes[exception];
+ m_intevt2 = sh3_intevt2_exception_codes[exception];
+ m_expevt = exception_codes[exception];
+ if (sh3_intevt2_exception_codes[exception] >= 0x600)
+ m_intevt = 0x3e0 - ((m_exception_priority[exception] >> 8) & 255) * 0x20;
+ else
+ m_intevt = sh3_intevt2_exception_codes[exception];
- LOG(("SH-3 '%s' interrupt exception #%d after [%s]\n", tag(), exception, message));
+ LOG("SH-3 '%s' interrupt exception #%d after [%s]\n", tag(), exception, message);
}
/***** END ASSUME THIS TO BE WRONG FOR NOW *****/
}
+
sh4_exception_process(exception, vector);
}
-uint32_t sh34_base_device::compute_ticks_refresh_timer(emu_timer *timer, int hertz, int base, int divisor)
+uint32_t sh4_base_device::compute_ticks_refresh_timer(emu_timer *timer, int hertz, int base, int divisor)
{
// elapsed:total = x : ticks
- // x=elapsed*tics/total -> x=elapsed*(double)100000000/rtcnt_div[(m_m[RTCSR] >> 3) & 7]
- // ticks/total=ticks / ((rtcnt_div[(m_m[RTCSR] >> 3) & 7] * ticks) / 100000000)=1/((rtcnt_div[(m_m[RTCSR] >> 3) & 7] / 100000000)=100000000/rtcnt_div[(m_m[RTCSR] >> 3) & 7]
- return base + (uint32_t)((timer->elapsed().as_double() * (double)hertz) / (double)divisor);
+ // x=elapsed*tics/total -> x=elapsed*(double)100000000/rtcnt_div[(m_rtcsr >> 3) & 7]
+ // ticks/total=ticks / ((rtcnt_div[(m_rtcsr >> 3) & 7] * ticks) / 100000000)=1/((rtcnt_div[(m_rtcsr >> 3) & 7] / 100000000)=100000000/rtcnt_div[(m_rtcsr >> 3) & 7]
+ return base + (uint32_t)((timer->elapsed().as_double() * hertz) / divisor);
}
-void sh34_base_device::sh4_refresh_timer_recompute()
+void sh4_base_device::sh4_refresh_timer_recompute()
{
- uint32_t ticks;
-
- if (m_cpu_type != CPU_TYPE_SH4)
- fatalerror("sh4_refresh_timer_recompute uses m_m[] with SH3\n");
-
-
//if rtcnt < rtcor then rtcor-rtcnt
//if rtcnt >= rtcor then 256-rtcnt+rtcor=256+rtcor-rtcnt
- ticks = m_m[RTCOR]-m_m[RTCNT];
+ uint32_t ticks = m_rtcor-m_rtcnt;
if (ticks <= 0)
ticks = 256 + ticks;
- m_refresh_timer->adjust(attotime::from_hz(m_bus_clock) * rtcnt_div[(m_m[RTCSR] >> 3) & 7] * ticks);
- m_refresh_timer_base = m_m[RTCNT];
+ m_refresh_timer->adjust(attotime::from_hz(m_bus_clock) * rtcnt_div[(m_rtcsr >> 3) & 7] * ticks);
+ m_refresh_timer_base = m_rtcnt;
}
-TIMER_CALLBACK_MEMBER( sh34_base_device::sh4_refresh_timer_callback )
+TIMER_CALLBACK_MEMBER(sh4_base_device::sh4_refresh_timer_callback)
{
- if (m_cpu_type != CPU_TYPE_SH4)
- fatalerror("sh4_refresh_timer_callback uses m_m[] with SH3\n");
-
- m_m[RTCNT] = 0;
+ m_rtcnt = 0;
sh4_refresh_timer_recompute();
- m_m[RTCSR] |= 128;
- if ((m_m[MCR] & 4) && !(m_m[MCR] & 2))
+ m_rtcsr |= 128;
+ if ((m_mcr & 4) && !(m_mcr & 2))
{
- m_m[RFCR] = (m_m[RFCR] + 1) & 1023;
- if (((m_m[RTCSR] & 1) && (m_m[RFCR] == 512)) || (m_m[RFCR] == 0))
+ m_rfcr = (m_rfcr + 1) & 1023;
+ if (((m_rtcsr & 1) && m_rfcr == 512) || m_rfcr == 0)
{
- m_m[RFCR] = 0;
- m_m[RTCSR] |= 4;
+ m_rfcr = 0;
+ m_rtcsr |= 4;
}
}
}
-void sh34_base_device::increment_rtc_time(int mode)
+void sh4_base_device::increment_rtc_time(int mode)
{
- int carry, year, leap, days;
-
- if (m_cpu_type != CPU_TYPE_SH4)
- fatalerror("increment_rtc_time uses m_m[] with SH3\n");
-
+ int carry;
if (mode == 0)
{
carry = 0;
- m_m[RSECCNT] = m_m[RSECCNT] + 1;
- if ((m_m[RSECCNT] & 0xf) == 0xa)
- m_m[RSECCNT] = m_m[RSECCNT] + 6;
- if (m_m[RSECCNT] == 0x60)
+ m_rseccnt = m_rseccnt + 1;
+ if ((m_rseccnt & 0xf) == 0xa)
+ m_rseccnt = m_rseccnt + 6;
+ if (m_rseccnt == 0x60)
{
- m_m[RSECCNT] = 0;
- carry=1;
+ m_rseccnt = 0;
+ carry = 1;
}
else
return;
@@ -538,91 +520,90 @@ void sh34_base_device::increment_rtc_time(int mode)
else
carry = 1;
- m_m[RMINCNT] = m_m[RMINCNT] + carry;
- if ((m_m[RMINCNT] & 0xf) == 0xa)
- m_m[RMINCNT] = m_m[RMINCNT] + 6;
- carry=0;
- if (m_m[RMINCNT] == 0x60)
+ m_rmincnt = m_rmincnt + carry;
+ if ((m_rmincnt & 0xf) == 0xa)
+ m_rmincnt = m_rmincnt + 6;
+ carry = 0;
+
+ if (m_rmincnt == 0x60)
{
- m_m[RMINCNT] = 0;
+ m_rmincnt = 0;
carry = 1;
}
- m_m[RHRCNT] = m_m[RHRCNT] + carry;
- if ((m_m[RHRCNT] & 0xf) == 0xa)
- m_m[RHRCNT] = m_m[RHRCNT] + 6;
+ m_rhrcnt = m_rhrcnt + carry;
+ if ((m_rhrcnt & 0xf) == 0xa)
+ m_rhrcnt = m_rhrcnt + 6;
carry = 0;
- if (m_m[RHRCNT] == 0x24)
+
+ if (m_rhrcnt == 0x24)
{
- m_m[RHRCNT] = 0;
+ m_rhrcnt = 0;
carry = 1;
}
- m_m[RWKCNT] = m_m[RWKCNT] + carry;
- if (m_m[RWKCNT] == 0x7)
+ m_rwkcnt = m_rwkcnt + carry;
+ if (m_rwkcnt == 0x7)
{
- m_m[RWKCNT] = 0;
+ m_rwkcnt = 0;
}
- days = 0;
- year = (m_m[RYRCNT] & 0xf) + ((m_m[RYRCNT] & 0xf0) >> 4)*10 + ((m_m[RYRCNT] & 0xf00) >> 8)*100 + ((m_m[RYRCNT] & 0xf000) >> 12)*1000;
- leap = 0;
- if (!(year%100))
+ int days = 0;
+ int year = (m_ryrcnt & 0xf) + ((m_ryrcnt & 0xf0) >> 4) * 10 + ((m_ryrcnt & 0xf00) >> 8) * 100 + ((m_ryrcnt & 0xf000) >> 12) * 1000;
+ int leap = 0;
+ if (!(year % 100))
{
- if (!(year%400))
+ if (!(year % 400))
leap = 1;
}
- else if (!(year%4))
+ else if (!(year % 4))
leap = 1;
- if (m_m[RMONCNT] != 2)
+ if (m_rmoncnt != 2)
leap = 0;
- if (m_m[RMONCNT])
- days = daysmonth[(m_m[RMONCNT] & 0xf) + ((m_m[RMONCNT] & 0xf0) >> 4)*10 - 1];
+ if (m_rmoncnt)
+ days = daysmonth[(m_rmoncnt & 0xf) + ((m_rmoncnt & 0xf0) >> 4) * 10 - 1];
- m_m[RDAYCNT] = m_m[RDAYCNT] + carry;
- if ((m_m[RDAYCNT] & 0xf) == 0xa)
- m_m[RDAYCNT] = m_m[RDAYCNT] + 6;
+ m_rdaycnt = m_rdaycnt + carry;
+ if ((m_rdaycnt & 0xf) == 0xa)
+ m_rdaycnt = m_rdaycnt + 6;
carry = 0;
- if (m_m[RDAYCNT] > (days+leap))
+
+ if (m_rdaycnt > (days + leap))
{
- m_m[RDAYCNT] = 1;
+ m_rdaycnt = 1;
carry = 1;
}
- m_m[RMONCNT] = m_m[RMONCNT] + carry;
- if ((m_m[RMONCNT] & 0xf) == 0xa)
- m_m[RMONCNT] = m_m[RMONCNT] + 6;
- carry=0;
- if (m_m[RMONCNT] == 0x13)
+ m_rmoncnt = m_rmoncnt + carry;
+ if ((m_rmoncnt & 0xf) == 0xa)
+ m_rmoncnt = m_rmoncnt + 6;
+ carry = 0;
+
+ if (m_rmoncnt == 0x13)
{
- m_m[RMONCNT] = 1;
+ m_rmoncnt = 1;
carry = 1;
}
- m_m[RYRCNT] = m_m[RYRCNT] + carry;
- if ((m_m[RYRCNT] & 0xf) >= 0xa)
- m_m[RYRCNT] = m_m[RYRCNT] + 6;
- if ((m_m[RYRCNT] & 0xf0) >= 0xa0)
- m_m[RYRCNT] = m_m[RYRCNT] + 0x60;
- if ((m_m[RYRCNT] & 0xf00) >= 0xa00)
- m_m[RYRCNT] = m_m[RYRCNT] + 0x600;
- if ((m_m[RYRCNT] & 0xf000) >= 0xa000)
- m_m[RYRCNT] = 0;
+ m_ryrcnt = m_ryrcnt + carry;
+ if ((m_ryrcnt & 0xf) >= 0xa)
+ m_ryrcnt = m_ryrcnt + 6;
+ if ((m_ryrcnt & 0xf0) >= 0xa0)
+ m_ryrcnt = m_ryrcnt + 0x60;
+ if ((m_ryrcnt & 0xf00) >= 0xa00)
+ m_ryrcnt = m_ryrcnt + 0x600;
+ if ((m_ryrcnt & 0xf000) >= 0xa000)
+ m_ryrcnt = 0;
}
-TIMER_CALLBACK_MEMBER( sh34_base_device::sh4_rtc_timer_callback )
+TIMER_CALLBACK_MEMBER(sh4_base_device::sh4_rtc_timer_callback)
{
- if (m_cpu_type != CPU_TYPE_SH4)
- {
- logerror("sh4_rtc_timer_callback uses m_m[] with SH3\n");
- return;
- }
-
m_rtc_timer->adjust(attotime::from_hz(128));
- m_m[R64CNT] = (m_m[R64CNT]+1) & 0x7f;
- if (m_m[R64CNT] == 64)
+
+ m_r64cnt = (m_r64cnt + 1) & 0x7f;
+ if (m_r64cnt == 64)
{
- m_m[RCR1] |= 0x80;
+ m_rcr1 |= 0x80;
increment_rtc_time(0);
//sh4_exception_request(SH4_INTC_NMI); // TEST
}
@@ -633,7 +614,7 @@ void sh34_base_device::sh4_dmac_nmi() // manage dma when nmi gets asserted
{
int s;
- m_SH4_DMAOR |= DMAOR_NMIF;
+ m_dmaor |= DMAOR_NMIF;
for (s = 0;s < 4;s++)
{
if (m_dma_timer_active[s])
@@ -645,446 +626,2151 @@ void sh34_base_device::sh4_dmac_nmi() // manage dma when nmi gets asserted
}
}
-void sh34_base_device::sh4_handler_ipra_w(uint32_t data, uint32_t mem_mask)
+// CCN
+uint32_t sh4_base_device::pteh_r(offs_t offset, uint32_t mem_mask)
+{
+ return m_pteh;
+}
+
+void sh4_base_device::pteh_w(offs_t offset, uint32_t data, uint32_t mem_mask)
+{
+ // for use with LDTLB opcode
+ /*
+ NNNN NNNN NNNN NNNN NNNN NN-- AAAA AAAA
+
+ N = VPM = Virtual Page Number
+ A = ASID = Address Space Identifier
+
+ same as the address table part of the utlb but with 2 unused bits (these are sourced from PTEL instead when LDTLB is called)
+ */
+ COMBINE_DATA(&m_pteh);
+}
+
+uint32_t sh4_base_device::ptel_r(offs_t offset, uint32_t mem_mask)
+{
+ return m_ptel;
+}
+
+void sh4_base_device::ptel_w(offs_t offset, uint32_t data, uint32_t mem_mask)
+{
+ /*
+ ---P PPPP PPPP PPPP PPPP PP-V zRRz CDHW
+
+ same format as data array 1 of the utlb
+ */
+ COMBINE_DATA(&m_ptel);
+}
+
+uint32_t sh4_base_device::ttb_r(offs_t offset, uint32_t mem_mask)
+{
+ return m_ttb;
+}
+
+void sh4_base_device::ttb_w(offs_t offset, uint32_t data, uint32_t mem_mask)
+{
+ COMBINE_DATA(&m_ttb);
+ logerror("TTB set to %08x\n", m_ttb);
+}
+
+uint32_t sh4_base_device::tea_r(offs_t offset, uint32_t mem_mask)
+{
+ return m_tea;
+}
+
+void sh4_base_device::tea_w(offs_t offset, uint32_t data, uint32_t mem_mask)
+{
+ COMBINE_DATA(&m_tea);
+ logerror("TEA set to %08x\n", m_tea);
+}
+
+uint32_t sh4_base_device::mmucr_r(offs_t offset, uint32_t mem_mask)
+{
+ return m_mmucr;
+}
+
+void sh4_base_device::mmucr_w(offs_t offset, uint32_t data, uint32_t mem_mask)
+{
+ // MMU Control
+ /*
+ LLLL LL-- BBBB BB-- CCCC CCQV ---- -T-A
+
+ L = LRUI = Least recently used ITLB
+ B = URB = UTLB replace boundary
+ C = URC = UTLB replace counter
+ Q = SQMD = Store Queue Mode Bit
+ V = SV = Single Virtual Mode Bit
+ T = TI = TLB invalidate
+ A = AT = Address translation bit (enable)
+ */
+ COMBINE_DATA(&m_mmucr);
+ // MMUCR_AT
+ m_sh4_mmu_enabled = BIT(data, 0);
+ logerror("%s: MMUCR %08x (enable: %d)\n", machine().describe_context(), data, m_sh4_mmu_enabled);
+
+ if (m_sh4_mmu_enabled)
+ {
+ // Newer versions of the Dreamcast Katana SDK use MMU to remap the SQ write-back space (cfr. ikaruga and several later NAOMI GD-ROM releases)
+ // Anything beyond that is bound to fail,
+ // i.e. DC WinCE games, DC Linux distros, v2 Sega checkers, aristmk6.cpp
+#if 0
+ if (m_mmuhack == 1)
+ {
+ printf("SH4 MMU Enabled\n");
+ printf("If you're seeing this, but running something other than a Naomi GD-ROM game then chances are it won't work\n");
+ printf("The MMU emulation is a hack specific to that system\n");
+ }
+#endif
+
+ if (m_mmuhack == 2)
+ {
+ for (int i = 0; i < 64; i++)
+ {
+ if (m_utlb[i].V)
+ {
+ // FIXME: potentially verbose, move to logmacro.h pattern
+ // cfr. MMU Check_4 in v2.xx DC CHECKER
+ logerror("(entry %02x | ASID: %02x VPN: %08x V: %02x PPN: %08x SZ: %02x SH: %02x C: %02x PPR: %02x D: %02x WT %02x: SA: %02x TC: %02x)\n",
+ i,
+ m_utlb[i].ASID,
+ m_utlb[i].VPN << 10,
+ m_utlb[i].V,
+ m_utlb[i].PPN << 10,
+ m_utlb[i].PSZ,
+ m_utlb[i].SH,
+ m_utlb[i].C,
+ m_utlb[i].PPR,
+ m_utlb[i].D,
+ m_utlb[i].WT,
+ m_utlb[i].SA,
+ m_utlb[i].TC);
+ }
+ }
+ }
+ }
+}
+
+uint8_t sh4_base_device::basra_r(offs_t offset, uint8_t mem_mask)
+{
+ return m_basra;
+}
+
+void sh4_base_device::basra_w(offs_t offset, uint8_t data, uint8_t mem_mask)
+{
+ COMBINE_DATA(&m_basra);
+ logerror("basra_w: Unmapped write %02x @ %02x\n", data, mem_mask);
+}
+
+uint8_t sh4_base_device::basrb_r(offs_t offset, uint8_t mem_mask)
+{
+ return m_basrb;
+}
+
+void sh4_base_device::basrb_w(offs_t offset, uint8_t data, uint8_t mem_mask)
+{
+ COMBINE_DATA(&m_basrb);
+ logerror("basrb_w: Unmapped write %02x @ %02x\n", data, mem_mask);
+}
+
+uint32_t sh4_base_device::ccr_r(offs_t offset, uint32_t mem_mask)
+{
+ return m_ccr;
+}
+
+void sh4_base_device::ccr_w(offs_t offset, uint32_t data, uint32_t mem_mask)
+{
+ COMBINE_DATA(&m_ccr);
+ logerror("ccr_w: Unmapped write %08x @ %08x\n", data, mem_mask);
+}
+
+uint32_t sh4_base_device::tra_r(offs_t offset, uint32_t mem_mask)
+{
+ return m_tra;
+}
+
+void sh4_base_device::tra_w(offs_t offset, uint32_t data, uint32_t mem_mask)
+{
+ COMBINE_DATA(&m_tra);
+ logerror("tra_w: Unmapped write %08x @ %08x\n", data, mem_mask);
+}
+
+uint32_t sh4_base_device::expevt_r(offs_t offset, uint32_t mem_mask)
+{
+ return m_expevt;
+}
+
+void sh4_base_device::expevt_w(offs_t offset, uint32_t data, uint32_t mem_mask)
+{
+ COMBINE_DATA(&m_expevt);
+ logerror("expevt: Unmapped write %08x @ %08x\n", data, mem_mask);
+}
+
+uint32_t sh4_base_device::intevt_r(offs_t offset, uint32_t mem_mask)
+{
+ return m_intevt;
+}
+
+void sh4_base_device::intevt_w(offs_t offset, uint32_t data, uint32_t mem_mask)
+{
+ COMBINE_DATA(&m_intevt);
+ logerror("intevt_w: Unmapped write %08x @ %08x\n", data, mem_mask);
+}
+
+uint32_t sh4_base_device::ptea_r(offs_t offset, uint32_t mem_mask)
+{
+ return m_ptea;
+}
+
+void sh4_base_device::ptea_w(offs_t offset, uint32_t data, uint32_t mem_mask)
+{
+ /*
+ ---- ---- ---- ---- ---- ---- ---- TSSS
+
+ same format as data array 2 of the utlb
+ */
+ COMBINE_DATA(&m_ptea);
+}
+
+uint32_t sh4_base_device::qacr0_r(offs_t offset, uint32_t mem_mask)
+{
+ return m_qacr0;
+}
+
+void sh4_base_device::qacr0_w(offs_t offset, uint32_t data, uint32_t mem_mask)
+{
+ COMBINE_DATA(&m_qacr0);
+}
+
+uint32_t sh4_base_device::qacr1_r(offs_t offset, uint32_t mem_mask)
+{
+ return m_qacr1;
+}
+
+void sh4_base_device::qacr1_w(offs_t offset, uint32_t data, uint32_t mem_mask)
+{
+ COMBINE_DATA(&m_qacr1);
+}
+
+// UBC
+uint32_t sh4_base_device::bara_r(offs_t offset, uint32_t mem_mask)
+{
+ return m_bara;
+}
+
+void sh4_base_device::bara_w(offs_t offset, uint32_t data, uint32_t mem_mask)
+{
+ COMBINE_DATA(&m_bara);
+ logerror("bara_w: Unmapped write %08x @ %08x\n", data, mem_mask);
+}
+
+uint8_t sh4_base_device::bamra_r(offs_t offset, uint8_t mem_mask)
+{
+ return m_bamra;
+}
+
+void sh4_base_device::bamra_w(offs_t offset, uint8_t data, uint8_t mem_mask)
+{
+ COMBINE_DATA(&m_bamra);
+ logerror("bamra_w: Unmapped write %02x @ %02x\n", data, mem_mask);
+}
+
+uint16_t sh4_base_device::bbra_r(offs_t offset, uint16_t mem_mask)
+{
+ return m_bbra;
+}
+
+void sh4_base_device::bbra_w(offs_t offset, uint16_t data, uint16_t mem_mask)
+{
+ COMBINE_DATA(&m_bbra);
+ logerror("bbra_w: Unmapped write %04x @ %04x\n", data, mem_mask);
+}
+
+uint32_t sh4_base_device::barb_r(offs_t offset, uint32_t mem_mask)
+{
+ return m_barb;
+}
+
+void sh4_base_device::barb_w(offs_t offset, uint32_t data, uint32_t mem_mask)
+{
+ COMBINE_DATA(&m_barb);
+ logerror("barb_w: Unmapped write %08x @ %08x\n", data, mem_mask);
+}
+
+uint8_t sh4_base_device::bamrb_r(offs_t offset, uint8_t mem_mask)
+{
+ return m_bamrb;
+}
+
+void sh4_base_device::bamrb_w(offs_t offset, uint8_t data, uint8_t mem_mask)
+{
+ COMBINE_DATA(&m_bamrb);
+ logerror("bamrb_w: Unmapped write %02x @ %02x\n", data, mem_mask);
+}
+
+uint16_t sh4_base_device::bbrb_r(offs_t offset, uint16_t mem_mask)
+{
+ return m_bbrb;
+}
+
+void sh4_base_device::bbrb_w(offs_t offset, uint16_t data, uint16_t mem_mask)
+{
+ COMBINE_DATA(&m_bbrb);
+ logerror("bbrb_w: Unmapped write %04x @ %04x\n", data, mem_mask);
+}
+
+uint32_t sh4_base_device::bdrb_r(offs_t offset, uint32_t mem_mask)
+{
+ return m_bdrb;
+}
+
+void sh4_base_device::bdrb_w(offs_t offset, uint32_t data, uint32_t mem_mask)
+{
+ COMBINE_DATA(&m_bdrb);
+ logerror("bdrb_w: Unmapped write %08x @ %08x\n", data, mem_mask);
+}
+
+uint32_t sh4_base_device::bdmrb_r(offs_t offset, uint32_t mem_mask)
+{
+ return m_bdmrb;
+}
+
+void sh4_base_device::bdmrb_w(offs_t offset, uint32_t data, uint32_t mem_mask)
+{
+ COMBINE_DATA(&m_bdmrb);
+ logerror("bdmrb_w: Unmapped write %08x @ %08x\n", data, mem_mask);
+}
+
+uint16_t sh4_base_device::brcr_r(offs_t offset, uint16_t mem_mask)
+{
+ return m_brcr;
+}
+
+void sh4_base_device::brcr_w(offs_t offset, uint16_t data, uint16_t mem_mask)
+{
+ COMBINE_DATA(&m_brcr);
+ logerror("brcr_w: Unmapped write %04x @ %04x\n", data, mem_mask);
+}
+
+// BSC
+uint32_t sh4_base_device::bcr1_r(offs_t offset, uint32_t mem_mask)
+{
+ return m_bcr1;
+}
+
+void sh4_base_device::bcr1_w(offs_t offset, uint32_t data, uint32_t mem_mask)
+{
+ COMBINE_DATA(&m_bcr1);
+ logerror("bcr1_w: Unmapped write %08x @ %08x\n", data, mem_mask);
+}
+
+uint16_t sh4_base_device::bcr2_r(offs_t offset, uint16_t mem_mask)
+{
+ return m_bcr2;
+}
+
+void sh4_base_device::bcr2_w(offs_t offset, uint16_t data, uint16_t mem_mask)
+{
+ COMBINE_DATA(&m_bcr2);
+ logerror("bcr2_w: Unmapped write %04x @ %04x\n", data, mem_mask);
+}
+
+uint32_t sh4_base_device::wcr1_r(offs_t offset, uint32_t mem_mask)
+{
+ return m_wcr1;
+}
+
+void sh4_base_device::wcr1_w(offs_t offset, uint32_t data, uint32_t mem_mask)
+{
+ COMBINE_DATA(&m_wcr1);
+ logerror("wcr1_w: Unmapped write %08x @ %08x\n", data, mem_mask);
+}
+
+uint32_t sh4_base_device::wcr2_r(offs_t offset, uint32_t mem_mask)
+{
+ return m_wcr2;
+}
+
+void sh4_base_device::wcr2_w(offs_t offset, uint32_t data, uint32_t mem_mask)
+{
+ COMBINE_DATA(&m_wcr2);
+ logerror("wcr2_w: Unmapped write %08x @ %08x\n", data, mem_mask);
+}
+
+uint32_t sh4_base_device::wcr3_r(offs_t offset, uint32_t mem_mask)
+{
+ return m_wcr3;
+}
+
+void sh4_base_device::wcr3_w(offs_t offset, uint32_t data, uint32_t mem_mask)
+{
+ COMBINE_DATA(&m_wcr3);
+ logerror("wcr3_w: Unmapped write %08x @ %08x\n", data, mem_mask);
+}
+
+uint32_t sh4_base_device::mcr_r(offs_t offset, uint32_t mem_mask)
+{
+ return m_mcr;
+}
+
+void sh4_base_device::mcr_w(offs_t offset, uint32_t data, uint32_t mem_mask)
+{
+ COMBINE_DATA(&m_mcr);
+ logerror("mcr_w: Unmapped write %08x @ %08x\n", data, mem_mask);
+}
+
+uint16_t sh4_base_device::pcr_r(offs_t offset, uint16_t mem_mask)
+{
+ return m_pcr;
+}
+
+void sh4_base_device::pcr_w(offs_t offset, uint16_t data, uint16_t mem_mask)
+{
+ COMBINE_DATA(&m_pcr);
+ logerror("pcr_w: Unmapped write %04x @ %04x\n", data, mem_mask);
+}
+
+uint16_t sh4_base_device::rtcsr_r(offs_t offset, uint16_t mem_mask)
+{
+ return m_rtcsr;
+}
+
+void sh4_base_device::rtcsr_w(offs_t offset, uint16_t data, uint16_t mem_mask)
+{
+ // Memory refresh
+ uint16_t old = m_rtcsr;
+ COMBINE_DATA(&m_rtcsr);
+ m_rtcsr &= 255;
+ if ((old >> 3) & 7)
+ m_rtcnt = compute_ticks_refresh_timer(m_refresh_timer, m_bus_clock, m_refresh_timer_base, rtcnt_div[(old >> 3) & 7]) & 0xff;
+ if ((m_rtcsr >> 3) & 7)
+ { // activated
+ sh4_refresh_timer_recompute();
+ }
+ else
+ {
+ m_refresh_timer->adjust(attotime::never);
+ }
+}
+
+uint16_t sh4_base_device::rtcnt_r(offs_t offset, uint16_t mem_mask)
+{
+ if ((m_rtcsr >> 3) & 7)
+ { // activated
+ //((double)rtcnt_div[(m_rtcsr >> 3) & 7] / (double)100000000)
+ //return (refresh_timer_base + (m_refresh_timer->elapsed() * (double)100000000) / (double)rtcnt_div[(m_rtcsr >> 3) & 7]) & 0xff;
+ return compute_ticks_refresh_timer(m_refresh_timer, m_bus_clock, m_refresh_timer_base, rtcnt_div[(m_rtcsr >> 3) & 7]) & 0xff;
+ }
+ else
+ return m_rtcnt;
+}
+
+void sh4_base_device::rtcnt_w(offs_t offset, uint16_t data, uint16_t mem_mask)
+{
+ COMBINE_DATA(&m_rtcnt);
+ m_rtcnt &= 255;
+ if ((m_rtcsr >> 3) & 7)
+ { // active
+ sh4_refresh_timer_recompute();
+ }
+}
+
+uint16_t sh4_base_device::rtcor_r(offs_t offset, uint16_t mem_mask)
+{
+ return m_rtcor;
+}
+
+void sh4_base_device::rtcor_w(offs_t offset, uint16_t data, uint16_t mem_mask)
+{
+ COMBINE_DATA(&m_rtcor);
+ m_rtcor &= 255;
+ if ((m_rtcsr >> 3) & 7)
+ { // active
+ m_rtcnt = compute_ticks_refresh_timer(m_refresh_timer, m_bus_clock, m_refresh_timer_base, rtcnt_div[(m_rtcsr >> 3) & 7]) & 0xff;
+ sh4_refresh_timer_recompute();
+ }
+}
+
+uint16_t sh4_base_device::rfcr_r(offs_t offset, uint16_t mem_mask)
+{
+ return m_rfcr;
+}
+
+void sh4_base_device::rfcr_w(offs_t offset, uint16_t data, uint16_t mem_mask)
+{
+ COMBINE_DATA(&m_rfcr);
+ m_rfcr &= 1023;
+}
+
+uint32_t sh4_base_device::pctra_r(offs_t offset, uint32_t mem_mask)
+{
+ return m_pctra;
+}
+
+void sh4_base_device::pctra_w(offs_t offset, uint32_t data, uint32_t mem_mask)
+{
+ COMBINE_DATA(&m_pctra);
+ m_ioport16_pullup = 0;
+ m_ioport16_direction = 0;
+ for (int a = 0; a < 16; a++)
+ {
+ m_ioport16_direction |= (m_pctra & (1 << (a * 2))) >> a;
+ m_ioport16_pullup |= (m_pctra & (1 << (a * 2 + 1))) >> (a + 1);
+ }
+ m_ioport16_direction &= 0xffff;
+ m_ioport16_pullup = (m_ioport16_pullup | m_ioport16_direction) ^ 0xffff;
+ if (m_bcr2 & 1)
+ m_io->write_dword(SH4_IOPORT_16, (uint64_t)(m_pdtra & m_ioport16_direction) | ((uint64_t)m_pctra << 16));
+}
+
+uint16_t sh4_base_device::pdtra_r(offs_t offset, uint16_t mem_mask)
+{
+ if (m_bcr2 & 1)
+ return (m_io->read_dword(SH4_IOPORT_16) & ~m_ioport16_direction) | (m_pdtra & m_ioport16_direction);
+
+ return m_pdtra;
+}
+
+void sh4_base_device::pdtra_w(offs_t offset, uint16_t data, uint16_t mem_mask)
+{
+ COMBINE_DATA(&m_pdtra);
+ if (m_bcr2 & 1)
+ m_io->write_dword(SH4_IOPORT_16, (uint64_t)(m_pdtra & m_ioport16_direction) | ((uint64_t)m_pctra << 16));
+}
+
+uint32_t sh4_base_device::pctrb_r(offs_t offset, uint32_t mem_mask)
+{
+ return m_pctrb;
+}
+
+void sh4_base_device::pctrb_w(offs_t offset, uint32_t data, uint32_t mem_mask)
+{
+ COMBINE_DATA(&m_pctrb);
+ m_ioport4_pullup = 0;
+ m_ioport4_direction = 0;
+ for (int a = 0; a < 4; a++)
+ {
+ m_ioport4_direction |= (m_pctrb & (1 << (a * 2))) >> a;
+ m_ioport4_pullup |= (m_pctrb & (1 << (a * 2 + 1))) >> (a + 1);
+ }
+ m_ioport4_direction &= 0xf;
+ m_ioport4_pullup = (m_ioport4_pullup | m_ioport4_direction) ^ 0xf;
+ if (m_bcr2 & 1)
+ m_io->write_dword(SH4_IOPORT_4, (m_pdtrb & m_ioport4_direction) | (m_pctrb << 16));
+}
+
+uint16_t sh4_base_device::pdtrb_r(offs_t offset, uint16_t mem_mask)
+{
+ if (m_bcr2 & 1)
+ return (m_io->read_dword(SH4_IOPORT_4) & ~m_ioport4_direction) | (m_pdtrb & m_ioport4_direction);
+
+ return m_pdtrb;
+}
+
+void sh4_base_device::pdtrb_w(offs_t offset, uint16_t data, uint16_t mem_mask)
+{
+ COMBINE_DATA(&m_pdtrb);
+ if (m_bcr2 & 1)
+ m_io->write_dword(SH4_IOPORT_4, (m_pdtrb & m_ioport4_direction) | (m_pctrb << 16));
+}
+
+uint16_t sh4_base_device::gpioic_r(offs_t offset, uint16_t mem_mask)
+{
+ return m_gpioic;
+}
+
+void sh4_base_device::gpioic_w(offs_t offset, uint16_t data, uint16_t mem_mask)
+{
+ COMBINE_DATA(&m_gpioic);
+ logerror("gpioic_w: Unmapped write %04x @ %04x\n", data, mem_mask);
+}
+
+void sh4_base_device::sdmr2_w(offs_t offset, uint8_t data, uint8_t mem_mask)
+{
+ logerror("sdmr2_w: Unmapped write %02x @ %02x\n", data, mem_mask);
+}
+
+void sh4_base_device::sdmr3_w(offs_t offset, uint8_t data, uint8_t mem_mask)
+{
+ logerror("sdmr3_w: Unmapped write %02x @ %02x\n", data, mem_mask);
+}
+
+// BSC 7750R
+uint16_t sh4_base_device::bcr3_r(offs_t offset, uint16_t mem_mask)
+{
+ return m_bcr3;
+}
+
+void sh4_base_device::bcr3_w(offs_t offset, uint16_t data, uint16_t mem_mask)
+{
+ COMBINE_DATA(&m_bcr3);
+ logerror("bcr3_w: Unmapped write %04x @ %04x\n", data, mem_mask);
+}
+
+uint32_t sh4_base_device::bcr4_r(offs_t offset, uint32_t mem_mask)
+{
+ return m_bcr4;
+}
+
+void sh4_base_device::bcr4_w(offs_t offset, uint32_t data, uint32_t mem_mask)
+{
+ COMBINE_DATA(&m_bcr4);
+ logerror("bcr4_w: Unmapped write %08x @ %08x\n", data, mem_mask);
+}
+
+// DMAC 7750R
+uint32_t sh4_base_device::sar4_r(offs_t offset, uint32_t mem_mask)
+{
+ return m_sar4;
+}
+
+void sh4_base_device::sar4_w(offs_t offset, uint32_t data, uint32_t mem_mask)
+{
+ COMBINE_DATA(&m_sar4);
+ logerror("sar4_w: Unmapped write %08x @ %08x\n", data, mem_mask);
+}
+
+uint32_t sh4_base_device::dar4_r(offs_t offset, uint32_t mem_mask)
+{
+ return m_dar4;
+}
+
+void sh4_base_device::dar4_w(offs_t offset, uint32_t data, uint32_t mem_mask)
+{
+ COMBINE_DATA(&m_dar4);
+ logerror("dar4_w: Unmapped write %08x @ %08x\n", data, mem_mask);
+}
+
+uint32_t sh4_base_device::dmatcr4_r(offs_t offset, uint32_t mem_mask)
+{
+ return m_dmatcr4;
+}
+
+void sh4_base_device::dmatcr4_w(offs_t offset, uint32_t data, uint32_t mem_mask)
+{
+ COMBINE_DATA(&m_dmatcr4);
+ logerror("dmatcr4_w: Unmapped write %08x @ %08x\n", data, mem_mask);
+}
+
+uint32_t sh4_base_device::chcr4_r(offs_t offset, uint32_t mem_mask)
+{
+ return m_chcr4;
+}
+
+void sh4_base_device::chcr4_w(offs_t offset, uint32_t data, uint32_t mem_mask)
+{
+ COMBINE_DATA(&m_chcr4);
+ logerror("chcr4_w: Unmapped write %08x @ %08x\n", data, mem_mask);
+}
+
+uint32_t sh4_base_device::sar5_r(offs_t offset, uint32_t mem_mask)
+{
+ return m_sar5;
+}
+
+void sh4_base_device::sar5_w(offs_t offset, uint32_t data, uint32_t mem_mask)
+{
+ COMBINE_DATA(&m_sar5);
+ logerror("sar5_w: Unmapped write %08x @ %08x\n", data, mem_mask);
+}
+
+uint32_t sh4_base_device::dar5_r(offs_t offset, uint32_t mem_mask)
+{
+ return m_dar5;
+}
+
+void sh4_base_device::dar5_w(offs_t offset, uint32_t data, uint32_t mem_mask)
+{
+ COMBINE_DATA(&m_dar5);
+ logerror("dar5_w: Unmapped write %08x @ %08x\n", data, mem_mask);
+}
+
+uint32_t sh4_base_device::dmatcr5_r(offs_t offset, uint32_t mem_mask)
+{
+ return m_dmatcr5;
+}
+
+void sh4_base_device::dmatcr5_w(offs_t offset, uint32_t data, uint32_t mem_mask)
+{
+ COMBINE_DATA(&m_dmatcr5);
+ logerror("dmatcr5_w: Unmapped write %08x @ %08x\n", data, mem_mask);
+}
+
+uint32_t sh4_base_device::chcr5_r(offs_t offset, uint32_t mem_mask)
+{
+ return m_chcr5;
+}
+
+void sh4_base_device::chcr5_w(offs_t offset, uint32_t data, uint32_t mem_mask)
+{
+ COMBINE_DATA(&m_chcr5);
+ logerror("chcr5_w: Unmapped write %08x @ %08x\n", data, mem_mask);
+}
+
+uint32_t sh4_base_device::sar6_r(offs_t offset, uint32_t mem_mask)
+{
+ return m_sar6;
+}
+
+void sh4_base_device::sar6_w(offs_t offset, uint32_t data, uint32_t mem_mask)
+{
+ COMBINE_DATA(&m_sar6);
+ logerror("sar6_w: Unmapped write %08x @ %08x\n", data, mem_mask);
+}
+
+uint32_t sh4_base_device::dar6_r(offs_t offset, uint32_t mem_mask)
+{
+ return m_dar6;
+}
+
+void sh4_base_device::dar6_w(offs_t offset, uint32_t data, uint32_t mem_mask)
+{
+ COMBINE_DATA(&m_dar6);
+ logerror("dar6_w: Unmapped write %08x @ %08x\n", data, mem_mask);
+}
+
+uint32_t sh4_base_device::dmatcr6_r(offs_t offset, uint32_t mem_mask)
+{
+ return m_dmatcr6;
+}
+
+void sh4_base_device::dmatcr6_w(offs_t offset, uint32_t data, uint32_t mem_mask)
+{
+ COMBINE_DATA(&m_dmatcr6);
+ logerror("dmatcr6_w: Unmapped write %08x @ %08x\n", data, mem_mask);
+}
+
+uint32_t sh4_base_device::chcr6_r(offs_t offset, uint32_t mem_mask)
+{
+ return m_chcr6;
+}
+
+void sh4_base_device::chcr6_w(offs_t offset, uint32_t data, uint32_t mem_mask)
+{
+ COMBINE_DATA(&m_chcr6);
+ logerror("chcr6_w: Unmapped write %08x @ %08x\n", data, mem_mask);
+}
+
+uint32_t sh4_base_device::sar7_r(offs_t offset, uint32_t mem_mask)
+{
+ return m_sar7;
+}
+
+void sh4_base_device::sar7_w(offs_t offset, uint32_t data, uint32_t mem_mask)
+{
+ COMBINE_DATA(&m_sar7);
+ logerror("sar7_w: Unmapped write %08x @ %08x\n", data, mem_mask);
+}
+
+uint32_t sh4_base_device::dar7_r(offs_t offset, uint32_t mem_mask)
+{
+ return m_dar7;
+}
+
+void sh4_base_device::dar7_w(offs_t offset, uint32_t data, uint32_t mem_mask)
+{
+ COMBINE_DATA(&m_dar7);
+ logerror("dar7_w: Unmapped write %08x @ %08x\n", data, mem_mask);
+}
+
+uint32_t sh4_base_device::dmatcr7_r(offs_t offset, uint32_t mem_mask)
+{
+ return m_dmatcr7;
+}
+
+void sh4_base_device::dmatcr7_w(offs_t offset, uint32_t data, uint32_t mem_mask)
+{
+ COMBINE_DATA(&m_dmatcr7);
+ logerror("dmatcr7_w: Unmapped write %08x @ %08x\n", data, mem_mask);
+}
+
+uint32_t sh4_base_device::chcr7_r(offs_t offset, uint32_t mem_mask)
+{
+ return m_chcr7;
+}
+
+void sh4_base_device::chcr7_w(offs_t offset, uint32_t data, uint32_t mem_mask)
+{
+ COMBINE_DATA(&m_chcr7);
+ logerror("chcr7_w: Unmapped write %08x @ %08x\n", data, mem_mask);
+}
+
+// CPG
+uint16_t sh4_base_device::frqcr_r(offs_t offset, uint16_t mem_mask)
+{
+ return m_frqcr;
+}
+
+void sh4_base_device::frqcr_w(offs_t offset, uint16_t data, uint16_t mem_mask)
+{
+ COMBINE_DATA(&m_frqcr);
+ logerror("frqcr_w: Unmapped write %04x @ %04x\n", data, mem_mask);
+}
+
+uint8_t sh4_base_device::stbcr_r(offs_t offset, uint8_t mem_mask)
+{
+ return m_stbcr;
+}
+
+void sh4_base_device::stbcr_w(offs_t offset, uint8_t data, uint8_t mem_mask)
+{
+ COMBINE_DATA(&m_stbcr);
+ logerror("stbcr_w: Unmapped write %02x @ %02x\n", data, mem_mask);
+}
+
+uint8_t sh4_base_device::wtcnt_r(offs_t offset, uint8_t mem_mask)
+{
+ return m_wtcnt;
+}
+
+void sh4_base_device::wtcnt_w(offs_t offset, uint16_t data, uint16_t mem_mask)
+{
+ COMBINE_DATA(&m_wtcnt);
+ logerror("wtcnt_w: Unmapped write %04x @ %04x\n", data, mem_mask);
+}
+
+uint8_t sh4_base_device::wtcsr_r(offs_t offset, uint8_t mem_mask)
+{
+ return m_wtcsr;
+}
+
+void sh4_base_device::wtcsr_w(offs_t offset, uint16_t data, uint16_t mem_mask)
+{
+ COMBINE_DATA(&m_wtcsr);
+ logerror("wtcsr_w: Unmapped write %04x @ %04x\n", data, mem_mask);
+}
+
+uint8_t sh4_base_device::stbcr2_r(offs_t offset, uint8_t mem_mask)
+{
+ return m_stbcr2;
+}
+
+void sh4_base_device::stbcr2_w(offs_t offset, uint8_t data, uint8_t mem_mask)
+{
+ COMBINE_DATA(&m_stbcr2);
+ logerror("stbcr2_w: Unmapped write %02x @ %02x\n", data, mem_mask);
+}
+
+// CPG 7750R
+uint32_t sh4_base_device::clkstp00_r(offs_t offset, uint32_t mem_mask)
+{
+ return m_clkstp00;
+}
+
+void sh4_base_device::clkstp00_w(offs_t offset, uint32_t data, uint32_t mem_mask)
+{
+ COMBINE_DATA(&m_clkstp00);
+ logerror("clkstp00_w: Unmapped write %08x @ %08x\n", data, mem_mask);
+}
+
+void sh4_base_device::clkstpclr_w(offs_t offset, uint32_t data, uint32_t mem_mask)
+{
+ logerror("clkstpclr_w: Unmapped write %08x @ %08x\n", data, mem_mask);
+}
+
+// RTC
+uint8_t sh4_base_device::r64cnt_r(offs_t offset, uint8_t mem_mask)
+{
+ return m_r64cnt;
+}
+
+uint8_t sh4_base_device::rseccnt_r(offs_t offset, uint8_t mem_mask)
+{
+ return m_rseccnt;
+}
+
+void sh4_base_device::rseccnt_w(offs_t offset, uint8_t data, uint8_t mem_mask)
+{
+ COMBINE_DATA(&m_rseccnt);
+}
+
+uint8_t sh4_base_device::rmincnt_r(offs_t offset, uint8_t mem_mask)
+{
+ return m_rmincnt;
+}
+
+void sh4_base_device::rmincnt_w(offs_t offset, uint8_t data, uint8_t mem_mask)
+{
+ COMBINE_DATA(&m_rmincnt);
+}
+
+uint8_t sh4_base_device::rhrcnt_r(offs_t offset, uint8_t mem_mask)
+{
+ return m_rhrcnt;
+}
+
+void sh4_base_device::rhrcnt_w(offs_t offset, uint8_t data, uint8_t mem_mask)
+{
+ COMBINE_DATA(&m_rhrcnt);
+}
+
+uint8_t sh4_base_device::rwkcnt_r(offs_t offset, uint8_t mem_mask)
+{
+ return m_rwkcnt;
+}
+
+void sh4_base_device::rwkcnt_w(offs_t offset, uint8_t data, uint8_t mem_mask)
+{
+ COMBINE_DATA(&m_rwkcnt);
+}
+
+uint8_t sh4_base_device::rdaycnt_r(offs_t offset, uint8_t mem_mask)
+{
+ return m_rdaycnt;
+}
+
+void sh4_base_device::rdaycnt_w(offs_t offset, uint8_t data, uint8_t mem_mask)
+{
+ COMBINE_DATA(&m_rdaycnt);
+}
+
+uint8_t sh4_base_device::rmoncnt_r(offs_t offset, uint8_t mem_mask)
+{
+ return m_rmoncnt;
+}
+
+void sh4_base_device::rmoncnt_w(offs_t offset, uint8_t data, uint8_t mem_mask)
+{
+ COMBINE_DATA(&m_rmoncnt);
+}
+
+uint16_t sh4_base_device::ryrcnt_r(offs_t offset, uint16_t mem_mask)
+{
+ return m_ryrcnt;
+}
+
+void sh4_base_device::ryrcnt_w(offs_t offset, uint16_t data, uint16_t mem_mask)
+{
+ COMBINE_DATA(&m_ryrcnt);
+}
+
+uint8_t sh4_base_device::rsecar_r(offs_t offset, uint8_t mem_mask)
+{
+ return m_rsecar;
+}
+
+void sh4_base_device::rsecar_w(offs_t offset, uint8_t data, uint8_t mem_mask)
+{
+ COMBINE_DATA(&m_rsecar);
+ logerror("rsecar_w: Unmapped write %02x @ %02x\n", data, mem_mask);
+}
+
+uint8_t sh4_base_device::rminar_r(offs_t offset, uint8_t mem_mask)
+{
+ return m_rminar;
+}
+
+void sh4_base_device::rminar_w(offs_t offset, uint8_t data, uint8_t mem_mask)
+{
+ COMBINE_DATA(&m_rminar);
+ logerror("rminar_w: Unmapped write %02x @ %02x\n", data, mem_mask);
+}
+
+uint8_t sh4_base_device::rhrar_r(offs_t offset, uint8_t mem_mask)
+{
+ return m_rhrar;
+}
+
+void sh4_base_device::rhrar_w(offs_t offset, uint8_t data, uint8_t mem_mask)
+{
+ COMBINE_DATA(&m_rhrar);
+ logerror("rhrar_w: Unmapped write %02x @ %02x\n", data, mem_mask);
+}
+
+uint8_t sh4_base_device::rwkar_r(offs_t offset, uint8_t mem_mask)
+{
+ return m_rwkar;
+}
+
+void sh4_base_device::rwkar_w(offs_t offset, uint8_t data, uint8_t mem_mask)
+{
+ COMBINE_DATA(&m_rwkar);
+ logerror("rwkar_w: Unmapped write %02x @ %02x\n", data, mem_mask);
+}
+
+uint8_t sh4_base_device::rdayar_r(offs_t offset, uint8_t mem_mask)
+{
+ return m_rdayar;
+}
+
+void sh4_base_device::rdayar_w(offs_t offset, uint8_t data, uint8_t mem_mask)
+{
+ COMBINE_DATA(&m_rdayar);
+ logerror("rdayar_w: Unmapped write %02x @ %02x\n", data, mem_mask);
+}
+
+uint8_t sh4_base_device::rmonar_r(offs_t offset, uint8_t mem_mask)
+{
+ return m_rmonar;
+}
+
+void sh4_base_device::rmonar_w(offs_t offset, uint8_t data, uint8_t mem_mask)
+{
+ COMBINE_DATA(&m_rmonar);
+ logerror("rmonar_w: Unmapped write %02x @ %02x\n", data, mem_mask);
+}
+
+uint8_t sh4_base_device::rcr1_r(offs_t offset, uint8_t mem_mask)
+{
+ return m_rcr1;
+}
+
+void sh4_base_device::rcr1_w(offs_t offset, uint8_t data, uint8_t mem_mask)
+{
+ uint8_t old = m_rcr1;
+ COMBINE_DATA(&m_rcr1);
+ if ((m_rcr1 & 8) && (~old & 8)) // 0 -> 1
+ m_rcr1 ^= 1;
+}
+
+uint8_t sh4_base_device::rcr2_r(offs_t offset, uint8_t mem_mask)
+{
+ return m_rcr2;
+}
+
+void sh4_base_device::rcr2_w(offs_t offset, uint8_t data, uint8_t mem_mask)
+{
+ uint8_t old = m_rcr2;
+ COMBINE_DATA(&m_rcr2);
+ if (m_rcr2 & 2)
+ {
+ m_r64cnt = 0;
+ m_rcr2 ^= 2;
+ }
+ if (m_rcr2 & 4)
+ {
+ m_r64cnt = 0;
+ if (m_rseccnt >= 30)
+ increment_rtc_time(1);
+ m_rseccnt = 0;
+ }
+ if ((m_rcr2 & 8) && (~old & 8))
+ { // 0 -> 1
+ m_rtc_timer->adjust(attotime::from_hz(128));
+ }
+ else if (~m_rcr2 & 8)
+ { // 0
+ m_rtc_timer->adjust(attotime::never);
+ }
+}
+
+// RTC 7750R
+uint8_t sh4_base_device::rcr3_r(offs_t offset, uint8_t mem_mask)
+{
+ return m_rcr3;
+}
+
+void sh4_base_device::rcr3_w(offs_t offset, uint8_t data, uint8_t mem_mask)
+{
+ COMBINE_DATA(&m_rcr3);
+ logerror("rcr3_w: Unmapped write %02x @ %02x\n", data, mem_mask);
+}
+
+uint16_t sh4_base_device::ryrar_r(offs_t offset, uint16_t mem_mask)
+{
+ return m_ryrar;
+}
+
+void sh4_base_device::ryrar_w(offs_t offset, uint16_t data, uint16_t mem_mask)
+{
+ COMBINE_DATA(&m_ryrar);
+ logerror("ryrar_w: Unmapped write %04x @ %04x\n", data, mem_mask);
+}
+
+// INTC
+uint16_t sh4_base_device::icr_r(offs_t offset, uint16_t mem_mask)
{
- COMBINE_DATA(&m_SH4_IPRA);
+ return m_icr;
+}
+
+void sh4_base_device::icr_w(offs_t offset, uint16_t data, uint16_t mem_mask)
+{
+ uint16_t old = m_icr;
+ COMBINE_DATA(&m_icr);
+ m_icr = (m_icr & 0x7fff) | (old & 0x8000);
+}
+
+uint16_t sh34_base_device::ipra_r(offs_t offset, uint16_t mem_mask)
+{
+ return m_ipra;
+}
+
+void sh34_base_device::ipra_w(offs_t offset, uint16_t data, uint16_t mem_mask)
+{
+ COMBINE_DATA(&m_ipra);
/* 15 - 12 TMU0 */
/* 11 - 8 TMU1 */
/* 7 - 4 TMU2 */
/* 3 - 0 RTC */
- m_exception_priority[SH4_INTC_ATI] = INTPRI(m_SH4_IPRA & 0x000f, SH4_INTC_ATI);
- m_exception_priority[SH4_INTC_PRI] = INTPRI(m_SH4_IPRA & 0x000f, SH4_INTC_PRI);
- m_exception_priority[SH4_INTC_CUI] = INTPRI(m_SH4_IPRA & 0x000f, SH4_INTC_CUI);
+ m_exception_priority[SH4_INTC_ATI] = INTPRI(m_ipra & 0x000f, SH4_INTC_ATI);
+ m_exception_priority[SH4_INTC_PRI] = INTPRI(m_ipra & 0x000f, SH4_INTC_PRI);
+ m_exception_priority[SH4_INTC_CUI] = INTPRI(m_ipra & 0x000f, SH4_INTC_CUI);
- m_exception_priority[SH4_INTC_TUNI2] = INTPRI((m_SH4_IPRA & 0x00f0) >> 4, SH4_INTC_TUNI2);
- m_exception_priority[SH4_INTC_TICPI2] = INTPRI((m_SH4_IPRA & 0x00f0) >> 4, SH4_INTC_TICPI2);
+ m_exception_priority[SH4_INTC_TUNI2] = INTPRI((m_ipra & 0x00f0) >> 4, SH4_INTC_TUNI2);
+ m_exception_priority[SH4_INTC_TICPI2] = INTPRI((m_ipra & 0x00f0) >> 4, SH4_INTC_TICPI2);
- m_exception_priority[SH4_INTC_TUNI1] = INTPRI((m_SH4_IPRA & 0x0f00) >> 8, SH4_INTC_TUNI1);
+ m_exception_priority[SH4_INTC_TUNI1] = INTPRI((m_ipra & 0x0f00) >> 8, SH4_INTC_TUNI1);
- m_exception_priority[SH4_INTC_TUNI0] = INTPRI((m_SH4_IPRA & 0xf000) >> 12, SH4_INTC_TUNI0);
+ m_exception_priority[SH4_INTC_TUNI0] = INTPRI((m_ipra & 0xf000) >> 12, SH4_INTC_TUNI0);
- logerror("setting priorities TMU0 %01x TMU1 %01x TMU2 %01x RTC %01x\n", (m_SH4_IPRA & 0xf000)>>12, (m_SH4_IPRA & 0x0f00)>>8, (m_SH4_IPRA & 0x00f0)>>4, (m_SH4_IPRA & 0x000f)>>0);
+ logerror("setting priorities TMU0 %01x TMU1 %01x TMU2 %01x RTC %01x\n", (m_ipra & 0xf000) >> 12, (m_ipra & 0x0f00) >> 8, (m_ipra & 0x00f0) >> 4, (m_ipra & 0x000f) >> 0);
sh4_exception_recompute();
}
+uint16_t sh4_base_device::iprb_r(offs_t offset, uint16_t mem_mask)
+{
+ return m_iprb;
+}
-WRITE32_MEMBER( sh4_base_device::sh4_internal_w )
+void sh4_base_device::iprb_w(offs_t offset, uint16_t data, uint16_t mem_mask)
{
- int a;
- uint32_t addr = (offset << 2) + 0xfe000000;
- offset = ((addr & 0xfc) >> 2) | ((addr & 0x1fe0000) >> 11);
+ COMBINE_DATA(&m_iprb);
+ m_exception_priority[SH4_INTC_SCI1ERI] = INTPRI((m_iprb & 0x00f0) >> 4, SH4_INTC_SCI1ERI);
+ m_exception_priority[SH4_INTC_SCI1RXI] = INTPRI((m_iprb & 0x00f0) >> 4, SH4_INTC_SCI1RXI);
+ m_exception_priority[SH4_INTC_SCI1TXI] = INTPRI((m_iprb & 0x00f0) >> 4, SH4_INTC_SCI1TXI);
+ m_exception_priority[SH4_INTC_SCI1TEI] = INTPRI((m_iprb & 0x00f0) >> 4, SH4_INTC_SCI1TEI);
+ m_exception_priority[SH4_INTC_RCMI] = INTPRI((m_iprb & 0x0f00) >> 8, SH4_INTC_RCMI);
+ m_exception_priority[SH4_INTC_ROVI] = INTPRI((m_iprb & 0x0f00) >> 8, SH4_INTC_ROVI);
+ m_exception_priority[SH4_INTC_ITI] = INTPRI((m_iprb & 0xf000) >> 12, SH4_INTC_ITI);
+ sh4_exception_recompute();
+}
- if (m_cpu_type != CPU_TYPE_SH4)
- fatalerror("sh4_internal_w uses m_m[] with SH3\n");
+uint16_t sh4_base_device::iprc_r(offs_t offset, uint16_t mem_mask)
+{
+ return m_iprc;
+}
- uint32_t old = m_m[offset];
- COMBINE_DATA(m_m+offset);
+void sh4_base_device::iprc_w(offs_t offset, uint16_t data, uint16_t mem_mask)
+{
+ COMBINE_DATA(&m_iprc);
+ m_exception_priority[SH4_INTC_HUDI] = INTPRI(m_iprc & 0x000f, SH4_INTC_HUDI);
+ m_exception_priority[SH4_INTC_SCIFERI] = INTPRI((m_iprc & 0x00f0) >> 4, SH4_INTC_SCIFERI);
+ m_exception_priority[SH4_INTC_SCIFRXI] = INTPRI((m_iprc & 0x00f0) >> 4, SH4_INTC_SCIFRXI);
+ m_exception_priority[SH4_INTC_SCIFBRI] = INTPRI((m_iprc & 0x00f0) >> 4, SH4_INTC_SCIFBRI);
+ m_exception_priority[SH4_INTC_SCIFTXI] = INTPRI((m_iprc & 0x00f0) >> 4, SH4_INTC_SCIFTXI);
+ m_exception_priority[SH4_INTC_DMTE0] = INTPRI((m_iprc & 0x0f00) >> 8, SH4_INTC_DMTE0);
+ m_exception_priority[SH4_INTC_DMTE1] = INTPRI((m_iprc & 0x0f00) >> 8, SH4_INTC_DMTE1);
+ m_exception_priority[SH4_INTC_DMTE2] = INTPRI((m_iprc & 0x0f00) >> 8, SH4_INTC_DMTE2);
+ m_exception_priority[SH4_INTC_DMTE3] = INTPRI((m_iprc & 0x0f00) >> 8, SH4_INTC_DMTE3);
+ m_exception_priority[SH4_INTC_DMAE] = INTPRI((m_iprc & 0x0f00) >> 8, SH4_INTC_DMAE);
+ m_exception_priority[SH4_INTC_GPOI] = INTPRI((m_iprc & 0xf000) >> 12, SH4_INTC_GPOI);
+ sh4_exception_recompute();
+}
-// printf("sh4_internal_w: Write %08x (%x), %08x @ %08x\n", 0xfe000000+((offset & 0x3fc0) << 11)+((offset & 0x3f) << 2), offset, data, mem_mask);
+// INTC 7750S
+uint16_t sh4_base_device::iprd_r(offs_t offset, uint16_t mem_mask)
+{
+ return m_iprd;
+}
- switch( offset )
- {
- case PTEH: // for use with LDTLB opcode
- m_m[PTEH] &= 0xffffffff;
- /*
- NNNN NNNN NNNN NNNN NNNN NN-- AAAA AAAA
+void sh4_base_device::iprd_w(offs_t offset, uint16_t data, uint16_t mem_mask)
+{
+ COMBINE_DATA(&m_iprd);
+ logerror("iprd_w: Unmapped write %04x @ %04x\n", data, mem_mask);
+}
- N = VPM = Virtual Page Number
- A = ASID = Address Space Identifier
+// INTC 7750R
+uint32_t sh4_base_device::intpri00_r(offs_t offset, uint32_t mem_mask)
+{
+ return m_intpri00;
+}
- same as the address table part of the utlb but with 2 unused bits (these are sourced from PTEL instead when LDTLB is called)
- */
+void sh4_base_device::intpri00_w(offs_t offset, uint32_t data, uint32_t mem_mask)
+{
+ COMBINE_DATA(&m_intpri00);
+ logerror("intpri00_w: Unmapped write %08x @ %08x\n", data, mem_mask);
+}
+uint32_t sh4_base_device::intreq00_r(offs_t offset, uint32_t mem_mask)
+{
+ return m_intreq00;
+}
- break;
+void sh4_base_device::intreq00_w(offs_t offset, uint32_t data, uint32_t mem_mask)
+{
+ COMBINE_DATA(&m_intreq00);
+ logerror("intreq00_w: Unmapped write %08x @ %08x\n", data, mem_mask);
+}
- case PTEL:
- m_m[PTEL] &= 0xffffffff;
- /*
- ---P PPPP PPPP PPPP PPPP PP-V zRRz CDHW
+uint32_t sh4_base_device::intmsk00_r(offs_t offset, uint32_t mem_mask)
+{
+ return m_intmsk00;
+}
- same format as data array 1 of the utlb
- */
- break;
+void sh4_base_device::intmsk00_w(offs_t offset, uint32_t data, uint32_t mem_mask)
+{
+ COMBINE_DATA(&m_intmsk00);
+ logerror("intmsk00_w: Unmapped write %08x @ %08x\n", data, mem_mask);
+}
- case PTEA:
- m_m[PTEA] &= 0xffffffff;
- /*
- ---- ---- ---- ---- ---- ---- ---- TSSS
+void sh4_base_device::intmskclr_w(offs_t offset, uint32_t data, uint32_t mem_mask)
+{
+ logerror("intmskclr_w: Unmapped write %08x @ %08x\n", data, mem_mask);
+}
- same format as data array 2 of the utlb
- */
- break;
+// TMU 7750R
+uint8_t sh4_base_device::tstr2_r(offs_t offset, uint8_t mem_mask)
+{
+ return m_tstr2;
+}
- case TTB:
- m_m[TTB] &= 0xffffffff;
- logerror("TTB set to %08x\n", data);
- break;
+void sh4_base_device::tstr2_w(offs_t offset, uint8_t data, uint8_t mem_mask)
+{
+ COMBINE_DATA(&m_tstr2);
+ logerror("tstr2_w: Unmapped write %02x @ %02x\n", data, mem_mask);
+}
- case TEA:
- m_m[TEA] &= 0xffffffff;
- logerror("TEA set to %08x\n", data);
- break;
+uint32_t sh4_base_device::tcor3_r(offs_t offset, uint32_t mem_mask)
+{
+ return m_tcor3;
+}
+void sh4_base_device::tcor3_w(offs_t offset, uint32_t data, uint32_t mem_mask)
+{
+ COMBINE_DATA(&m_tcor3);
+ logerror("tcor3_w: Unmapped write %08x @ %08x\n", data, mem_mask);
+}
- case MMUCR: // MMU Control
- logerror("%s: MMUCR %08x\n", machine().describe_context(), data);
- m_m[MMUCR] &= 0xffffffff;
- /*
- LLLL LL-- BBBB BB-- CCCC CCQV ---- -T-A
+uint32_t sh4_base_device::tcnt3_r(offs_t offset, uint32_t mem_mask)
+{
+ return m_tcnt3;
+}
- L = LRUI = Least recently used ITLB
- B = URB = UTLB replace boundary
- C = URC = UTLB replace counter
- Q = SQMD = Store Queue Mode Bit
- V = SV = Single Virtual Mode Bit
- T = TI = TLB invaldiate
- A = AT = Address translation bit (enable)
- */
+void sh4_base_device::tcnt3_w(offs_t offset, uint32_t data, uint32_t mem_mask)
+{
+ COMBINE_DATA(&m_tcnt3);
+ logerror("tcnt3_w: Unmapped write %08x @ %08x\n", data, mem_mask);
+}
+uint16_t sh4_base_device::tcr3_r(offs_t offset, uint16_t mem_mask)
+{
+ return m_tcr3;
+}
+void sh4_base_device::tcr3_w(offs_t offset, uint16_t data, uint16_t mem_mask)
+{
+ COMBINE_DATA(&m_tcr3);
+ logerror("tcr3_w: Unmapped write %04x @ %04x\n", data, mem_mask);
+}
- if (data & MMUCR_AT)
- {
- m_sh4_mmu_enabled = 1;
+uint32_t sh4_base_device::tcor4_r(offs_t offset, uint32_t mem_mask)
+{
+ return m_tcor4;
+}
+void sh4_base_device::tcor4_w(offs_t offset, uint32_t data, uint32_t mem_mask)
+{
+ COMBINE_DATA(&m_tcor4);
+ logerror("tcor4_w: Unmapped write %08x @ %08x\n", data, mem_mask);
+}
- if (m_mmuhack == 1)
- {
- printf("SH4 MMU Enabled\n");
- printf("If you're seeing this, but running something other than a Naomi GD-ROM game then chances are it won't work\n");
- printf("The MMU emulation is a hack specific to that system\n");
- }
+uint32_t sh4_base_device::tcnt4_r(offs_t offset, uint32_t mem_mask)
+{
+ return m_tcnt4;
+}
+void sh4_base_device::tcnt4_w(offs_t offset, uint32_t data, uint32_t mem_mask)
+{
+ COMBINE_DATA(&m_tcnt4);
+ logerror("tcnt4_w: Unmapped write %08x @ %08x\n", data, mem_mask);
+}
- if (m_mmuhack == 2)
- {
- for (int i = 0;i < 64;i++)
- {
- if (m_utlb[i].V)
- {
- printf("(entry %02x | ASID: %02x VPN: %08x V: %02x PPN: %08x SZ: %02x SH: %02x C: %02x PPR: %02x D: %02x WT %02x: SA: %02x TC: %02x)\n",
- i,
- m_utlb[i].ASID,
- m_utlb[i].VPN << 10,
- m_utlb[i].V,
- m_utlb[i].PPN << 10,
- m_utlb[i].PSZ,
- m_utlb[i].SH,
- m_utlb[i].C,
- m_utlb[i].PPR,
- m_utlb[i].D,
- m_utlb[i].WT,
- m_utlb[i].SA,
- m_utlb[i].TC);
- }
- }
- }
+uint16_t sh4_base_device::tcr4_r(offs_t offset, uint16_t mem_mask)
+{
+ return m_tcr4;
+}
+void sh4_base_device::tcr4_w(offs_t offset, uint16_t data, uint16_t mem_mask)
+{
+ COMBINE_DATA(&m_tcr4);
+ logerror("tcr4_w: Unmapped write %04x @ %04x\n", data, mem_mask);
+}
- }
- else
- {
- m_sh4_mmu_enabled = 0;
- }
+// SCI
+uint8_t sh4_base_device::scsmr1_r(offs_t offset, uint8_t mem_mask)
+{
+ return m_scsmr1;
+}
- break;
+void sh4_base_device::scsmr1_w(offs_t offset, uint8_t data, uint8_t mem_mask)
+{
+ COMBINE_DATA(&m_scsmr1);
+ logerror("scsmr1_w: Unmapped write %02x @ %02x\n", data, mem_mask);
+}
- // Memory refresh
- case RTCSR:
- m_m[RTCSR] &= 255;
- if ((old >> 3) & 7)
- m_m[RTCNT] = compute_ticks_refresh_timer(m_refresh_timer, m_bus_clock, m_refresh_timer_base, rtcnt_div[(old >> 3) & 7]) & 0xff;
- if ((m_m[RTCSR] >> 3) & 7)
- { // activated
- sh4_refresh_timer_recompute();
- }
- else
- {
- m_refresh_timer->adjust(attotime::never);
- }
- break;
+uint8_t sh4_base_device::scbrr1_r(offs_t offset, uint8_t mem_mask)
+{
+ return m_scbrr1;
+}
- case RTCNT:
- m_m[RTCNT] &= 255;
- if ((m_m[RTCSR] >> 3) & 7)
- { // active
- sh4_refresh_timer_recompute();
- }
- break;
-
- case RTCOR:
- m_m[RTCOR] &= 255;
- if ((m_m[RTCSR] >> 3) & 7)
- { // active
- m_m[RTCNT] = compute_ticks_refresh_timer(m_refresh_timer, m_bus_clock, m_refresh_timer_base, rtcnt_div[(m_m[RTCSR] >> 3) & 7]) & 0xff;
- sh4_refresh_timer_recompute();
- }
- break;
+void sh4_base_device::scbrr1_w(offs_t offset, uint8_t data, uint8_t mem_mask)
+{
+ COMBINE_DATA(&m_scbrr1);
+ logerror("scbrr1_w: Unmapped write %02x @ %02x\n", data, mem_mask);
+}
- case RFCR:
- m_m[RFCR] &= 1023;
- break;
+uint8_t sh4_base_device::scscr1_r(offs_t offset, uint8_t mem_mask)
+{
+ return m_scscr1;
+}
- // RTC
- case RCR1:
- if ((m_m[RCR1] & 8) && (~old & 8)) // 0 -> 1
- m_m[RCR1] ^= 1;
- break;
+void sh4_base_device::scscr1_w(offs_t offset, uint8_t data, uint8_t mem_mask)
+{
+ COMBINE_DATA(&m_scscr1);
+ logerror("scscr1_w: Unmapped write %02x @ %02x\n", data, mem_mask);
+}
- case RCR2:
- if (m_m[RCR2] & 2)
- {
- m_m[R64CNT] = 0;
- m_m[RCR2] ^= 2;
- }
- if (m_m[RCR2] & 4)
- {
- m_m[R64CNT] = 0;
- if (m_m[RSECCNT] >= 30)
- increment_rtc_time(1);
- m_m[RSECCNT] = 0;
- }
- if ((m_m[RCR2] & 8) && (~old & 8))
- { // 0 -> 1
- m_rtc_timer->adjust(attotime::from_hz(128));
- }
- else if (~(m_m[RCR2]) & 8)
- { // 0
- m_rtc_timer->adjust(attotime::never);
- }
- break;
-
-/*********************************************************************************************************************
- TMU (Timer Unit)
-*********************************************************************************************************************/
- case SH4_TSTR_ADDR: sh4_handle_tstr_addr_w(data,mem_mask); break;
- case SH4_TCR0_ADDR: sh4_handle_tcr0_addr_w(data,mem_mask); break;
- case SH4_TCR1_ADDR: sh4_handle_tcr1_addr_w(data,mem_mask); break;
- case SH4_TCR2_ADDR: sh4_handle_tcr2_addr_w(data,mem_mask); break;
- case SH4_TCOR0_ADDR: sh4_handle_tcor0_addr_w(data,mem_mask); break;
- case SH4_TCNT0_ADDR: sh4_handle_tcnt0_addr_w(data,mem_mask); break;
- case SH4_TCOR1_ADDR: sh4_handle_tcor1_addr_w(data,mem_mask); break;
- case SH4_TCNT1_ADDR: sh4_handle_tcnt1_addr_w(data,mem_mask); break;
- case SH4_TCOR2_ADDR: sh4_handle_tcor2_addr_w(data,mem_mask); break;
- case SH4_TCNT2_ADDR: sh4_handle_tcnt2_addr_w(data,mem_mask); break;
- case SH4_TOCR_ADDR: sh4_handle_tocr_addr_w(data,mem_mask); break; // not supported
- case SH4_TCPR2_ADDR: sh4_handle_tcpr2_addr_w(data,mem_mask); break; // not supported
-/*********************************************************************************************************************
- INTC (Interrupt Controller)
-*********************************************************************************************************************/
- case ICR:
- m_m[ICR] = (m_m[ICR] & 0x7fff) | (old & 0x8000);
- break;
- case IPRA: sh4_handler_ipra_w(data, mem_mask); break;
- case IPRB:
- m_exception_priority[SH4_INTC_SCI1ERI] = INTPRI((m_m[IPRB] & 0x00f0) >> 4, SH4_INTC_SCI1ERI);
- m_exception_priority[SH4_INTC_SCI1RXI] = INTPRI((m_m[IPRB] & 0x00f0) >> 4, SH4_INTC_SCI1RXI);
- m_exception_priority[SH4_INTC_SCI1TXI] = INTPRI((m_m[IPRB] & 0x00f0) >> 4, SH4_INTC_SCI1TXI);
- m_exception_priority[SH4_INTC_SCI1TEI] = INTPRI((m_m[IPRB] & 0x00f0) >> 4, SH4_INTC_SCI1TEI);
- m_exception_priority[SH4_INTC_RCMI] = INTPRI((m_m[IPRB] & 0x0f00) >> 8, SH4_INTC_RCMI);
- m_exception_priority[SH4_INTC_ROVI] = INTPRI((m_m[IPRB] & 0x0f00) >> 8, SH4_INTC_ROVI);
- m_exception_priority[SH4_INTC_ITI] = INTPRI((m_m[IPRB] & 0xf000) >> 12, SH4_INTC_ITI);
- sh4_exception_recompute();
- break;
- case IPRC:
- m_exception_priority[SH4_INTC_HUDI] = INTPRI(m_m[IPRC] & 0x000f, SH4_INTC_HUDI);
- m_exception_priority[SH4_INTC_SCIFERI] = INTPRI((m_m[IPRC] & 0x00f0) >> 4, SH4_INTC_SCIFERI);
- m_exception_priority[SH4_INTC_SCIFRXI] = INTPRI((m_m[IPRC] & 0x00f0) >> 4, SH4_INTC_SCIFRXI);
- m_exception_priority[SH4_INTC_SCIFBRI] = INTPRI((m_m[IPRC] & 0x00f0) >> 4, SH4_INTC_SCIFBRI);
- m_exception_priority[SH4_INTC_SCIFTXI] = INTPRI((m_m[IPRC] & 0x00f0) >> 4, SH4_INTC_SCIFTXI);
- m_exception_priority[SH4_INTC_DMTE0] = INTPRI((m_m[IPRC] & 0x0f00) >> 8, SH4_INTC_DMTE0);
- m_exception_priority[SH4_INTC_DMTE1] = INTPRI((m_m[IPRC] & 0x0f00) >> 8, SH4_INTC_DMTE1);
- m_exception_priority[SH4_INTC_DMTE2] = INTPRI((m_m[IPRC] & 0x0f00) >> 8, SH4_INTC_DMTE2);
- m_exception_priority[SH4_INTC_DMTE3] = INTPRI((m_m[IPRC] & 0x0f00) >> 8, SH4_INTC_DMTE3);
- m_exception_priority[SH4_INTC_DMAE] = INTPRI((m_m[IPRC] & 0x0f00) >> 8, SH4_INTC_DMAE);
- m_exception_priority[SH4_INTC_GPOI] = INTPRI((m_m[IPRC] & 0xf000) >> 12, SH4_INTC_GPOI);
- sh4_exception_recompute();
- break;
-/*********************************************************************************************************************
- DMAC (DMA Controller)
-*********************************************************************************************************************/
- case SH4_SAR0_ADDR: sh4_handle_sar0_addr_w(data,mem_mask); break;
- case SH4_SAR1_ADDR: sh4_handle_sar1_addr_w(data,mem_mask); break;
- case SH4_SAR2_ADDR: sh4_handle_sar2_addr_w(data,mem_mask); break;
- case SH4_SAR3_ADDR: sh4_handle_sar3_addr_w(data,mem_mask); break;
- case SH4_DAR0_ADDR: sh4_handle_dar0_addr_w(data,mem_mask); break;
- case SH4_DAR1_ADDR: sh4_handle_dar1_addr_w(data,mem_mask); break;
- case SH4_DAR2_ADDR: sh4_handle_dar2_addr_w(data,mem_mask); break;
- case SH4_DAR3_ADDR: sh4_handle_dar3_addr_w(data,mem_mask); break;
- case SH4_DMATCR0_ADDR: sh4_handle_dmatcr0_addr_w(data,mem_mask); break;
- case SH4_DMATCR1_ADDR: sh4_handle_dmatcr1_addr_w(data,mem_mask); break;
- case SH4_DMATCR2_ADDR: sh4_handle_dmatcr2_addr_w(data,mem_mask); break;
- case SH4_DMATCR3_ADDR: sh4_handle_dmatcr3_addr_w(data,mem_mask); break;
- case SH4_CHCR0_ADDR: sh4_handle_chcr0_addr_w(data,mem_mask); break;
- case SH4_CHCR1_ADDR: sh4_handle_chcr1_addr_w(data,mem_mask); break;
- case SH4_CHCR2_ADDR: sh4_handle_chcr2_addr_w(data,mem_mask); break;
- case SH4_CHCR3_ADDR: sh4_handle_chcr3_addr_w(data,mem_mask); break;
- case SH4_DMAOR_ADDR: sh4_handle_dmaor_addr_w(data,mem_mask); break;
-/*********************************************************************************************************************
- Store Queues
-*********************************************************************************************************************/
- case QACR0:
- case QACR1:
- break;
-/*********************************************************************************************************************
- I/O
-*********************************************************************************************************************/
- case PCTRA:
- m_ioport16_pullup = 0;
- m_ioport16_direction = 0;
- for (a=0;a < 16;a++) {
- m_ioport16_direction |= (m_m[PCTRA] & (1 << (a*2))) >> a;
- m_ioport16_pullup |= (m_m[PCTRA] & (1 << (a*2+1))) >> (a+1);
- }
- m_ioport16_direction &= 0xffff;
- m_ioport16_pullup = (m_ioport16_pullup | m_ioport16_direction) ^ 0xffff;
- if (m_m[BCR2] & 1)
- m_io->write_dword(SH4_IOPORT_16, (uint64_t)(m_m[PDTRA] & m_ioport16_direction) | ((uint64_t)m_m[PCTRA] << 16));
- break;
- case PDTRA:
- if (m_m[BCR2] & 1)
- m_io->write_dword(SH4_IOPORT_16, (uint64_t)(m_m[PDTRA] & m_ioport16_direction) | ((uint64_t)m_m[PCTRA] << 16));
- break;
- case PCTRB:
- m_ioport4_pullup = 0;
- m_ioport4_direction = 0;
- for (a=0;a < 4;a++) {
- m_ioport4_direction |= (m_m[PCTRB] & (1 << (a*2))) >> a;
- m_ioport4_pullup |= (m_m[PCTRB] & (1 << (a*2+1))) >> (a+1);
- }
- m_ioport4_direction &= 0xf;
- m_ioport4_pullup = (m_ioport4_pullup | m_ioport4_direction) ^ 0xf;
- if (m_m[BCR2] & 1)
- m_io->write_dword(SH4_IOPORT_4, (m_m[PDTRB] & m_ioport4_direction) | (m_m[PCTRB] << 16));
- break;
- case PDTRB:
- if (m_m[BCR2] & 1)
- m_io->write_dword(SH4_IOPORT_4, (m_m[PDTRB] & m_ioport4_direction) | (m_m[PCTRB] << 16));
- break;
-
- case SCBRR2:
- break;
-
- case SCSPTR2: //trips often in aristocrat mk-6
- break;
-
- default:
- logerror("sh4_internal_w: Unmapped write %08x, %08x @ %08x\n", 0xfe000000+((offset & 0x3fc0) << 11)+((offset & 0x3f) << 2), data, mem_mask);
- break;
- }
+uint8_t sh4_base_device::sctdr1_r(offs_t offset, uint8_t mem_mask)
+{
+ return m_sctdr1;
}
-READ32_MEMBER( sh4_base_device::sh4_internal_r )
+void sh4_base_device::sctdr1_w(offs_t offset, uint8_t data, uint8_t mem_mask)
{
- if (m_cpu_type != CPU_TYPE_SH4)
- fatalerror("sh4_internal_r uses m_m[] with SH3\n");
+ COMBINE_DATA(&m_sctdr1);
+ logerror("sctdr1_w: Unmapped write %02x @ %02x\n", data, mem_mask);
+}
- uint32_t addr = (offset << 2) + 0xfe000000;
- offset = ((addr & 0xfc) >> 2) | ((addr & 0x1fe0000) >> 11);
+uint8_t sh4_base_device::scssr1_r(offs_t offset, uint8_t mem_mask)
+{
+ return m_scssr1;
+}
-// printf("sh4_internal_r: Read %08x (%x) @ %08x\n", 0xfe000000+((offset & 0x3fc0) << 11)+((offset & 0x3f) << 2), offset, mem_mask);
+void sh4_base_device::scssr1_w(offs_t offset, uint8_t data, uint8_t mem_mask)
+{
+ COMBINE_DATA(&m_scssr1);
+ logerror("scssr1_w: Unmapped write %02x @ %02x\n", data, mem_mask);
+}
- switch( offset )
- {
- case VERSION:
- return PVR_SH7091; // 0x040205c1, this is what a real SH7091 in a Dreamcast returns - the later Naomi BIOSes check and care!
- case PRR:
- return 0;
- case IPRD:
- return 0x00000000; // SH7750 ignores writes here and always returns zero
- case RTCNT:
- if ((m_m[RTCSR] >> 3) & 7)
- { // activated
- //((double)rtcnt_div[(m_m[RTCSR] >> 3) & 7] / (double)100000000)
- //return (refresh_timer_base + (m_refresh_timer->elapsed() * (double)100000000) / (double)rtcnt_div[(m_m[RTCSR] >> 3) & 7]) & 0xff;
- return compute_ticks_refresh_timer(m_refresh_timer, m_bus_clock, m_refresh_timer_base, rtcnt_div[(m_m[RTCSR] >> 3) & 7]) & 0xff;
- }
- else
- return m_m[RTCNT];
-
-/*********************************************************************************************************************
- INTC (Interrupt Controller)
-*********************************************************************************************************************/
-
- case IPRA:
- return m_SH4_IPRA;
-
-/*********************************************************************************************************************
- TMU (Timer Unit)
-*********************************************************************************************************************/
- case SH4_TSTR_ADDR: return sh4_handle_tstr_addr_r(mem_mask);
- case SH4_TCR0_ADDR: return sh4_handle_tcr0_addr_r(mem_mask);
- case SH4_TCR1_ADDR: return sh4_handle_tcr1_addr_r(mem_mask);
- case SH4_TCR2_ADDR: return sh4_handle_tcr2_addr_r(mem_mask);
- case SH4_TCNT0_ADDR: return sh4_handle_tcnt0_addr_r(mem_mask);
- case SH4_TCNT1_ADDR: return sh4_handle_tcnt1_addr_r(mem_mask);
- case SH4_TCNT2_ADDR: return sh4_handle_tcnt2_addr_r(mem_mask);
- case SH4_TCOR0_ADDR: return sh4_handle_tcor0_addr_r(mem_mask);
- case SH4_TCOR1_ADDR: return sh4_handle_tcor1_addr_r(mem_mask);
- case SH4_TCOR2_ADDR: return sh4_handle_tcor2_addr_r(mem_mask);
- case SH4_TOCR_ADDR: return sh4_handle_tocr_addr_r(mem_mask); // not supported
- case SH4_TCPR2_ADDR: return sh4_handle_tcpr2_addr_r(mem_mask); // not supported
-/*********************************************************************************************************************
- DMAC (DMA Controller)
-*********************************************************************************************************************/
- case SH4_SAR0_ADDR: return sh4_handle_sar0_addr_r(mem_mask);
- case SH4_SAR1_ADDR: return sh4_handle_sar1_addr_r(mem_mask);
- case SH4_SAR2_ADDR: return sh4_handle_sar2_addr_r(mem_mask);
- case SH4_SAR3_ADDR: return sh4_handle_sar3_addr_r(mem_mask);
- case SH4_DAR0_ADDR: return sh4_handle_dar0_addr_r(mem_mask);
- case SH4_DAR1_ADDR: return sh4_handle_dar1_addr_r(mem_mask);
- case SH4_DAR2_ADDR: return sh4_handle_dar2_addr_r(mem_mask);
- case SH4_DAR3_ADDR: return sh4_handle_dar3_addr_r(mem_mask);
- case SH4_DMATCR0_ADDR: return sh4_handle_dmatcr0_addr_r(mem_mask);
- case SH4_DMATCR1_ADDR: return sh4_handle_dmatcr1_addr_r(mem_mask);
- case SH4_DMATCR2_ADDR: return sh4_handle_dmatcr2_addr_r(mem_mask);
- case SH4_DMATCR3_ADDR: return sh4_handle_dmatcr3_addr_r(mem_mask);
- case SH4_CHCR0_ADDR: return sh4_handle_chcr0_addr_r(mem_mask);
- case SH4_CHCR1_ADDR: return sh4_handle_chcr1_addr_r(mem_mask);
- case SH4_CHCR2_ADDR: return sh4_handle_chcr2_addr_r(mem_mask);
- case SH4_CHCR3_ADDR: return sh4_handle_chcr3_addr_r(mem_mask);
- case SH4_DMAOR_ADDR: return sh4_handle_dmaor_addr_r(mem_mask);
-/*********************************************************************************************************************
- I/O Ports
-*********************************************************************************************************************/
-
- case PDTRA:
- if (m_m[BCR2] & 1)
- return (m_io->read_dword(SH4_IOPORT_16) & ~m_ioport16_direction) | (m_m[PDTRA] & m_ioport16_direction);
- break;
- case PDTRB:
- if (m_m[BCR2] & 1)
- return (m_io->read_dword(SH4_IOPORT_4) & ~m_ioport4_direction) | (m_m[PDTRB] & m_ioport4_direction);
- break;
-
- // SCIF (UART with FIFO)
- case SCFSR2:
- return 0x60; //read-only status register
- }
- return m_m[offset];
+uint8_t sh4_base_device::scrdr1_r(offs_t offset, uint8_t mem_mask)
+{
+ return m_scrdr1;
}
-void sh34_base_device::set_frt_input(int state)
+uint8_t sh4_base_device::scscmr1_r(offs_t offset, uint8_t mem_mask)
{
- if (m_cpu_type != CPU_TYPE_SH4)
- fatalerror("sh4_set_frt_input uses m_m[] with SH3\n");
+ return m_scscmr1;
+}
+
+void sh4_base_device::scscmr1_w(offs_t offset, uint8_t data, uint8_t mem_mask)
+{
+ COMBINE_DATA(&m_scscmr1);
+ logerror("scscmr1_w: Unmapped write %02x @ %02x\n", data, mem_mask);
+}
+
+uint8_t sh4_base_device::scsptr1_r(offs_t offset, uint8_t mem_mask)
+{
+ return m_scsptr1;
+}
+
+void sh4_base_device::scsptr1_w(offs_t offset, uint8_t data, uint8_t mem_mask)
+{
+ COMBINE_DATA(&m_scsptr1);
+ logerror("scsptr1_w: Unmapped write %02x @ %02x\n", data, mem_mask);
+}
+
+// SCIF
+uint16_t sh4_base_device::scsmr2_r(offs_t offset, uint16_t mem_mask)
+{
+ return m_scsmr2;
+}
+
+void sh4_base_device::scsmr2_w(offs_t offset, uint16_t data, uint16_t mem_mask)
+{
+ COMBINE_DATA(&m_scsmr2);
+ logerror("scsmr2_w: Unmapped write %04x @ %04x\n", data, mem_mask);
+}
+
+uint8_t sh4_base_device::scbrr2_r(offs_t offset, uint8_t mem_mask)
+{
+ return m_scbrr2;
+}
+
+void sh4_base_device::scbrr2_w(offs_t offset, uint8_t data, uint8_t mem_mask)
+{
+ COMBINE_DATA(&m_scbrr2);
+ logerror("scbrr2_w: Unmapped write %02x @ %02x\n", data, mem_mask);
+}
+
+uint16_t sh4_base_device::scscr2_r(offs_t offset, uint16_t mem_mask)
+{
+ return m_scscr2;
+}
+
+void sh4_base_device::scscr2_w(offs_t offset, uint16_t data, uint16_t mem_mask)
+{
+ COMBINE_DATA(&m_scscr2);
+ logerror("scscr2_w: Unmapped write %04x @ %04x\n", data, mem_mask);
+}
+
+uint8_t sh4_base_device::scftdr2_r(offs_t offset, uint8_t mem_mask)
+{
+ return m_scftdr2;
+}
+
+void sh4_base_device::scftdr2_w(offs_t offset, uint8_t data, uint8_t mem_mask)
+{
+ COMBINE_DATA(&m_scftdr2);
+ logerror("scftdr2_w: Unmapped write %02x @ %02x\n", data, mem_mask);
+}
+
+uint16_t sh4_base_device::scfsr2_r(offs_t offset, uint16_t mem_mask)
+{
+ return m_scfsr2;
+}
+
+void sh4_base_device::scfsr2_w(offs_t offset, uint16_t data, uint16_t mem_mask)
+{
+ m_scfsr2 &= data | 0xff0c;
+ logerror("scfsr2_w: Unmapped write %04x @ %04x\n", data, mem_mask);
+}
+
+uint8_t sh4_base_device::scfrdr2_r(offs_t offset, uint8_t mem_mask)
+{
+ return m_scfrdr2;
+}
+
+uint16_t sh4_base_device::scfcr2_r(offs_t offset, uint16_t mem_mask)
+{
+ return m_scfcr2;
+}
+
+void sh4_base_device::scfcr2_w(offs_t offset, uint16_t data, uint16_t mem_mask)
+{
+ COMBINE_DATA(&m_scfcr2);
+ logerror("scfcr2_w: Unmapped write %04x @ %04x\n", data, mem_mask);
+}
+
+uint16_t sh4_base_device::scfdr2_r(offs_t offset, uint16_t mem_mask)
+{
+ return m_scfdr2;
+}
+
+uint16_t sh4_base_device::scsptr2_r(offs_t offset, uint16_t mem_mask)
+{
+ return m_scsptr2;
+}
+
+void sh4_base_device::scsptr2_w(offs_t offset, uint16_t data, uint16_t mem_mask)
+{
+ COMBINE_DATA(&m_scsptr2);
+ //trips often in aristocrat mk-6
+}
+
+uint16_t sh4_base_device::sclsr2_r(offs_t offset, uint16_t mem_mask)
+{
+ return m_sclsr2;
+}
+
+void sh4_base_device::sclsr2_w(offs_t offset, uint16_t data, uint16_t mem_mask)
+{
+ m_sclsr2 &= data | 0xfffe;
+ logerror("sclsr2_w: Unmapped write %04x @ %04x\n", data, mem_mask);
+}
+
+// H-UDI
+uint16_t sh4_base_device::sdir_r(offs_t offset, uint16_t mem_mask)
+{
+ return m_sdir;
+}
+
+void sh4_base_device::sdir_w(offs_t offset, uint16_t data, uint16_t mem_mask)
+{
+ COMBINE_DATA(&m_sdir);
+ logerror("sdir_w: Unmapped write %04x @ %04x\n", data, mem_mask);
+}
+
+uint32_t sh4_base_device::sddr_r(offs_t offset, uint32_t mem_mask)
+{
+ return m_sddr;
+}
+
+void sh4_base_device::sddr_w(offs_t offset, uint32_t data, uint32_t mem_mask)
+{
+ COMBINE_DATA(&m_sddr);
+ logerror("sddr_w: Unmapped write %08x @ %08x\n", data, mem_mask);
+}
+
+// H-UDI 7750R
+uint16_t sh4_base_device::sdint_r(offs_t offset, uint16_t mem_mask)
+{
+ return m_sdint;
+}
+
+void sh4_base_device::sdint_w(offs_t offset, uint16_t data, uint16_t mem_mask)
+{
+ COMBINE_DATA(&m_sdint);
+ logerror("sdint_w: Unmapped write %04x @ %04x\n", data, mem_mask);
+}
+
+// PCI 7751
+uint32_t sh4_base_device::pciconf0_r(offs_t offset, uint32_t mem_mask)
+{
+ return m_pciconf0;
+}
+
+uint32_t sh4_base_device::pciconf1_r(offs_t offset, uint32_t mem_mask)
+{
+ return m_pciconf1;
+}
+
+void sh4_base_device::pciconf1_w(offs_t offset, uint32_t data, uint32_t mem_mask)
+{
+ COMBINE_DATA(&m_pciconf1);
+ logerror("pciconf1_w: Unmapped write %08x @ %08x\n", data, mem_mask);
+}
+
+uint32_t sh4_base_device::pciconf2_r(offs_t offset, uint32_t mem_mask)
+{
+ return m_pciconf2;
+}
+
+void sh4_base_device::pciconf2_w(offs_t offset, uint32_t data, uint32_t mem_mask)
+{
+ COMBINE_DATA(&m_pciconf2);
+ logerror("pciconf2_w: Unmapped write %08x @ %08x\n", data, mem_mask);
+}
+
+uint32_t sh4_base_device::pciconf3_r(offs_t offset, uint32_t mem_mask)
+{
+ return m_pciconf3;
+}
+
+void sh4_base_device::pciconf3_w(offs_t offset, uint32_t data, uint32_t mem_mask)
+{
+ COMBINE_DATA(&m_pciconf3);
+ logerror("pciconf3_w: Unmapped write %08x @ %08x\n", data, mem_mask);
+}
+
+uint32_t sh4_base_device::pciconf4_r(offs_t offset, uint32_t mem_mask)
+{
+ return m_pciconf4;
+}
+
+void sh4_base_device::pciconf4_w(offs_t offset, uint32_t data, uint32_t mem_mask)
+{
+ COMBINE_DATA(&m_pciconf4);
+ logerror("pciconf4_w: Unmapped write %08x @ %08x\n", data, mem_mask);
+}
+
+uint32_t sh4_base_device::pciconf5_r(offs_t offset, uint32_t mem_mask)
+{
+ return m_pciconf5;
+}
+
+void sh4_base_device::pciconf5_w(offs_t offset, uint32_t data, uint32_t mem_mask)
+{
+ COMBINE_DATA(&m_pciconf5);
+ logerror("pciconf5_w: Unmapped write %08x @ %08x\n", data, mem_mask);
+}
+
+uint32_t sh4_base_device::pciconf6_r(offs_t offset, uint32_t mem_mask)
+{
+ return m_pciconf6;
+}
+
+void sh4_base_device::pciconf6_w(offs_t offset, uint32_t data, uint32_t mem_mask)
+{
+ COMBINE_DATA(&m_pciconf6);
+ logerror("pciconf6_w: Unmapped write %08x @ %08x\n", data, mem_mask);
+}
+
+uint32_t sh4_base_device::pciconf7_r(offs_t offset, uint32_t mem_mask)
+{
+ return m_pciconf7;
+}
+
+uint32_t sh4_base_device::pciconf8_r(offs_t offset, uint32_t mem_mask)
+{
+ return m_pciconf8;
+}
+
+uint32_t sh4_base_device::pciconf9_r(offs_t offset, uint32_t mem_mask)
+{
+ return m_pciconf9;
+}
+
+uint32_t sh4_base_device::pciconf10_r(offs_t offset, uint32_t mem_mask)
+{
+ return m_pciconf10;
+}
+
+uint32_t sh4_base_device::pciconf11_r(offs_t offset, uint32_t mem_mask)
+{
+ return m_pciconf11;
+}
+
+void sh4_base_device::pciconf11_w(offs_t offset, uint32_t data, uint32_t mem_mask)
+{
+ COMBINE_DATA(&m_pciconf11);
+ logerror("pciconf11_w: Unmapped write %08x @ %08x\n", data, mem_mask);
+}
+
+uint32_t sh4_base_device::pciconf12_r(offs_t offset, uint32_t mem_mask)
+{
+ return m_pciconf12;
+}
+
+uint32_t sh4_base_device::pciconf13_r(offs_t offset, uint32_t mem_mask)
+{
+ return m_pciconf13;
+}
+
+uint32_t sh4_base_device::pciconf14_r(offs_t offset, uint32_t mem_mask)
+{
+ return m_pciconf14;
+}
+
+uint32_t sh4_base_device::pciconf15_r(offs_t offset, uint32_t mem_mask)
+{
+ return m_pciconf15;
+}
+
+void sh4_base_device::pciconf15_w(offs_t offset, uint32_t data, uint32_t mem_mask)
+{
+ COMBINE_DATA(&m_pciconf15);
+ logerror("pciconf15_w: Unmapped write %08x @ %08x\n", data, mem_mask);
+}
+
+uint32_t sh4_base_device::pciconf16_r(offs_t offset, uint32_t mem_mask)
+{
+ return m_pciconf16;
+}
+
+void sh4_base_device::pciconf16_w(offs_t offset, uint32_t data, uint32_t mem_mask)
+{
+ COMBINE_DATA(&m_pciconf16);
+ logerror("pciconf16_w: Unmapped write %08x @ %08x\n", data, mem_mask);
+}
+
+uint32_t sh4_base_device::pciconf17_r(offs_t offset, uint32_t mem_mask)
+{
+ return m_pciconf17;
+}
+
+void sh4_base_device::pciconf17_w(offs_t offset, uint32_t data, uint32_t mem_mask)
+{
+ COMBINE_DATA(&m_pciconf17);
+ logerror("pciconf17_w: Unmapped write %08x @ %08x\n", data, mem_mask);
+}
+
+uint32_t sh4_base_device::pcicr_r(offs_t offset, uint32_t mem_mask)
+{
+ return m_pcicr;
+}
+
+void sh4_base_device::pcicr_w(offs_t offset, uint32_t data, uint32_t mem_mask)
+{
+ COMBINE_DATA(&m_pcicr);
+ logerror("pcicr_w: Unmapped write %08x @ %08x\n", data, mem_mask);
+}
+
+uint32_t sh4_base_device::pcilsr0_r(offs_t offset, uint32_t mem_mask)
+{
+ return m_pcilsr0;
+}
+
+void sh4_base_device::pcilsr0_w(offs_t offset, uint32_t data, uint32_t mem_mask)
+{
+ COMBINE_DATA(&m_pcilsr0);
+ logerror("pcilsr0_w: Unmapped write %08x @ %08x\n", data, mem_mask);
+}
+
+uint32_t sh4_base_device::pcilsr1_r(offs_t offset, uint32_t mem_mask)
+{
+ return m_pcilsr1;
+}
+
+void sh4_base_device::pcilsr1_w(offs_t offset, uint32_t data, uint32_t mem_mask)
+{
+ COMBINE_DATA(&m_pcilsr1);
+ logerror("pcilsr1_w: Unmapped write %08x @ %08x\n", data, mem_mask);
+}
+
+uint32_t sh4_base_device::pcilar0_r(offs_t offset, uint32_t mem_mask)
+{
+ return m_pcilar0;
+}
+
+void sh4_base_device::pcilar0_w(offs_t offset, uint32_t data, uint32_t mem_mask)
+{
+ COMBINE_DATA(&m_pcilar0);
+ logerror("pcilar0_w: Unmapped write %08x @ %08x\n", data, mem_mask);
+}
+
+uint32_t sh4_base_device::pcilar1_r(offs_t offset, uint32_t mem_mask)
+{
+ return m_pcilar1;
+}
+
+void sh4_base_device::pcilar1_w(offs_t offset, uint32_t data, uint32_t mem_mask)
+{
+ COMBINE_DATA(&m_pcilar1);
+ logerror("pcilar1_w: Unmapped write %08x @ %08x\n", data, mem_mask);
+}
+
+uint32_t sh4_base_device::pciint_r(offs_t offset, uint32_t mem_mask)
+{
+ return m_pciint;
+}
+
+void sh4_base_device::pciint_w(offs_t offset, uint32_t data, uint32_t mem_mask)
+{
+ COMBINE_DATA(&m_pciint);
+ logerror("pciint_w: Unmapped write %08x @ %08x\n", data, mem_mask);
+}
+
+uint32_t sh4_base_device::pciintm_r(offs_t offset, uint32_t mem_mask)
+{
+ return m_pciintm;
+}
+
+void sh4_base_device::pciintm_w(offs_t offset, uint32_t data, uint32_t mem_mask)
+{
+ COMBINE_DATA(&m_pciintm);
+ logerror("pciintm_w: Unmapped write %08x @ %08x\n", data, mem_mask);
+}
+
+uint32_t sh4_base_device::pcialr_r(offs_t offset, uint32_t mem_mask)
+{
+ return m_pcialr;
+}
+
+void sh4_base_device::pcialr_w(offs_t offset, uint32_t data, uint32_t mem_mask)
+{
+ COMBINE_DATA(&m_pcialr);
+ logerror("pcialr_w: Unmapped write %08x @ %08x\n", data, mem_mask);
+}
+
+uint32_t sh4_base_device::pciclr_r(offs_t offset, uint32_t mem_mask)
+{
+ return m_pciclr;
+}
+
+void sh4_base_device::pciclr_w(offs_t offset, uint32_t data, uint32_t mem_mask)
+{
+ COMBINE_DATA(&m_pciclr);
+ logerror("pciclr_w: Unmapped write %08x @ %08x\n", data, mem_mask);
+}
+
+uint32_t sh4_base_device::pciaint_r(offs_t offset, uint32_t mem_mask)
+{
+ return m_pciaint;
+}
+
+void sh4_base_device::pciaint_w(offs_t offset, uint32_t data, uint32_t mem_mask)
+{
+ COMBINE_DATA(&m_pciaint);
+ logerror("pciaint_w: Unmapped write %08x @ %08x\n", data, mem_mask);
+}
+
+uint32_t sh4_base_device::pciaintm_r(offs_t offset, uint32_t mem_mask)
+{
+ return m_pciaintm;
+}
+
+void sh4_base_device::pciaintm_w(offs_t offset, uint32_t data, uint32_t mem_mask)
+{
+ COMBINE_DATA(&m_pciaintm);
+ logerror("pciaintm_w: Unmapped write %08x @ %08x\n", data, mem_mask);
+}
+
+uint32_t sh4_base_device::pcibllr_r(offs_t offset, uint32_t mem_mask)
+{
+ return m_pcibllr;
+}
+
+void sh4_base_device::pcibllr_w(offs_t offset, uint32_t data, uint32_t mem_mask)
+{
+ COMBINE_DATA(&m_pcibllr);
+ logerror("pcibllr_w: Unmapped write %08x @ %08x\n", data, mem_mask);
+}
+
+uint32_t sh4_base_device::pcidmabt_r(offs_t offset, uint32_t mem_mask)
+{
+ return m_pcidmabt;
+}
+
+void sh4_base_device::pcidmabt_w(offs_t offset, uint32_t data, uint32_t mem_mask)
+{
+ COMBINE_DATA(&m_pcidmabt);
+ logerror("pcidmabt_w: Unmapped write %08x @ %08x\n", data, mem_mask);
+}
+
+uint32_t sh4_base_device::pcidpa0_r(offs_t offset, uint32_t mem_mask)
+{
+ return m_pcidpa0;
+}
+
+void sh4_base_device::pcidpa0_w(offs_t offset, uint32_t data, uint32_t mem_mask)
+{
+ COMBINE_DATA(&m_pcidpa0);
+ logerror("pcidpa0_w: Unmapped write %08x @ %08x\n", data, mem_mask);
+}
+
+uint32_t sh4_base_device::pcidla0_r(offs_t offset, uint32_t mem_mask)
+{
+ return m_pcidla0;
+}
+
+void sh4_base_device::pcidla0_w(offs_t offset, uint32_t data, uint32_t mem_mask)
+{
+ COMBINE_DATA(&m_pcidla0);
+ logerror("pcidla0_w: Unmapped write %08x @ %08x\n", data, mem_mask);
+}
+
+uint32_t sh4_base_device::pcidtc0_r(offs_t offset, uint32_t mem_mask)
+{
+ return m_pcidtc0;
+}
+
+void sh4_base_device::pcidtc0_w(offs_t offset, uint32_t data, uint32_t mem_mask)
+{
+ COMBINE_DATA(&m_pcidtc0);
+ logerror("pcidtc0_w: Unmapped write %08x @ %08x\n", data, mem_mask);
+}
+
+uint32_t sh4_base_device::pcidcr0_r(offs_t offset, uint32_t mem_mask)
+{
+ return m_pcidcr0;
+}
+
+void sh4_base_device::pcidcr0_w(offs_t offset, uint32_t data, uint32_t mem_mask)
+{
+ COMBINE_DATA(&m_pcidcr0);
+ logerror("pcidcr0_w: Unmapped write %08x @ %08x\n", data, mem_mask);
+}
+
+uint32_t sh4_base_device::pcidpa1_r(offs_t offset, uint32_t mem_mask)
+{
+ return m_pcidpa1;
+}
+
+void sh4_base_device::pcidpa1_w(offs_t offset, uint32_t data, uint32_t mem_mask)
+{
+ COMBINE_DATA(&m_pcidpa1);
+ logerror("pcidpa1_w: Unmapped write %08x @ %08x\n", data, mem_mask);
+}
+
+uint32_t sh4_base_device::pcidla1_r(offs_t offset, uint32_t mem_mask)
+{
+ return m_pcidla1;
+}
+
+void sh4_base_device::pcidla1_w(offs_t offset, uint32_t data, uint32_t mem_mask)
+{
+ COMBINE_DATA(&m_pcidla1);
+ logerror("pcidla1_w: Unmapped write %08x @ %08x\n", data, mem_mask);
+}
+
+uint32_t sh4_base_device::pcidtc1_r(offs_t offset, uint32_t mem_mask)
+{
+ return m_pcidtc1;
+}
+
+void sh4_base_device::pcidtc1_w(offs_t offset, uint32_t data, uint32_t mem_mask)
+{
+ COMBINE_DATA(&m_pcidtc1);
+ logerror("pcidtc1_w: Unmapped write %08x @ %08x\n", data, mem_mask);
+}
+
+uint32_t sh4_base_device::pcidcr1_r(offs_t offset, uint32_t mem_mask)
+{
+ return m_pcidcr1;
+}
+
+void sh4_base_device::pcidcr1_w(offs_t offset, uint32_t data, uint32_t mem_mask)
+{
+ COMBINE_DATA(&m_pcidcr1);
+ logerror("pcidcr1_w: Unmapped write %08x @ %08x\n", data, mem_mask);
+}
+
+uint32_t sh4_base_device::pcidpa2_r(offs_t offset, uint32_t mem_mask)
+{
+ return m_pcidpa2;
+}
+
+void sh4_base_device::pcidpa2_w(offs_t offset, uint32_t data, uint32_t mem_mask)
+{
+ COMBINE_DATA(&m_pcidpa2);
+ logerror("pcidpa2_w: Unmapped write %08x @ %08x\n", data, mem_mask);
+}
+
+uint32_t sh4_base_device::pcidla2_r(offs_t offset, uint32_t mem_mask)
+{
+ return m_pcidla2;
+}
+
+void sh4_base_device::pcidla2_w(offs_t offset, uint32_t data, uint32_t mem_mask)
+{
+ COMBINE_DATA(&m_pcidla2);
+ logerror("pcidla2_w: Unmapped write %08x @ %08x\n", data, mem_mask);
+}
+
+uint32_t sh4_base_device::pcidtc2_r(offs_t offset, uint32_t mem_mask)
+{
+ return m_pcidtc2;
+}
+
+void sh4_base_device::pcidtc2_w(offs_t offset, uint32_t data, uint32_t mem_mask)
+{
+ COMBINE_DATA(&m_pcidtc2);
+ logerror("pcidtc2_w: Unmapped write %08x @ %08x\n", data, mem_mask);
+}
+
+uint32_t sh4_base_device::pcidcr2_r(offs_t offset, uint32_t mem_mask)
+{
+ return m_pcidcr2;
+}
+
+void sh4_base_device::pcidcr2_w(offs_t offset, uint32_t data, uint32_t mem_mask)
+{
+ COMBINE_DATA(&m_pcidcr2);
+ logerror("pcidcr2_w: Unmapped write %08x @ %08x\n", data, mem_mask);
+}
+
+uint32_t sh4_base_device::pcidpa3_r(offs_t offset, uint32_t mem_mask)
+{
+ return m_pcidpa3;
+}
+
+void sh4_base_device::pcidpa3_w(offs_t offset, uint32_t data, uint32_t mem_mask)
+{
+ COMBINE_DATA(&m_pcidpa3);
+ logerror("pcidpa3_w: Unmapped write %08x @ %08x\n", data, mem_mask);
+}
+
+uint32_t sh4_base_device::pcidla3_r(offs_t offset, uint32_t mem_mask)
+{
+ return m_pcidla3;
+}
+
+void sh4_base_device::pcidla3_w(offs_t offset, uint32_t data, uint32_t mem_mask)
+{
+ COMBINE_DATA(&m_pcidla3);
+ logerror("pcidla3_w: Unmapped write %08x @ %08x\n", data, mem_mask);
+}
+
+uint32_t sh4_base_device::pcidtc3_r(offs_t offset, uint32_t mem_mask)
+{
+ return m_pcidtc3;
+}
+
+void sh4_base_device::pcidtc3_w(offs_t offset, uint32_t data, uint32_t mem_mask)
+{
+ COMBINE_DATA(&m_pcidtc3);
+ logerror("pcidtc3_w: Unmapped write %08x @ %08x\n", data, mem_mask);
+}
+
+uint32_t sh4_base_device::pcidcr3_r(offs_t offset, uint32_t mem_mask)
+{
+ return m_pcidcr3;
+}
+
+void sh4_base_device::pcidcr3_w(offs_t offset, uint32_t data, uint32_t mem_mask)
+{
+ COMBINE_DATA(&m_pcidcr3);
+ logerror("pcidcr3_w: Unmapped write %08x @ %08x\n", data, mem_mask);
+}
+
+uint32_t sh4_base_device::pcipar_r(offs_t offset, uint32_t mem_mask)
+{
+ return m_pcipar;
+}
+
+void sh4_base_device::pcipar_w(offs_t offset, uint32_t data, uint32_t mem_mask)
+{
+ COMBINE_DATA(&m_pcipar);
+ logerror("pcipar_w: Unmapped write %08x @ %08x\n", data, mem_mask);
+}
+
+uint32_t sh4_base_device::pcimbr_r(offs_t offset, uint32_t mem_mask)
+{
+ return m_pcimbr;
+}
+
+void sh4_base_device::pcimbr_w(offs_t offset, uint32_t data, uint32_t mem_mask)
+{
+ COMBINE_DATA(&m_pcimbr);
+ logerror("pcimbr_w: Unmapped write %08x @ %08x\n", data, mem_mask);
+}
+
+uint32_t sh4_base_device::pciiobr_r(offs_t offset, uint32_t mem_mask)
+{
+ return m_pciiobr;
+}
+
+void sh4_base_device::pciiobr_w(offs_t offset, uint32_t data, uint32_t mem_mask)
+{
+ COMBINE_DATA(&m_pciiobr);
+ logerror("pciiobr_w: Unmapped write %08x @ %08x\n", data, mem_mask);
+}
+
+uint32_t sh4_base_device::pcipint_r(offs_t offset, uint32_t mem_mask)
+{
+ return m_pcipint;
+}
+
+void sh4_base_device::pcipint_w(offs_t offset, uint32_t data, uint32_t mem_mask)
+{
+ COMBINE_DATA(&m_pcipint);
+ logerror("pcipint_w: Unmapped write %08x @ %08x\n", data, mem_mask);
+}
+
+uint32_t sh4_base_device::pcipintm_r(offs_t offset, uint32_t mem_mask)
+{
+ return m_pcipintm;
+}
+
+void sh4_base_device::pcipintm_w(offs_t offset, uint32_t data, uint32_t mem_mask)
+{
+ COMBINE_DATA(&m_pcipintm);
+ logerror("pcipintm_w: Unmapped write %08x @ %08x\n", data, mem_mask);
+}
+
+uint32_t sh4_base_device::pciclkr_r(offs_t offset, uint32_t mem_mask)
+{
+ return m_pciclkr;
+}
+
+void sh4_base_device::pciclkr_w(offs_t offset, uint32_t data, uint32_t mem_mask)
+{
+ COMBINE_DATA(&m_pciclkr);
+ logerror("pciclkr_w: Unmapped write %08x @ %08x\n", data, mem_mask);
+}
+
+uint32_t sh4_base_device::pcibcr1_r(offs_t offset, uint32_t mem_mask)
+{
+ return m_pcibcr1;
+}
+
+void sh4_base_device::pcibcr1_w(offs_t offset, uint32_t data, uint32_t mem_mask)
+{
+ COMBINE_DATA(&m_pcibcr1);
+ logerror("pcibcr1_w: Unmapped write %08x @ %08x\n", data, mem_mask);
+}
+
+uint32_t sh4_base_device::pcibcr2_r(offs_t offset, uint32_t mem_mask)
+{
+ return m_pcibcr2;
+}
+
+void sh4_base_device::pcibcr2_w(offs_t offset, uint32_t data, uint32_t mem_mask)
+{
+ COMBINE_DATA(&m_pcibcr2);
+ logerror("pcibcr2_w: Unmapped write %08x @ %08x\n", data, mem_mask);
+}
+
+uint32_t sh4_base_device::pcibcr3_r(offs_t offset, uint32_t mem_mask)
+{
+ return m_pcibcr3;
+}
+
+void sh4_base_device::pcibcr3_w(offs_t offset, uint32_t data, uint32_t mem_mask)
+{
+ COMBINE_DATA(&m_pcibcr3);
+ logerror("pcibcr3_w: Unmapped write %08x @ %08x\n", data, mem_mask);
+}
+
+uint32_t sh4_base_device::pciwcr1_r(offs_t offset, uint32_t mem_mask)
+{
+ return m_pciwcr1;
+}
- if(m_sh2_state->m_frt_input == state) {
+void sh4_base_device::pciwcr1_w(offs_t offset, uint32_t data, uint32_t mem_mask)
+{
+ COMBINE_DATA(&m_pciwcr1);
+ logerror("pciwcr1_w: Unmapped write %08x @ %08x\n", data, mem_mask);
+}
+
+uint32_t sh4_base_device::pciwcr2_r(offs_t offset, uint32_t mem_mask)
+{
+ return m_pciwcr2;
+}
+
+void sh4_base_device::pciwcr2_w(offs_t offset, uint32_t data, uint32_t mem_mask)
+{
+ COMBINE_DATA(&m_pciwcr2);
+ logerror("pciwcr2_w: Unmapped write %08x @ %08x\n", data, mem_mask);
+}
+
+uint32_t sh4_base_device::pciwcr3_r(offs_t offset, uint32_t mem_mask)
+{
+ return m_pciwcr3;
+}
+
+void sh4_base_device::pciwcr3_w(offs_t offset, uint32_t data, uint32_t mem_mask)
+{
+ COMBINE_DATA(&m_pciwcr3);
+ logerror("pciwcr3_w: Unmapped write %08x @ %08x\n", data, mem_mask);
+}
+
+uint32_t sh4_base_device::pcimcr_r(offs_t offset, uint32_t mem_mask)
+{
+ return m_pcimcr;
+}
+
+void sh4_base_device::pcimcr_w(offs_t offset, uint32_t data, uint32_t mem_mask)
+{
+ COMBINE_DATA(&m_pcimcr);
+ logerror("pcimcr_w: Unmapped write %08x @ %08x\n", data, mem_mask);
+}
+
+uint32_t sh4_base_device::pcipctr_r(offs_t offset, uint32_t mem_mask)
+{
+ return m_pcipctr;
+}
+
+void sh4_base_device::pcipctr_w(offs_t offset, uint32_t data, uint32_t mem_mask)
+{
+ COMBINE_DATA(&m_pcipctr);
+ logerror("pcipctr_w: Unmapped write %08x @ %08x\n", data, mem_mask);
+}
+
+uint32_t sh4_base_device::pcipdtr_r(offs_t offset, uint32_t mem_mask)
+{
+ return m_pcipdtr;
+}
+
+void sh4_base_device::pcipdtr_w(offs_t offset, uint32_t data, uint32_t mem_mask)
+{
+ COMBINE_DATA(&m_pcipdtr);
+ logerror("pcipdtr_w: Unmapped write %08x @ %08x\n", data, mem_mask);
+}
+
+uint32_t sh4_base_device::pcipdr_r(offs_t offset, uint32_t mem_mask)
+{
+ return m_pcipdr;
+}
+
+void sh4_base_device::pcipdr_w(offs_t offset, uint32_t data, uint32_t mem_mask)
+{
+ COMBINE_DATA(&m_pcipdr);
+ logerror("pcipdr_w: Unmapped write %08x @ %08x\n", data, mem_mask);
+}
+
+void sh34_base_device::set_frt_input(int state)
+{
+ if (m_sh2_state->m_frt_input == state)
+ {
return;
}
m_sh2_state->m_frt_input = state;
+#if 0
if (m_cpu_type == CPU_TYPE_SH4)
{
- if(m_m[5] & 0x8000) {
- if(state == CLEAR_LINE) {
+ if (m_m[5] & 0x8000)
+ {
+ if (state == CLEAR_LINE)
+ {
return;
}
- } else {
- if(state == ASSERT_LINE) {
+ }
+ else
+ {
+ if (state == ASSERT_LINE)
+ {
return;
}
}
@@ -1094,7 +2780,6 @@ void sh34_base_device::set_frt_input(int state)
fatalerror("sh4_set_frt_input uses m_m[] with SH3\n");
}
-#if 0
sh4_timer_resync();
m_icr = m_frc;
m_m[4] |= ICF;
@@ -1130,15 +2815,15 @@ void sh34_base_device::execute_set_input(int irqline, int state) // set state of
return;
m_irq_line_state[irqline] = state;
- if( state == CLEAR_LINE )
+ if (state == CLEAR_LINE)
{
- LOG(("SH-4 '%s' cleared external irq IRL%d\n", tag(), irqline));
- sh4_exception_unrequest(SH4_INTC_IRL0+irqline-SH4_IRL0);
+ LOG("SH-4 '%s' cleared external irq IRL%d\n", tag(), irqline);
+ sh4_exception_unrequest(SH4_INTC_IRL0 + irqline - SH4_IRL0);
}
else
{
- LOG(("SH-4 '%s' assert external irq IRL%d\n", tag(), irqline));
- sh4_exception_request(SH4_INTC_IRL0+irqline-SH4_IRL0);
+ LOG("SH-4 '%s' assert external irq IRL%d\n", tag(), irqline);
+ sh4_exception_request(SH4_INTC_IRL0 + irqline - SH4_IRL0);
}
}
@@ -1147,39 +2832,38 @@ void sh34_base_device::execute_set_input(int irqline, int state) // set state of
}
else
{
- int s;
-
if (irqline == INPUT_LINE_NMI)
{
if (m_nmi_line_state == state)
return;
- if (m_m[ICR] & 0x100)
+
+ if (m_icr & 0x100)
{
- if ((state == CLEAR_LINE) && (m_nmi_line_state == ASSERT_LINE)) // rising
+ if (state == CLEAR_LINE && m_nmi_line_state == ASSERT_LINE) // rising
{
- LOG(("SH-4 '%s' assert nmi\n", tag()));
+ LOG("SH-4 '%s' assert nmi\n", tag());
sh4_exception_request(SH4_INTC_NMI);
sh4_dmac_nmi();
}
}
else
{
- if ((state == ASSERT_LINE) && (m_nmi_line_state == CLEAR_LINE)) // falling
+ if (state == ASSERT_LINE && m_nmi_line_state == CLEAR_LINE) // falling
{
- LOG(("SH-4 '%s' assert nmi\n", tag()));
+ LOG("SH-4 '%s' assert nmi\n", tag());
sh4_exception_request(SH4_INTC_NMI);
sh4_dmac_nmi();
}
}
if (state == CLEAR_LINE)
- m_m[ICR] ^= 0x8000;
+ m_icr ^= 0x8000;
else
- m_m[ICR] |= 0x8000;
+ m_icr |= 0x8000;
m_nmi_line_state = state;
}
else
{
- if (m_m[ICR] & 0x80) // four independent external interrupt sources
+ if (m_icr & 0x80) // four independent external interrupt sources
{
if (irqline > SH4_IRL3)
return;
@@ -1187,40 +2871,40 @@ void sh34_base_device::execute_set_input(int irqline, int state) // set state of
return;
m_irq_line_state[irqline] = state;
- if( state == CLEAR_LINE )
+ if (state == CLEAR_LINE)
{
- LOG(("SH-4 '%s' cleared external irq IRL%d\n", tag(), irqline));
- sh4_exception_unrequest(SH4_INTC_IRL0+irqline-SH4_IRL0);
+ LOG("SH-4 '%s' cleared external irq IRL%d\n", tag(), irqline);
+ sh4_exception_unrequest(SH4_INTC_IRL0 + irqline - SH4_IRL0);
}
else
{
- LOG(("SH-4 '%s' assert external irq IRL%d\n", tag(), irqline));
- sh4_exception_request(SH4_INTC_IRL0+irqline-SH4_IRL0);
+ LOG("SH-4 '%s' assert external irq IRL%d\n", tag(), irqline);
+ sh4_exception_request(SH4_INTC_IRL0 + irqline - SH4_IRL0);
}
}
else // level-encoded interrupt
{
if (irqline != SH4_IRLn)
return;
- if ((m_irln > 15) || (m_irln < 0))
+ if (m_irln > 15 || m_irln < 0)
return;
- for (s = 0; s < 15; s++)
- sh4_exception_unrequest(SH4_INTC_IRLn0+s);
+ for (int s = 0; s < 15; s++)
+ sh4_exception_unrequest(SH4_INTC_IRLn0 + s);
if (m_irln < 15)
- sh4_exception_request(SH4_INTC_IRLn0+m_irln);
- LOG(("SH-4 '%s' IRLn0-IRLn3 level #%d\n", tag(), m_irln));
+ sh4_exception_request(SH4_INTC_IRLn0 + m_irln);
+ LOG("SH-4 '%s' IRLn0-IRLn3 level #%d\n", tag(), m_irln);
}
}
- if (m_sh2_state->m_test_irq && (!m_sh2_state->m_delay))
+ if (m_sh2_state->m_test_irq && !m_sh2_state->m_delay)
sh4_check_pending_irq("sh4_set_irq_line");
}
}
void sh34_base_device::sh4_parse_configuration()
{
- if(m_clock > 0)
+ if (m_clock > 0)
{
- switch((m_md[2] << 2) | (m_md[1] << 1) | (m_md[0]))
+ switch ((m_md[2] << 2) | (m_md[1] << 1) | (m_md[0]))
{
case 0:
m_cpu_clock = m_clock;
@@ -1253,7 +2937,7 @@ void sh34_base_device::sh4_parse_configuration()
m_pm_clock = m_clock / 4;
break;
}
- m_is_slave = (~(m_md[7])) & 1;
+ m_is_slave = (~m_md[7]) & 1;
}
else
{
@@ -1275,10 +2959,9 @@ uint32_t sh4_base_device::get_remap(uint32_t address)
return address;
// is this the correct way around?
- int i;
uint32_t topaddr = address&0xfff00000;
- for (i=0;i<64;i++)
+ for (int i = 0; i < 64; i++)
{
if (m_utlb[i].V)
{
@@ -1289,8 +2972,6 @@ uint32_t sh4_base_device::get_remap(uint32_t address)
}
//printf("address not in UTLB? %08x\n", address);
-
-
return address;
}
@@ -1301,18 +2982,17 @@ uint32_t sh34_base_device::sh4_getsqremap(uint32_t address)
uint32_t sh4_base_device::sh4_getsqremap(uint32_t address)
{
- if (!m_sh4_mmu_enabled || (m_mmuhack != 1))
+ if (!m_sh4_mmu_enabled || m_mmuhack != 1)
return address;
else
{
- int i;
- uint32_t topaddr = address&0xfff00000;
+ uint32_t topaddr = address & 0xfff00000;
- for (i=0;i<64;i++)
+ for (int i = 0; i < 64; i++)
{
- uint32_t topcmp = (m_utlb[i].VPN<<10)&0xfff00000;
- if (topcmp==topaddr)
- return (address&0x000fffff) | ((m_utlb[i].PPN<<10)&0xfff00000);
+ uint32_t topcmp = (m_utlb[i].VPN << 10) & 0xfff00000;
+ if (topcmp == topaddr)
+ return (address & 0x000fffff) | ((m_utlb[i].PPN << 10) & 0xfff00000);
}
}
@@ -1320,7 +3000,7 @@ uint32_t sh4_base_device::sh4_getsqremap(uint32_t address)
}
-WRITE64_MEMBER( sh4_base_device::sh4_utlb_address_array_w )
+void sh4_base_device::sh4_utlb_address_array_w(offs_t offset, uint64_t data)
{
/* uses bits 13:8 of address to select which UTLB entry we're addressing
bit 7 of the address enables 'associative' mode, causing a search
@@ -1334,16 +3014,13 @@ WRITE64_MEMBER( sh4_base_device::sh4_utlb_address_array_w )
A = ASID = Address Space Identifier
*/
- logerror("sh4_utlb_address_array_w %08x %08x\n", offset, data);
- int offs = offset << 3;
-
- uint8_t associative = (offs >> 7) & 1;
+ LOG("sh4_utlb_address_array_w %08x %08x\n", offset, data);
+ const bool associative = BIT(offset, 4);
if (!associative)
{
// non-associative mode
- uint8_t i = (offs >> 8) & 63;
-
+ uint8_t i = (offset >> 5) & 63;
m_utlb[i].VPN = (data & 0xfffffc00) >> 10;
m_utlb[i].D = (data & 0x00000200) >> 9;
m_utlb[i].V = (data & 0x00000100) >> 8;
@@ -1356,16 +3033,11 @@ WRITE64_MEMBER( sh4_base_device::sh4_utlb_address_array_w )
}
}
-READ64_MEMBER( sh4_base_device::sh4_utlb_address_array_r )
+uint64_t sh4_base_device::sh4_utlb_address_array_r(offs_t offset)
{
// associative bit is ignored for reads
- int offs = offset*8;
-
- uint32_t ret = 0;
-
- uint8_t i = (offs >> 8) & 63;
-
- ret |= m_utlb[i].VPN << 10;
+ uint8_t i = (offset >> 5) & 63;
+ uint32_t ret = m_utlb[i].VPN << 10;
ret |= m_utlb[i].D << 9;
ret |= m_utlb[i].V << 8;
ret |= m_utlb[i].ASID << 0;
@@ -1374,7 +3046,7 @@ READ64_MEMBER( sh4_base_device::sh4_utlb_address_array_r )
}
-WRITE64_MEMBER( sh4_base_device::sh4_utlb_data_array1_w )
+void sh4_base_device::sh4_utlb_data_array1_w(offs_t offset, uint64_t data)
{
/* uses bits 13:8 of address to select which UTLB entry we're addressing
@@ -1390,11 +3062,8 @@ WRITE64_MEMBER( sh4_base_device::sh4_utlb_data_array1_w )
W = Write through
- = unused (should be 0)
*/
- logerror("sh4_utlb_data_array1_w %08x %08x\n", offset, data);
- int offs = offset*8;
-
- uint8_t i = (offs>>8)&63;
-
+ LOG("sh4_utlb_data_array1_w %08x %08x\n", offset, data);
+ uint8_t i = (offset >> 5) & 63;
m_utlb[i].PPN = (data & 0x1ffffc00) >> 10;
m_utlb[i].V = (data & 0x00000100) >> 8;
m_utlb[i].PSZ = (data & 0x00000080) >> 6;
@@ -1407,14 +3076,10 @@ WRITE64_MEMBER( sh4_base_device::sh4_utlb_data_array1_w )
}
-READ64_MEMBER(sh4_base_device::sh4_utlb_data_array1_r)
+uint64_t sh4_base_device::sh4_utlb_data_array1_r(offs_t offset)
{
- uint32_t ret = 0;
- int offs = offset*8;
-
- uint8_t i = (offs>>8)&63;
-
- ret |= m_utlb[i].PPN << 10;
+ uint8_t i = (offset >> 5) & 63;
+ uint32_t ret = m_utlb[i].PPN << 10;
ret |= m_utlb[i].V << 8;
ret |= (m_utlb[i].PSZ & 2) << 6;
ret |= (m_utlb[i].PSZ & 1) << 4;
@@ -1429,7 +3094,7 @@ READ64_MEMBER(sh4_base_device::sh4_utlb_data_array1_r)
-WRITE64_MEMBER( sh4_base_device::sh4_utlb_data_array2_w )
+void sh4_base_device::sh4_utlb_data_array2_w(offs_t offset, uint64_t data)
{
/* uses bits 13:8 of address to select which UTLB entry we're addressing
@@ -1440,26 +3105,15 @@ WRITE64_MEMBER( sh4_base_device::sh4_utlb_data_array2_w )
- = unused (should be 0)
*/
-
- logerror("sh4_utlb_data_array2_w %08x %08x\n", offset, data);
- int offs = offset*8;
-
- uint8_t i = (offs>>8)&63;
-
+ LOG("sh4_utlb_data_array2_w %08x %08x\n", offset, data);
+ uint8_t i = (offset >> 5) & 63;
m_utlb[i].TC = (data & 0x00000008) >> 3;
m_utlb[i].SA = (data & 0x00000007) >> 0;
}
-READ64_MEMBER(sh4_base_device::sh4_utlb_data_array2_r)
+uint64_t sh4_base_device::sh4_utlb_data_array2_r(offs_t offset)
{
- uint32_t ret = 0;
- int offs = offset*8;
-
- uint8_t i = (offs>>8)&63;
-
- ret |= m_utlb[i].TC << 3;
- ret |= m_utlb[i].SA << 0;
-
- return ret;
+ uint8_t i = (offset >> 5) & 63;
+ return (m_utlb[i].TC << 3) | (m_utlb[i].SA);
}
diff --git a/src/devices/cpu/sh/sh4comn.h b/src/devices/cpu/sh/sh4comn.h
index 0d856012581..bac004d36b4 100644
--- a/src/devices/cpu/sh/sh4comn.h
+++ b/src/devices/cpu/sh/sh4comn.h
@@ -8,32 +8,31 @@
*
*****************************************************************************/
-#pragma once
+#ifndef MAME_CPU_SH_SH4COMN_H
+#define MAME_CPU_SH_SH4COMN_H
-#ifndef __SH4COMN_H__
-#define __SH4COMN_H__
+#pragma once
#include "sh.h"
-#define VERBOSE 0
-
-#define LOG(x) do { if (VERBOSE) logerror x; } while (0)
+#define VERBOSE (0)
+#include "logmacro.h"
-#define EXPPRI(pl,po,p,n) (((4-(pl)) << 24) | ((15-(po)) << 16) | ((p) << 8) | (255-(n)))
-#define NMIPRI() EXPPRI(3,0,16,SH4_INTC_NMI)
-#define INTPRI(p,n) EXPPRI(4,2,p,n)
+#define EXPPRI(pl, po, p, n) (((4 - (pl)) << 24) | ((15 - (po)) << 16) | ((p) << 8) | (255 - (n)))
+#define NMIPRI() EXPPRI(3, 0, 16, SH4_INTC_NMI)
+#define INTPRI(p, n) EXPPRI(4, 2, p, n)
#define FP_RS(r) m_sh2_state->m_fr[(r)] // binary representation of single precision floating point register r
-#define FP_RFS(r) *( (float *)(m_sh2_state->m_fr+(r)) ) // single precision floating point register r
-#define FP_RFD(r) *( (double *)(m_sh2_state->m_fr+(r)) ) // double precision floating point register r
+#define FP_RFS(r) *( (float *)(m_sh2_state->m_fr + (r)) ) // single precision floating point register r
+#define FP_RFD(r) *( (double *)(m_sh2_state->m_fr + (r)) ) // double precision floating point register r
#define FP_XS(r) m_sh2_state->m_xf[(r)] // binary representation of extended single precision floating point register r
-#define FP_XFS(r) *( (float *)(m_sh2_state->m_xf+(r)) ) // single precision extended floating point register r
-#define FP_XFD(r) *( (double *)(m_sh2_state->m_xf+(r)) ) // double precision extended floating point register r
+#define FP_XFS(r) *( (float *)(m_sh2_state->m_xf + (r)) ) // single precision extended floating point register r
+#define FP_XFD(r) *( (double *)(m_sh2_state->m_xf + (r)) ) // double precision extended floating point register r
#ifdef LSB_FIRST
#define FP_RS2(r) m_sh2_state->m_fr[(r) ^ m_sh2_state->m_fpu_pr]
-#define FP_RFS2(r) *( (float *)(m_sh2_state->m_fr+((r) ^ m_sh2_state->m_fpu_pr)) )
+#define FP_RFS2(r) *( (float *)(m_sh2_state->m_fr + ((r) ^ m_sh2_state->m_fpu_pr)) )
#define FP_XS2(r) m_sh2_state->m_xf[(r) ^ m_sh2_state->m_fpu_pr]
-#define FP_XFS2(r) *( (float *)(m_sh2_state->m_xf+((r) ^ m_sh2_state->m_fpu_pr)) )
+#define FP_XFS2(r) *( (float *)(m_sh2_state->m_xf + ((r) ^ m_sh2_state->m_fpu_pr)) )
#endif
#define FPSCR mem(&m_sh2_state->m_fpscr)
@@ -55,7 +54,7 @@ enum
/* 29 bits */
#define SH34_AM 0x1fffffff
-#define SH34_FLAGS (MD|sRB|BL|FD|SH_M|SH_Q|SH_I|SH_S|SH_T)
+#define SH34_FLAGS (MD | sRB | BL | FD | SH_M | SH_Q | SH_I | SH_S | SH_T)
/* Bits in FPSCR */
#define RM 0x00000003
@@ -74,4 +73,4 @@ enum
#define REGFLAG_SSR (1 << 10)
#define REGFLAG_SPC (1 << 11)
-#endif /* __SH4COMN_H__ */
+#endif // MAME_CPU_SH_SH4COMN_H
diff --git a/src/devices/cpu/sh/sh4dmac.cpp b/src/devices/cpu/sh/sh4dmac.cpp
index ba727d324c5..77d571c4477 100644
--- a/src/devices/cpu/sh/sh4dmac.cpp
+++ b/src/devices/cpu/sh/sh4dmac.cpp
@@ -3,7 +3,6 @@
/* SHA3/4 DMA Controller */
#include "emu.h"
-#include "debugger.h"
#include "sh4.h"
#include "sh4comn.h"
#include "sh3comn.h"
@@ -17,32 +16,32 @@ TIMER_CALLBACK_MEMBER( sh34_base_device::sh4_dmac_callback )
{
int channel = param;
- LOG(("SH4 '%s': DMA %d complete\n", tag(), channel));
+ LOG("SH4 '%s': DMA %d complete\n", tag(), channel);
m_dma_timer_active[channel] = 0;
switch (channel)
{
case 0:
- m_SH4_DMATCR0 = 0;
- m_SH4_CHCR0 |= CHCR_TE;
- if (m_SH4_CHCR0 & CHCR_IE)
+ m_dmatcr0 = 0;
+ m_chcr0 |= CHCR_TE;
+ if (m_chcr0 & CHCR_IE)
sh4_exception_request(SH4_INTC_DMTE0);
break;
case 1:
- m_SH4_DMATCR1 = 0;
- m_SH4_CHCR1 |= CHCR_TE;
- if (m_SH4_CHCR1 & CHCR_IE)
+ m_dmatcr1 = 0;
+ m_chcr1 |= CHCR_TE;
+ if (m_chcr1 & CHCR_IE)
sh4_exception_request(SH4_INTC_DMTE1);
break;
case 2:
- m_SH4_DMATCR2 = 0;
- m_SH4_CHCR2 |= CHCR_TE;
- if (m_SH4_CHCR2 & CHCR_IE)
+ m_dmatcr2 = 0;
+ m_chcr2 |= CHCR_TE;
+ if (m_chcr2 & CHCR_IE)
sh4_exception_request(SH4_INTC_DMTE2);
break;
case 3:
- m_SH4_DMATCR3 = 0;
- m_SH4_CHCR3 |= CHCR_TE;
- if (m_SH4_CHCR3 & CHCR_IE)
+ m_dmatcr3 = 0;
+ m_chcr3 |= CHCR_TE;
+ if (m_chcr3 & CHCR_IE)
sh4_exception_request(SH4_INTC_DMTE3);
break;
}
@@ -50,12 +49,10 @@ TIMER_CALLBACK_MEMBER( sh34_base_device::sh4_dmac_callback )
int sh34_base_device::sh4_dma_transfer(int channel, int timermode, uint32_t chcr, uint32_t *sar, uint32_t *dar, uint32_t *dmatcr)
{
- int incs, incd, size;
- uint32_t src, dst, count;
-
- incd = (chcr & CHCR_DM) >> 14;
- incs = (chcr & CHCR_SM) >> 12;
+ int incd = (chcr & CHCR_DM) >> 14;
+ int incs = (chcr & CHCR_SM) >> 12;
+ int size;
if (m_cpu_type == CPU_TYPE_SH4)
{
size = dmasize[(chcr & CHCR_TS) >> 4];
@@ -65,18 +62,19 @@ int sh34_base_device::sh4_dma_transfer(int channel, int timermode, uint32_t chcr
size = sh3_dmasize[(chcr >> 3) & 3];
}
- if(incd == 3 || incs == 3)
+ if (incd == 3 || incs == 3)
{
logerror("SH4: DMA: bad increment values (%d, %d, %d, %04x)\n", incd, incs, size, chcr);
return 0;
}
- src = *sar;
- dst = *dar;
- count = *dmatcr;
+
+ uint32_t src = *sar;
+ uint32_t dst = *dar;
+ uint32_t count = *dmatcr;
if (!count)
count = 0x1000000;
- LOG(("SH4: DMA %d start %x, %x, %x, %04x, %d, %d, %d\n", channel, src, dst, count, chcr, incs, incd, size));
+ LOG("SH4: DMA %d start %x, %x, %x, %04x, %d, %d, %d\n", channel, src, dst, count, chcr, incs, incd, size);
if (timermode == 1) // timer actvated after a time based on the number of words to transfer
{
@@ -92,51 +90,51 @@ int sh34_base_device::sh4_dma_transfer(int channel, int timermode, uint32_t chcr
src &= SH34_AM;
dst &= SH34_AM;
- switch(size)
+ switch (size)
{
case 1: // 8 bit
- for(;count > 0; count --)
+ for (;count > 0; count --)
{
- if(incs == 2)
+ if (incs == 2)
src --;
- if(incd == 2)
+ if (incd == 2)
dst --;
- m_program->write_byte(dst, m_program->read_byte(src));
- if(incs == 1)
+ m_program->write_byte(dst & SH34_AM, m_program->read_byte(src & SH34_AM));
+ if (incs == 1)
src ++;
- if(incd == 1)
+ if (incd == 1)
dst ++;
}
break;
case 2: // 16 bit
src &= ~1;
dst &= ~1;
- for(;count > 0; count --)
+ for (;count > 0; count --)
{
- if(incs == 2)
+ if (incs == 2)
src -= 2;
- if(incd == 2)
+ if (incd == 2)
dst -= 2;
- m_program->write_word(dst, m_program->read_word(src));
- if(incs == 1)
+ m_program->write_word(dst & SH34_AM, m_program->read_word(src & SH34_AM));
+ if (incs == 1)
src += 2;
- if(incd == 1)
+ if (incd == 1)
dst += 2;
}
break;
case 8: // 64 bit
src &= ~7;
dst &= ~7;
- for(;count > 0; count --)
+ for (;count > 0; count --)
{
- if(incs == 2)
+ if (incs == 2)
src -= 8;
- if(incd == 2)
+ if (incd == 2)
dst -= 8;
- m_program->write_qword(dst, m_program->read_qword(src));
- if(incs == 1)
+ m_program->write_qword(dst & SH34_AM, m_program->read_qword(src & SH34_AM));
+ if (incs == 1)
src += 8;
- if(incd == 1)
+ if (incd == 1)
dst += 8;
}
@@ -144,16 +142,16 @@ int sh34_base_device::sh4_dma_transfer(int channel, int timermode, uint32_t chcr
case 4: // 32 bit
src &= ~3;
dst &= ~3;
- for(;count > 0; count --)
+ for (;count > 0; count --)
{
- if(incs == 2)
+ if (incs == 2)
src -= 4;
- if(incd == 2)
+ if (incd == 2)
dst -= 4;
- m_program->write_dword(dst, m_program->read_dword(src));
- if(incs == 1)
+ m_program->write_dword(dst & SH34_AM, m_program->read_dword(src & SH34_AM));
+ if (incs == 1)
src += 4;
- if(incd == 1)
+ if (incd == 1)
dst += 4;
}
@@ -161,19 +159,19 @@ int sh34_base_device::sh4_dma_transfer(int channel, int timermode, uint32_t chcr
case 32:
src &= ~31;
dst &= ~31;
- for(;count > 0; count --)
+ for (;count > 0; count --)
{
- if(incs == 2)
+ if (incs == 2)
src -= 32;
- if(incd == 2)
+ if (incd == 2)
dst -= 32;
- m_program->write_qword(dst, m_program->read_qword(src));
- m_program->write_qword(dst+8, m_program->read_qword(src+8));
- m_program->write_qword(dst+16, m_program->read_qword(src+16));
- m_program->write_qword(dst+24, m_program->read_qword(src+24));
- if(incs == 1)
+ m_program->write_qword(dst & SH34_AM, m_program->read_qword(src & SH34_AM));
+ m_program->write_qword((dst + 8) & SH34_AM, m_program->read_qword((src + 8) & SH34_AM));
+ m_program->write_qword((dst + 16) & SH34_AM, m_program->read_qword((src + 16) & SH34_AM));
+ m_program->write_qword((dst + 24) & SH34_AM, m_program->read_qword((src + 24) & SH34_AM));
+ if (incs == 1)
src += 32;
- if(incd == 1)
+ if (incd == 1)
dst += 32;
}
break;
@@ -186,13 +184,10 @@ int sh34_base_device::sh4_dma_transfer(int channel, int timermode, uint32_t chcr
int sh34_base_device::sh4_dma_transfer_device(int channel, uint32_t chcr, uint32_t *sar, uint32_t *dar, uint32_t *dmatcr)
{
- int incs, incd, size, mod;
- uint32_t src, dst, count;
-
- incd = (chcr & CHCR_DM) >> 14;
- incs = (chcr & CHCR_SM) >> 12;
-
+ int incd = (chcr & CHCR_DM) >> 14;
+ int incs = (chcr & CHCR_SM) >> 12;
+ int size;
if (m_cpu_type == CPU_TYPE_SH4)
{
size = dmasize[(chcr & CHCR_TS) >> 4];
@@ -202,19 +197,20 @@ int sh34_base_device::sh4_dma_transfer_device(int channel, uint32_t chcr, uint32
size = sh3_dmasize[(chcr >> 3) & 3];
}
- mod = ((chcr & CHCR_RS) >> 8);
+ int mod = ((chcr & CHCR_RS) >> 8);
if (incd == 3 || incs == 3)
{
logerror("SH4: DMA: bad increment values (%d, %d, %d, %04x)\n", incd, incs, size, chcr);
return 0;
}
- src = *sar;
- dst = *dar;
- count = *dmatcr;
+
+ uint32_t src = *sar;
+ uint32_t dst = *dar;
+ uint32_t count = *dmatcr;
if (!count)
count = 0x1000000;
- LOG(("SH4: DMA %d start device<->memory %x, %x, %x, %04x, %d, %d, %d\n", channel, src, dst, count, chcr, incs, incd, size));
+ LOG("SH4: DMA %d start device<->memory %x, %x, %x, %04x, %d, %d, %d\n", channel, src, dst, count, chcr, incs, incd, size);
m_dma_timer_active[channel] = 1;
@@ -242,41 +238,41 @@ void sh34_base_device::sh4_dmac_check(int channel)
switch (channel)
{
case 0:
- sar = m_SH4_SAR0;
- dar = m_SH4_DAR0;
- chcr = m_SH4_CHCR0;
- dmatcr = m_SH4_DMATCR0;
+ sar = m_sar0;
+ dar = m_dar0;
+ chcr = m_chcr0;
+ dmatcr = m_dmatcr0;
break;
case 1:
- sar = m_SH4_SAR1;
- dar = m_SH4_DAR1;
- chcr = m_SH4_CHCR1;
- dmatcr = m_SH4_DMATCR1;
+ sar = m_sar1;
+ dar = m_dar1;
+ chcr = m_chcr1;
+ dmatcr = m_dmatcr1;
break;
case 2:
- sar = m_SH4_SAR2;
- dar = m_SH4_DAR2;
- chcr = m_SH4_CHCR2;
- dmatcr = m_SH4_DMATCR2;
+ sar = m_sar2;
+ dar = m_dar2;
+ chcr = m_chcr2;
+ dmatcr = m_dmatcr2;
break;
case 3:
- sar = m_SH4_SAR3;
- dar = m_SH4_DAR3;
- chcr = m_SH4_CHCR3;
- dmatcr = m_SH4_DMATCR3;
+ sar = m_sar3;
+ dar = m_dar3;
+ chcr = m_chcr3;
+ dmatcr = m_dmatcr3;
break;
default:
return;
}
- if (chcr & m_SH4_DMAOR & DMAOR_DME)
+ if (chcr & m_dmaor & DMAOR_DME)
{
if ((((chcr & CHCR_RS) >> 8) < 2) || (((chcr & CHCR_RS) >> 8) > 6))
return;
- if (!m_dma_timer_active[channel] && !(chcr & CHCR_TE) && !(m_SH4_DMAOR & (DMAOR_AE | DMAOR_NMIF)))
+ if (!m_dma_timer_active[channel] && !(chcr & CHCR_TE) && !(m_dmaor & (DMAOR_AE | DMAOR_NMIF)))
{
if (((chcr & CHCR_RS) >> 8) > 3)
sh4_dma_transfer(channel, 1, chcr, &sar, &dar, &dmatcr);
- else if ((m_SH4_DMAOR & DMAOR_DDT) == 0)
+ else if ((m_dmaor & DMAOR_DDT) == 0)
sh4_dma_transfer_device(channel, chcr, &sar, &dar, &dmatcr); // tell device we are ready to transfer
}
}
@@ -295,7 +291,6 @@ void sh34_base_device::sh4_dmac_check(int channel)
// called by drivers to transfer data in a cpu<->device dma. 'device' must be a SH4 cpu
int sh34_base_device::sh4_dma_data(struct sh4_device_dma *s)
{
- uint32_t pos, len, siz;
int channel = s->channel;
void *data = s->buffer;
@@ -305,48 +300,49 @@ int sh34_base_device::sh4_dma_data(struct sh4_device_dma *s)
if (m_dma_mode[channel] == 2)
{
// device receives data
- len = m_dma_count[channel];
+ uint32_t len = m_dma_count[channel];
if (s->length < len)
len = s->length;
- siz = m_dma_wordsize[channel];
- for (pos = 0;pos < len;pos++) {
+ uint32_t siz = m_dma_wordsize[channel];
+ for (uint32_t pos = 0; pos < len; pos++)
+ {
switch (siz)
{
case 8:
if (m_dma_source_increment[channel] == 2)
m_dma_source[channel] -= 8;
- *(uint64_t *)data = m_program->read_qword(m_dma_source[channel] & ~7);
+ *(uint64_t *)data = m_program->read_qword(m_dma_source[channel] & SH34_AM & ~7);
if (m_dma_source_increment[channel] == 1)
m_dma_source[channel] += 8;
break;
case 1:
if (m_dma_source_increment[channel] == 2)
m_dma_source[channel]--;
- *(uint8_t *)data = m_program->read_byte(m_dma_source[channel]);
+ *(uint8_t *)data = m_program->read_byte(m_dma_source[channel] & SH34_AM);
if (m_dma_source_increment[channel] == 1)
m_dma_source[channel]++;
break;
case 2:
if (m_dma_source_increment[channel] == 2)
m_dma_source[channel] -= 2;
- *(uint16_t *)data = m_program->read_word(m_dma_source[channel] & ~1);
+ *(uint16_t *)data = m_program->read_word(m_dma_source[channel] & SH34_AM & ~1);
if (m_dma_source_increment[channel] == 1)
m_dma_source[channel] += 2;
break;
case 4:
if (m_dma_source_increment[channel] == 2)
m_dma_source[channel] -= 4;
- *(uint32_t *)data = m_program->read_dword(m_dma_source[channel] & ~3);
+ *(uint32_t *)data = m_program->read_dword(m_dma_source[channel] & SH34_AM & ~3);
if (m_dma_source_increment[channel] == 1)
m_dma_source[channel] += 4;
break;
case 32:
if (m_dma_source_increment[channel] == 2)
m_dma_source[channel] -= 32;
- *(uint64_t *)data = m_program->read_qword(m_dma_source[channel] & ~31);
- *((uint64_t *)data+1) = m_program->read_qword((m_dma_source[channel] & ~31)+8);
- *((uint64_t *)data+2) = m_program->read_qword((m_dma_source[channel] & ~31)+16);
- *((uint64_t *)data+3) = m_program->read_qword((m_dma_source[channel] & ~31)+24);
+ *(uint64_t *)data = m_program->read_qword(m_dma_source[channel] & SH34_AM & ~31);
+ *((uint64_t *)data+1) = m_program->read_qword((m_dma_source[channel] & SH34_AM & ~31)+8);
+ *((uint64_t *)data+2) = m_program->read_qword((m_dma_source[channel] & SH34_AM & ~31)+16);
+ *((uint64_t *)data+3) = m_program->read_qword((m_dma_source[channel] & SH34_AM & ~31)+24);
if (m_dma_source_increment[channel] == 1)
m_dma_source[channel] += 32;
break;
@@ -363,48 +359,49 @@ int sh34_base_device::sh4_dma_data(struct sh4_device_dma *s)
else if (m_dma_mode[channel] == 3)
{
// device sends data
- len = m_dma_count[channel];
+ uint32_t len = m_dma_count[channel];
if (s->length < len)
len = s->length;
- siz = m_dma_wordsize[channel];
- for (pos = 0;pos < len;pos++) {
+ uint32_t siz = m_dma_wordsize[channel];
+ for (uint32_t pos = 0; pos < len; pos++)
+ {
switch (siz)
{
case 8:
if (m_dma_destination_increment[channel] == 2)
m_dma_destination[channel]-=8;
- m_program->write_qword(m_dma_destination[channel] & ~7, *(uint64_t *)data);
+ m_program->write_qword(m_dma_destination[channel] & SH34_AM & ~7, *(uint64_t *)data);
if (m_dma_destination_increment[channel] == 1)
m_dma_destination[channel]+=8;
break;
case 1:
if (m_dma_destination_increment[channel] == 2)
m_dma_destination[channel]--;
- m_program->write_byte(m_dma_destination[channel], *(uint8_t *)data);
+ m_program->write_byte(m_dma_destination[channel] & SH34_AM, *(uint8_t *)data);
if (m_dma_destination_increment[channel] == 1)
m_dma_destination[channel]++;
break;
case 2:
if (m_dma_destination_increment[channel] == 2)
m_dma_destination[channel]-=2;
- m_program->write_word(m_dma_destination[channel] & ~1, *(uint16_t *)data);
+ m_program->write_word(m_dma_destination[channel] & SH34_AM & ~1, *(uint16_t *)data);
if (m_dma_destination_increment[channel] == 1)
m_dma_destination[channel]+=2;
break;
case 4:
if (m_dma_destination_increment[channel] == 2)
m_dma_destination[channel]-=4;
- m_program->write_dword(m_dma_destination[channel] & ~3, *(uint32_t *)data);
+ m_program->write_dword(m_dma_destination[channel] & SH34_AM & ~3, *(uint32_t *)data);
if (m_dma_destination_increment[channel] == 1)
m_dma_destination[channel]+=4;
break;
case 32:
if (m_dma_destination_increment[channel] == 2)
m_dma_destination[channel]-=32;
- m_program->write_qword(m_dma_destination[channel] & ~31, *(uint64_t *)data);
- m_program->write_qword((m_dma_destination[channel] & ~31)+8, *((uint64_t *)data+1));
- m_program->write_qword((m_dma_destination[channel] & ~31)+16, *((uint64_t *)data+2));
- m_program->write_qword((m_dma_destination[channel] & ~31)+24, *((uint64_t *)data+3));
+ m_program->write_qword(m_dma_destination[channel] & SH34_AM & ~31, *(uint64_t *)data);
+ m_program->write_qword((m_dma_destination[channel] & SH34_AM & ~31)+8, *((uint64_t *)data+1));
+ m_program->write_qword((m_dma_destination[channel] & SH34_AM & ~31)+16, *((uint64_t *)data+2));
+ m_program->write_qword((m_dma_destination[channel] & SH34_AM & ~31)+24, *((uint64_t *)data+3));
if (m_dma_destination_increment[channel] == 1)
m_dma_destination[channel]+=32;
break;
@@ -426,88 +423,86 @@ int sh34_base_device::sh4_dma_data(struct sh4_device_dma *s)
// called by drivers to transfer data in a DDT dma.
void sh34_base_device::sh4_dma_ddt(struct sh4_ddt_dma *s)
{
- uint32_t chcr;
- uint32_t *p32bits;
- uint64_t *p32bytes;
- uint32_t pos,len,siz;
-
if (m_cpu_type != CPU_TYPE_SH4)
fatalerror("sh4_dma_ddt uses m_m[] with SH3\n");
if (m_dma_timer_active[s->channel])
return;
- if (s->mode >= 0) {
+ if (s->mode >= 0)
+ {
switch (s->channel)
{
case 0:
if (s->mode & 1)
- s->source = m_SH4_SAR0;
+ s->source = m_sar0;
if (s->mode & 2)
- m_SH4_SAR0 = s->source;
+ m_sar0 = s->source;
if (s->mode & 4)
- s->destination = m_SH4_DAR0;
+ s->destination = m_dar0;
if (s->mode & 8)
- m_SH4_DAR0 = s->destination;
+ m_dar0 = s->destination;
break;
case 1:
if (s->mode & 1)
- s->source = m_SH4_SAR1;
+ s->source = m_sar1;
if (s->mode & 2)
- m_SH4_SAR1 = s->source;
+ m_sar1 = s->source;
if (s->mode & 4)
- s->destination = m_SH4_DAR1;
+ s->destination = m_dar1;
if (s->mode & 8)
- m_SH4_DAR1 = s->destination;
+ m_dar1 = s->destination;
break;
case 2:
if (s->mode & 1)
- s->source = m_SH4_SAR2;
+ s->source = m_sar2;
if (s->mode & 2)
- m_SH4_SAR2 = s->source;
+ m_sar2 = s->source;
if (s->mode & 4)
- s->destination = m_SH4_DAR2;
+ s->destination = m_dar2;
if (s->mode & 8)
- m_SH4_DAR2 = s->destination;
+ m_dar2 = s->destination;
break;
case 3:
default:
if (s->mode & 1)
- s->source = m_SH4_SAR3;
+ s->source = m_sar3;
if (s->mode & 2)
- m_SH4_SAR3 = s->source;
+ m_sar3 = s->source;
if (s->mode & 4)
- s->destination = m_SH4_DAR3;
+ s->destination = m_dar3;
if (s->mode & 8)
- m_SH4_DAR3 = s->destination;
+ m_dar3 = s->destination;
break;
}
+ uint32_t len;
+ uint32_t chcr;
switch (s->channel)
{
case 0:
- chcr = m_SH4_CHCR0;
- len = m_SH4_DMATCR0;
+ chcr = m_chcr0;
+ len = m_dmatcr0;
break;
case 1:
- chcr = m_SH4_CHCR1;
- len = m_SH4_DMATCR1;
+ chcr = m_chcr1;
+ len = m_dmatcr1;
break;
case 2:
- chcr = m_SH4_CHCR2;
- len = m_SH4_DMATCR2;
+ chcr = m_chcr2;
+ len = m_dmatcr2;
break;
case 3:
default:
- chcr = m_SH4_CHCR3;
- len = m_SH4_DMATCR3;
+ chcr = m_chcr3;
+ len = m_dmatcr3;
break;
}
- if ((s->direction) == 0) {
+
+ if (s->direction == 0)
chcr = (chcr & 0xffff3fff) | ((s->mode & 0x30) << 10);
- } else {
+ else
chcr = (chcr & 0xffffcfff) | ((s->mode & 0x30) << 8);
- }
-
+ uint32_t siz = 0;
if (m_cpu_type == CPU_TYPE_SH4)
{
//siz = dmasize[(chcr & CHCR_TS) >> 4];
@@ -519,44 +514,52 @@ void sh34_base_device::sh4_dma_ddt(struct sh4_ddt_dma *s)
}
- if (siz && (s->size))
- if ((len * siz) != (s->length * s->size))
+ if (siz && s->size)
+ if (len * siz != s->length * s->size)
return;
sh4_dma_transfer(s->channel, 0, chcr, &s->source, &s->destination, &len);
- } else {
- if (s->size == 4) {
- if ((s->direction) == 0) {
- len = s->length;
- p32bits = (uint32_t *)(s->buffer);
- for (pos = 0;pos < len;pos++) {
- *p32bits = m_program->read_dword(s->source);
- p32bits++;
+ }
+ else
+ {
+ if (s->size == 4)
+ {
+ if ((s->direction) == 0)
+ {
+ uint32_t *p32bits = (uint32_t *)s->buffer;
+ for (uint32_t pos = 0; pos < s->length; pos++)
+ {
+ *p32bits++ = m_program->read_dword(s->source & SH34_AM);
s->source = s->source + 4;
}
- } else {
- len = s->length;
- p32bits = (uint32_t *)(s->buffer);
- for (pos = 0;pos < len;pos++) {
- m_program->write_dword(s->destination, *p32bits);
+ }
+ else
+ {
+ uint32_t *p32bits = (uint32_t *)s->buffer;
+ for (uint32_t pos = 0; pos < s->length; pos++)
+ {
+ m_program->write_dword(s->destination & SH34_AM, *p32bits);
p32bits++;
s->destination = s->destination + 4;
}
}
}
- if (s->size == 32) {
- if ((s->direction) == 0) {
- len = s->length * 4;
- p32bytes = (uint64_t *)(s->buffer);
- for (pos = 0;pos < len;pos++) {
- *p32bytes = m_program->read_qword(s->source);
- p32bytes++;
+ if (s->size == 32)
+ {
+ if ((s->direction) == 0)
+ {
+ uint64_t *p32bytes = (uint64_t *)s->buffer;
+ for (uint32_t pos = 0; pos < s->length * 4; pos++)
+ {
+ *p32bytes++ = m_program->read_qword(s->source & SH34_AM);
s->destination = s->destination + 8;
}
- } else {
- len = s->length * 4;
- p32bytes = (uint64_t *)(s->buffer);
- for (pos = 0;pos < len;pos++) {
- m_program->write_qword(s->destination, *p32bytes);
+ }
+ else
+ {
+ uint64_t *p32bytes = (uint64_t *)s->buffer;
+ for (uint32_t pos = 0; pos < s->length * 4; pos++)
+ {
+ m_program->write_qword(s->destination & SH34_AM, *p32bytes);
p32bytes++;
s->destination = s->destination + 8;
}
@@ -565,100 +568,184 @@ void sh34_base_device::sh4_dma_ddt(struct sh4_ddt_dma *s)
}
}
+uint32_t sh34_base_device::sar0_r(offs_t offset, uint32_t mem_mask)
+{
+ return m_sar0;
+}
+
+void sh34_base_device::sar0_w(offs_t offset, uint32_t data, uint32_t mem_mask)
+{
+ COMBINE_DATA(&m_sar0);
+}
- void sh34_base_device::sh4_handle_sar0_addr_w(uint32_t data, uint32_t mem_mask)
+uint32_t sh34_base_device::dar0_r(offs_t offset, uint32_t mem_mask)
{
- COMBINE_DATA(&m_SH4_SAR0);
+ return m_dar0;
}
- void sh34_base_device::sh4_handle_sar1_addr_w(uint32_t data, uint32_t mem_mask)
+void sh34_base_device::dar0_w(offs_t offset, uint32_t data, uint32_t mem_mask)
{
- COMBINE_DATA(&m_SH4_SAR1);
+ COMBINE_DATA(&m_dar0);
}
- void sh34_base_device::sh4_handle_sar2_addr_w(uint32_t data, uint32_t mem_mask)
+uint32_t sh34_base_device::dmatcr0_r(offs_t offset, uint32_t mem_mask)
{
- COMBINE_DATA(&m_SH4_SAR2);
+ return m_dmatcr0;
}
- void sh34_base_device::sh4_handle_sar3_addr_w(uint32_t data, uint32_t mem_mask)
+void sh34_base_device::dmatcr0_w(offs_t offset, uint32_t data, uint32_t mem_mask)
{
- COMBINE_DATA(&m_SH4_SAR3);
+ COMBINE_DATA(&m_dmatcr0);
}
- void sh34_base_device::sh4_handle_dar0_addr_w(uint32_t data, uint32_t mem_mask)
+uint32_t sh34_base_device::chcr0_r(offs_t offset, uint32_t mem_mask)
{
- COMBINE_DATA(&m_SH4_DAR0);
+ return m_chcr0;
}
- void sh34_base_device::sh4_handle_dar1_addr_w(uint32_t data, uint32_t mem_mask)
+void sh34_base_device::chcr0_w(offs_t offset, uint32_t data, uint32_t mem_mask)
{
- COMBINE_DATA(&m_SH4_DAR1);
+ COMBINE_DATA(&m_chcr0);
+ sh4_dmac_check(0);
}
- void sh34_base_device::sh4_handle_dar2_addr_w(uint32_t data, uint32_t mem_mask)
+uint32_t sh34_base_device::sar1_r(offs_t offset, uint32_t mem_mask)
{
- COMBINE_DATA(&m_SH4_DAR2);
+ return m_sar1;
}
- void sh34_base_device::sh4_handle_dar3_addr_w(uint32_t data, uint32_t mem_mask)
+void sh34_base_device::sar1_w(offs_t offset, uint32_t data, uint32_t mem_mask)
{
- COMBINE_DATA(&m_SH4_DAR3);
+ COMBINE_DATA(&m_sar1);
}
- void sh34_base_device::sh4_handle_dmatcr0_addr_w(uint32_t data, uint32_t mem_mask)
+uint32_t sh34_base_device::dar1_r(offs_t offset, uint32_t mem_mask)
{
- COMBINE_DATA(&m_SH4_DMATCR0);
+ return m_dar1;
}
- void sh34_base_device::sh4_handle_dmatcr1_addr_w(uint32_t data, uint32_t mem_mask)
+void sh34_base_device::dar1_w(offs_t offset, uint32_t data, uint32_t mem_mask)
{
- COMBINE_DATA(&m_SH4_DMATCR1);
+ COMBINE_DATA(&m_dar1);
}
- void sh34_base_device::sh4_handle_dmatcr2_addr_w(uint32_t data, uint32_t mem_mask)
+uint32_t sh34_base_device::dmatcr1_r(offs_t offset, uint32_t mem_mask)
{
- COMBINE_DATA(&m_SH4_DMATCR2);
+ return m_dmatcr1;
}
- void sh34_base_device::sh4_handle_dmatcr3_addr_w(uint32_t data, uint32_t mem_mask)
+void sh34_base_device::dmatcr1_w(offs_t offset, uint32_t data, uint32_t mem_mask)
{
- COMBINE_DATA(&m_SH4_DMATCR3);
+ COMBINE_DATA(&m_dmatcr1);
}
- void sh34_base_device::sh4_handle_chcr0_addr_w(uint32_t data, uint32_t mem_mask)
+uint32_t sh34_base_device::chcr1_r(offs_t offset, uint32_t mem_mask)
{
- COMBINE_DATA(&m_SH4_CHCR0);
- sh4_dmac_check(0);
+ return m_chcr1;
}
- void sh34_base_device::sh4_handle_chcr1_addr_w(uint32_t data, uint32_t mem_mask)
+void sh34_base_device::chcr1_w(offs_t offset, uint32_t data, uint32_t mem_mask)
{
- COMBINE_DATA(&m_SH4_CHCR1);
+ COMBINE_DATA(&m_chcr1);
sh4_dmac_check(1);
}
- void sh34_base_device::sh4_handle_chcr2_addr_w(uint32_t data, uint32_t mem_mask)
+uint32_t sh34_base_device::sar2_r(offs_t offset, uint32_t mem_mask)
+{
+ return m_sar2;
+}
+
+void sh34_base_device::sar2_w(offs_t offset, uint32_t data, uint32_t mem_mask)
+{
+ COMBINE_DATA(&m_sar2);
+}
+
+uint32_t sh34_base_device::dar2_r(offs_t offset, uint32_t mem_mask)
{
- COMBINE_DATA(&m_SH4_CHCR2);
+ return m_dar2;
+}
+
+void sh34_base_device::dar2_w(offs_t offset, uint32_t data, uint32_t mem_mask)
+{
+ COMBINE_DATA(&m_dar2);
+}
+
+uint32_t sh34_base_device::dmatcr2_r(offs_t offset, uint32_t mem_mask)
+{
+ return m_dmatcr2;
+}
+
+void sh34_base_device::dmatcr2_w(offs_t offset, uint32_t data, uint32_t mem_mask)
+{
+ COMBINE_DATA(&m_dmatcr2);
+}
+
+uint32_t sh34_base_device::chcr2_r(offs_t offset, uint32_t mem_mask)
+{
+ return m_chcr2;
+}
+
+void sh34_base_device::chcr2_w(offs_t offset, uint32_t data, uint32_t mem_mask)
+{
+ COMBINE_DATA(&m_chcr2);
sh4_dmac_check(2);
}
- void sh34_base_device::sh4_handle_chcr3_addr_w(uint32_t data, uint32_t mem_mask)
+uint32_t sh34_base_device::sar3_r(offs_t offset, uint32_t mem_mask)
{
- COMBINE_DATA(&m_SH4_CHCR3);
+ return m_sar3;
+}
+
+void sh34_base_device::sar3_w(offs_t offset, uint32_t data, uint32_t mem_mask)
+{
+ COMBINE_DATA(&m_sar3);
+}
+
+uint32_t sh34_base_device::dar3_r(offs_t offset, uint32_t mem_mask)
+{
+ return m_dar3;
+}
+
+void sh34_base_device::dar3_w(offs_t offset, uint32_t data, uint32_t mem_mask)
+{
+ COMBINE_DATA(&m_dar3);
+}
+
+uint32_t sh34_base_device::dmatcr3_r(offs_t offset, uint32_t mem_mask)
+{
+ return m_dmatcr3;
+}
+
+void sh34_base_device::dmatcr3_w(offs_t offset, uint32_t data, uint32_t mem_mask)
+{
+ COMBINE_DATA(&m_dmatcr3);
+}
+
+uint32_t sh34_base_device::chcr3_r(offs_t offset, uint32_t mem_mask)
+{
+ return m_chcr3;
+}
+
+void sh34_base_device::chcr3_w(offs_t offset, uint32_t data, uint32_t mem_mask)
+{
+ COMBINE_DATA(&m_chcr3);
sh4_dmac_check(3);
}
- void sh34_base_device::sh4_handle_dmaor_addr_w(uint32_t data, uint32_t mem_mask)
+uint32_t sh34_base_device::dmaor_r(offs_t offset, uint32_t mem_mask)
+{
+ return m_dmaor;
+}
+
+void sh34_base_device::dmaor_w(offs_t offset, uint32_t data, uint32_t mem_mask)
{
- uint32_t old = m_SH4_DMAOR;
- COMBINE_DATA(&m_SH4_DMAOR);
+ uint32_t old = m_dmaor;
+ COMBINE_DATA(&m_dmaor);
- if ((m_SH4_DMAOR & DMAOR_AE) && (~old & DMAOR_AE))
- m_SH4_DMAOR &= ~DMAOR_AE;
- if ((m_SH4_DMAOR & DMAOR_NMIF) && (~old & DMAOR_NMIF))
- m_SH4_DMAOR &= ~DMAOR_NMIF;
+ if ((m_dmaor & DMAOR_AE) && (~old & DMAOR_AE))
+ m_dmaor &= ~DMAOR_AE;
+ if ((m_dmaor & DMAOR_NMIF) && (~old & DMAOR_NMIF))
+ m_dmaor &= ~DMAOR_NMIF;
sh4_dmac_check(0);
sh4_dmac_check(1);
sh4_dmac_check(2);
diff --git a/src/devices/cpu/sh/sh4dmac.h b/src/devices/cpu/sh/sh4dmac.h
index b7918fac997..a3ad1d0b5dc 100644
--- a/src/devices/cpu/sh/sh4dmac.h
+++ b/src/devices/cpu/sh/sh4dmac.h
@@ -26,38 +26,3 @@
#define DMAOR_AE 0x0004
#define DMAOR_NMIF 0x0002
#define DMAOR_DME 0x0001
-
-void sh4_handle_sar0_addr_w(uint32_t data, uint32_t mem_mask);
-void sh4_handle_sar1_addr_w(uint32_t data, uint32_t mem_mask);
-void sh4_handle_sar2_addr_w(uint32_t data, uint32_t mem_mask);
-void sh4_handle_sar3_addr_w(uint32_t data, uint32_t mem_mask);
-void sh4_handle_dar0_addr_w(uint32_t data, uint32_t mem_mask);
-void sh4_handle_dar1_addr_w(uint32_t data, uint32_t mem_mask);
-void sh4_handle_dar2_addr_w(uint32_t data, uint32_t mem_mask);
-void sh4_handle_dar3_addr_w(uint32_t data, uint32_t mem_mask);
-void sh4_handle_dmatcr0_addr_w(uint32_t data, uint32_t mem_mask);
-void sh4_handle_dmatcr1_addr_w(uint32_t data, uint32_t mem_mask);
-void sh4_handle_dmatcr2_addr_w(uint32_t data, uint32_t mem_mask);
-void sh4_handle_dmatcr3_addr_w(uint32_t data, uint32_t mem_mask);
-void sh4_handle_chcr0_addr_w(uint32_t data, uint32_t mem_mask);
-void sh4_handle_chcr1_addr_w(uint32_t data, uint32_t mem_mask);
-void sh4_handle_chcr2_addr_w(uint32_t data, uint32_t mem_mask);
-void sh4_handle_chcr3_addr_w(uint32_t data, uint32_t mem_mask);
-void sh4_handle_dmaor_addr_w(uint32_t data, uint32_t mem_mask);
-uint32_t sh4_handle_sar0_addr_r(uint32_t mem_mask);
-uint32_t sh4_handle_sar1_addr_r(uint32_t mem_mask);
-uint32_t sh4_handle_sar2_addr_r(uint32_t mem_mask);
-uint32_t sh4_handle_sar3_addr_r(uint32_t mem_mask);
-uint32_t sh4_handle_dar0_addr_r(uint32_t mem_mask);
-uint32_t sh4_handle_dar1_addr_r(uint32_t mem_mask);
-uint32_t sh4_handle_dar2_addr_r(uint32_t mem_mask);
-uint32_t sh4_handle_dar3_addr_r(uint32_t mem_mask);
-uint32_t sh4_handle_dmatcr0_addr_r(uint32_t mem_mask);
-uint32_t sh4_handle_dmatcr1_addr_r(uint32_t mem_mask);
-uint32_t sh4_handle_dmatcr2_addr_r(uint32_t mem_mask);
-uint32_t sh4_handle_dmatcr3_addr_r(uint32_t mem_mask);
-uint32_t sh4_handle_chcr0_addr_r(uint32_t mem_mask);
-uint32_t sh4_handle_chcr1_addr_r(uint32_t mem_mask);
-uint32_t sh4_handle_chcr2_addr_r(uint32_t mem_mask);
-uint32_t sh4_handle_chcr3_addr_r(uint32_t mem_mask);
-uint32_t sh4_handle_dmaor_addr_r(uint32_t mem_mask);
diff --git a/src/devices/cpu/sh/sh4fe.cpp b/src/devices/cpu/sh/sh4fe.cpp
index 0f88f98b9ae..cb3afaba6fe 100644
--- a/src/devices/cpu/sh/sh4fe.cpp
+++ b/src/devices/cpu/sh/sh4fe.cpp
@@ -2,7 +2,7 @@
// copyright-holders:R. Belmont, David Haywood
/***************************************************************************
- sh4fe.c
+ sh4fe.cpp
Front end for SH-4 recompiler
@@ -31,14 +31,6 @@ uint16_t sh4_frontend::read_word(opcode_desc &desc)
return m_sh->m_pr16(desc.physpc & SH34_AM);
}
-uint16_t sh4be_frontend::read_word(opcode_desc &desc)
-{
- if (desc.physpc >= 0xe0000000)
- return m_sh->m_pr16(desc.physpc);
-
- return m_sh->m_pr16(desc.physpc & SH34_AM);
-}
-
bool sh4_frontend::describe_group_0(opcode_desc &desc, const opcode_desc *prev, uint16_t opcode)
{
@@ -291,8 +283,10 @@ bool sh4_frontend::describe_op1111_0x13(opcode_desc &desc, const opcode_desc *pr
bool sh4_frontend::describe_op1111_0xf13(opcode_desc &desc, const opcode_desc *prev, uint16_t opcode)
{
- if (opcode & 0x100) {
- if (opcode & 0x200) {
+ if (opcode & 0x100)
+ {
+ if (opcode & 0x200)
+ {
switch (opcode & 0xC00)
{
case 0x000:
@@ -306,11 +300,13 @@ bool sh4_frontend::describe_op1111_0xf13(opcode_desc &desc, const opcode_desc *p
break;
}
}
- else {
+ else
+ {
return true; // FTRV(opcode);
}
}
- else {
+ else
+ {
return true; // FSSCA(opcode);
}
return false;
diff --git a/src/devices/cpu/sh/sh4regs.h b/src/devices/cpu/sh/sh4regs.h
index 384f062858e..691fef33998 100644
--- a/src/devices/cpu/sh/sh4regs.h
+++ b/src/devices/cpu/sh/sh4regs.h
@@ -1,166 +1,9 @@
// license:BSD-3-Clause
// copyright-holders:R. Belmont
-#pragma once
-
-#ifndef __SH4REGS_H__
-#define __SH4REGS_H__
-
-/* 00000001111111100000000011111100 */
-#define PTEH 0x2000 /* FF000000 */
-#define PTEL 0x2001 /* FF000004 */
-#define TTB 0x2002 /* FF000008 */
-#define TEA 0x2003 /* FF00000C */
-#define MMUCR 0x2004 /* FF000010 */
-#define BASRA 0x2005 /* FF000014 */
-#define BASRB 0x2006 /* FF000018 */
-#define CCR 0x2007 /* FF00001C */
-#define TRA 0x2008 /* FF000020 */
-#define EXPEVT 0x2009 /* FF000024 */
-#define INTEVT 0x200A /* FF000028 */
-#define VERSION 0x200C /* FF000030 */
-#define PTEA 0x200D /* FF000034 */
-#define QACR0 0x200E /* FF000038 */
-#define QACR1 0x200F /* FF00003C */
-#define PRR 0x2011 /* FF000044 */
-#define BARA 0x2400 /* FF200000 */
-#define BAMRA 0x2401 /* FF200004 */
-#define BBRA 0x2402 /* FF200008 */
-#define BARB 0x2403 /* FF20000C */
-#define BAMRB 0x2404 /* FF200010 */
-#define BBRB 0x2405 /* FF200014 */
-#define BDRB 0x2406 /* FF200018 */
-#define BDMRB 0x2407 /* FF20001C */
-#define BRCR 0x2408 /* FF200020 */
-#define BCR1 0x3000 /* FF800000 */
-#define BCR2 0x3001 /* FF800004 */
-#define BCR3 0x3014 /* FF800050 */
-#define BCR4 0x17C /* FE0A00F0 */
-#define WCR1 0x3002 /* FF800008 */
-#define WCR2 0x3003 /* FF80000C */
-#define WCR3 0x3004 /* FF800010 */
-#define MCR 0x3005 /* FF800014 */
-#define PCR 0x3006 /* FF800018 */
-#define RTCSR 0x3007 /* FF80001C */
-#define RTCNT 0x3008 /* FF800020 */
-#define RTCOR 0x3009 /* FF800024 */
-#define RFCR 0x300A /* FF800028 */
-#define PCTRA 0x300B /* FF80002C */
-#define PDTRA 0x300C /* FF800030 */
-#define PCTRB 0x3010 /* FF800040 */
-#define PDTRB 0x3011 /* FF800044 */
-#define GPIOIC 0x3012 /* FF800048 */
-#define SDMR2 0x3200 /* FF900000 */
-#define SDMR3 0x3280 /* FF940000 */
-#define SH4_SAR0_ADDR 0x3400 /* FFA00000 */
-#define SH4_DAR0_ADDR 0x3401 /* FFA00004 */
-#define SH4_DMATCR0_ADDR 0x3402 /* FFA00008 */
-#define SH4_CHCR0_ADDR 0x3403 /* FFA0000C */
-#define SH4_SAR1_ADDR 0x3404 /* FFA00010 */
-#define SH4_DAR1_ADDR 0x3405 /* FFA00014 */
-#define SH4_DMATCR1_ADDR 0x3406 /* FFA00018 */
-#define SH4_CHCR1_ADDR 0x3407 /* FFA0001C */
-#define SH4_SAR2_ADDR 0x3408 /* FFA00020 */
-#define SH4_DAR2_ADDR 0x3409 /* FFA00024 */
-#define SH4_DMATCR2_ADDR 0x340A /* FFA00028 */
-#define SH4_CHCR2_ADDR 0x340B /* FFA0002C */
-#define SH4_SAR3_ADDR 0x340C /* FFA00030 */
-#define SH4_DAR3_ADDR 0x340D /* FFA00034 */
-#define SH4_DMATCR3_ADDR 0x340E /* FFA00038 */
-#define SH4_CHCR3_ADDR 0x340F /* FFA0003C */
-#define SH4_DMAOR_ADDR 0x3410 /* FFA00040 */
-#define SAR4 0x3414 /* FFA00050 */
-#define DAR4 0x3415 /* FFA00054 */
-#define DMATCR4 0x3416 /* FFA00058 */
-#define CHCR4 0x3417 /* FFA0005C */
-#define SAR5 0x3418 /* FFA00060 */
-#define DAR5 0x3419 /* FFA00064 */
-#define DMATCR5 0x341A /* FFA00068 */
-#define CHCR5 0x341B /* FFA0006C */
-#define SAR6 0x341C /* FFA00070 */
-#define DAR6 0x341D /* FFA00074 */
-#define DMATCR6 0x341E /* FFA00078 */
-#define CHCR6 0x341F /* FFA0007C */
-#define SAR7 0x3420 /* FFA00080 */
-#define DAR7 0x3421 /* FFA00084 */
-#define DMATCR7 0x3422 /* FFA00088 */
-#define CHCR7 0x3423 /* FFA0008C */
-#define FRQCR 0x3800 /* FFC00000 */
-#define STBCR 0x3801 /* FFC00004 */
-#define WTCNT 0x3802 /* FFC00008 */
-#define WTCSR 0x3803 /* FFC0000C */
-#define STBCR2 0x3804 /* FFC00010 */
-#define R64CNT 0x3900 /* FFC80000 */
-#define RSECCNT 0x3901 /* FFC80004 */
-#define RMINCNT 0x3902 /* FFC80008 */
-#define RHRCNT 0x3903 /* FFC8000C */
-#define RWKCNT 0x3904 /* FFC80010 */
-#define RDAYCNT 0x3905 /* FFC80014 */
-#define RMONCNT 0x3906 /* FFC80018 */
-#define RYRCNT 0x3907 /* FFC8001C */
-#define RSECAR 0x3908 /* FFC80020 */
-#define RMINAR 0x3909 /* FFC80024 */
-#define RHRAR 0x390A /* FFC80028 */
-#define RWKAR 0x390B /* FFC8002C */
-#define RDAYAR 0x390C /* FFC80030 */
-#define RMONAR 0x390D /* FFC80034 */
-#define RCR1 0x390E /* FFC80038 */
-#define RCR2 0x390F /* FFC8003C */
-#define RCR3 0x3914 /* FFC80050 */
-#define RYRAR 0x3915 /* FFC80054 */
-#define ICR 0x3A00 /* FFD00000 */
-#define IPRA 0x3A01 /* FFD00004 */
-#define IPRB 0x3A02 /* FFD00008 */
-#define IPRC 0x3A03 /* FFD0000C */
-#define IPRD 0x3A04 /* FFD00010 */
-#define INTPRI00 0x100 /* FE080000 */
-#define INTREQ00 0x108 /* FE080020 */
-#define INTMSK00 0x110 /* FE080040 */
-#define INTMSKCLR00 0x118 /* FE080060 */
-#define CLKSTP00 0x140 /* FE0A0000 */
-#define CLKSTPCLR00 0x142 /* FE0A0008 */
-#define TSTR2 0x201 /* FE100004 */
-#define TCOR3 0x202 /* FE100008 */
-#define TCNT3 0x203 /* FE10000C */
-#define TCR3 0x204 /* FE100010 */
-#define TCOR4 0x205 /* FE100014 */
-#define TCNT4 0x206 /* FE100018 */
-#define TCR4 0x207 /* FE10001C */
-#define SH4_TOCR_ADDR 0x3B00 /* FFD80000 */
-#define SH4_TSTR_ADDR 0x3B01 /* FFD80004 */
-#define SH4_TCOR0_ADDR 0x3B02 /* FFD80008 */
-#define SH4_TCNT0_ADDR 0x3B03 /* FFD8000C */
-#define SH4_TCR0_ADDR 0x3B04 /* FFD80010 */
-#define SH4_TCOR1_ADDR 0x3B05 /* FFD80014 */
-#define SH4_TCNT1_ADDR 0x3B06 /* FFD80018 */
-#define SH4_TCR1_ADDR 0x3B07 /* FFD8001C */
-#define SH4_TCOR2_ADDR 0x3B08 /* FFD80020 */
-#define SH4_TCNT2_ADDR 0x3B09 /* FFD80024 */
-#define SH4_TCR2_ADDR 0x3B0A /* FFD80028 */
-#define SH4_TCPR2_ADDR 0x3B0B /* FFD8002C */
-#define SCSMR1 0x3C00 /* FFE00000 */
-#define SCBRR1 0x3C01 /* FFE00004 */
-#define SCSCR1 0x3C02 /* FFE00008 */
-#define SCTDR1 0x3C03 /* FFE0000C */
-#define SCSSR1 0x3C04 /* FFE00010 */
-#define SCRDR1 0x3C05 /* FFE00014 */
-#define SCSCMR1 0x3C06 /* FFE00018 */
-#define SCSPTR1 0x3C07 /* FFE0001C */
-#define SCSMR2 0x3D00 /* FFE80000 */
-#define SCBRR2 0x3D01 /* FFE80004 */
-#define SCSCR2 0x3D02 /* FFE80008 */
-#define SCFTDR2 0x3D03 /* FFE8000C */
-#define SCFSR2 0x3D04 /* FFE80010 */
-#define SCFRDR2 0x3D05 /* FFE80014 */
-#define SCFCR2 0x3D06 /* FFE80018 */
-#define SCFDR2 0x3D07 /* FFE8001C */
-#define SCSPTR2 0x3D08 /* FFE80020 */
-#define SCLSR2 0x3D09 /* FFE80024 */
-#define SDIR 0x3E00 /* FFF00000 */
-#define SDDR 0x3E02 /* FFF00008 */
-#define SDINT 0x3E05 /* FFF00014 */
-#define SIZEREGS 15878
-
+#ifndef MAME_CPU_SH_SH4REGS_H
+#define MAME_CPU_SH_SH4REGS_H
+#pragma once
#define MMUCR_LRUI 0xfc000000
#define MMUCR_URB 0x00fc0000
@@ -180,4 +23,4 @@
#define PVR_SH7751R 0x04050000
#define PRR_SH7751R 0x00000110
-#endif /* __SH4REGS_H__ */
+#endif // MAME_CPU_SH_SH4REGS_H
diff --git a/src/devices/cpu/sh/sh4tmu.cpp b/src/devices/cpu/sh/sh4tmu.cpp
index 4735b8bba67..dcdb9454e32 100644
--- a/src/devices/cpu/sh/sh4tmu.cpp
+++ b/src/devices/cpu/sh/sh4tmu.cpp
@@ -3,7 +3,6 @@
/* SH3/4 Timer Unit */
#include "emu.h"
-#include "debugger.h"
#include "sh4.h"
#include "sh4comn.h"
#include "sh3comn.h"
@@ -38,18 +37,18 @@ void sh34_base_device::sh4_timer_recompute(int which)
switch (which)
{
case 0:
- tcr = m_SH4_TCR0;
- tcnt = m_SH4_TCNT0;
+ tcr = m_tcr0;
+ tcnt = m_tcnt0;
break;
case 1:
- tcr = m_SH4_TCR1;
- tcnt = m_SH4_TCNT1;
+ tcr = m_tcr1;
+ tcnt = m_tcnt1;
break;
case 2:
- tcr = m_SH4_TCR2;
- tcnt = m_SH4_TCNT2;
+ tcr = m_tcr2;
+ tcnt = m_tcnt2;
break;
}
@@ -65,15 +64,15 @@ TIMER_CALLBACK_MEMBER( sh34_base_device::sh4_timer_callback )
switch (which)
{
case 0:
- m_SH4_TCNT0 = m_SH4_TCOR0;
+ m_tcnt0 = m_tcor0;
break;
case 1:
- m_SH4_TCNT1 = m_SH4_TCOR1;
+ m_tcnt1 = m_tcor1;
break;
case 2:
- m_SH4_TCNT2 = m_SH4_TCOR2;
+ m_tcnt2 = m_tcor2;
break;
}
@@ -83,15 +82,15 @@ TIMER_CALLBACK_MEMBER( sh34_base_device::sh4_timer_callback )
switch (which)
{
case 0:
- m_SH4_TCR0 |= 0x100;
+ m_tcr0 |= 0x100;
break;
case 1:
- m_SH4_TCR1 |= 0x100;
+ m_tcr1 |= 0x100;
break;
case 2:
- m_SH4_TCR2 |= 0x100;
+ m_tcr2 |= 0x100;
break;
}
@@ -99,7 +98,7 @@ TIMER_CALLBACK_MEMBER( sh34_base_device::sh4_timer_callback )
switch (which)
{
case 0:
- if (m_SH4_TCR0 & 0x20)
+ if (m_tcr0 & 0x20)
{
sh4_exception_request(SH4_INTC_TUNI0);
// logerror("SH4_INTC_TUNI0 requested\n");
@@ -107,7 +106,7 @@ TIMER_CALLBACK_MEMBER( sh34_base_device::sh4_timer_callback )
break;
case 1:
- if (m_SH4_TCR1 & 0x20)
+ if (m_tcr1 & 0x20)
{
sh4_exception_request(SH4_INTC_TUNI1);
// logerror("SH4_INTC_TUNI1 requested\n");
@@ -115,7 +114,7 @@ TIMER_CALLBACK_MEMBER( sh34_base_device::sh4_timer_callback )
break;
case 2:
- if (m_SH4_TCR2 & 0x20)
+ if (m_tcr2 & 0x20)
{
sh4_exception_request(SH4_INTC_TUNI2);
// logerror("SH4_INTC_TUNI2 requested\n");
@@ -125,200 +124,196 @@ TIMER_CALLBACK_MEMBER( sh34_base_device::sh4_timer_callback )
}
}
-
-uint32_t sh34_base_device::sh4_handle_tcnt0_addr_r(uint32_t mem_mask)
+void sh34_base_device::tocr_w(offs_t offset, uint8_t data, uint8_t mem_mask)
{
- if (m_SH4_TSTR & 1)
- return compute_ticks_timer(m_timer[0], m_pm_clock, tcnt_div[m_SH4_TCR0 & 7]);
- else
- return m_SH4_TCNT0;
+ COMBINE_DATA(&m_tocr);
}
-uint32_t sh34_base_device::sh4_handle_tcnt1_addr_r(uint32_t mem_mask)
+uint8_t sh34_base_device::tocr_r(offs_t offset, uint8_t mem_mask)
{
- if (m_SH4_TSTR & 2)
- return compute_ticks_timer(m_timer[1], m_pm_clock, tcnt_div[m_SH4_TCR1 & 7]);
- else
- return m_SH4_TCNT1;
+ return m_tocr;
}
-uint32_t sh34_base_device::sh4_handle_tcnt2_addr_r(uint32_t mem_mask)
+uint8_t sh34_base_device::tstr_r(offs_t offset, uint8_t mem_mask)
{
- if (m_SH4_TSTR & 4)
- return compute_ticks_timer(m_timer[2], m_pm_clock, tcnt_div[m_SH4_TCR2 & 7]);
- else
- return m_SH4_TCNT2;
+ return m_tstr;
}
-uint32_t sh34_base_device::sh4_handle_tcor0_addr_r(uint32_t mem_mask)
+void sh34_base_device::tstr_w(offs_t offset, uint8_t data, uint8_t mem_mask)
{
- return m_SH4_TCOR0;
+ uint32_t chg = m_tstr;
+ COMBINE_DATA(&m_tstr);
+ chg ^= m_tstr;
+
+ if (chg & 1)
+ {
+ if ((m_tstr & 1) == 0)
+ {
+ m_tcnt0 = compute_ticks_timer(m_timer[0], m_pm_clock, tcnt_div[m_tcr0 & 7]);
+ m_timer[0]->adjust(attotime::never);
+ }
+ else
+ sh4_timer_recompute(0);
+ }
+
+ if (chg & 2)
+ {
+ if ((m_tstr & 2) == 0)
+ {
+ m_tcnt1 = compute_ticks_timer(m_timer[1], m_pm_clock, tcnt_div[m_tcr1 & 7]);
+ m_timer[1]->adjust(attotime::never);
+ }
+ else
+ sh4_timer_recompute(1);
+ }
+
+ if (chg & 4)
+ {
+ if ((m_tstr & 4) == 0)
+ {
+ m_tcnt2 = compute_ticks_timer(m_timer[2], m_pm_clock, tcnt_div[m_tcr2 & 7]);
+ m_timer[2]->adjust(attotime::never);
+ }
+ else
+ sh4_timer_recompute(2);
+ }
}
-uint32_t sh34_base_device::sh4_handle_tcor1_addr_r(uint32_t mem_mask)
+uint32_t sh34_base_device::tcor0_r(offs_t offset, uint32_t mem_mask)
{
- return m_SH4_TCOR1;
+ return m_tcor0;
}
-uint32_t sh34_base_device::sh4_handle_tcor2_addr_r(uint32_t mem_mask)
+void sh34_base_device::tcor0_w(offs_t offset, uint32_t data, uint32_t mem_mask)
{
- return m_SH4_TCOR2;
+ COMBINE_DATA(&m_tcor0);
}
-uint32_t sh34_base_device::sh4_handle_tcr0_addr_r(uint32_t mem_mask)
+uint32_t sh34_base_device::tcnt0_r(offs_t offset, uint32_t mem_mask)
{
- return m_SH4_TCR0;
+ if (m_tstr & 1)
+ return compute_ticks_timer(m_timer[0], m_pm_clock, tcnt_div[m_tcr0 & 7]);
+ else
+ return m_tcnt0;
}
-uint32_t sh34_base_device::sh4_handle_tcr1_addr_r(uint32_t mem_mask)
+void sh34_base_device::tcnt0_w(offs_t offset, uint32_t data, uint32_t mem_mask)
{
- return m_SH4_TCR1;
+ COMBINE_DATA(&m_tcnt0);
+ if (m_tstr & 1)
+ sh4_timer_recompute(0);
}
-uint32_t sh34_base_device::sh4_handle_tcr2_addr_r(uint32_t mem_mask)
+uint16_t sh34_base_device::tcr0_r(offs_t offset, uint16_t mem_mask)
{
- return m_SH4_TCR2;
+ return m_tcr0;
}
-uint32_t sh34_base_device::sh4_handle_tstr_addr_r(uint32_t mem_mask)
+void sh34_base_device::tcr0_w(offs_t offset, uint16_t data, uint16_t mem_mask)
{
- return m_SH4_TSTR;
+ uint32_t old2 = m_tcr0;
+ COMBINE_DATA(&m_tcr0);
+ if (m_tstr & 1)
+ {
+ m_tcnt0 = compute_ticks_timer(m_timer[0], m_pm_clock, tcnt_div[old2 & 7]);
+ sh4_timer_recompute(0);
+ }
+ if (!(m_tcr0 & 0x20) || !(m_tcr0 & 0x100))
+ sh4_exception_unrequest(SH4_INTC_TUNI0);
}
-uint32_t sh34_base_device::sh4_handle_tocr_addr_r(uint32_t mem_mask)
+uint32_t sh34_base_device::tcor1_r(offs_t offset, uint32_t mem_mask)
{
- return m_SH4_TOCR;
+ return m_tcor1;
}
-uint32_t sh34_base_device::sh4_handle_tcpr2_addr_r(uint32_t mem_mask)
+void sh34_base_device::tcor1_w(offs_t offset, uint32_t data, uint32_t mem_mask)
{
- return m_SH4_TCPR2;
+ COMBINE_DATA(&m_tcor1);
}
-
-void sh34_base_device::sh4_handle_tstr_addr_w(uint32_t data, uint32_t mem_mask)
+uint32_t sh34_base_device::tcnt1_r(offs_t offset, uint32_t mem_mask)
{
- uint32_t old2 = m_SH4_TSTR;
- COMBINE_DATA(&m_SH4_TSTR);
-
- if (old2 & 1)
- m_SH4_TCNT0 = compute_ticks_timer(m_timer[0], m_pm_clock, tcnt_div[m_SH4_TCR0 & 7]);
- if ((m_SH4_TSTR & 1) == 0) {
- m_timer[0]->adjust(attotime::never);
- } else
- sh4_timer_recompute(0);
+ if (m_tstr & 2)
+ return compute_ticks_timer(m_timer[1], m_pm_clock, tcnt_div[m_tcr1 & 7]);
+ else
+ return m_tcnt1;
+}
- if (old2 & 2)
- m_SH4_TCNT1 = compute_ticks_timer(m_timer[1], m_pm_clock, tcnt_div[m_SH4_TCR1 & 7]);
- if ((m_SH4_TSTR & 2) == 0) {
- m_timer[1]->adjust(attotime::never);
- } else
+void sh34_base_device::tcnt1_w(offs_t offset, uint32_t data, uint32_t mem_mask)
+{
+ COMBINE_DATA(&m_tcnt1);
+ if (m_tstr & 2)
sh4_timer_recompute(1);
-
- if (old2 & 4)
- m_SH4_TCNT2 = compute_ticks_timer(m_timer[2], m_pm_clock, tcnt_div[m_SH4_TCR2 & 7]);
- if ((m_SH4_TSTR & 4) == 0) {
- m_timer[2]->adjust(attotime::never);
- } else
- sh4_timer_recompute(2);
}
-void sh34_base_device::sh4_handle_tcr0_addr_w(uint32_t data, uint32_t mem_mask)
+uint16_t sh34_base_device::tcr1_r(offs_t offset, uint16_t mem_mask)
{
- uint32_t old2 = m_SH4_TCR0;
- COMBINE_DATA(&m_SH4_TCR0);
- if (m_SH4_TSTR & 1)
- {
- m_SH4_TCNT0 = compute_ticks_timer(m_timer[0], m_pm_clock, tcnt_div[old2 & 7]);
- sh4_timer_recompute(0);
- }
- if (!(m_SH4_TCR0 & 0x20) || !(m_SH4_TCR0 & 0x100))
- sh4_exception_unrequest(SH4_INTC_TUNI0);
+ return m_tcr1;
}
-void sh34_base_device::sh4_handle_tcr1_addr_w(uint32_t data, uint32_t mem_mask)
+void sh34_base_device::tcr1_w(offs_t offset, uint16_t data, uint16_t mem_mask)
{
- uint32_t old2 = m_SH4_TCR1;
- COMBINE_DATA(&m_SH4_TCR1);
- if (m_SH4_TSTR & 2)
+ uint32_t old2 = m_tcr1;
+ COMBINE_DATA(&m_tcr1);
+ if (m_tstr & 2)
{
- m_SH4_TCNT1 = compute_ticks_timer(m_timer[1], m_pm_clock, tcnt_div[old2 & 7]);
+ m_tcnt1 = compute_ticks_timer(m_timer[1], m_pm_clock, tcnt_div[old2 & 7]);
sh4_timer_recompute(1);
}
- if (!(m_SH4_TCR1 & 0x20) || !(m_SH4_TCR1 & 0x100))
+ if (!(m_tcr1 & 0x20) || !(m_tcr1 & 0x100))
sh4_exception_unrequest(SH4_INTC_TUNI1);
}
-void sh34_base_device::sh4_handle_tcr2_addr_w(uint32_t data, uint32_t mem_mask)
+uint32_t sh34_base_device::tcor2_r(offs_t offset, uint32_t mem_mask)
{
- uint32_t old2 = m_SH4_TCR2;
- COMBINE_DATA(&m_SH4_TCR2);
- if (m_SH4_TSTR & 4)
- {
- m_SH4_TCNT2 = compute_ticks_timer(m_timer[2], m_pm_clock, tcnt_div[old2 & 7]);
- sh4_timer_recompute(2);
- }
- if (!(m_SH4_TCR2 & 0x20) || !(m_SH4_TCR2 & 0x100))
- sh4_exception_unrequest(SH4_INTC_TUNI2);
+ return m_tcor2;
}
-void sh34_base_device::sh4_handle_tcor0_addr_w(uint32_t data, uint32_t mem_mask)
+void sh34_base_device::tcor2_w(offs_t offset, uint32_t data, uint32_t mem_mask)
{
- COMBINE_DATA(&m_SH4_TCOR0);
- if (m_SH4_TSTR & 1)
- {
- m_SH4_TCNT0 = compute_ticks_timer(m_timer[0], m_pm_clock, tcnt_div[m_SH4_TCR0 & 7]);
- sh4_timer_recompute(0);
- }
+ COMBINE_DATA(&m_tcor2);
}
-void sh34_base_device::sh4_handle_tcor1_addr_w(uint32_t data, uint32_t mem_mask)
+uint32_t sh34_base_device::tcnt2_r(offs_t offset, uint32_t mem_mask)
{
- COMBINE_DATA(&m_SH4_TCOR1);
- if (m_SH4_TSTR & 2)
- {
- m_SH4_TCNT1 = compute_ticks_timer(m_timer[1], m_pm_clock, tcnt_div[m_SH4_TCR1 & 7]);
- sh4_timer_recompute(1);
- }
+ if (m_tstr & 4)
+ return compute_ticks_timer(m_timer[2], m_pm_clock, tcnt_div[m_tcr2 & 7]);
+ else
+ return m_tcnt2;
}
-void sh34_base_device::sh4_handle_tcor2_addr_w(uint32_t data, uint32_t mem_mask)
+void sh34_base_device::tcnt2_w(offs_t offset, uint32_t data, uint32_t mem_mask)
{
- COMBINE_DATA(&m_SH4_TCOR2);
- if (m_SH4_TSTR & 4)
- {
- m_SH4_TCNT2 = compute_ticks_timer(m_timer[2], m_pm_clock, tcnt_div[m_SH4_TCR2 & 7]);
+ COMBINE_DATA(&m_tcnt2);
+ if (m_tstr & 4)
sh4_timer_recompute(2);
- }
-}
-
-void sh34_base_device::sh4_handle_tcnt0_addr_w(uint32_t data, uint32_t mem_mask)
-{
- COMBINE_DATA(&m_SH4_TCNT0);
- if (m_SH4_TSTR & 1)
- sh4_timer_recompute(0);
}
-void sh34_base_device::sh4_handle_tcnt1_addr_w(uint32_t data, uint32_t mem_mask)
+uint16_t sh34_base_device::tcr2_r(offs_t offset, uint16_t mem_mask)
{
- COMBINE_DATA(&m_SH4_TCNT1);
- if (m_SH4_TSTR & 2)
- sh4_timer_recompute(1);
+ return m_tcr2;
}
-void sh34_base_device::sh4_handle_tcnt2_addr_w(uint32_t data, uint32_t mem_mask)
+void sh34_base_device::tcr2_w(offs_t offset, uint16_t data, uint16_t mem_mask)
{
- COMBINE_DATA(&m_SH4_TCNT2);
- if (m_SH4_TSTR & 4)
+ uint32_t old2 = m_tcr2;
+ COMBINE_DATA(&m_tcr2);
+ if (m_tstr & 4)
+ {
+ m_tcnt2 = compute_ticks_timer(m_timer[2], m_pm_clock, tcnt_div[old2 & 7]);
sh4_timer_recompute(2);
+ }
+ if (!(m_tcr2 & 0x20) || !(m_tcr2 & 0x100))
+ sh4_exception_unrequest(SH4_INTC_TUNI2);
}
-void sh34_base_device::sh4_handle_tocr_addr_w(uint32_t data, uint32_t mem_mask)
+uint32_t sh34_base_device::tcpr2_r(offs_t offset, uint32_t mem_mask)
{
- COMBINE_DATA(&m_SH4_TOCR);
+ return m_tcpr2;
}
-void sh34_base_device::sh4_handle_tcpr2_addr_w(uint32_t data, uint32_t mem_mask)
+void sh34_base_device::tcpr2_w(offs_t offset, uint32_t data, uint32_t mem_mask)
{
- COMBINE_DATA(&m_SH4_TCPR2);
+ COMBINE_DATA(&m_tcpr2);
}
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);
+}
diff --git a/src/devices/cpu/sh/sh7014.h b/src/devices/cpu/sh/sh7014.h
new file mode 100644
index 00000000000..8999558b6ef
--- /dev/null
+++ b/src/devices/cpu/sh/sh7014.h
@@ -0,0 +1,83 @@
+// license:BSD-3-Clause
+// copyright-holders:windyfairy
+/***************************************************************************
+
+ SH-2 SH7014
+
+***************************************************************************/
+
+#ifndef MAME_CPU_SH_SH7014_H
+#define MAME_CPU_SH_SH7014_H
+
+#pragma once
+
+#include "sh2.h"
+#include "sh7014_bsc.h"
+#include "sh7014_dmac.h"
+#include "sh7014_intc.h"
+#include "sh7014_mtu.h"
+#include "sh7014_port.h"
+#include "sh7014_sci.h"
+
+class sh7014_device : public sh2_device
+{
+public:
+ sh7014_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+ template<int Sci> auto sci_tx_w() {
+ return m_sci[Sci].lookup()->write_sci_tx();
+ }
+
+ template<int Sci> void sci_set_external_clock_period(const attotime &period) {
+ m_sci[Sci].lookup()->set_external_clock_period(period);
+ }
+
+ template<int Sci> void sci_set_send_full_data_transmit_on_sync_hack(bool enabled) {
+ m_sci[Sci].lookup()->set_send_full_data_transmit_on_sync_hack(enabled);
+ }
+
+ auto read_porta() { return m_port.lookup()->port_a_read_callback(); }
+ auto write_porta() { return m_port.lookup()->port_a_write_callback(); }
+
+ auto read_portb() { return m_port.lookup()->port_b_read_callback(); }
+ auto write_portb() { return m_port.lookup()->port_b_write_callback(); }
+
+ auto read_porte() { return m_port.lookup()->port_e_read_callback(); }
+ auto write_porte() { return m_port.lookup()->port_e_write_callback(); }
+
+ auto read_portf() { return m_port.lookup()->port_f_read_callback(); }
+
+protected:
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+
+ virtual void execute_set_input(int inputnum, int state) override;
+
+ virtual void sh2_exception_internal(const char *message, int irqline, int vector) override;
+
+private:
+ void sh7014_map(address_map &map) ATTR_COLD;
+
+ void set_irq(int vector, int level, bool is_internal);
+
+ void notify_dma_source(uint32_t source);
+
+ uint16_t ccr_r();
+ void ccr_w(offs_t offset, uint16_t dat, uint16_t mem_mask = ~0);
+
+ required_device_array<sh7014_sci_device, 2> m_sci;
+ required_device<sh7014_bsc_device> m_bsc;
+ required_device<sh7014_dmac_device> m_dmac;
+ required_device<sh7014_intc_device> m_intc;
+ required_device<sh7014_mtu_device> m_mtu;
+ required_device<sh7014_port_device> m_port;
+
+ devcb_write_line::array<2> m_sci_tx_cb;
+
+ uint16_t m_ccr;
+};
+
+DECLARE_DEVICE_TYPE(SH7014, sh7014_device)
+
+#endif // MAME_CPU_SH_SH7014_H
diff --git a/src/devices/cpu/sh/sh7014_bsc.cpp b/src/devices/cpu/sh/sh7014_bsc.cpp
new file mode 100644
index 00000000000..c0014cea17b
--- /dev/null
+++ b/src/devices/cpu/sh/sh7014_bsc.cpp
@@ -0,0 +1,148 @@
+// license:BSD-3-Clause
+// copyright-holders:windyfairy
+/***************************************************************************
+
+ SH7014 Bus State Controller
+
+***************************************************************************/
+
+#include "emu.h"
+#include "sh7014_bsc.h"
+
+// #define VERBOSE (LOG_GENERAL)
+
+#include "logmacro.h"
+
+
+DEFINE_DEVICE_TYPE(SH7014_BSC, sh7014_bsc_device, "sh7014bsc", "SH7014 Bus State Controller")
+
+
+sh7014_bsc_device::sh7014_bsc_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : device_t(mconfig, SH7014_BSC, tag, owner, clock)
+{
+}
+
+void sh7014_bsc_device::device_start()
+{
+ save_item(NAME(m_bcr1));
+ save_item(NAME(m_bcr2));
+ save_item(NAME(m_wcr1));
+ save_item(NAME(m_wcr2));
+ save_item(NAME(m_dcr));
+ save_item(NAME(m_rtcsr));
+ save_item(NAME(m_rtcnt));
+ save_item(NAME(m_rtcor));
+}
+
+void sh7014_bsc_device::device_reset()
+{
+ m_bcr1 = 0;
+ m_bcr2 = 0xffff;
+ m_wcr1 = 0xffff;
+ m_wcr2 = 0x000f;
+ m_dcr = 0;
+ m_rtcsr = 0;
+ m_rtcnt = 0;
+ m_rtcor = 0;
+}
+
+void sh7014_bsc_device::map(address_map &map)
+{
+ map(0x00, 0x01).rw(FUNC(sh7014_bsc_device::bcr1_r), FUNC(sh7014_bsc_device::bcr1_w));
+ map(0x02, 0x03).rw(FUNC(sh7014_bsc_device::bcr2_r), FUNC(sh7014_bsc_device::bcr2_w));
+ map(0x04, 0x05).rw(FUNC(sh7014_bsc_device::wcr1_r), FUNC(sh7014_bsc_device::wcr1_w));
+ map(0x06, 0x07).rw(FUNC(sh7014_bsc_device::wcr2_r), FUNC(sh7014_bsc_device::wcr2_w));
+ map(0x0a, 0x0b).rw(FUNC(sh7014_bsc_device::dcr_r), FUNC(sh7014_bsc_device::dcr_w));
+ map(0x0c, 0x0d).rw(FUNC(sh7014_bsc_device::rtcsr_r), FUNC(sh7014_bsc_device::rtcsr_w));
+ map(0x0e, 0x0f).rw(FUNC(sh7014_bsc_device::rtcnt_r), FUNC(sh7014_bsc_device::rtcnt_w));
+ map(0x10, 0x11).rw(FUNC(sh7014_bsc_device::rtcor_r), FUNC(sh7014_bsc_device::rtcor_w));
+}
+
+///
+
+uint16_t sh7014_bsc_device::bcr1_r()
+{
+ // bit 0 [R/W] CS0 Space Size Specification (A0SZ)
+ // bit 1 [R/W] CS1 Space Size Specification (A1SZ)
+ // bit 2 [R/W] CS2 Space Size Specification (A2SZ)
+ // bit 3 [R/W] CS3 Space Size Specification (A3SZ)
+ // bit 8 [R/W] Multiplex I/O Enable (IOE)
+ // bit 13 [R] Always returns 1
+ // Everything else is read-only and will return 0
+ return (m_bcr1 & 0x10f) | (1 << 13);
+}
+
+void sh7014_bsc_device::bcr1_w(offs_t offset, uint16_t data, uint16_t mem_mask)
+{
+ COMBINE_DATA(&m_bcr1);
+}
+
+uint16_t sh7014_bsc_device::bcr2_r()
+{
+ return m_bcr2;
+}
+
+void sh7014_bsc_device::bcr2_w(offs_t offset, uint16_t data, uint16_t mem_mask)
+{
+ COMBINE_DATA(&m_bcr2);
+}
+
+uint16_t sh7014_bsc_device::wcr1_r()
+{
+ return m_wcr1;
+}
+
+void sh7014_bsc_device::wcr1_w(offs_t offset, uint16_t data, uint16_t mem_mask)
+{
+ COMBINE_DATA(&m_wcr1);
+}
+
+uint16_t sh7014_bsc_device::wcr2_r()
+{
+ return m_wcr2 & 0x3ff;
+}
+
+void sh7014_bsc_device::wcr2_w(offs_t offset, uint16_t data, uint16_t mem_mask)
+{
+ COMBINE_DATA(&m_wcr2);
+}
+
+uint16_t sh7014_bsc_device::dcr_r()
+{
+ return m_dcr & ~0x48;
+}
+
+void sh7014_bsc_device::dcr_w(offs_t offset, uint16_t data, uint16_t mem_mask)
+{
+ COMBINE_DATA(&m_dcr);
+}
+
+uint16_t sh7014_bsc_device::rtcsr_r()
+{
+ return m_rtcsr & 0x7f;
+}
+
+void sh7014_bsc_device::rtcsr_w(offs_t offset, uint16_t data, uint16_t mem_mask)
+{
+ COMBINE_DATA(&m_rtcsr);
+}
+
+uint16_t sh7014_bsc_device::rtcnt_r()
+{
+ return m_rtcnt & 0xff;
+}
+
+void sh7014_bsc_device::rtcnt_w(offs_t offset, uint16_t data, uint16_t mem_mask)
+{
+ COMBINE_DATA(&m_rtcnt);
+}
+
+uint16_t sh7014_bsc_device::rtcor_r()
+{
+ return m_rtcor & 0xff;
+}
+
+void sh7014_bsc_device::rtcor_w(offs_t offset, uint16_t data, uint16_t mem_mask)
+{
+ COMBINE_DATA(&m_rtcor);
+}
diff --git a/src/devices/cpu/sh/sh7014_bsc.h b/src/devices/cpu/sh/sh7014_bsc.h
new file mode 100644
index 00000000000..0a2f77df123
--- /dev/null
+++ b/src/devices/cpu/sh/sh7014_bsc.h
@@ -0,0 +1,62 @@
+// license:BSD-3-Clause
+// copyright-holders:windyfairy
+/***************************************************************************
+
+ SH7014 Bus State Controller
+
+***************************************************************************/
+
+#ifndef MAME_CPU_SH_SH7014_BSC_H
+#define MAME_CPU_SH_SH7014_BSC_H
+
+#pragma once
+
+
+class sh7014_bsc_device : public device_t
+{
+public:
+ sh7014_bsc_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock = 0);
+
+ void map(address_map &map) ATTR_COLD;
+
+protected:
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+
+private:
+ uint16_t bcr1_r();
+ void bcr1_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0);
+
+ uint16_t bcr2_r();
+ void bcr2_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0);
+
+ uint16_t wcr1_r();
+ void wcr1_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0);
+
+ uint16_t wcr2_r();
+ void wcr2_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0);
+
+ uint16_t dcr_r();
+ void dcr_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0);
+
+ uint16_t rtcsr_r();
+ void rtcsr_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0);
+
+ uint16_t rtcor_r();
+ void rtcor_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0);
+
+ uint16_t rtcnt_r();
+ void rtcnt_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0);
+
+ uint16_t m_bcr1, m_bcr2;
+ uint16_t m_wcr1, m_wcr2;
+ uint16_t m_dcr;
+ uint16_t m_rtcsr;
+ uint16_t m_rtcnt;
+ uint16_t m_rtcor;
+};
+
+
+DECLARE_DEVICE_TYPE(SH7014_BSC, sh7014_bsc_device)
+
+#endif // MAME_CPU_SH_SH7014_BSC_H
diff --git a/src/devices/cpu/sh/sh7014_dmac.cpp b/src/devices/cpu/sh/sh7014_dmac.cpp
new file mode 100644
index 00000000000..5dcb02304e6
--- /dev/null
+++ b/src/devices/cpu/sh/sh7014_dmac.cpp
@@ -0,0 +1,400 @@
+// license:BSD-3-Clause
+// copyright-holders:windyfairy
+/***************************************************************************
+
+ SH7014 Direct Memory Access Controller
+
+ TODO list (not comprehensive):
+ - Channel priority
+ - External dual and single address modes
+ - DREQ, DACK, DRAK pins
+
+***************************************************************************/
+
+#include "emu.h"
+#include "sh7014_dmac.h"
+
+#define LOG_TX (1U << 1)
+
+// #define VERBOSE (LOG_GENERAL | LOG_TX)
+
+#include "logmacro.h"
+
+
+DEFINE_DEVICE_TYPE(SH7014_DMAC, sh7014_dmac_device, "sh7014dmac", "SH7014 Direct Memory Access Controller")
+DEFINE_DEVICE_TYPE(SH7014_DMAC_CHANNEL, sh7014_dmac_channel_device, "sh7014dmacchan", "SH7014 Direct Memory Access Controller Channel")
+
+
+sh7014_dmac_device::sh7014_dmac_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : device_t(mconfig, SH7014_DMAC, tag, owner, clock)
+ , m_cpu(*this, finder_base::DUMMY_TAG)
+ , m_intc(*this, finder_base::DUMMY_TAG)
+ , m_chan(*this, "ch%u", 0u)
+{
+}
+
+void sh7014_dmac_device::device_start()
+{
+ save_item(NAME(m_dmaor));
+}
+
+void sh7014_dmac_device::device_reset()
+{
+ m_dmaor = 0;
+}
+
+void sh7014_dmac_device::device_add_mconfig(machine_config &config)
+{
+ SH7014_DMAC_CHANNEL(config, m_chan[0], DERIVED_CLOCK(1, 1), *this, m_cpu, m_intc,
+ 0, // channel
+ sh7014_intc_device::INT_VECTOR_DMA_CH0
+ );
+
+ SH7014_DMAC_CHANNEL(config, m_chan[1], DERIVED_CLOCK(1, 1), *this, m_cpu, m_intc,
+ 1, // channel
+ sh7014_intc_device::INT_VECTOR_DMA_CH1
+ );
+}
+
+void sh7014_dmac_device::map(address_map &map)
+{
+ map(0x00, 0x01).rw(FUNC(sh7014_dmac_device::dmaor_r), FUNC(sh7014_dmac_device::dmaor_w));
+ map(0x10, 0x1f).m(m_chan[0], FUNC(sh7014_dmac_channel_device::map));
+ map(0x20, 0x2f).m(m_chan[1], FUNC(sh7014_dmac_channel_device::map));
+}
+
+///
+
+uint16_t sh7014_dmac_device::dmaor_r()
+{
+ return m_dmaor & 7;
+}
+
+void sh7014_dmac_device::dmaor_w(uint16_t data)
+{
+ m_dmaor = (data & ~6) | (m_dmaor & data & 6);
+ m_chan[0]->dma_check();
+ m_chan[1]->dma_check();
+}
+
+bool sh7014_dmac_device::is_transfer_allowed()
+{
+ const bool is_enabled = (m_dmaor & DMAOR_DME) != 0;
+ const bool has_address_error = (m_dmaor & DMAOR_AE) != 0;
+ const bool has_nmi_flag = (m_dmaor & DMAOR_NMIF) != 0;
+ return is_enabled && !has_nmi_flag && !has_address_error;
+}
+
+int sh7014_dmac_device::is_dma_activated(int vector)
+{
+ int activated = 0;
+
+ if (!is_transfer_allowed())
+ return 0;
+
+ if (m_chan[0]->is_dma_activated(vector))
+ activated |= 1;
+ if (m_chan[1]->is_dma_activated(vector))
+ activated |= 2;
+
+ return activated;
+}
+
+
+//////////////////
+
+
+void sh7014_dmac_channel_device::map(address_map &map)
+{
+ map(0x00, 0x03).rw(FUNC(sh7014_dmac_channel_device::sar_r), FUNC(sh7014_dmac_channel_device::sar_w));
+ map(0x04, 0x07).rw(FUNC(sh7014_dmac_channel_device::dar_r), FUNC(sh7014_dmac_channel_device::dar_w));
+ map(0x08, 0x0b).rw(FUNC(sh7014_dmac_channel_device::dmatcr_r), FUNC(sh7014_dmac_channel_device::dmatcr_w));
+ map(0x0c, 0x0f).rw(FUNC(sh7014_dmac_channel_device::chcr_r), FUNC(sh7014_dmac_channel_device::chcr_w));
+}
+
+sh7014_dmac_channel_device::sh7014_dmac_channel_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : device_t(mconfig, SH7014_DMAC_CHANNEL, tag, owner, clock)
+ , m_dmac(*this, finder_base::DUMMY_TAG)
+ , m_cpu(*this, finder_base::DUMMY_TAG)
+ , m_intc(*this, finder_base::DUMMY_TAG)
+ , m_notify_dma_source_cb(*this)
+{
+}
+
+void sh7014_dmac_channel_device::device_start()
+{
+ save_item(NAME(m_sar));
+ save_item(NAME(m_dar));
+ save_item(NAME(m_dmatcr));
+ save_item(NAME(m_chcr));
+
+ save_item(NAME(m_dma_timer_active));
+ save_item(NAME(m_active_dma_addr_mode_source));
+ save_item(NAME(m_active_dma_addr_mode_dest));
+ save_item(NAME(m_active_dma_unit_size));
+ save_item(NAME(m_active_dma_is_burst));
+
+ save_item(NAME(m_selected_resource));
+ save_item(NAME(m_request_source_type));
+ save_item(NAME(m_expected_irq_vector));
+
+ m_dma_current_active_timer = timer_alloc(FUNC(sh7014_dmac_channel_device::dma_timer_callback), this);
+}
+
+void sh7014_dmac_channel_device::device_reset()
+{
+ m_sar = m_dar = 0;
+ m_dmatcr = 0;
+ m_chcr = 0;
+
+ m_dma_timer_active = false;
+ m_active_dma_addr_mode_source = 0;
+ m_active_dma_addr_mode_dest = 0;
+ m_active_dma_unit_size = 1;
+ m_active_dma_is_burst = false;
+
+ m_selected_resource = RS_EXTERNAL_DUAL_ADDR;
+ m_request_source_type = RS_TYPE_EXTERNAL_DUAL;
+ m_expected_irq_vector = -1;
+
+ m_dma_current_active_timer->adjust(attotime::never);
+}
+
+///
+
+bool sh7014_dmac_channel_device::is_enabled()
+{
+ return (m_chcr & CHCR_DE) != 0;
+}
+
+uint32_t sh7014_dmac_channel_device::sar_r()
+{
+ return m_sar;
+}
+
+void sh7014_dmac_channel_device::sar_w(offs_t offset, uint32_t data, uint32_t mem_mask)
+{
+ COMBINE_DATA(&m_sar);
+}
+
+uint32_t sh7014_dmac_channel_device::dar_r()
+{
+ return m_dar;
+}
+
+void sh7014_dmac_channel_device::dar_w(offs_t offset, uint32_t data, uint32_t mem_mask)
+{
+ COMBINE_DATA(&m_dar);
+}
+
+uint32_t sh7014_dmac_channel_device::dmatcr_r()
+{
+ return m_dmatcr & 0xffff;
+}
+
+void sh7014_dmac_channel_device::dmatcr_w(offs_t offset, uint32_t data, uint32_t mem_mask)
+{
+ COMBINE_DATA(&m_dmatcr);
+ m_dmatcr &= 0xffff;
+}
+
+uint32_t sh7014_dmac_channel_device::chcr_r()
+{
+ return m_chcr & 0xbff7f;
+}
+
+void sh7014_dmac_channel_device::chcr_w(offs_t offset, uint32_t data, uint32_t mem_mask)
+{
+ COMBINE_DATA(&m_chcr);
+
+ m_selected_resource = BIT(m_chcr, 8, 4);
+ m_expected_irq_vector = -1;
+
+ switch (m_selected_resource) {
+ case RS_MTU_TGI0A:
+ m_request_source_type = RS_TYPE_INTERNAL;
+ m_expected_irq_vector = sh7014_intc_device::INT_VECTOR_MTU_TGI0A;
+ break;
+ case RS_MTU_TGI1A:
+ m_request_source_type = RS_TYPE_INTERNAL;
+ m_expected_irq_vector = sh7014_intc_device::INT_VECTOR_MTU_TGI1A;
+ break;
+ case RS_MTU_TGI2A:
+ m_request_source_type = RS_TYPE_INTERNAL;
+ m_expected_irq_vector = sh7014_intc_device::INT_VECTOR_MTU_TGI2A;
+ break;
+ case RS_AD:
+ m_request_source_type = RS_TYPE_INTERNAL;
+ m_expected_irq_vector = sh7014_intc_device::INT_VECTOR_AD;
+ break;
+ case RS_SCI_TXI0:
+ m_request_source_type = RS_TYPE_INTERNAL;
+ m_expected_irq_vector = sh7014_intc_device::INT_VECTOR_SCI_TXI0;
+ break;
+ case RS_SCI_RXI0:
+ m_request_source_type = RS_TYPE_INTERNAL;
+ m_expected_irq_vector = sh7014_intc_device::INT_VECTOR_SCI_RXI0;
+ break;
+ case RS_SCI_TXI1:
+ m_request_source_type = RS_TYPE_INTERNAL;
+ m_expected_irq_vector = sh7014_intc_device::INT_VECTOR_SCI_TXI1;
+ break;
+ case RS_SCI_RXI1:
+ m_request_source_type = RS_TYPE_INTERNAL;
+ m_expected_irq_vector = sh7014_intc_device::INT_VECTOR_SCI_RXI1;
+ break;
+
+ case RS_AUTO_REQUEST:
+ m_request_source_type = RS_TYPE_AUTO;
+ break;
+
+ case RS_EXTERNAL_DUAL_ADDR:
+ m_request_source_type = RS_TYPE_EXTERNAL_DUAL;
+ break;
+
+ case RS_EXTERNAL_SINGLE_ADDR_TO_DEV:
+ case RS_EXTERNAL_SINGLE_DEV_TO_ADDR:
+ m_request_source_type = RS_TYPE_EXTERNAL_SINGLE;
+ break;
+
+ default:
+ m_request_source_type = RS_TYPE_PROHIBITED;
+ break;
+ }
+
+ dma_check();
+}
+
+bool sh7014_dmac_channel_device::is_dma_activated(int vector)
+{
+ if (m_request_source_type != RS_TYPE_INTERNAL || m_expected_irq_vector == -1 || vector != m_expected_irq_vector)
+ return false;
+
+ if (!m_dma_timer_active)
+ dma_check();
+
+ if (!m_dma_timer_active)
+ return false;
+
+ m_dma_current_active_timer->adjust(attotime::from_ticks(2, clock()));
+
+ return true;
+}
+
+TIMER_CALLBACK_MEMBER( sh7014_dmac_channel_device::dma_timer_callback )
+{
+ if (!m_dma_timer_active)
+ return;
+
+ if (!m_dmac->is_transfer_allowed()) {
+ LOG("SH7014: DMA %d transfer aborted\n", m_channel_id);
+ m_dma_timer_active = false;
+ return;
+ }
+
+ LOGMASKED(LOG_TX, "DMAC ch %d remaining %08x size %d | source %08x dest %08x\n", m_channel_id, m_dmatcr, m_active_dma_unit_size, m_sar, m_dar);
+
+ if (m_active_dma_addr_mode_source == DMA_ADDR_MODE_DEC)
+ m_sar -= m_active_dma_unit_size;
+
+ if (m_active_dma_addr_mode_dest == DMA_ADDR_MODE_DEC)
+ m_dar -= m_active_dma_unit_size;
+
+ if (m_request_source_type == RS_TYPE_INTERNAL)
+ m_notify_dma_source_cb(m_selected_resource);
+
+ switch (m_active_dma_unit_size) {
+ case 1:
+ m_cpu->m_program->write_byte(
+ m_dar,
+ m_cpu->m_program->read_byte(m_sar)
+ );
+ break;
+ case 2:
+ m_cpu->m_program->write_word(
+ m_dar,
+ m_cpu->m_program->read_word(m_sar)
+ );
+ break;
+ case 4:
+ m_cpu->m_program->write_dword(
+ m_dar,
+ m_cpu->m_program->read_dword(m_sar)
+ );
+ break;
+ }
+
+ if (m_active_dma_addr_mode_source == DMA_ADDR_MODE_INC)
+ m_sar += m_active_dma_unit_size;
+
+ if (m_active_dma_addr_mode_dest == DMA_ADDR_MODE_INC)
+ m_dar += m_active_dma_unit_size;
+
+ m_dmatcr--;
+
+ if (m_dmatcr <= 0) {
+ LOGMASKED(LOG_TX, "SH7014: DMA %d complete\n", m_channel_id);
+
+ m_dmatcr = 0;
+ m_chcr |= CHCR_TE; // transfer end
+ m_dma_timer_active = false;
+
+ if (m_active_dma_is_burst)
+ m_cpu->resume(SUSPEND_REASON_HALT);
+
+ const auto interrupt_enable = (m_chcr & CHCR_IE) != 0;
+ if (interrupt_enable)
+ m_intc->set_interrupt(m_vector, ASSERT_LINE);
+ } else {
+ // schedule next DMA callback
+ // Internal source transfers in burst mode end on last transfer, otherwise should end after the first transfer when burst mode is off
+ // TODO: DREQ and DACK are needed for external sources instead of being handled like an auto requests
+ if (m_request_source_type != RS_TYPE_INTERNAL || (m_request_source_type == RS_TYPE_INTERNAL && m_active_dma_is_burst))
+ m_dma_current_active_timer->adjust(attotime::from_ticks(2, clock()));
+ }
+}
+
+void sh7014_dmac_channel_device::dma_check()
+{
+ if (!m_dmac->is_transfer_allowed()) {
+ if (m_dma_timer_active) {
+ LOG("SH7014: DMA %d cancelled in-flight\n", m_channel_id);
+ m_dma_current_active_timer->adjust(attotime::never);
+ m_dma_timer_active = false;
+ }
+
+ return;
+ }
+
+ if (m_dma_timer_active)
+ return;
+
+ m_active_dma_addr_mode_dest = BIT(m_chcr, 14, 2); // DM
+ m_active_dma_addr_mode_source = BIT(m_chcr, 12, 2); // SM
+ m_active_dma_unit_size = 1 << BIT(m_chcr, 3, 2); // TS
+ m_active_dma_is_burst = (m_chcr & CHCR_TM) != 0;
+
+ if (m_active_dma_addr_mode_dest == DMA_ADDR_MODE_PROHIBITED || m_active_dma_addr_mode_source == DMA_ADDR_MODE_PROHIBITED || m_active_dma_unit_size > 4) {
+ LOG("SH7014: DMA %d: bad increment values (%d, %d, %d, %04x)\n", m_channel_id, m_active_dma_addr_mode_dest, m_active_dma_addr_mode_source, m_active_dma_unit_size, m_chcr);
+ return;
+ }
+
+ if (m_dmatcr == 0)
+ m_dmatcr = 0x10000;
+
+ m_dma_timer_active = true;
+
+ LOG("SH7014: DMA %d start %x, %x, %x, %04x, %d, %d, %d, %d\n", m_channel_id, m_sar, m_dar, m_dmatcr, m_chcr, m_active_dma_addr_mode_source, m_active_dma_addr_mode_dest, m_active_dma_unit_size, m_active_dma_is_burst);
+
+ if (m_active_dma_unit_size > 1) {
+ const int mask = m_active_dma_unit_size - 1;
+ m_sar &= ~mask;
+ m_dar &= ~mask;
+ }
+
+ if (m_active_dma_is_burst)
+ m_cpu->suspend(SUSPEND_REASON_HALT, 1);
+
+ if (m_request_source_type != RS_TYPE_INTERNAL || (m_request_source_type == RS_TYPE_INTERNAL && m_active_dma_is_burst))
+ m_dma_current_active_timer->adjust(attotime::from_ticks(2, clock()));
+}
diff --git a/src/devices/cpu/sh/sh7014_dmac.h b/src/devices/cpu/sh/sh7014_dmac.h
new file mode 100644
index 00000000000..d44b3414a0d
--- /dev/null
+++ b/src/devices/cpu/sh/sh7014_dmac.h
@@ -0,0 +1,173 @@
+// license:BSD-3-Clause
+// copyright-holders:windyfairy
+/***************************************************************************
+
+ SH7014 Direct Memory Access Controller
+
+***************************************************************************/
+
+#ifndef MAME_CPU_SH_SH7014_DMAC_H
+#define MAME_CPU_SH_SH7014_DMAC_H
+
+#pragma once
+
+#include "sh2.h"
+#include "sh7014_intc.h"
+
+DECLARE_DEVICE_TYPE(SH7014_DMAC, sh7014_dmac_device)
+DECLARE_DEVICE_TYPE(SH7014_DMAC_CHANNEL, sh7014_dmac_channel_device)
+
+class sh7014_dmac_device;
+
+class sh7014_dmac_channel_device : public device_t
+{
+public:
+ enum {
+ RS_EXTERNAL_DUAL_ADDR = 0, // External request, dual address mode
+ RS_EXTERNAL_SINGLE_ADDR_TO_DEV = 2, // External request, single address mode. External address space -> external device
+ RS_EXTERNAL_SINGLE_DEV_TO_ADDR = 3, // External request, single address mode. External device -> external address space
+ RS_AUTO_REQUEST = 4,
+ RS_MTU_TGI0A = 6,
+ RS_MTU_TGI1A = 7,
+ RS_MTU_TGI2A = 8,
+ RS_AD = 11,
+ RS_SCI_TXI0 = 12,
+ RS_SCI_RXI0 = 13,
+ RS_SCI_TXI1 = 14,
+ RS_SCI_RXI1 = 15,
+ };
+
+ sh7014_dmac_channel_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+ template<typename T, typename U, typename V> sh7014_dmac_channel_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock, T &&dmac, U &&cpu, V &&intc, int chan_id, int vector)
+ : sh7014_dmac_channel_device(mconfig, tag, owner, clock)
+ {
+ m_dmac.set_tag(std::forward<T>(dmac));
+ m_cpu.set_tag(std::forward<U>(cpu));
+ m_intc.set_tag(std::forward<V>(intc));
+ m_channel_id = chan_id;
+ m_vector = vector;
+ }
+
+ auto notify_dma_source_callback() { return m_notify_dma_source_cb.bind(); }
+
+ void map(address_map &map) ATTR_COLD;
+
+ void dma_check();
+
+ bool is_dma_activated(int vector);
+
+protected:
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+
+private:
+ enum {
+ RS_TYPE_EXTERNAL_DUAL = 0,
+ RS_TYPE_EXTERNAL_SINGLE,
+ RS_TYPE_AUTO,
+ RS_TYPE_INTERNAL,
+ RS_TYPE_PROHIBITED,
+ };
+
+ enum {
+ DMA_ADDR_MODE_FIXED = 0,
+ DMA_ADDR_MODE_INC,
+ DMA_ADDR_MODE_DEC,
+ DMA_ADDR_MODE_PROHIBITED,
+ };
+
+ enum {
+ CHCR_DE = 1 << 0,
+ CHCR_TE = 1 << 1,
+ CHCR_IE = 1 << 2,
+ CHCR_TM = 1 << 5,
+ };
+
+ bool is_enabled();
+
+ uint32_t sar_r();
+ void sar_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0);
+
+ uint32_t dar_r();
+ void dar_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0);
+
+ uint32_t dmatcr_r();
+ void dmatcr_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0);
+
+ uint32_t chcr_r();
+ void chcr_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0);
+
+ TIMER_CALLBACK_MEMBER( dma_timer_callback );
+
+ required_device<sh7014_dmac_device> m_dmac;
+ required_device<sh2_device> m_cpu;
+ required_device<sh7014_intc_device> m_intc;
+
+ emu_timer *m_dma_current_active_timer;
+
+ devcb_write32 m_notify_dma_source_cb;
+
+ uint32_t m_channel_id;
+ uint32_t m_vector;
+
+ uint32_t m_chcr;
+ uint32_t m_sar;
+ uint32_t m_dar;
+ int32_t m_dmatcr;
+
+ bool m_dma_timer_active;
+ uint32_t m_active_dma_addr_mode_source;
+ uint32_t m_active_dma_addr_mode_dest;
+ uint32_t m_active_dma_unit_size;
+ bool m_active_dma_is_burst;
+
+ int32_t m_request_source_type, m_selected_resource;
+ int32_t m_expected_irq_vector;
+};
+
+class sh7014_dmac_device : public device_t
+{
+public:
+ sh7014_dmac_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+ template<typename T, typename U> sh7014_dmac_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock, T &&cpu, U &&intc)
+ : sh7014_dmac_device(mconfig, tag, owner, clock)
+ {
+ m_cpu.set_tag(std::forward<T>(cpu));
+ m_intc.set_tag(std::forward<U>(intc));
+ }
+
+ template <typename... T> void set_notify_dma_source_callback(T &&... args) {
+ m_chan[0].lookup()->notify_dma_source_callback().set(std::forward<T>(args)...);
+ m_chan[1].lookup()->notify_dma_source_callback().set(std::forward<T>(args)...);
+ }
+
+ void map(address_map &map) ATTR_COLD;
+
+ int is_dma_activated(int vector);
+ bool is_transfer_allowed();
+
+protected:
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+
+private:
+ enum {
+ DMAOR_DME = 1 << 0,
+ DMAOR_NMIF = 1 << 1,
+ DMAOR_AE = 1 << 2,
+ };
+
+ void dmaor_w(uint16_t data);
+ uint16_t dmaor_r();
+
+ required_device<sh2_device> m_cpu;
+ required_device<sh7014_intc_device> m_intc;
+ required_device_array<sh7014_dmac_channel_device, 2> m_chan;
+
+ uint16_t m_dmaor;
+};
+
+#endif // MAME_CPU_SH_SH7014_DMAC_H
diff --git a/src/devices/cpu/sh/sh7014_intc.cpp b/src/devices/cpu/sh/sh7014_intc.cpp
new file mode 100644
index 00000000000..c6f1ea521ad
--- /dev/null
+++ b/src/devices/cpu/sh/sh7014_intc.cpp
@@ -0,0 +1,313 @@
+// license:BSD-3-Clause
+// copyright-holders:windyfairy
+/***************************************************************************
+
+ SH7014 Interrupt Controller
+
+***************************************************************************/
+
+#include "emu.h"
+#include "sh7014_intc.h"
+
+// #define VERBOSE (LOG_GENERAL)
+
+#include "logmacro.h"
+
+
+DEFINE_DEVICE_TYPE(SH7014_INTC, sh7014_intc_device, "sh7014intc", "SH7014 Interrupt Controller")
+
+
+sh7014_intc_device::sh7014_intc_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : device_t(mconfig, SH7014_INTC, tag, owner, clock)
+ , m_set_irq_cb(*this)
+{
+}
+
+void sh7014_intc_device::device_start()
+{
+ m_set_irq_cb.resolve();
+
+ save_item(NAME(m_ipra));
+ save_item(NAME(m_iprb));
+ save_item(NAME(m_iprc));
+ save_item(NAME(m_iprd));
+ save_item(NAME(m_ipre));
+ save_item(NAME(m_iprf));
+ save_item(NAME(m_iprg));
+ save_item(NAME(m_iprh));
+ save_item(NAME(m_icr));
+ save_item(NAME(m_isr));
+ save_item(NAME(m_irq_type));
+ save_item(NAME(m_nmi_input));
+ save_item(NAME(m_pending_irqs));
+ save_item(NAME(m_irq_levels));
+}
+
+void sh7014_intc_device::device_reset()
+{
+ m_ipra = 0;
+ m_iprb = 0;
+ m_iprc = 0;
+ m_iprd = 0;
+ m_ipre = 0;
+ m_iprf = 0;
+ m_iprg = 0;
+ m_iprh = 0;
+ m_icr = m_isr = 0;
+ m_nmi_input = false;
+
+ std::fill(std::begin(m_irq_type), std::end(m_irq_type), IRQ_LEVEL);
+ std::fill(std::begin(m_irq_levels), std::end(m_irq_levels), 0);
+ std::fill(std::begin(m_pending_irqs), std::end(m_pending_irqs), 0);
+
+ m_irq_levels[INT_VECTOR_NMI] = 16; // fixed value
+}
+
+void sh7014_intc_device::map(address_map &map)
+{
+ map(0x00, 0x01).rw(FUNC(sh7014_intc_device::ipra_r), FUNC(sh7014_intc_device::ipra_w));
+ map(0x02, 0x03).rw(FUNC(sh7014_intc_device::iprb_r), FUNC(sh7014_intc_device::iprb_w));
+ map(0x04, 0x05).rw(FUNC(sh7014_intc_device::iprc_r), FUNC(sh7014_intc_device::iprc_w));
+ map(0x06, 0x07).rw(FUNC(sh7014_intc_device::iprd_r), FUNC(sh7014_intc_device::iprd_w));
+ map(0x08, 0x09).rw(FUNC(sh7014_intc_device::ipre_r), FUNC(sh7014_intc_device::ipre_w));
+ map(0x0a, 0x0b).rw(FUNC(sh7014_intc_device::iprf_r), FUNC(sh7014_intc_device::iprf_w));
+ map(0x0c, 0x0d).rw(FUNC(sh7014_intc_device::iprg_r), FUNC(sh7014_intc_device::iprg_w));
+ map(0x0e, 0x0f).rw(FUNC(sh7014_intc_device::iprh_r), FUNC(sh7014_intc_device::iprh_w));
+ map(0x10, 0x11).rw(FUNC(sh7014_intc_device::icr_r), FUNC(sh7014_intc_device::icr_w));
+ map(0x12, 0x13).rw(FUNC(sh7014_intc_device::isr_r), FUNC(sh7014_intc_device::isr_w));
+}
+
+///
+
+uint16_t sh7014_intc_device::ipra_r()
+{
+ return m_ipra;
+}
+
+void sh7014_intc_device::ipra_w(offs_t offset, uint16_t data, uint16_t mem_mask)
+{
+ COMBINE_DATA(&m_ipra);
+
+ m_irq_levels[INT_VECTOR_IRQ0] = BIT(m_ipra, 12, 4);
+ m_irq_levels[INT_VECTOR_IRQ1] = BIT(m_ipra, 8, 4);
+ m_irq_levels[INT_VECTOR_IRQ2] = BIT(m_ipra, 4, 4);
+ m_irq_levels[INT_VECTOR_IRQ3] = BIT(m_ipra, 0, 4);
+
+ update_irq_state();
+}
+
+uint16_t sh7014_intc_device::iprb_r()
+{
+ return m_iprb & 0xff00;
+}
+
+void sh7014_intc_device::iprb_w(offs_t offset, uint16_t data, uint16_t mem_mask)
+{
+ COMBINE_DATA(&m_iprb);
+
+ m_irq_levels[INT_VECTOR_IRQ6] = BIT(m_iprb, 4, 4);
+ m_irq_levels[INT_VECTOR_IRQ7] = BIT(m_iprb, 0, 4);
+
+ update_irq_state();
+}
+
+uint16_t sh7014_intc_device::iprc_r()
+{
+ return m_iprc;
+}
+
+void sh7014_intc_device::iprc_w(offs_t offset, uint16_t data, uint16_t mem_mask)
+{
+ COMBINE_DATA(&m_iprc);
+
+ m_irq_levels[INT_VECTOR_DMA_CH0] = BIT(m_iprc, 12, 4);
+ m_irq_levels[INT_VECTOR_DMA_CH1] = BIT(m_iprc, 8, 4);
+
+ update_irq_state();
+}
+
+uint16_t sh7014_intc_device::iprd_r()
+{
+ return m_iprd;
+}
+
+void sh7014_intc_device::iprd_w(offs_t offset, uint16_t data, uint16_t mem_mask)
+{
+ COMBINE_DATA(&m_iprd);
+
+ m_irq_levels[INT_VECTOR_MTU_TGI0A] = m_irq_levels[INT_VECTOR_MTU_TGI0B] = m_irq_levels[INT_VECTOR_MTU_TGI0C] = m_irq_levels[INT_VECTOR_MTU_TGI0D] = BIT(m_iprd, 12, 4);
+ m_irq_levels[INT_VECTOR_MTU_TGI0V] = BIT(m_iprd, 8, 4);
+ m_irq_levels[INT_VECTOR_MTU_TGI1A] = m_irq_levels[INT_VECTOR_MTU_TGI1B] = BIT(m_iprd, 4, 4);
+ m_irq_levels[INT_VECTOR_MTU_TGI1V] = m_irq_levels[INT_VECTOR_MTU_TGI1U] = BIT(m_iprd, 0, 4);
+
+ update_irq_state();
+}
+
+uint16_t sh7014_intc_device::ipre_r()
+{
+ return m_ipre & 0xff00;
+}
+
+void sh7014_intc_device::ipre_w(offs_t offset, uint16_t data, uint16_t mem_mask)
+{
+ COMBINE_DATA(&m_ipre);
+
+ m_irq_levels[INT_VECTOR_MTU_TGI2A] = m_irq_levels[INT_VECTOR_MTU_TGI2B] = BIT(m_ipre, 12, 4);
+ m_irq_levels[INT_VECTOR_MTU_TGI2V] = m_irq_levels[INT_VECTOR_MTU_TGI2U] = BIT(m_ipre, 8, 4);
+
+ update_irq_state();
+}
+
+uint16_t sh7014_intc_device::iprf_r()
+{
+ return m_iprf & 0xff;
+}
+
+void sh7014_intc_device::iprf_w(offs_t offset, uint16_t data, uint16_t mem_mask)
+{
+ COMBINE_DATA(&m_iprf);
+
+ m_irq_levels[INT_VECTOR_SCI_ERI0] = m_irq_levels[INT_VECTOR_SCI_RXI0] = m_irq_levels[INT_VECTOR_SCI_TXI0] = m_irq_levels[INT_VECTOR_SCI_TEI0] = BIT(m_iprf, 4, 4);
+ m_irq_levels[INT_VECTOR_SCI_ERI1] = m_irq_levels[INT_VECTOR_SCI_RXI1] = m_irq_levels[INT_VECTOR_SCI_TXI1] = m_irq_levels[INT_VECTOR_SCI_TEI1] = BIT(m_iprf, 0, 4);
+
+ update_irq_state();
+}
+
+uint16_t sh7014_intc_device::iprg_r()
+{
+ return m_iprg & 0xf0ff;
+}
+
+void sh7014_intc_device::iprg_w(offs_t offset, uint16_t data, uint16_t mem_mask)
+{
+ COMBINE_DATA(&m_iprg);
+
+ m_irq_levels[INT_VECTOR_AD] = BIT(m_iprg, 12, 4);
+ m_irq_levels[INT_VECTOR_CMT_CH0] = BIT(m_iprg, 4, 4);
+ m_irq_levels[INT_VECTOR_CMT_CH1] = BIT(m_iprg, 0, 4);
+
+ update_irq_state();
+}
+
+uint16_t sh7014_intc_device::iprh_r()
+{
+ return m_iprh & 0xf000;
+}
+
+void sh7014_intc_device::iprh_w(offs_t offset, uint16_t data, uint16_t mem_mask)
+{
+ COMBINE_DATA(&m_iprh);
+
+ m_irq_levels[INT_VECTOR_WDT] = m_irq_levels[INT_VECTOR_BSC] = BIT(m_iprh, 12, 4);
+
+ update_irq_state();
+}
+
+uint16_t sh7014_intc_device::icr_r()
+{
+ uint16_t r = m_icr & 0x01f3;
+
+ if (m_nmi_input == ((m_icr & ICR_NMIE) ? ASSERT_LINE : CLEAR_LINE))
+ r |= ICR_NMIL;
+
+ return r;
+}
+
+void sh7014_intc_device::icr_w(offs_t offset, uint16_t data, uint16_t mem_mask)
+{
+ COMBINE_DATA(&m_icr);
+
+ for (int i = 0; i < 8; i++)
+ m_irq_type[i] = BIT(m_icr, 7 - i);
+}
+
+uint16_t sh7014_intc_device::isr_r()
+{
+ return m_isr & 0xf3;
+}
+
+void sh7014_intc_device::isr_w(offs_t offset, uint16_t data, uint16_t mem_mask)
+{
+ // ICR will be set to 1 for edge detection, and it's only possible to
+ // clear flags in ISR for IRQs set to edge detection
+ auto old = m_isr;
+
+ COMBINE_DATA(&m_isr);
+
+ m_isr = (old & ~m_icr) | (old & m_isr & m_icr);
+
+ update_irq_state();
+}
+
+void sh7014_intc_device::set_interrupt(int vector, int state)
+{
+ if (vector != -1) {
+ if (state == ASSERT_LINE)
+ m_pending_irqs[vector >> 5] |= 1 << (vector & 31);
+ else if (state == CLEAR_LINE)
+ m_pending_irqs[vector >> 5] &= ~(1 << (vector & 31));
+
+ if (vector == INT_VECTOR_NMI) {
+ m_nmi_input = state == ASSERT_LINE;
+ } else if ((vector >= INT_VECTOR_IRQ0 && vector <= INT_VECTOR_IRQ3) || vector == INT_VECTOR_IRQ6 || vector == INT_VECTOR_IRQ7) {
+ const int irq = vector - INT_VECTOR_IRQ0;
+
+ if (state == ASSERT_LINE) {
+ if (m_irq_type[irq] == IRQ_LEVEL)
+ m_isr |= 1 << (7 - irq);
+ } else if (state == CLEAR_LINE) {
+ if (m_irq_type[irq] == IRQ_LEVEL)
+ m_isr &= ~(1 << (7 - irq));
+ }
+ }
+ }
+
+ update_irq_state();
+}
+
+void sh7014_intc_device::update_irq_state()
+{
+ int cur_vector = 0;
+ int cur_level = -1;
+
+ // isr has the bits in reverse order
+ m_pending_irqs[INT_VECTOR_IRQ0 >> 5] &= ~0xff;
+ m_pending_irqs[INT_VECTOR_IRQ0 >> 5] |= BIT(m_isr, 7)
+ | (BIT(m_isr, 6) << 1)
+ | (BIT(m_isr, 5) << 2)
+ | (BIT(m_isr, 4) << 3)
+ | (BIT(m_isr, 1) << 6)
+ | (BIT(m_isr, 0) << 7);
+
+ for (int i = 0; i < MAX_VECTORS / 32; i++) {
+ if (!m_pending_irqs[i])
+ continue;
+
+ for (int j = 0; j < 32; j++) {
+ if (BIT(m_pending_irqs[i], j)) {
+ const int vector = i * 32 + j;
+ const int level = m_irq_levels[vector];
+
+ if (level > cur_level) {
+ cur_vector = vector;
+ cur_level = level;
+ }
+ }
+ }
+ }
+
+ if (cur_vector == INT_VECTOR_NMI)
+ m_set_irq_cb(INPUT_LINE_NMI, cur_level, false);
+ else if ((cur_vector >= INT_VECTOR_IRQ0 && cur_vector <= INT_VECTOR_IRQ3) || cur_vector == INT_VECTOR_IRQ6 || cur_vector == INT_VECTOR_IRQ7)
+ m_set_irq_cb(cur_vector - INT_VECTOR_IRQ0, cur_level, false);
+ else if (cur_vector > INT_VECTOR_IRQ7)
+ m_set_irq_cb(cur_vector, cur_level, true);
+}
+
+void sh7014_intc_device::set_input(int inputnum, int state)
+{
+ if (inputnum == INPUT_LINE_NMI)
+ set_interrupt(INT_VECTOR_NMI, state);
+ else if ((inputnum >= INPUT_LINE_IRQ0 && inputnum <= INPUT_LINE_IRQ3) || inputnum == INPUT_LINE_IRQ6 || inputnum == INPUT_LINE_IRQ7)
+ set_interrupt(INT_VECTOR_IRQ0 + (inputnum - INPUT_LINE_IRQ0), state);
+}
diff --git a/src/devices/cpu/sh/sh7014_intc.h b/src/devices/cpu/sh/sh7014_intc.h
new file mode 100644
index 00000000000..3a6629dcb60
--- /dev/null
+++ b/src/devices/cpu/sh/sh7014_intc.h
@@ -0,0 +1,147 @@
+// license:BSD-3-Clause
+// copyright-holders:windyfairy
+/***************************************************************************
+
+ SH7014 Interrupt Controller
+
+***************************************************************************/
+
+#ifndef MAME_CPU_SH_SH7014_INTC_H
+#define MAME_CPU_SH_SH7014_INTC_H
+
+#pragma once
+
+
+class sh7014_intc_device : public device_t
+{
+public:
+ enum {
+ INT_VECTOR_NMI = 11,
+
+ INT_VECTOR_IRQ0 = 64,
+ INT_VECTOR_IRQ1 = 65,
+ INT_VECTOR_IRQ2 = 66,
+ INT_VECTOR_IRQ3 = 67,
+ // 68 and 69 are reserved
+ INT_VECTOR_IRQ6 = 70,
+ INT_VECTOR_IRQ7 = 71,
+
+ INT_VECTOR_DMA_CH0 = 72,
+ INT_VECTOR_DMA_CH1 = 76,
+
+ INT_VECTOR_MTU_TGI0A = 88,
+ INT_VECTOR_MTU_TGI0B = 89,
+ INT_VECTOR_MTU_TGI0C = 90,
+ INT_VECTOR_MTU_TGI0D = 91,
+ INT_VECTOR_MTU_TGI0V = 92,
+
+ INT_VECTOR_MTU_TGI1A = 96,
+ INT_VECTOR_MTU_TGI1B = 97,
+ INT_VECTOR_MTU_TGI1V = 100,
+ INT_VECTOR_MTU_TGI1U = 101,
+
+ INT_VECTOR_MTU_TGI2A = 104,
+ INT_VECTOR_MTU_TGI2B = 105,
+ INT_VECTOR_MTU_TGI2V = 108,
+ INT_VECTOR_MTU_TGI2U = 109,
+
+ INT_VECTOR_SCI_ERI0 = 128,
+ INT_VECTOR_SCI_RXI0 = 129,
+ INT_VECTOR_SCI_TXI0 = 130,
+ INT_VECTOR_SCI_TEI0 = 131,
+
+ INT_VECTOR_SCI_ERI1 = 132,
+ INT_VECTOR_SCI_RXI1 = 133,
+ INT_VECTOR_SCI_TXI1 = 134,
+ INT_VECTOR_SCI_TEI1 = 135,
+
+ INT_VECTOR_AD = 136,
+
+ INT_VECTOR_CMT_CH0 = 144,
+ INT_VECTOR_CMT_CH1 = 148,
+
+ INT_VECTOR_WDT = 152,
+
+ INT_VECTOR_BSC = 153,
+ };
+
+ typedef device_delegate<void (int vector, int level, bool is_internal)> set_irq_delegate;
+
+ sh7014_intc_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock = 0);
+
+ template <typename... T> void set_irq_callback(T &&... args) { m_set_irq_cb.set(std::forward<T>(args)...); }
+
+ void map(address_map &map) ATTR_COLD;
+
+ void set_input(int inputnum, int state);
+
+ void set_interrupt(int vector, int state);
+
+protected:
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+
+private:
+ enum {
+ IRQ_LEVEL,
+ IRQ_EDGE,
+ };
+
+ enum {
+ MAX_VECTORS = 256,
+ };
+
+ enum {
+ ICR_NMIE = 1 << 8,
+ ICR_NMIL = 1 << 15,
+ };
+
+ uint16_t ipra_r();
+ void ipra_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0);
+
+ uint16_t iprb_r();
+ void iprb_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0);
+
+ uint16_t iprc_r();
+ void iprc_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0);
+
+ uint16_t iprd_r();
+ void iprd_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0);
+
+ uint16_t ipre_r();
+ void ipre_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0);
+
+ uint16_t iprf_r();
+ void iprf_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0);
+
+ uint16_t iprg_r();
+ void iprg_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0);
+
+ uint16_t iprh_r();
+ void iprh_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0);
+
+ uint16_t icr_r();
+ void icr_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0);
+
+ uint16_t isr_r();
+ void isr_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0);
+
+ void update_irq_state();
+
+ set_irq_delegate m_set_irq_cb;
+
+ uint16_t m_ipra, m_iprb, m_iprc, m_iprd, m_ipre, m_iprf, m_iprg, m_iprh;
+ uint16_t m_icr, m_isr;
+
+ int8_t m_irq_levels[MAX_VECTORS];
+
+ uint32_t m_irq_type[8];
+ bool m_nmi_input;
+
+ uint32_t m_pending_irqs[MAX_VECTORS/32];
+};
+
+
+DECLARE_DEVICE_TYPE(SH7014_INTC, sh7014_intc_device)
+
+#endif // MAME_CPU_SH_SH7014_INTC_H
diff --git a/src/devices/cpu/sh/sh7014_mtu.cpp b/src/devices/cpu/sh/sh7014_mtu.cpp
new file mode 100644
index 00000000000..1f1f2ddf879
--- /dev/null
+++ b/src/devices/cpu/sh/sh7014_mtu.cpp
@@ -0,0 +1,571 @@
+// license:BSD-3-Clause
+// copyright-holders:windyfairy
+/***************************************************************************
+
+ SH7014 Multifunction Timer Pulse Unit
+
+ TODO list (not comprehensive):
+ - Synchronized operation
+ - Cascade connection operation
+ - External clocks
+ - Timer modes (PWM mode, phase counting mode (+ decrementing counter mode), etc)
+
+***************************************************************************/
+
+#include "emu.h"
+
+#include "sh7014_mtu.h"
+
+// #define VERBOSE (LOG_GENERAL)
+
+#include "logmacro.h"
+
+
+DEFINE_DEVICE_TYPE(SH7014_MTU, sh7014_mtu_device, "sh7014mtu", "SH7014 Multifunction Timer Pulse Unit")
+DEFINE_DEVICE_TYPE(SH7014_MTU_CHANNEL, sh7014_mtu_channel_device, "sh7014mtuchan", "SH7014 Multifunction Timer Pulse Unit Channel")
+
+sh7014_mtu_device::sh7014_mtu_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : device_t(mconfig, SH7014_MTU, tag, owner, clock)
+ , m_intc(*this, finder_base::DUMMY_TAG)
+ , m_chan(*this, "ch%u", 0u)
+{
+}
+
+void sh7014_mtu_device::device_start()
+{
+ save_item(NAME(m_tsyr));
+}
+
+void sh7014_mtu_device::device_reset()
+{
+ m_tsyr = 0;
+}
+
+void sh7014_mtu_device::device_add_mconfig(machine_config &config)
+{
+ SH7014_MTU_CHANNEL(config, m_chan[0], DERIVED_CLOCK(1, 1), m_intc,
+ 0, // channel
+ sh7014_intc_device::INT_VECTOR_MTU_TGI0A,
+ sh7014_intc_device::INT_VECTOR_MTU_TGI0B,
+ sh7014_intc_device::INT_VECTOR_MTU_TGI0C,
+ sh7014_intc_device::INT_VECTOR_MTU_TGI0D,
+ sh7014_intc_device::INT_VECTOR_MTU_TGI0V,
+ -1
+ );
+
+ SH7014_MTU_CHANNEL(config, m_chan[1], DERIVED_CLOCK(1, 1), m_intc,
+ 1, // channel
+ sh7014_intc_device::INT_VECTOR_MTU_TGI1A,
+ sh7014_intc_device::INT_VECTOR_MTU_TGI1B,
+ -1,
+ -1,
+ sh7014_intc_device::INT_VECTOR_MTU_TGI1V,
+ sh7014_intc_device::INT_VECTOR_MTU_TGI1U
+ );
+
+ SH7014_MTU_CHANNEL(config, m_chan[2], DERIVED_CLOCK(1, 1), m_intc,
+ 2, // channel
+ sh7014_intc_device::INT_VECTOR_MTU_TGI2A,
+ sh7014_intc_device::INT_VECTOR_MTU_TGI2B,
+ -1,
+ -1,
+ sh7014_intc_device::INT_VECTOR_MTU_TGI2V,
+ sh7014_intc_device::INT_VECTOR_MTU_TGI2U
+ );
+}
+
+void sh7014_mtu_device::map(address_map &map)
+{
+ map(0x00, 0x00).rw(FUNC(sh7014_mtu_device::tstr_r), FUNC(sh7014_mtu_device::tstr_w));
+ map(0x01, 0x01).rw(FUNC(sh7014_mtu_device::tsyr_r), FUNC(sh7014_mtu_device::tsyr_w));
+
+ map(0x20, 0x3f).m(m_chan[0], FUNC(sh7014_mtu_channel_device::map_chan0));
+ map(0x40, 0x5f).m(m_chan[1], FUNC(sh7014_mtu_channel_device::map_chan1_2));
+ map(0x60, 0x7f).m(m_chan[2], FUNC(sh7014_mtu_channel_device::map_chan1_2));
+}
+
+///
+
+uint8_t sh7014_mtu_device::tstr_r()
+{
+ return m_chan[0]->is_enabled()
+ | (m_chan[1]->is_enabled() << 1)
+ | (m_chan[2]->is_enabled() << 2);
+}
+
+void sh7014_mtu_device::tstr_w(uint8_t data)
+{
+ LOG("%s: tstr_w %02x\n", machine().describe_context().c_str(), data);
+
+ m_chan[0]->set_enable((data & TSTR_CST0) != 0);
+ m_chan[1]->set_enable((data & TSTR_CST1) != 0);
+ m_chan[2]->set_enable((data & TSTR_CST2) != 0);
+}
+
+uint8_t sh7014_mtu_device::tsyr_r()
+{
+ return m_tsyr & (TSYR_SYNC0 | TSYR_SYNC1 | TSYR_SYNC2);
+}
+
+void sh7014_mtu_device::tsyr_w(uint8_t data)
+{
+ LOG("%s: tsyr_w %02x\n", machine().describe_context().c_str(), data);
+
+ m_tsyr = data;
+}
+
+
+//////////////////
+
+sh7014_mtu_channel_device::sh7014_mtu_channel_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : device_t(mconfig, SH7014_MTU_CHANNEL, tag, owner, clock)
+ , m_intc(*this, finder_base::DUMMY_TAG)
+ , m_timer(nullptr)
+{
+}
+
+void sh7014_mtu_channel_device::device_start()
+{
+ save_item(NAME(m_tcr));
+ save_item(NAME(m_tmdr));
+ save_item(NAME(m_tiorh));
+ save_item(NAME(m_tiorl));
+ save_item(NAME(m_tier));
+ save_item(NAME(m_tsr));
+ save_item(NAME(m_tcnt));
+ save_item(NAME(m_tgr));
+
+ save_item(NAME(m_last_clock_update));
+ save_item(NAME(m_clock_type));
+ save_item(NAME(m_clock_divider));
+ save_item(NAME(m_channel_active));
+ save_item(NAME(m_phase));
+ save_item(NAME(m_counter_cycle));
+ save_item(NAME(m_tgr_clearing));
+
+ m_timer = timer_alloc(FUNC(sh7014_mtu_channel_device::timer_callback), this);
+}
+
+void sh7014_mtu_channel_device::device_reset()
+{
+ m_tcr = 0;
+ m_tmdr = 0;
+ m_tier = 0;
+ m_tsr = TSR_TCFD;
+ m_tiorh = m_tiorl = 0;
+ std::fill(std::begin(m_tgr), std::end(m_tgr), 0);
+
+ m_tcnt = 0;
+ m_last_clock_update = 0;
+ m_clock_type = INPUT_INTERNAL;
+ m_clock_divider = DIV_1;
+ m_channel_active = false;
+ m_phase = 0;
+ m_counter_cycle = 0x10000;
+ m_tgr_clearing = TGR_CLEAR_NONE;
+
+ m_timer->adjust(attotime::never);
+}
+
+void sh7014_mtu_channel_device::map_chan0(address_map &map)
+{
+ map(0x00, 0x00).rw(FUNC(sh7014_mtu_channel_device::tcr_r), FUNC(sh7014_mtu_channel_device::tcr_w));
+ map(0x01, 0x01).rw(FUNC(sh7014_mtu_channel_device::tmdr_r), FUNC(sh7014_mtu_channel_device::tmdr_w));
+ map(0x02, 0x02).rw(FUNC(sh7014_mtu_channel_device::tiorh_r), FUNC(sh7014_mtu_channel_device::tiorh_w));
+ map(0x03, 0x03).rw(FUNC(sh7014_mtu_channel_device::tiorl_r), FUNC(sh7014_mtu_channel_device::tiorl_w));
+ map(0x04, 0x04).rw(FUNC(sh7014_mtu_channel_device::tier_r), FUNC(sh7014_mtu_channel_device::tier_w));
+ map(0x05, 0x05).rw(FUNC(sh7014_mtu_channel_device::tsr_r), FUNC(sh7014_mtu_channel_device::tsr_w));
+ map(0x06, 0x07).rw(FUNC(sh7014_mtu_channel_device::tcnt_r), FUNC(sh7014_mtu_channel_device::tcnt_w));
+ map(0x08, 0x09).rw(FUNC(sh7014_mtu_channel_device::tgra_r), FUNC(sh7014_mtu_channel_device::tgra_w));
+ map(0x0a, 0x0b).rw(FUNC(sh7014_mtu_channel_device::tgrb_r), FUNC(sh7014_mtu_channel_device::tgrb_w));
+ map(0x0c, 0x0d).rw(FUNC(sh7014_mtu_channel_device::tgrc_r), FUNC(sh7014_mtu_channel_device::tgrc_w));
+ map(0x0e, 0x0f).rw(FUNC(sh7014_mtu_channel_device::tgrd_r), FUNC(sh7014_mtu_channel_device::tgrd_w));
+}
+
+void sh7014_mtu_channel_device::map_chan1_2(address_map &map)
+{
+ map(0x00, 0x00).rw(FUNC(sh7014_mtu_channel_device::tcr_r), FUNC(sh7014_mtu_channel_device::tcr_w));
+ map(0x01, 0x01).rw(FUNC(sh7014_mtu_channel_device::tmdr_r), FUNC(sh7014_mtu_channel_device::tmdr_w));
+ map(0x02, 0x02).rw(FUNC(sh7014_mtu_channel_device::tiorh_r), FUNC(sh7014_mtu_channel_device::tiorh_w));
+ map(0x04, 0x04).rw(FUNC(sh7014_mtu_channel_device::tier_r), FUNC(sh7014_mtu_channel_device::tier_w));
+ map(0x05, 0x05).rw(FUNC(sh7014_mtu_channel_device::tsr_r), FUNC(sh7014_mtu_channel_device::tsr_w));
+ map(0x06, 0x07).rw(FUNC(sh7014_mtu_channel_device::tcnt_r), FUNC(sh7014_mtu_channel_device::tcnt_w));
+ map(0x08, 0x09).rw(FUNC(sh7014_mtu_channel_device::tgra_r), FUNC(sh7014_mtu_channel_device::tgra_w));
+ map(0x0a, 0x0b).rw(FUNC(sh7014_mtu_channel_device::tgrb_r), FUNC(sh7014_mtu_channel_device::tgrb_w));
+}
+
+///
+
+TIMER_CALLBACK_MEMBER( sh7014_mtu_channel_device::timer_callback )
+{
+ update_counter();
+ schedule_next_event();
+}
+
+void sh7014_mtu_channel_device::set_enable(bool enabled)
+{
+ update_counter();
+
+ m_channel_active = enabled;
+
+ schedule_next_event();
+}
+
+uint8_t sh7014_mtu_channel_device::tcr_r()
+{
+ uint8_t r = m_tcr;
+
+ if (m_channel_id > 0)
+ r &= 0x7f;
+
+ return r;
+}
+
+void sh7014_mtu_channel_device::tcr_w(uint8_t data)
+{
+ LOG("%s: tcr_w<%d> %02x\n", machine().describe_context().c_str(), m_channel_id, data);
+
+ update_counter();
+
+ m_tcr = data;
+
+ constexpr uint32_t divider_type[3][8] = {
+ {INPUT_INTERNAL, INPUT_INTERNAL, INPUT_INTERNAL, INPUT_INTERNAL, INPUT_A, INPUT_B, INPUT_C, INPUT_D},
+ {INPUT_INTERNAL, INPUT_INTERNAL, INPUT_INTERNAL, INPUT_INTERNAL, INPUT_A, INPUT_B, INPUT_INTERNAL, INPUT_TCNT2},
+ {INPUT_INTERNAL, INPUT_INTERNAL, INPUT_INTERNAL, INPUT_INTERNAL, INPUT_A, INPUT_B, INPUT_C, INPUT_INTERNAL},
+ };
+
+ const int prescaler = BIT(m_tcr, 0, 3);
+
+ m_clock_type = divider_type[m_channel_id][prescaler];
+
+ if (m_clock_type == INPUT_INTERNAL) {
+ constexpr int32_t dividers[3][8] = {
+ {DIV_1, DIV_4, DIV_16, DIV_64, -1, -1, -1, -1},
+ {DIV_1, DIV_4, DIV_16, DIV_64, -1, -1, DIV_256, -1},
+ {DIV_1, DIV_4, DIV_16, DIV_64, -1, -1, -1, DIV_1024},
+ };
+
+ m_clock_divider = dividers[m_channel_id][prescaler];
+ } else {
+ m_clock_divider = DIV_1;
+ }
+
+ const int clock_edge = BIT(m_tcr, 3, 2);
+ if (m_clock_divider < DIV_4) {
+ m_phase = 0;
+ } else {
+ switch (clock_edge) {
+ case 0:
+ m_phase = 0;
+ break;
+ case 1:
+ m_phase = 1 << (m_clock_divider - 1);
+ break;
+ case 2:
+ // If count on both rising and falling edges, input clock frequency becomes 1/2
+ m_phase = 0;
+ m_clock_divider--;
+ break;
+ }
+ }
+
+ const int counting_clear = BIT(m_tcr, 5, m_channel_id == 0 ? 3 : 2);
+ if (counting_clear == 3 || (m_channel_id == 0 && counting_clear == 7))
+ m_tgr_clearing = TGR_CLEAR_SYNC;
+ else if (counting_clear >= 1 && counting_clear <= 2)
+ m_tgr_clearing = counting_clear - 1; // TGRA, TGRB
+ else if (m_channel_id == 0 && counting_clear >= 5 && counting_clear <= 6)
+ m_tgr_clearing = counting_clear - 3; // TGRC, TGRD (ch 0 only)
+ else
+ m_tgr_clearing = TGR_CLEAR_NONE; // 0, 4, and anything else
+
+ schedule_next_event();
+}
+
+uint8_t sh7014_mtu_channel_device::tmdr_r()
+{
+ uint8_t r = m_tmdr;
+
+ if (m_channel_id > 0)
+ r &= 0x0f;
+
+ return r | 0xc0;
+}
+
+void sh7014_mtu_channel_device::tmdr_w(uint8_t data)
+{
+ LOG("%s: tmdr_w<%d> %02x\n", machine().describe_context().c_str(), m_channel_id, data);
+
+ m_tmdr = data;
+}
+
+uint8_t sh7014_mtu_channel_device::tiorh_r()
+{
+ return m_tiorh;
+}
+
+void sh7014_mtu_channel_device::tiorh_w(uint8_t data)
+{
+ LOG("%s: tiorh_w<%d> %02x\n", machine().describe_context().c_str(), m_channel_id, data);
+
+ const bool trga_is_output_compare_register = BIT(data, 3) == 0;
+ const bool trga_was_output_compare_register = BIT(m_tiorh, 3) == 0;
+ if (trga_is_output_compare_register) {
+ const auto tgra_mode = BIT(data, 2);
+ const auto old_tgra_mode = BIT(m_tiorh, 2);
+
+ if ((tgra_mode != old_tgra_mode) || (trga_is_output_compare_register != trga_was_output_compare_register)) {
+ const auto initial_output = tgra_mode ? TSR_TGFA : 0;
+ m_tsr = (m_tsr & ~TSR_TGFA) | initial_output;
+ }
+ }
+
+ const bool trgb_is_output_compare_register = BIT(data, 7) == 0;
+ const bool trgb_was_output_compare_register = BIT(m_tiorh, 7) == 0;
+ if (trgb_is_output_compare_register) {
+ const auto tgrb_mode = BIT(data, 6);
+ const auto old_tgrb_mode = BIT(m_tiorh, 6);
+
+ if ((tgrb_mode != old_tgrb_mode) || (trgb_is_output_compare_register != trgb_was_output_compare_register)) {
+ const auto initial_output = tgrb_mode ? TSR_TGFB : 0;
+ m_tsr = (m_tsr & ~TSR_TGFB) | initial_output;
+ }
+ }
+
+ m_tiorh = data;
+}
+
+uint8_t sh7014_mtu_channel_device::tiorl_r()
+{
+ if (m_channel_id > 0)
+ return 0;
+
+ return m_tiorl;
+}
+
+void sh7014_mtu_channel_device::tiorl_w(uint8_t data)
+{
+ LOG("%s: tiorl_w<%d> %02x\n", machine().describe_context().c_str(), m_channel_id, data);
+
+ if (m_channel_id > 0)
+ return;
+
+ const bool trgc_is_output_compare_register = BIT(data, 3) == 0;
+ const bool trgc_was_output_compare_register = BIT(m_tiorl, 3) == 0;
+ if (trgc_is_output_compare_register) {
+ const auto tgrc_mode = BIT(data, 2);
+ const auto old_tgrc_mode = BIT(m_tiorl, 2);
+
+ if ((tgrc_mode != old_tgrc_mode) || (trgc_is_output_compare_register != trgc_was_output_compare_register)) {
+ const auto initial_output = tgrc_mode ? TSR_TGFC : 0;
+ m_tsr = (m_tsr & ~TSR_TGFC) | initial_output;
+ }
+ }
+
+ const bool trgd_is_output_compare_register = BIT(data, 7) == 0;
+ const bool trgd_was_output_compare_register = BIT(m_tiorl, 7) == 0;
+ if (trgd_is_output_compare_register) {
+ const auto tgrd_mode = BIT(data, 6);
+ const auto old_tgrd_mode = BIT(m_tiorl, 6);
+
+ if ((tgrd_mode != old_tgrd_mode) || (trgd_is_output_compare_register != trgd_was_output_compare_register)) {
+ const auto initial_output = tgrd_mode ? TSR_TGFD : 0;
+ m_tsr = (m_tsr & ~TSR_TGFD) | initial_output;
+ }
+ }
+
+ m_tiorl = data;
+}
+
+uint8_t sh7014_mtu_channel_device::tier_r()
+{
+ return m_tier | 0x40;
+}
+
+void sh7014_mtu_channel_device::tier_w(uint8_t data)
+{
+ LOG("%s: tier_w<%d> %02x\n", machine().describe_context().c_str(), m_channel_id, data);
+
+ m_tier = data;
+}
+
+uint8_t sh7014_mtu_channel_device::tsr_r()
+{
+ uint8_t r;
+
+ if (m_channel_id == 0)
+ r = (m_tsr & (TSR_TGFA | TSR_TGFB | TSR_TGFC | TSR_TGFD | TSR_TCFV)) | TSR_TCFD;
+ else
+ r = m_tsr & (TSR_TGFA | TSR_TGFB | TSR_TCFV | TSR_TCFU | TSR_TCFD);
+
+ return r | (1 << 6);
+}
+
+void sh7014_mtu_channel_device::tsr_w(uint8_t data)
+{
+ LOG("%s: tsr_w<%d> %02x\n", machine().describe_context().c_str(), m_channel_id, data);
+
+ if (m_channel_id == 0) {
+ const uint8_t mask = TSR_TGFA | TSR_TGFB | TSR_TGFC | TSR_TGFD | TSR_TCFV;
+ m_tsr = (data & ~mask) | (m_tsr & data & mask);
+ } else {
+ const uint8_t mask = TSR_TGFA | TSR_TGFB | TSR_TCFV | TSR_TCFU;
+ m_tsr = (data & ~mask) | (m_tsr & data & mask) | (m_tsr & TSR_TCFD);
+ }
+}
+
+uint16_t sh7014_mtu_channel_device::tcnt_r()
+{
+ update_counter();
+ return m_tcnt;
+}
+
+void sh7014_mtu_channel_device::tcnt_w(uint16_t data)
+{
+ LOG("%s: tcnt_w<%d> %04x -> %04x\n", machine().describe_context().c_str(), m_channel_id, m_tcnt, data);
+
+ m_tcnt = data;
+}
+
+uint16_t sh7014_mtu_channel_device::tgra_r()
+{
+ return m_tgr[0];
+}
+
+void sh7014_mtu_channel_device::tgra_w(uint16_t data)
+{
+ LOG("%s: tgra_w<%d> %04x -> %04x\n", machine().describe_context().c_str(), m_channel_id, m_tgr[0], data);
+
+ m_tgr[0] = data;
+}
+
+uint16_t sh7014_mtu_channel_device::tgrb_r()
+{
+ return m_tgr[1];
+}
+
+void sh7014_mtu_channel_device::tgrb_w(uint16_t data)
+{
+ LOG("%s: tgrb_w<%d> %04x -> %04x\n", machine().describe_context().c_str(), m_channel_id, m_tgr[1], data);
+
+ m_tgr[1] = data;
+}
+
+uint16_t sh7014_mtu_channel_device::tgrc_r()
+{
+ return m_tgr[2];
+}
+
+void sh7014_mtu_channel_device::tgrc_w(uint16_t data)
+{
+ LOG("%s: tgrc_w<%d> %04x -> %04x\n", machine().describe_context().c_str(), m_channel_id, m_tgr[2], data);
+
+ m_tgr[2] = data;
+}
+
+uint16_t sh7014_mtu_channel_device::tgrd_r()
+{
+ return m_tgr[3];
+}
+
+void sh7014_mtu_channel_device::tgrd_w(uint16_t data)
+{
+ LOG("%s: tgrd_w<%d> %04x -> %04x\n", machine().describe_context().c_str(), m_channel_id, m_tgr[3], data);
+
+ m_tgr[3] = data;
+}
+
+void sh7014_mtu_channel_device::update_counter()
+{
+ if (m_clock_type != INPUT_INTERNAL)
+ return;
+
+ uint64_t cur_time = machine().time().as_ticks(clock());
+
+ if (!m_channel_active) {
+ m_last_clock_update = cur_time;
+ return;
+ }
+
+ if (m_last_clock_update == cur_time)
+ return;
+
+ uint64_t base_time = (m_last_clock_update + m_phase) >> m_clock_divider;
+ uint64_t new_time = (cur_time + m_phase) >> m_clock_divider;
+ int tt = m_tcnt + (new_time - base_time);
+ m_tcnt = tt % m_counter_cycle;
+
+ for (int i = 0; i < m_tgr_count; i++) {
+ if (!BIT(m_tsr, i) && BIT(m_tier, i) && tt >= m_tgr[i]) {
+ m_tsr |= 1 << i;
+ m_intc->set_interrupt(m_vectors[i], ASSERT_LINE);
+ }
+ }
+
+ if (!(m_tsr & TSR_TCFV) && tt >= 0x10000) {
+ // Overflowed
+ m_tsr |= TSR_TCFV;
+
+ if (m_tier & TIER_TCIEV)
+ m_intc->set_interrupt(m_vectors[VECTOR_TCIV], ASSERT_LINE);
+ } else if (m_channel_id == 0 && !(m_tsr & TSR_TCFU) && tt < 0) {
+ // Underflowed, only usable on channel 0
+ m_tsr |= TSR_TCFU;
+
+ if (m_tier & TIER_TCIEU)
+ m_intc->set_interrupt(m_vectors[VECTOR_TCIU], ASSERT_LINE);
+ }
+
+ m_last_clock_update = cur_time;
+}
+
+void sh7014_mtu_channel_device::schedule_next_event()
+{
+ m_timer->adjust(attotime::never);
+
+ if (!m_channel_active || m_clock_type != INPUT_INTERNAL) {
+ return;
+ }
+
+ uint32_t event_delay = 0xffffffff;
+ if (m_tgr_clearing >= 0 && m_tgr[m_tgr_clearing]) {
+ m_counter_cycle = m_tgr[m_tgr_clearing];
+ } else {
+ m_counter_cycle = 0x10000;
+
+ if (m_tier & TIER_TCIEV) {
+ // Try to schedule next event for when the overflow should happen if overflow interrupt is enabled
+ event_delay = m_counter_cycle - m_tcnt;
+
+ if (event_delay == 0)
+ event_delay = m_counter_cycle;
+ }
+ }
+
+ // If one of the comparison register interrupts is enabled then set the next event time to be when the next interrupt should happen
+ for (int i = 0; i < m_tgr_count; i++) {
+ if (BIT(m_tier, i)) {
+ uint32_t new_delay = 0xffffffff;
+
+ if (m_tgr[i] > m_tcnt) {
+ if (m_tcnt >= m_counter_cycle || m_tgr[i] <= m_counter_cycle)
+ new_delay = m_tgr[i] - m_tcnt;
+ } else if (m_tgr[i] <= m_counter_cycle) {
+ if (m_tcnt < m_counter_cycle)
+ new_delay = (m_counter_cycle - m_tcnt) + m_tgr[i];
+ else
+ new_delay = (0x10000 - m_tcnt) + m_tgr[i];
+ }
+
+ if (event_delay > new_delay)
+ event_delay = new_delay;
+ }
+ }
+
+ if (event_delay != 0xffffffff) {
+ const uint32_t next_event = (((((1ULL << m_clock_divider) - m_phase) >> m_clock_divider) + event_delay - 1) << m_clock_divider) + m_phase;
+ m_timer->adjust(attotime::from_ticks(next_event, clock()));
+
+ }
+}
diff --git a/src/devices/cpu/sh/sh7014_mtu.h b/src/devices/cpu/sh/sh7014_mtu.h
new file mode 100644
index 00000000000..1dc2f71653e
--- /dev/null
+++ b/src/devices/cpu/sh/sh7014_mtu.h
@@ -0,0 +1,211 @@
+// license:BSD-3-Clause
+// copyright-holders:windyfairy
+/***************************************************************************
+
+ SH7014 Multifunction Timer Pulse Unit
+
+***************************************************************************/
+
+#ifndef MAME_CPU_SH_SH7014_MTU_H
+#define MAME_CPU_SH_SH7014_MTU_H
+
+#pragma once
+
+#include "sh7014_intc.h"
+
+DECLARE_DEVICE_TYPE(SH7014_MTU, sh7014_mtu_device)
+DECLARE_DEVICE_TYPE(SH7014_MTU_CHANNEL, sh7014_mtu_channel_device)
+
+
+class sh7014_mtu_device : public device_t
+{
+public:
+ sh7014_mtu_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+ template<typename T> sh7014_mtu_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock, T &&intc)
+ : sh7014_mtu_device(mconfig, tag, owner, clock)
+ {
+ m_intc.set_tag(std::forward<T>(intc));
+ }
+
+ void map(address_map &map) ATTR_COLD;
+
+protected:
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+
+private:
+ enum {
+ TSTR_CST0 = 1 << 0,
+ TSTR_CST1 = 1 << 1,
+ TSTR_CST2 = 1 << 2,
+
+ TSYR_SYNC0 = 1 << 0,
+ TSYR_SYNC1 = 1 << 1,
+ TSYR_SYNC2 = 1 << 2,
+ };
+
+ uint8_t tstr_r();
+ void tstr_w(uint8_t data);
+
+ uint8_t tsyr_r();
+ void tsyr_w(uint8_t data);
+
+ required_device<sh7014_intc_device> m_intc;
+ required_device_array<sh7014_mtu_channel_device, 3> m_chan;
+
+ uint8_t m_tsyr;
+};
+
+
+class sh7014_mtu_channel_device : public device_t
+{
+public:
+ sh7014_mtu_channel_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+ template<typename T> sh7014_mtu_channel_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock, T &&intc, int chan_id, int32_t vector_tgia, int32_t vector_tgib, int32_t vector_tgic, int32_t vector_tgid, int32_t vector_tgiv, int32_t vector_tgiu)
+ : sh7014_mtu_channel_device(mconfig, tag, owner, clock)
+ {
+ m_intc.set_tag(std::forward<T>(intc));
+ m_channel_id = chan_id;
+ m_vectors[VECTOR_TGIA] = vector_tgia;
+ m_vectors[VECTOR_TGIB] = vector_tgib;
+ m_vectors[VECTOR_TGIC] = vector_tgic;
+ m_vectors[VECTOR_TGID] = vector_tgid;
+ m_vectors[VECTOR_TCIV] = vector_tgiv;
+ m_vectors[VECTOR_TCIU] = vector_tgiu;
+ m_tgr_count = chan_id == 0 ? 4 : 2;
+ }
+
+ void map_chan0(address_map &map) ATTR_COLD;
+ void map_chan1_2(address_map &map) ATTR_COLD;
+
+ void set_enable(bool enabled);
+ bool is_enabled() { return m_channel_active; }
+
+protected:
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+
+private:
+ enum {
+ INPUT_INTERNAL = 0,
+ INPUT_A,
+ INPUT_B,
+ INPUT_C,
+ INPUT_D,
+ INPUT_TCNT2
+ };
+
+ enum {
+ DIV_1 = 0,
+ DIV_2,
+ DIV_4,
+ DIV_8,
+ DIV_16,
+ DIV_32,
+ DIV_64,
+ DIV_128,
+ DIV_256,
+ DIV_512,
+ DIV_1024
+ };
+
+ enum {
+ TGR_CLEAR_NONE = -1,
+ TGR_CLEAR_SYNC = -2
+ };
+
+ enum {
+ VECTOR_TGIA = 0,
+ VECTOR_TGIB = 1,
+ VECTOR_TGIC = 2,
+ VECTOR_TGID = 3,
+ VECTOR_TCIV = 4,
+ VECTOR_TCIU = 5
+ };
+
+ enum {
+
+ TSR_TGFA = 1 << 0,
+ TSR_TGFB = 1 << 1,
+ TSR_TGFC = 1 << 2, // ch 0 only
+ TSR_TGFD = 1 << 3, // ch 0 only
+ TSR_TCFV = 1 << 4,
+ TSR_TCFU = 1 << 5, // ch 1/2 only
+ TSR_TCFD = 1 << 7, // ch 1/2 only
+
+ TIER_TGIEA = 1 << 0,
+ TIER_TGIEB = 1 << 1,
+ TIER_TGIEC = 1 << 2, // ch 0 only
+ TIER_TGIED = 1 << 3, // ch 0 only
+ TIER_TCIEV = 1 << 4,
+ TIER_TCIEU = 1 << 5, // ch 1/2 only
+ TIER_TTGE = 1 << 7,
+ };
+
+ uint8_t tcr_r();
+ void tcr_w(uint8_t data);
+
+ uint8_t tmdr_r();
+ void tmdr_w(uint8_t data);
+
+ uint8_t tiorh_r();
+ void tiorh_w(uint8_t data);
+
+ uint8_t tiorl_r();
+ void tiorl_w(uint8_t data);
+
+ uint8_t tier_r();
+ void tier_w(uint8_t data);
+
+ uint8_t tsr_r();
+ void tsr_w(uint8_t data);
+
+ uint16_t tcnt_r();
+ void tcnt_w(uint16_t data);
+
+ uint16_t tgra_r();
+ void tgra_w(uint16_t data);
+
+ uint16_t tgrb_r();
+ void tgrb_w(uint16_t data);
+
+ uint16_t tgrc_r();
+ void tgrc_w(uint16_t data);
+
+ uint16_t tgrd_r();
+ void tgrd_w(uint16_t data);
+
+ void update_counter();
+ void schedule_next_event();
+
+ TIMER_CALLBACK_MEMBER( timer_callback );
+
+ required_device<sh7014_intc_device> m_intc;
+
+ emu_timer *m_timer;
+
+ uint32_t m_channel_id;
+ int32_t m_vectors[6];
+ uint32_t m_tgr_count;
+
+ uint8_t m_tcr;
+ uint8_t m_tmdr;
+ uint8_t m_tiorh, m_tiorl;
+ uint8_t m_tier;
+ uint8_t m_tsr;
+ uint16_t m_tgr[4];
+ uint16_t m_tcnt;
+
+ uint64_t m_last_clock_update;
+ uint32_t m_clock_type, m_clock_divider;
+ uint32_t m_phase;
+ uint32_t m_counter_cycle;
+ int32_t m_tgr_clearing;
+
+ bool m_channel_active;
+};
+
+#endif // MAME_CPU_SH_SH7014_MTU_H
diff --git a/src/devices/cpu/sh/sh7014_port.cpp b/src/devices/cpu/sh/sh7014_port.cpp
new file mode 100644
index 00000000000..96ed0701648
--- /dev/null
+++ b/src/devices/cpu/sh/sh7014_port.cpp
@@ -0,0 +1,243 @@
+// license:BSD-3-Clause
+// copyright-holders:windyfairy
+/***************************************************************************
+
+ SH7014 I/O Port
+
+ TODO list (not comprehensive):
+ - Special functions specified by control registers are not implemented
+
+***************************************************************************/
+
+#include "emu.h"
+#include "sh7014_port.h"
+
+#define LOG_READ (1U << 1)
+#define LOG_WRITE (1U << 2)
+
+// #define VERBOSE (LOG_GENERAL | LOG_READ | LOG_WRITE)
+
+#include "logmacro.h"
+
+
+DEFINE_DEVICE_TYPE(SH7014_PORT, sh7014_port_device, "sh7014port", "SH7014 I/O Port")
+
+
+sh7014_port_device::sh7014_port_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : device_t(mconfig, SH7014_PORT, tag, owner, clock)
+ , m_port_a_read_cb(*this, 0)
+ , m_port_a_write_cb(*this)
+ , m_port_b_read_cb(*this, 0)
+ , m_port_b_write_cb(*this)
+ , m_port_e_read_cb(*this, 0)
+ , m_port_e_write_cb(*this)
+ , m_port_f_read_cb(*this, 0)
+{
+}
+
+void sh7014_port_device::device_start()
+{
+ save_item(NAME(m_padr));
+ save_item(NAME(m_paior));
+ save_item(NAME(m_pacr1));
+ save_item(NAME(m_pacr2));
+
+ save_item(NAME(m_pbdr));
+ save_item(NAME(m_pbior));
+ save_item(NAME(m_pbcr1));
+ save_item(NAME(m_pbcr2));
+
+ save_item(NAME(m_pedr));
+ save_item(NAME(m_peior));
+ save_item(NAME(m_pecr1));
+ save_item(NAME(m_pecr2));
+
+ save_item(NAME(m_pfdr));
+}
+
+void sh7014_port_device::device_reset()
+{
+ m_padr = 0;
+ m_paior = 0;
+ m_pacr1 = m_pacr2 = 0;
+
+ m_pbdr = 0;
+ m_pbior = 0;
+ m_pbcr1 = m_pbcr2 = 0;
+
+ m_pedr = 0;
+ m_peior = 0;
+ m_pecr1 = m_pecr2 = 0;
+
+ m_pfdr = 0;
+}
+
+///
+
+uint16_t sh7014_port_device::padrl_r()
+{
+ uint16_t pins = m_port_a_read_cb();
+ uint16_t r = ((m_padr & m_paior) | (pins & ~m_paior)) & 0x83ff;
+ LOGMASKED(LOG_READ, "padrl_r %04x (pins: %04x %04x)\n", r, m_paior, pins);
+ return r;
+}
+
+void sh7014_port_device::padrl_w(uint16_t data)
+{
+ m_padr = data & 0x83ff;
+ LOGMASKED(LOG_WRITE, "padrl_w %04x\n", m_padr);
+
+ if (m_paior)
+ m_port_a_write_cb(m_padr & m_paior);
+}
+
+uint16_t sh7014_port_device::paiorl_r()
+{
+ LOGMASKED(LOG_READ, "paiorl_r %04x\n", m_paior);
+ return m_paior;
+}
+
+void sh7014_port_device::paiorl_w(uint16_t data)
+{
+ m_paior = data & 0x83ff;
+ LOGMASKED(LOG_WRITE, "paiorl_w %04x\n", m_paior);
+}
+
+uint16_t sh7014_port_device::pacrl1_r()
+{
+ LOGMASKED(LOG_READ, "m_pacr1 %04x\n", m_pacr1);
+ return m_pacr1;
+}
+
+void sh7014_port_device::pacrl1_w(uint16_t data)
+{
+ m_pacr1 = data & 0x400f;
+ LOGMASKED(LOG_WRITE, "pacrl1_w %04x\n", m_pacr1);
+}
+
+uint16_t sh7014_port_device::pacrl2_r()
+{
+ LOGMASKED(LOG_READ, "pacrl2_r %04x\n", m_pacr2);
+ return m_pacr2;
+}
+
+void sh7014_port_device::pacrl2_w(uint16_t data)
+{
+ m_pacr2 = data & 0xfd75;
+ LOGMASKED(LOG_WRITE, "pacrl2_w %04x\n", m_pacr2);
+}
+
+uint16_t sh7014_port_device::pbdr_r()
+{
+ uint16_t pins = m_port_b_read_cb();
+ uint16_t r = ((m_pbdr & m_pbior) | (pins & ~m_pbior)) & 0x3ff;
+ LOGMASKED(LOG_READ, "pbdr_r %04x (pins: %04x %04x)\n", r, m_pbior, pins);
+ return r;
+}
+
+void sh7014_port_device::pbdr_w(uint16_t data)
+{
+ m_pbdr = data;
+ LOGMASKED(LOG_WRITE, "pbdr_w %04x\n", m_pbdr);
+
+ if (m_pbior)
+ m_port_b_write_cb(m_pbdr & m_pbior);
+}
+
+uint16_t sh7014_port_device::pbior_r()
+{
+ LOGMASKED(LOG_READ, "pbior_r %04x\n", m_pbior);
+ return m_pbior;
+}
+
+void sh7014_port_device::pbior_w(uint16_t data)
+{
+ // For SH7014 specifically, bits 0 and 1 are read only
+ m_pbior = data & 0x3fc;
+ LOGMASKED(LOG_WRITE, "pbior_w %04x\n", m_pbior);
+}
+
+uint16_t sh7014_port_device::pbcr1_r()
+{
+ LOGMASKED(LOG_READ, "pbcr1_r %04x\n", m_pbcr1);
+ return m_pbcr1;
+}
+
+void sh7014_port_device::pbcr1_w(uint16_t data)
+{
+ m_pbcr1 = data & 0xf;
+ LOGMASKED(LOG_WRITE, "pbcr1_w %04x\n", m_pbcr1);
+}
+
+uint16_t sh7014_port_device::pbcr2_r()
+{
+ LOGMASKED(LOG_READ, "pbcr2_r %04x\n", m_pbcr2);
+ return m_pbcr2;
+}
+
+void sh7014_port_device::pbcr2_w(uint16_t data)
+{
+ m_pbcr2 = data & 0xfff5;
+ LOGMASKED(LOG_WRITE, "pbcr2_w %04x\n", m_pbcr2);
+}
+
+uint16_t sh7014_port_device::pedr_r()
+{
+ uint16_t pins = m_port_e_read_cb();
+ uint16_t r = ((m_pedr & m_peior) | (pins & ~m_peior));
+ LOGMASKED(LOG_READ, "pedr_r %04x (pins: %04x %04x)\n", r, m_peior, pins);
+ return r;
+}
+
+void sh7014_port_device::pedr_w(uint16_t data)
+{
+ m_pedr = data;
+ LOGMASKED(LOG_WRITE, "pedr_w %04x\n", m_pedr);
+
+ if (m_peior)
+ m_port_e_write_cb(m_pedr & m_peior);
+}
+
+uint16_t sh7014_port_device::peior_r()
+{
+ LOGMASKED(LOG_READ, "peior_r %04x\n", m_peior);
+ return m_peior;
+}
+
+void sh7014_port_device::peior_w(uint16_t data)
+{
+ m_peior = data;
+ LOGMASKED(LOG_WRITE, "peior_w %04x\n", m_peior);
+}
+
+uint16_t sh7014_port_device::pecr1_r()
+{
+ LOGMASKED(LOG_READ, "pecr1_r %04x\n", m_pecr1);
+ return m_pecr1;
+}
+
+void sh7014_port_device::pecr1_w(uint16_t data)
+{
+ m_pecr1 = data & 0xf000;
+ LOGMASKED(LOG_WRITE, "pecr1_w %04x\n", m_pecr1);
+}
+
+uint16_t sh7014_port_device::pecr2_r()
+{
+ LOGMASKED(LOG_READ, "pecr2_r %04x\n", m_pecr2);
+ return m_pecr2;
+}
+
+void sh7014_port_device::pecr2_w(uint16_t data)
+{
+ m_pecr2 = data & 0x55ff;
+ LOGMASKED(LOG_WRITE, "pecr2_w %04x\n", m_pecr2);
+}
+
+
+uint8_t sh7014_port_device::pfdr_r()
+{
+ auto r = m_port_f_read_cb();
+ LOGMASKED(LOG_READ, "pfdr_r %02x\n", r);
+ return r;
+}
diff --git a/src/devices/cpu/sh/sh7014_port.h b/src/devices/cpu/sh/sh7014_port.h
new file mode 100644
index 00000000000..dc69a62a839
--- /dev/null
+++ b/src/devices/cpu/sh/sh7014_port.h
@@ -0,0 +1,98 @@
+// license:BSD-3-Clause
+// copyright-holders:windyfairy
+/***************************************************************************
+
+ SH7014 Bus State Controller
+
+***************************************************************************/
+
+#ifndef MAME_CPU_SH_SH7014_PORT_H
+#define MAME_CPU_SH_SH7014_PORT_H
+
+#pragma once
+
+
+class sh7014_port_device : public device_t
+{
+public:
+ sh7014_port_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock = 0);
+
+ auto port_a_read_callback() { return m_port_a_read_cb.bind(); }
+ auto port_a_write_callback() { return m_port_a_write_cb.bind(); }
+
+ auto port_b_read_callback() { return m_port_b_read_cb.bind(); }
+ auto port_b_write_callback() { return m_port_b_write_cb.bind(); }
+
+ auto port_e_read_callback() { return m_port_e_read_cb.bind(); }
+ auto port_e_write_callback() { return m_port_e_write_cb.bind(); }
+
+ auto port_f_read_callback() { return m_port_f_read_cb.bind(); }
+
+ // port A
+ uint16_t padrl_r();
+ void padrl_w(uint16_t data);
+
+ uint16_t paiorl_r();
+ void paiorl_w(uint16_t data);
+
+ uint16_t pacrl1_r();
+ void pacrl1_w(uint16_t data);
+
+ uint16_t pacrl2_r();
+ void pacrl2_w(uint16_t data);
+
+ // port b
+ uint16_t pbdr_r();
+ void pbdr_w(uint16_t data);
+
+ uint16_t pbior_r();
+ void pbior_w(uint16_t data);
+
+ uint16_t pbcr1_r();
+ void pbcr1_w(uint16_t data);
+
+ uint16_t pbcr2_r();
+ void pbcr2_w(uint16_t data);
+
+ // port e
+ uint16_t pedr_r();
+ void pedr_w(uint16_t data);
+
+ uint16_t peior_r();
+ void peior_w(uint16_t data);
+
+ uint16_t pecr1_r();
+ void pecr1_w(uint16_t data);
+
+ uint16_t pecr2_r();
+ void pecr2_w(uint16_t data);
+
+ // port f
+ uint8_t pfdr_r();
+
+protected:
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+
+private:
+ devcb_read16 m_port_a_read_cb;
+ devcb_write16 m_port_a_write_cb;
+
+ devcb_read16 m_port_b_read_cb;
+ devcb_write16 m_port_b_write_cb;
+
+ devcb_read16 m_port_e_read_cb;
+ devcb_write16 m_port_e_write_cb;
+
+ devcb_read16 m_port_f_read_cb;
+
+ uint16_t m_padr, m_paior, m_pacr1, m_pacr2;
+ uint16_t m_pbdr, m_pbior, m_pbcr1, m_pbcr2;
+ uint16_t m_pedr, m_peior, m_pecr1, m_pecr2;
+ uint8_t m_pfdr;
+};
+
+
+DECLARE_DEVICE_TYPE(SH7014_PORT, sh7014_port_device)
+
+#endif // MAME_CPU_SH_SH7014_PORT_H
diff --git a/src/devices/cpu/sh/sh7014_sci.cpp b/src/devices/cpu/sh/sh7014_sci.cpp
new file mode 100644
index 00000000000..ffa19247382
--- /dev/null
+++ b/src/devices/cpu/sh/sh7014_sci.cpp
@@ -0,0 +1,380 @@
+// license:BSD-3-Clause
+// copyright-holders:windyfairy
+/***************************************************************************
+
+ SH7014 SCI Controller
+
+ TODO list (not comprehensive):
+ - RX is untested
+ - Multiprocessor bit is not handled at all
+
+***************************************************************************/
+
+#include "emu.h"
+#include "sh7014_sci.h"
+
+#define LOG_REGISTERS (1U << 1)
+#define LOG_TXRX (1U << 2)
+#define LOG_CLOCK (1U << 3)
+
+// #define VERBOSE (LOG_GENERAL | LOG_REGISTERS | LOG_TXRX | LOG_CLOCK)
+
+#include "logmacro.h"
+
+DEFINE_DEVICE_TYPE(SH7014_SCI, sh7014_sci_device, "sh7014sci", "SH7014 SCI Controller")
+
+sh7014_sci_device::sh7014_sci_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : device_t(mconfig, SH7014_SCI, tag, owner, clock)
+ , device_serial_interface(mconfig, *this)
+ , m_intc(*this, finder_base::DUMMY_TAG)
+ , m_sci_tx_cb(*this)
+ , m_hack_set_full_data_transmit_on_sync(false)
+{
+ m_external_clock_period = attotime::never;
+}
+
+void sh7014_sci_device::device_start()
+{
+ save_item(NAME(m_smr));
+ save_item(NAME(m_brr));
+ save_item(NAME(m_scr));
+ save_item(NAME(m_tdr));
+ save_item(NAME(m_ssr));
+ save_item(NAME(m_rdr));
+ save_item(NAME(m_is_dma_source_tx));
+ save_item(NAME(m_is_dma_source_rx));
+ save_item(NAME(m_clock_speed));
+ save_item(NAME(m_external_clock_period));
+}
+
+void sh7014_sci_device::device_reset()
+{
+ m_smr = 0;
+ m_brr = 0xff;
+ m_scr = 0;
+ m_tdr = 0xff;
+ m_ssr = SSR_TDRE | SSR_TEND;
+ m_rdr = 0;
+ m_is_dma_source_tx = m_is_dma_source_rx = false;
+ m_clock_speed = attotime::never;
+
+ update_data_format();
+ update_clock();
+}
+
+void sh7014_sci_device::map(address_map &map)
+{
+ map(0x00, 0x00).rw(FUNC(sh7014_sci_device::smr_r), FUNC(sh7014_sci_device::smr_w));
+ map(0x01, 0x01).rw(FUNC(sh7014_sci_device::brr_r), FUNC(sh7014_sci_device::brr_w));
+ map(0x02, 0x02).rw(FUNC(sh7014_sci_device::scr_r), FUNC(sh7014_sci_device::scr_w));
+ map(0x03, 0x03).rw(FUNC(sh7014_sci_device::tdr_r), FUNC(sh7014_sci_device::tdr_w));
+ map(0x04, 0x04).rw(FUNC(sh7014_sci_device::ssr_r), FUNC(sh7014_sci_device::ssr_w));
+ map(0x05, 0x05).r(FUNC(sh7014_sci_device::rdr_r));
+}
+
+///
+
+void sh7014_sci_device::set_send_full_data_transmit_on_sync_hack(bool enabled)
+{
+ // Synchronous clock mode forces a fixed 8-bit transmissions with no start, stop, parity, or multiprocessor bits.
+ // This flag makes it so that all 8 bits in the transmit register will be transferred at the start of a transmission
+ // instead of transmitting 1 bit at a time when in synchronous clock mode, allowing the transmit clock to be set to
+ // 1/8th of its normal speed.
+ m_hack_set_full_data_transmit_on_sync = enabled;
+}
+
+void sh7014_sci_device::set_external_clock_period(const attotime &period)
+{
+ m_external_clock_period = period;
+
+ // Update clock again if it's being used
+ if (m_scr & SCR_CKE1)
+ update_clock();
+}
+
+uint8_t sh7014_sci_device::smr_r()
+{
+ return m_smr;
+}
+
+void sh7014_sci_device::smr_w(uint8_t data)
+{
+ LOGMASKED(LOG_REGISTERS, "smr_w %02x %s %c%c%c%s /%d\n", data,
+ data & SMR_CA ? "sync" : "async",
+ data & SMR_CHR ? '7' : '8',
+ data & SMR_PE ? data & SMR_OE ? 'o' : 'e' : 'n',
+ data & SMR_STOP ? '2' : '1',
+ data & SMR_MP ? " mp" : "",
+ 1 << (2 * (data & SMR_CKS)));
+
+ bool do_clock_update = (data & (SMR_CKS | SMR_CA)) != (m_smr & (SMR_CKS | SMR_CA));
+ bool do_format_update = false;
+
+ if (!(data & SMR_CA))
+ do_format_update = (data & ~SMR_CKS) != (m_smr & ~SMR_CKS);
+ else
+ do_format_update = (data & SMR_CA) != (m_smr & SMR_CA);
+
+ m_smr = data;
+
+ if (do_format_update)
+ update_data_format();
+
+ if (do_clock_update)
+ update_clock();
+}
+
+uint8_t sh7014_sci_device::scr_r()
+{
+ return m_scr;
+}
+
+void sh7014_sci_device::scr_w(uint8_t data)
+{
+ const auto old = m_scr;
+
+ LOGMASKED(LOG_REGISTERS, "scr_w %02x%s%s%s%s%s%s clk=%d\n", data,
+ (data & SCR_TIE) ? " txi" : "",
+ (data & SCR_RIE) ? " rxi" : "",
+ (data & SCR_TE) ? " tx" : "",
+ (data & SCR_RE) ? " rx" : "",
+ (data & SCR_MPIE) ? " mpi" : "",
+ (data & SCR_TEIE) ? " tei" : "",
+ data & SCR_CKE);
+
+ if ((m_scr & SCR_TE) && !(data & SCR_TE))
+ m_ssr |= SSR_TEND | SSR_TDRE;
+
+ if ((m_scr & SCR_TIE) && !(data & SCR_TIE))
+ m_intc->set_interrupt(m_txi_int, CLEAR_LINE);
+
+ if ((m_scr & SCR_TEIE) && !(data & SCR_TEIE))
+ m_intc->set_interrupt(m_tei_int, CLEAR_LINE);
+
+ if ((m_scr & SCR_RIE) && !(data & SCR_RIE)) {
+ m_intc->set_interrupt(m_rxi_int, CLEAR_LINE);
+ m_intc->set_interrupt(m_eri_int, CLEAR_LINE);
+ }
+
+ m_scr = data;
+
+ if ((data & SCR_CKE) != (old & SCR_CKE))
+ update_clock();
+}
+
+uint8_t sh7014_sci_device::ssr_r()
+{
+ LOGMASKED(LOG_REGISTERS, "ssr_r %02x\n", m_ssr);
+ return m_ssr;
+}
+
+void sh7014_sci_device::ssr_w(uint8_t data)
+{
+ const auto old = m_ssr;
+ bool do_tx_update = false;
+
+ m_ssr = (data & (m_ssr & (SSR_TDRE | SSR_RDRF | SSR_ORER | SSR_FER | SSR_PER)))
+ | (m_ssr & (SSR_TEND | SSR_MPB))
+ | (data & SSR_MPBT);
+
+ if (!(m_scr & SCR_TE)) {
+ m_ssr |= SSR_TEND | SSR_TDRE;
+ } else if ((old & SSR_TDRE) || !(m_scr & SSR_TDRE)) {
+ do_tx_update = true;
+ m_ssr &= ~(SSR_TEND | SSR_TDRE);
+ }
+
+ if ((old & (SSR_ORER | SSR_FER | SSR_PER)) && !(data & (SSR_ORER | SSR_FER | SSR_PER)))
+ m_intc->set_interrupt(m_eri_int, CLEAR_LINE);
+
+ LOGMASKED(LOG_REGISTERS, "ssr_w %02x | %02x -> %02x\n", data, old, m_ssr);
+
+ if (do_tx_update)
+ update_tx_state();
+}
+
+uint8_t sh7014_sci_device::brr_r()
+{
+ return m_brr;
+}
+
+void sh7014_sci_device::brr_w(uint8_t data)
+{
+ LOGMASKED(LOG_REGISTERS, "brr_w %02x\n", data);
+ m_brr = data;
+ update_clock();
+}
+
+uint8_t sh7014_sci_device::tdr_r()
+{
+ LOGMASKED(LOG_TXRX, "tdr_r %02x\n", m_tdr);
+ return m_tdr;
+}
+
+void sh7014_sci_device::tdr_w(uint8_t data)
+{
+ LOGMASKED(LOG_TXRX, "tdr_w%s %02x %d %d\n", m_is_dma_source_tx ? " (dma)" : "", data, is_transmit_register_empty(), (m_scr & SCR_TE) != 0);
+
+ m_tdr = data;
+
+ if (!(m_scr & SCR_TE))
+ return;
+
+ if (m_is_dma_source_tx) {
+ // Normally this would happen with a write to SCR but DMAs can only write to TDR,
+ // so these flags are handled here as a special case for DMA writes only
+ m_ssr &= ~(SSR_TEND | SSR_TDRE);
+ m_is_dma_source_tx = false;
+
+ update_tx_state();
+ }
+}
+
+void sh7014_sci_device::tra_callback()
+{
+ if (!is_transmit_register_empty())
+ m_sci_tx_cb(transmit_register_get_data_bit());
+
+ if ((m_smr & SMR_CA) && m_hack_set_full_data_transmit_on_sync) {
+ while (!is_transmit_register_empty())
+ m_sci_tx_cb(transmit_register_get_data_bit());
+ }
+}
+
+void sh7014_sci_device::tra_complete()
+{
+ if (!(m_ssr & SSR_TDRE)) {
+ update_tx_state();
+ return;
+ }
+
+ LOGMASKED(LOG_TXRX, "transmit ended\n");
+
+ m_ssr |= SSR_TEND;
+ if (m_scr & SCR_TEIE)
+ m_intc->set_interrupt(m_tei_int, ASSERT_LINE);
+}
+
+void sh7014_sci_device::update_tx_state()
+{
+ if (!(m_scr & SCR_TE) || (m_ssr & SSR_TDRE) || !is_transmit_register_empty())
+ return;
+
+ LOGMASKED(LOG_TXRX, "transmitting %02x\n", m_tdr);
+
+ transmit_register_setup(m_tdr);
+
+ m_ssr = (m_ssr & ~SSR_TEND) | SSR_TDRE;
+
+ if (m_scr & SCR_TIE)
+ m_intc->set_interrupt(m_txi_int, ASSERT_LINE);
+}
+
+uint8_t sh7014_sci_device::rdr_r()
+{
+ auto r = m_rdr;
+
+ LOGMASKED(LOG_TXRX, "rdr_r%s %02x\n", m_is_dma_source_rx ? " (dma)" : "", m_rdr);
+
+ // DMA reads cause RDRF to be cleared
+ if (m_is_dma_source_rx)
+ m_ssr &= ~SSR_RDRF;
+
+ return r;
+}
+
+void sh7014_sci_device::rcv_complete()
+{
+ receive_register_extract();
+
+ if (!(m_scr & SCR_RE))
+ return;
+
+ if (is_receive_framing_error())
+ m_ssr |= SSR_FER;
+ if (is_receive_parity_error())
+ m_ssr |= SSR_PER;
+
+ if (!(m_ssr & SSR_RDRF)) {
+ m_rdr = get_received_char();
+ m_ssr |= SSR_RDRF;
+
+ if (m_scr & SCR_RIE)
+ m_intc->set_interrupt(m_rxi_int, ASSERT_LINE);
+
+ if ((m_ssr & SSR_FER) | (m_ssr & SSR_PER) || (m_ssr & SSR_ORER))
+ m_intc->set_interrupt(m_eri_int, ASSERT_LINE);
+ } else {
+ m_ssr |= SSR_ORER;
+ }
+}
+
+void sh7014_sci_device::update_data_format()
+{
+ if (m_smr & SMR_CA) {
+ // Synchronous clock is a fixed 8-bit data length transmission
+ set_data_frame(0, 8, PARITY_NONE, STOP_BITS_0);
+ return;
+ }
+
+ // Async
+ set_data_frame(
+ 1,
+ (m_smr & SMR_CHR) ? 8 : 7,
+ (m_smr & SMR_MP) ? PARITY_NONE : ((m_smr & SMR_PE) ? PARITY_ODD : PARITY_EVEN), // Multiprocessor mode does not use parity
+ (m_smr & SMR_STOP) ? STOP_BITS_1 : STOP_BITS_2
+ );
+}
+
+void sh7014_sci_device::update_clock()
+{
+ auto clock_mode = INTERNAL_SYNC_OUT;
+ if (m_smr & SMR_CA) {
+ if (m_scr & SCR_CKE1)
+ clock_mode = EXTERNAL_SYNC;
+ else
+ clock_mode = INTERNAL_SYNC_OUT;
+ } else {
+ if (m_scr & SCR_CKE1)
+ clock_mode = EXTERNAL_ASYNC;
+ else if (m_scr & SCR_CKE0)
+ clock_mode = INTERNAL_ASYNC_OUT;
+ else
+ clock_mode = INTERNAL_ASYNC;
+ }
+
+ if (clock_mode == EXTERNAL_ASYNC && !m_external_clock_period.is_never())
+ clock_mode = EXTERNAL_RATE_ASYNC;
+ else if (clock_mode == EXTERNAL_SYNC && !m_external_clock_period.is_never())
+ clock_mode = EXTERNAL_RATE_SYNC;
+
+ auto clock_speed = attotime::zero;
+ switch (clock_mode) {
+ case INTERNAL_ASYNC:
+ case INTERNAL_ASYNC_OUT:
+ case INTERNAL_SYNC_OUT:
+ {
+ int divider = (1 << (2 * (m_smr & SMR_CKS))) * (m_brr + 1);
+ clock_speed = attotime::from_ticks(divider, clock());
+ }
+ break;
+
+ case EXTERNAL_ASYNC:
+ case EXTERNAL_RATE_ASYNC:
+ case EXTERNAL_SYNC:
+ case EXTERNAL_RATE_SYNC:
+ clock_speed = m_external_clock_period;
+ break;
+ }
+
+ if (clock_speed != m_clock_speed && !clock_speed.is_never()) {
+ LOGMASKED(LOG_CLOCK, "Changing SCI ch %d rate set to %lf (%d %04x %04x)\n", m_channel_id, clock_speed.as_hz(), clock_mode, m_brr, m_smr);
+
+ if (m_hack_set_full_data_transmit_on_sync && (m_smr & SMR_CA))
+ set_rate(clock_speed * 8);
+ else
+ set_rate(clock_speed);
+
+ m_clock_speed = clock_speed;
+ }
+}
diff --git a/src/devices/cpu/sh/sh7014_sci.h b/src/devices/cpu/sh/sh7014_sci.h
new file mode 100644
index 00000000000..1673c631477
--- /dev/null
+++ b/src/devices/cpu/sh/sh7014_sci.h
@@ -0,0 +1,135 @@
+// license:BSD-3-Clause
+// copyright-holders:windyfairy
+/***************************************************************************
+
+ SH7014 SCI Controller
+
+***************************************************************************/
+
+#ifndef MAME_CPU_SH_SH7014_SCI_H
+#define MAME_CPU_SH_SH7014_SCI_H
+
+#pragma once
+
+#include "sh2.h"
+#include "sh7014_intc.h"
+#include "diserial.h"
+
+class sh7014_sci_device : public device_t, public device_serial_interface
+{
+public:
+ sh7014_sci_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+ template<typename T> sh7014_sci_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock, T &&intc, int channel_id, int eri, int rxi, int txi, int tei)
+ : sh7014_sci_device(mconfig, tag, owner, clock)
+ {
+ m_intc.set_tag(std::forward<T>(intc));
+ m_channel_id = channel_id;
+ m_eri_int = eri;
+ m_rxi_int = rxi;
+ m_txi_int = txi;
+ m_tei_int = tei;
+ }
+
+ auto write_sci_tx() { return m_sci_tx_cb.bind(); }
+
+ void set_dma_source_tx(bool val) { m_is_dma_source_tx = val; }
+ void set_dma_source_rx(bool val) { m_is_dma_source_rx = val; }
+
+ void set_external_clock_period(const attotime &_period);
+ void set_send_full_data_transmit_on_sync_hack(bool enabled);
+
+ void map(address_map &map) ATTR_COLD;
+
+protected:
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+
+ virtual void rcv_complete() override;
+
+ virtual void tra_callback() override;
+ virtual void tra_complete() override;
+
+private:
+ enum : uint32_t {
+ INTERNAL_ASYNC = 0,
+ INTERNAL_ASYNC_OUT,
+ EXTERNAL_ASYNC,
+ EXTERNAL_RATE_ASYNC,
+ INTERNAL_SYNC_OUT,
+ EXTERNAL_SYNC,
+ EXTERNAL_RATE_SYNC
+ };
+
+ enum {
+ SMR_CA = 1 << 7,
+ SMR_CHR = 1 << 6,
+ SMR_PE = 1 << 5,
+ SMR_OE = 1 << 4,
+ SMR_STOP = 1 << 3,
+ SMR_MP = 1 << 2,
+ SMR_CKS = (1 << 1) | (1 << 0),
+
+ SCR_TIE = 1 << 7,
+ SCR_RIE = 1 << 6,
+ SCR_TE = 1 << 5,
+ SCR_RE = 1 << 4,
+ SCR_MPIE = 1 << 3,
+ SCR_TEIE = 1 << 2,
+ SCR_CKE = (1 << 1) | (1 << 0),
+ SCR_CKE1 = 1 << 1,
+ SCR_CKE0 = 1 << 0,
+
+ SSR_TDRE = 1 << 7,
+ SSR_RDRF = 1 << 6,
+ SSR_ORER = 1 << 5,
+ SSR_FER = 1 << 4,
+ SSR_PER = 1 << 3,
+ SSR_TEND = 1 << 2,
+ SSR_MPB = 1 << 1,
+ SSR_MPBT = 1 << 0
+ };
+
+ uint8_t smr_r();
+ void smr_w(uint8_t data);
+
+ uint8_t brr_r();
+ void brr_w(uint8_t data);
+
+ uint8_t scr_r();
+ void scr_w(uint8_t data);
+
+ uint8_t tdr_r();
+ void tdr_w(uint8_t data);
+
+ uint8_t ssr_r();
+ void ssr_w(uint8_t data);
+
+ uint8_t rdr_r();
+
+ void update_tx_state();
+ void update_clock();
+ void update_data_format();
+
+ required_device<sh7014_intc_device> m_intc;
+
+ devcb_write_line m_sci_tx_cb;
+
+ int m_channel_id, m_eri_int, m_rxi_int, m_txi_int, m_tei_int;
+ bool m_hack_set_full_data_transmit_on_sync;
+
+ uint8_t m_smr;
+ uint8_t m_brr;
+ uint8_t m_scr;
+ uint8_t m_tdr;
+ uint8_t m_ssr;
+ uint8_t m_rdr;
+
+ attotime m_external_clock_period, m_clock_speed;
+ bool m_is_dma_source_tx, m_is_dma_source_rx;
+};
+
+
+DECLARE_DEVICE_TYPE(SH7014_SCI, sh7014_sci_device)
+
+#endif // MAME_CPU_SH_SH7014_SCI_H
diff --git a/src/devices/cpu/sh/sh7021.cpp b/src/devices/cpu/sh/sh7021.cpp
new file mode 100644
index 00000000000..6b61621cb5c
--- /dev/null
+++ b/src/devices/cpu/sh/sh7021.cpp
@@ -0,0 +1,2243 @@
+// license:BSD-3-Clause
+// copyright-holders:Ryan Holtz
+/*****************************************************************************
+ *
+ * sh7021.cpp
+ * Portable Hitachi SH-1 (model SH7021) emulator
+ *
+ *****************************************************************************/
+
+#include "emu.h"
+#include "sh7021.h"
+#include "sh_dasm.h"
+
+#define LOG_INTC_RD (1u << 1)
+#define LOG_INTC_WR (1u << 2)
+#define LOG_UBC_RD (1u << 3)
+#define LOG_UBC_WR (1u << 4)
+#define LOG_BSC_RD (1u << 5)
+#define LOG_BSC_WR (1u << 6)
+#define LOG_DMA_RD (1u << 7)
+#define LOG_DMA_WR (1u << 8)
+#define LOG_ITU_RD (1u << 9)
+#define LOG_ITU_WR (1u << 10)
+#define LOG_TPC_RD (1u << 11)
+#define LOG_TPC_WR (1u << 12)
+#define LOG_WDT_RD (1u << 13)
+#define LOG_WDT_WR (1u << 14)
+#define LOG_SCI_RD (1u << 15)
+#define LOG_SCI_WR (1u << 16)
+#define LOG_PFC_RD (1u << 17)
+#define LOG_PFC_WR (1u << 18)
+#define LOG_INTC (LOG_INTC_RD | LOG_INTC_WR)
+#define LOG_UBC (LOG_UBC_RD | LOG_UBC_WR)
+#define LOG_BSC (LOG_BSC_RD | LOG_BSC_WR)
+#define LOG_DMA (LOG_DMA_RD | LOG_DMA_WR)
+#define LOG_ITU (LOG_ITU_RD | LOG_ITU_WR)
+#define LOG_TPC (LOG_TPC_RD | LOG_TPC_WR)
+#define LOG_WDT (LOG_WDT_RD | LOG_WDT_WR)
+#define LOG_SCI (LOG_SCI_RD | LOG_SCI_WR)
+#define LOG_PFC (LOG_PFC_RD | LOG_PFC_WR)
+#define LOG_ALL (LOG_INTC | LOG_UBC | LOG_BSC | LOG_DMA | LOG_ITU | LOG_TPC | LOG_WDT | LOG_SCI | LOG_PFC)
+
+#define VERBOSE (0)
+#include "logmacro.h"
+
+
+DEFINE_DEVICE_TYPE(SH7021, sh7021_device, "sh7021", "Hitachi SH7021")
+
+/*-------------------------------------------------
+ internal_map - maps SH7021 built-ins
+-------------------------------------------------*/
+
+void sh7021_device::internal_map(address_map &map)
+{
+ map(0x00000000, 0x00007fff).rom().region(DEVICE_SELF, 0).mirror(0x00ff8000); // 32KB internal ROM
+
+ map(0x05fffec0, 0x05fffec0).rw(FUNC(sh7021_device::sci_smr_r<0>), FUNC(sh7021_device::sci_smr_w<0>));
+ map(0x05fffec1, 0x05fffec1).rw(FUNC(sh7021_device::sci_brr_r<0>), FUNC(sh7021_device::sci_brr_w<0>));
+ map(0x05fffec2, 0x05fffec2).rw(FUNC(sh7021_device::sci_scr_r<0>), FUNC(sh7021_device::sci_scr_w<0>));
+ map(0x05fffec3, 0x05fffec3).rw(FUNC(sh7021_device::sci_tdr_r<0>), FUNC(sh7021_device::sci_tdr_w<0>));
+ map(0x05fffec4, 0x05fffec4).rw(FUNC(sh7021_device::sci_ssr_r<0>), FUNC(sh7021_device::sci_ssr_w<0>));
+ map(0x05fffec5, 0x05fffec5).r(FUNC(sh7021_device::sci_rdr_r<0>));
+ map(0x05fffec8, 0x05fffec8).rw(FUNC(sh7021_device::sci_smr_r<1>), FUNC(sh7021_device::sci_smr_w<1>));
+ map(0x05fffec9, 0x05fffec9).rw(FUNC(sh7021_device::sci_brr_r<1>), FUNC(sh7021_device::sci_brr_w<1>));
+ map(0x05fffeca, 0x05fffeca).rw(FUNC(sh7021_device::sci_scr_r<1>), FUNC(sh7021_device::sci_scr_w<1>));
+ map(0x05fffecb, 0x05fffecb).rw(FUNC(sh7021_device::sci_tdr_r<1>), FUNC(sh7021_device::sci_tdr_w<1>));
+ map(0x05fffecc, 0x05fffecc).rw(FUNC(sh7021_device::sci_ssr_r<1>), FUNC(sh7021_device::sci_ssr_w<1>));
+ map(0x05fffecd, 0x05fffecd).r(FUNC(sh7021_device::sci_rdr_r<1>));
+
+ map(0x05ffff00, 0x05ffff00).rw(FUNC(sh7021_device::itu_tstr_r), FUNC(sh7021_device::itu_tstr_w));
+ map(0x05ffff01, 0x05ffff01).rw(FUNC(sh7021_device::itu_tsnc_r), FUNC(sh7021_device::itu_tsnc_w));
+ map(0x05ffff02, 0x05ffff02).rw(FUNC(sh7021_device::itu_tmdr_r), FUNC(sh7021_device::itu_tmdr_w));
+ map(0x05ffff03, 0x05ffff03).rw(FUNC(sh7021_device::itu_tfcr_r), FUNC(sh7021_device::itu_tfcr_w));
+ map(0x05ffff31, 0x05ffff31).rw(FUNC(sh7021_device::itu_tocr_r), FUNC(sh7021_device::itu_tocr_w));
+
+ map(0x05ffff04, 0x05ffff04).rw(FUNC(sh7021_device::itu_tcr_r<0>), FUNC(sh7021_device::itu_tcr_w<0>));
+ map(0x05ffff05, 0x05ffff05).rw(FUNC(sh7021_device::itu_tior_r<0>), FUNC(sh7021_device::itu_tior_w<0>));
+ map(0x05ffff06, 0x05ffff06).rw(FUNC(sh7021_device::itu_tier_r<0>), FUNC(sh7021_device::itu_tier_w<0>));
+ map(0x05ffff07, 0x05ffff07).rw(FUNC(sh7021_device::itu_tsr_r<0>), FUNC(sh7021_device::itu_tsr_w<0>));
+ map(0x05ffff08, 0x05ffff09).rw(FUNC(sh7021_device::itu_tcnt_r<0>), FUNC(sh7021_device::itu_tcnt_w<0>));
+ map(0x05ffff0a, 0x05ffff0b).rw(FUNC(sh7021_device::itu_gra_r<0>), FUNC(sh7021_device::itu_gra_w<0>));
+ map(0x05ffff0c, 0x05ffff0d).rw(FUNC(sh7021_device::itu_grb_r<0>), FUNC(sh7021_device::itu_grb_w<0>));
+
+ map(0x05ffff0e, 0x05ffff0e).rw(FUNC(sh7021_device::itu_tcr_r<1>), FUNC(sh7021_device::itu_tcr_w<1>));
+ map(0x05ffff0f, 0x05ffff0f).rw(FUNC(sh7021_device::itu_tior_r<1>), FUNC(sh7021_device::itu_tior_w<1>));
+ map(0x05ffff10, 0x05ffff10).rw(FUNC(sh7021_device::itu_tier_r<1>), FUNC(sh7021_device::itu_tier_w<1>));
+ map(0x05ffff11, 0x05ffff11).rw(FUNC(sh7021_device::itu_tsr_r<1>), FUNC(sh7021_device::itu_tsr_w<1>));
+ map(0x05ffff12, 0x05ffff13).rw(FUNC(sh7021_device::itu_tcnt_r<1>), FUNC(sh7021_device::itu_tcnt_w<1>));
+ map(0x05ffff14, 0x05ffff15).rw(FUNC(sh7021_device::itu_gra_r<1>), FUNC(sh7021_device::itu_gra_w<1>));
+ map(0x05ffff16, 0x05ffff17).rw(FUNC(sh7021_device::itu_grb_r<1>), FUNC(sh7021_device::itu_grb_w<1>));
+
+ map(0x05ffff18, 0x05ffff18).rw(FUNC(sh7021_device::itu_tcr_r<2>), FUNC(sh7021_device::itu_tcr_w<2>));
+ map(0x05ffff19, 0x05ffff19).rw(FUNC(sh7021_device::itu_tior_r<2>), FUNC(sh7021_device::itu_tior_w<2>));
+ map(0x05ffff1a, 0x05ffff1a).rw(FUNC(sh7021_device::itu_tier_r<2>), FUNC(sh7021_device::itu_tier_w<2>));
+ map(0x05ffff1b, 0x05ffff1b).rw(FUNC(sh7021_device::itu_tsr_r<2>), FUNC(sh7021_device::itu_tsr_w<2>));
+ map(0x05ffff1c, 0x05ffff1d).rw(FUNC(sh7021_device::itu_tcnt_r<2>), FUNC(sh7021_device::itu_tcnt_w<2>));
+ map(0x05ffff1e, 0x05ffff1f).rw(FUNC(sh7021_device::itu_gra_r<2>), FUNC(sh7021_device::itu_gra_w<2>));
+ map(0x05ffff20, 0x05ffff21).rw(FUNC(sh7021_device::itu_grb_r<2>), FUNC(sh7021_device::itu_grb_w<2>));
+
+ map(0x05ffff22, 0x05ffff22).rw(FUNC(sh7021_device::itu_tcr_r<3>), FUNC(sh7021_device::itu_tcr_w<3>));
+ map(0x05ffff23, 0x05ffff23).rw(FUNC(sh7021_device::itu_tior_r<3>), FUNC(sh7021_device::itu_tior_w<3>));
+ map(0x05ffff24, 0x05ffff24).rw(FUNC(sh7021_device::itu_tier_r<3>), FUNC(sh7021_device::itu_tier_w<3>));
+ map(0x05ffff25, 0x05ffff25).rw(FUNC(sh7021_device::itu_tsr_r<3>), FUNC(sh7021_device::itu_tsr_w<3>));
+ map(0x05ffff26, 0x05ffff27).rw(FUNC(sh7021_device::itu_tcnt_r<3>), FUNC(sh7021_device::itu_tcnt_w<3>));
+ map(0x05ffff28, 0x05ffff29).rw(FUNC(sh7021_device::itu_gra_r<3>), FUNC(sh7021_device::itu_gra_w<3>));
+ map(0x05ffff2a, 0x05ffff2b).rw(FUNC(sh7021_device::itu_grb_r<3>), FUNC(sh7021_device::itu_grb_w<3>));
+ map(0x05ffff2c, 0x05ffff2d).rw(FUNC(sh7021_device::itu_bra_r<3>), FUNC(sh7021_device::itu_bra_w<3>));
+ map(0x05ffff2e, 0x05ffff2f).rw(FUNC(sh7021_device::itu_brb_r<3>), FUNC(sh7021_device::itu_brb_w<3>));
+
+ map(0x05ffff32, 0x05ffff32).rw(FUNC(sh7021_device::itu_tcr_r<4>), FUNC(sh7021_device::itu_tcr_w<4>));
+ map(0x05ffff33, 0x05ffff33).rw(FUNC(sh7021_device::itu_tior_r<4>), FUNC(sh7021_device::itu_tior_w<4>));
+ map(0x05ffff34, 0x05ffff34).rw(FUNC(sh7021_device::itu_tier_r<4>), FUNC(sh7021_device::itu_tier_w<4>));
+ map(0x05ffff35, 0x05ffff35).rw(FUNC(sh7021_device::itu_tsr_r<4>), FUNC(sh7021_device::itu_tsr_w<4>));
+ map(0x05ffff36, 0x05ffff37).rw(FUNC(sh7021_device::itu_tcnt_r<4>), FUNC(sh7021_device::itu_tcnt_w<4>));
+ map(0x05ffff38, 0x05ffff39).rw(FUNC(sh7021_device::itu_gra_r<4>), FUNC(sh7021_device::itu_gra_w<4>));
+ map(0x05ffff3a, 0x05ffff3b).rw(FUNC(sh7021_device::itu_grb_r<4>), FUNC(sh7021_device::itu_grb_w<4>));
+ map(0x05ffff3c, 0x05ffff3d).rw(FUNC(sh7021_device::itu_bra_r<4>), FUNC(sh7021_device::itu_bra_w<4>));
+ map(0x05ffff3e, 0x05ffff3f).rw(FUNC(sh7021_device::itu_brb_r<4>), FUNC(sh7021_device::itu_brb_w<4>));
+
+ map(0x05ffff40, 0x05ffff43).rw(FUNC(sh7021_device::dma_sar_r<0>), FUNC(sh7021_device::dma_sar_w<0>));
+ map(0x05ffff44, 0x05ffff47).rw(FUNC(sh7021_device::dma_dar_r<0>), FUNC(sh7021_device::dma_dar_w<0>));
+ map(0x05ffff48, 0x05ffff49).rw(FUNC(sh7021_device::dmaor_r), FUNC(sh7021_device::dmaor_w));
+ map(0x05ffff4a, 0x05ffff4b).rw(FUNC(sh7021_device::dma_tcr_r<0>), FUNC(sh7021_device::dma_tcr_w<0>));
+ map(0x05ffff4e, 0x05ffff4f).rw(FUNC(sh7021_device::dma_chcr_r<0>), FUNC(sh7021_device::dma_chcr_w<0>));
+
+ map(0x05ffff50, 0x05ffff53).rw(FUNC(sh7021_device::dma_sar_r<1>), FUNC(sh7021_device::dma_sar_w<1>));
+ map(0x05ffff54, 0x05ffff57).rw(FUNC(sh7021_device::dma_dar_r<1>), FUNC(sh7021_device::dma_dar_w<1>));
+ map(0x05ffff5a, 0x05ffff5b).rw(FUNC(sh7021_device::dma_tcr_r<1>), FUNC(sh7021_device::dma_tcr_w<1>));
+ map(0x05ffff5e, 0x05ffff5f).rw(FUNC(sh7021_device::dma_chcr_r<1>), FUNC(sh7021_device::dma_chcr_w<1>));
+
+ map(0x05ffff60, 0x05ffff63).rw(FUNC(sh7021_device::dma_sar_r<2>), FUNC(sh7021_device::dma_sar_w<2>));
+ map(0x05ffff64, 0x05ffff67).rw(FUNC(sh7021_device::dma_dar_r<2>), FUNC(sh7021_device::dma_dar_w<2>));
+ map(0x05ffff6a, 0x05ffff6b).rw(FUNC(sh7021_device::dma_tcr_r<2>), FUNC(sh7021_device::dma_tcr_w<2>));
+ map(0x05ffff6e, 0x05ffff6f).rw(FUNC(sh7021_device::dma_chcr_r<2>), FUNC(sh7021_device::dma_chcr_w<2>));
+
+ map(0x05ffff70, 0x05ffff73).rw(FUNC(sh7021_device::dma_sar_r<3>), FUNC(sh7021_device::dma_sar_w<3>));
+ map(0x05ffff74, 0x05ffff77).rw(FUNC(sh7021_device::dma_dar_r<3>), FUNC(sh7021_device::dma_dar_w<3>));
+ map(0x05ffff7a, 0x05ffff7b).rw(FUNC(sh7021_device::dma_tcr_r<3>), FUNC(sh7021_device::dma_tcr_w<3>));
+ map(0x05ffff7e, 0x05ffff7f).rw(FUNC(sh7021_device::dma_chcr_r<3>), FUNC(sh7021_device::dma_chcr_w<3>));
+
+ map(0x05ffff84, 0x05ffff85).rw(FUNC(sh7021_device::intc_ipra_r), FUNC(sh7021_device::intc_ipra_w));
+ map(0x05ffff86, 0x05ffff87).rw(FUNC(sh7021_device::intc_iprb_r), FUNC(sh7021_device::intc_iprb_w));
+ map(0x05ffff88, 0x05ffff89).rw(FUNC(sh7021_device::intc_iprc_r), FUNC(sh7021_device::intc_iprc_w));
+ map(0x05ffff8a, 0x05ffff8b).rw(FUNC(sh7021_device::intc_iprd_r), FUNC(sh7021_device::intc_iprd_w));
+ map(0x05ffff8c, 0x05ffff8d).rw(FUNC(sh7021_device::intc_ipre_r), FUNC(sh7021_device::intc_ipre_w));
+ map(0x05ffff8e, 0x05ffff8f).rw(FUNC(sh7021_device::intc_icr_r), FUNC(sh7021_device::intc_icr_w));
+
+ map(0x05ffff90, 0x05ffff91).rw(FUNC(sh7021_device::ubc_barh_r), FUNC(sh7021_device::ubc_barh_w));
+ map(0x05ffff92, 0x05ffff93).rw(FUNC(sh7021_device::ubc_barl_r), FUNC(sh7021_device::ubc_barl_w));
+ map(0x05ffff94, 0x05ffff95).rw(FUNC(sh7021_device::ubc_bamrh_r), FUNC(sh7021_device::ubc_bamrh_w));
+ map(0x05ffff96, 0x05ffff97).rw(FUNC(sh7021_device::ubc_bamrl_r), FUNC(sh7021_device::ubc_bamrl_w));
+ map(0x05ffff98, 0x05ffff99).rw(FUNC(sh7021_device::ubc_bbr_r), FUNC(sh7021_device::ubc_bbr_w));
+
+ map(0x05ffffa0, 0x05ffffa1).rw(FUNC(sh7021_device::bsc_bcr_r), FUNC(sh7021_device::bsc_bcr_w));
+ map(0x05ffffa2, 0x05ffffa3).rw(FUNC(sh7021_device::bsc_wcr1_r), FUNC(sh7021_device::bsc_wcr1_w));
+ map(0x05ffffa4, 0x05ffffa5).rw(FUNC(sh7021_device::bsc_wcr2_r), FUNC(sh7021_device::bsc_wcr2_w));
+ map(0x05ffffa6, 0x05ffffa7).rw(FUNC(sh7021_device::bsc_wcr3_r), FUNC(sh7021_device::bsc_wcr3_w));
+ map(0x05ffffa8, 0x05ffffa9).rw(FUNC(sh7021_device::bsc_dcr_r), FUNC(sh7021_device::bsc_dcr_w));
+ map(0x05ffffaa, 0x05ffffab).rw(FUNC(sh7021_device::bsc_pcr_r), FUNC(sh7021_device::bsc_pcr_w));
+ map(0x05ffffac, 0x05ffffad).rw(FUNC(sh7021_device::bsc_rcr_r), FUNC(sh7021_device::bsc_rcr_w));
+ map(0x05ffffae, 0x05ffffaf).rw(FUNC(sh7021_device::bsc_rtcsr_r), FUNC(sh7021_device::bsc_rtcsr_w));
+ map(0x05ffffb0, 0x05ffffb1).rw(FUNC(sh7021_device::bsc_rtcnt_r), FUNC(sh7021_device::bsc_rtcnt_w));
+ map(0x05ffffb2, 0x05ffffb3).rw(FUNC(sh7021_device::bsc_rtcor_r), FUNC(sh7021_device::bsc_rtcor_w));
+
+ map(0x05ffffb8, 0x05ffffb8).rw(FUNC(sh7021_device::wdt_tcsr_r), FUNC(sh7021_device::wdt_tcsr_w));
+ map(0x05ffffb9, 0x05ffffb9).rw(FUNC(sh7021_device::wdt_tcnt_r), FUNC(sh7021_device::wdt_tcnt_w));
+ map(0x05ffffba, 0x05ffffba).rw(FUNC(sh7021_device::wdt_rstcsr_r), FUNC(sh7021_device::wdt_rstcsr_w));
+
+ map(0x05ffffc0, 0x05ffffc1).rw(FUNC(sh7021_device::pfc_padr_r), FUNC(sh7021_device::pfc_padr_w));
+ map(0x05ffffc2, 0x05ffffc3).rw(FUNC(sh7021_device::pfc_pbdr_r), FUNC(sh7021_device::pfc_pbdr_w));
+ map(0x05ffffc4, 0x05ffffc5).rw(FUNC(sh7021_device::pfc_paior_r), FUNC(sh7021_device::pfc_paior_w));
+ map(0x05ffffc6, 0x05ffffc7).rw(FUNC(sh7021_device::pfc_pbior_r), FUNC(sh7021_device::pfc_pbior_w));
+ map(0x05ffffc8, 0x05ffffc9).rw(FUNC(sh7021_device::pfc_pacr1_r), FUNC(sh7021_device::pfc_pacr1_w));
+ map(0x05ffffca, 0x05ffffcb).rw(FUNC(sh7021_device::pfc_pacr2_r), FUNC(sh7021_device::pfc_pacr2_w));
+ map(0x05ffffcc, 0x05ffffcd).rw(FUNC(sh7021_device::pfc_pbcr1_r), FUNC(sh7021_device::pfc_pbcr1_w));
+ map(0x05ffffce, 0x05ffffcf).rw(FUNC(sh7021_device::pfc_pbcr2_r), FUNC(sh7021_device::pfc_pbcr2_w));
+
+ map(0x05fffff0, 0x05fffff0).rw(FUNC(sh7021_device::tpc_tpmr_r), FUNC(sh7021_device::tpc_tpmr_w));
+ map(0x05fffff1, 0x05fffff1).rw(FUNC(sh7021_device::tpc_tpcr_r), FUNC(sh7021_device::tpc_tpcr_w));
+ map(0x05fffff2, 0x05fffff2).rw(FUNC(sh7021_device::tpc_ndera_r), FUNC(sh7021_device::tpc_ndera_w));
+ map(0x05fffff3, 0x05fffff3).rw(FUNC(sh7021_device::tpc_nderb_r), FUNC(sh7021_device::tpc_nderb_w));
+ map(0x05fffff4, 0x05fffff4).rw(FUNC(sh7021_device::tpc_ndrb_r), FUNC(sh7021_device::tpc_ndrb_w));
+ map(0x05fffff5, 0x05fffff5).rw(FUNC(sh7021_device::tpc_ndra_r), FUNC(sh7021_device::tpc_ndra_w));
+ map(0x05fffff6, 0x05fffff6).rw(FUNC(sh7021_device::tpc_ndrb_alt_r), FUNC(sh7021_device::tpc_ndrb_alt_w));
+ map(0x05fffff7, 0x05fffff7).rw(FUNC(sh7021_device::tpc_ndra_alt_r), FUNC(sh7021_device::tpc_ndra_alt_w));
+
+ map(0x07000000, 0x070003ff).ram().mirror(0x00fffc00); // 1KB internal RAM, actually at 0xf000000
+}
+
+sh7021_device::sh7021_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : sh2_device(mconfig, SH7021, tag, owner, clock, CPU_TYPE_SH2, address_map_constructor(FUNC(sh7021_device::internal_map), this), 28, 0xc7ffffff)
+ , m_pa_out(*this)
+ , m_pb_out(*this)
+ , m_pa_bit_out(*this)
+ , m_pb_bit_out(*this)
+{
+ m_isdrc = false; // FIXME
+}
+
+void sh7021_device::execute_run()
+{
+ int consumed_cycles = 0;
+ do
+ {
+ int icount_before = m_sh2_state->icount;
+ debugger_instruction_hook(m_sh2_state->pc);
+
+ const uint16_t opcode = decrypted_read_word(m_sh2_state->pc >= 0x40000000 ? m_sh2_state->pc : m_sh2_state->pc & m_am);
+
+ if (m_sh2_state->m_delay)
+ {
+ m_sh2_state->pc = m_sh2_state->m_delay;
+ m_sh2_state->m_delay = 0;
+ }
+ else
+ m_sh2_state->pc += 2;
+
+ execute_peripherals(consumed_cycles);
+ execute_one(opcode);
+
+ if (m_test_irq && !m_sh2_state->m_delay)
+ {
+ check_pending_irq("mame_sh2_execute");
+ m_test_irq = 0;
+ }
+ m_sh2_state->icount--;
+ consumed_cycles = icount_before - m_sh2_state->icount;
+ } while (m_sh2_state->icount > 0);
+}
+
+void sh7021_device::device_start()
+{
+ sh2_device::device_start();
+
+ m_itu.timer[0].et = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(sh7021_device::sh7021_timer_callback<0>), this));
+ m_itu.timer[1].et = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(sh7021_device::sh7021_timer_callback<1>), this));
+ m_itu.timer[2].et = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(sh7021_device::sh7021_timer_callback<2>), this));
+ m_itu.timer[3].et = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(sh7021_device::sh7021_timer_callback<3>), this));
+ m_itu.timer[4].et = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(sh7021_device::sh7021_timer_callback<4>), this));
+
+ for (uint32_t i = 0; i < 5; ++i)
+ {
+ m_itu.timer[i].et->adjust(attotime::never);
+ }
+
+ m_sci[0].et = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(sh7021_device::sh7021_sci_callback<0>), this));
+ m_sci[1].et = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(sh7021_device::sh7021_sci_callback<1>), this));
+
+ for (uint32_t i = 0; i < 2; ++i)
+ {
+ m_sci[i].et->adjust(attotime::never);
+ }
+
+ // Interrupt Controller (INTC)
+ save_item(NAME(m_iprc));
+ save_item(NAME(m_iprd));
+ save_item(NAME(m_ipre));
+ save_item(NAME(m_icr));
+
+ // User Break Controller (UBC)
+ save_item(STRUCT_MEMBER(m_ubc, barh));
+ save_item(STRUCT_MEMBER(m_ubc, barl));
+ save_item(STRUCT_MEMBER(m_ubc, bamrh));
+ save_item(STRUCT_MEMBER(m_ubc, bamrl));
+ save_item(STRUCT_MEMBER(m_ubc, bbr));
+
+ // Bus State Controller (BSC)
+ save_item(STRUCT_MEMBER(m_bsc, bcr));
+ save_item(STRUCT_MEMBER(m_bsc, wcr1));
+ save_item(STRUCT_MEMBER(m_bsc, wcr2));
+ save_item(STRUCT_MEMBER(m_bsc, wcr3));
+ save_item(STRUCT_MEMBER(m_bsc, dcr));
+ save_item(STRUCT_MEMBER(m_bsc, pcr));
+ save_item(STRUCT_MEMBER(m_bsc, rcr));
+ save_item(STRUCT_MEMBER(m_bsc, rtcsr));
+ save_item(STRUCT_MEMBER(m_bsc, rtcsr_read));
+ save_item(STRUCT_MEMBER(m_bsc, rtcnt));
+ save_item(STRUCT_MEMBER(m_bsc, rtcor));
+
+ // DMA Controller (DMAC)
+ save_item(STRUCT_MEMBER(m_dma, sar));
+ save_item(STRUCT_MEMBER(m_dma, dar));
+ save_item(STRUCT_MEMBER(m_dma, tcr));
+ save_item(STRUCT_MEMBER(m_dma, chcr));
+ save_item(NAME(m_dma_cycles));
+
+ // 16-Bit Integrated-Timer Pulse Unit (ITU)
+ save_item(STRUCT_MEMBER(m_itu, tstr));
+ save_item(STRUCT_MEMBER(m_itu, tsnc));
+ save_item(STRUCT_MEMBER(m_itu, tmdr));
+ save_item(STRUCT_MEMBER(m_itu, tfcr));
+ save_item(STRUCT_MEMBER(m_itu, tocr));
+ save_item(STRUCT_MEMBER(m_itu.timer, tcr));
+ save_item(STRUCT_MEMBER(m_itu.timer, tior));
+ save_item(STRUCT_MEMBER(m_itu.timer, tier));
+ save_item(STRUCT_MEMBER(m_itu.timer, tsr));
+ save_item(STRUCT_MEMBER(m_itu.timer, tcnt));
+ save_item(STRUCT_MEMBER(m_itu.timer, gra));
+ save_item(STRUCT_MEMBER(m_itu.timer, grb));
+ save_item(STRUCT_MEMBER(m_itu.timer, bra));
+ save_item(STRUCT_MEMBER(m_itu.timer, brb));
+
+ // Programmable Timing Pattern Controller (TPC)
+ save_item(STRUCT_MEMBER(m_tpc, tpmr));
+ save_item(STRUCT_MEMBER(m_tpc, tpcr));
+ save_item(STRUCT_MEMBER(m_tpc, ndera));
+ save_item(STRUCT_MEMBER(m_tpc, nderb));
+ save_item(STRUCT_MEMBER(m_tpc, ndra));
+ save_item(STRUCT_MEMBER(m_tpc, ndrb));
+
+ // Watchdog Timer (WDT)
+ save_item(STRUCT_MEMBER(m_wdt, tcsr));
+ save_item(STRUCT_MEMBER(m_wdt, tcnt));
+ save_item(STRUCT_MEMBER(m_wdt, rstcsr));
+
+ // Serial Communication Interface (SCI)
+ save_item(STRUCT_MEMBER(m_sci, smr));
+ save_item(STRUCT_MEMBER(m_sci, brr));
+ save_item(STRUCT_MEMBER(m_sci, scr));
+ save_item(STRUCT_MEMBER(m_sci, tsr));
+ save_item(STRUCT_MEMBER(m_sci, tdr));
+ save_item(STRUCT_MEMBER(m_sci, ssr));
+ save_item(STRUCT_MEMBER(m_sci, ssr_read));
+ save_item(STRUCT_MEMBER(m_sci, rsr));
+ save_item(STRUCT_MEMBER(m_sci, rdr));
+
+ // Pin Function Controller (PFC)
+ save_item(STRUCT_MEMBER(m_pfc, paior));
+ save_item(STRUCT_MEMBER(m_pfc, pacr1));
+ save_item(STRUCT_MEMBER(m_pfc, pacr2));
+ save_item(STRUCT_MEMBER(m_pfc, pbior));
+ save_item(STRUCT_MEMBER(m_pfc, pbcr1));
+ save_item(STRUCT_MEMBER(m_pfc, pbcr2));
+ save_item(STRUCT_MEMBER(m_pfc, padr));
+ save_item(STRUCT_MEMBER(m_pfc, pbdr));
+ save_item(STRUCT_MEMBER(m_pfc, padr_in));
+ save_item(STRUCT_MEMBER(m_pfc, pbdr_in));
+ save_item(STRUCT_MEMBER(m_pfc, cascr));
+ save_item(STRUCT_MEMBER(m_pfc, pafunc));
+ save_item(STRUCT_MEMBER(m_pfc, pbfunc));
+ save_item(STRUCT_MEMBER(m_pfc, pa_gpio_mask));
+ save_item(STRUCT_MEMBER(m_pfc, pb_gpio_mask));
+}
+
+void sh7021_device::device_reset()
+{
+ sh2_device::device_reset();
+
+ // Interrupt Controller (INTC)
+ m_ipra = 0;
+ m_iprb = 0;
+ m_iprc = 0;
+ m_iprd = 0;
+ m_ipre = 0;
+ m_icr = 0;
+
+ // User Break Controller (UBC)
+ m_ubc.barh = 0;
+ m_ubc.barl = 0;
+ m_ubc.bamrh = 0;
+ m_ubc.bamrl = 0;
+ m_ubc.bbr = 0;
+
+ // Bus State Controller (BSC)
+ m_bsc.bcr = 0;
+ m_bsc.wcr1 = 0xffff;
+ m_bsc.wcr2 = 0xffff;
+ m_bsc.wcr3 = 0xf800;
+ m_bsc.dcr = 0;
+ m_bsc.pcr = 0;
+ m_bsc.rcr = 0;
+ m_bsc.rtcsr = 0;
+ m_bsc.rtcsr_read = false;
+ m_bsc.rtcnt = 0;
+ m_bsc.rtcor = 0x00ff;
+
+ // DMA Controller (DMAC)
+ for (uint32_t i = 0; i < 4; i++)
+ {
+ m_dma[i].sar = 0;
+ m_dma[i].dar = 0;
+ m_dma[i].tcr = 0;
+ m_dma[i].chcr = 0;
+ }
+ m_dmaor = 0;
+ m_dma_cycles = 0;
+
+ // 16-Bit Integrated-Timer Pulse Unit (ITU)
+ m_itu.tstr = 0x60;
+ m_itu.tsnc = 0x60;
+ m_itu.tmdr = 0;
+ m_itu.tfcr = 0x40;
+ m_itu.tocr = 0x7f;
+ for (uint32_t i = 0; i < 5; i++)
+ {
+ m_itu.timer[i].tcr = 0;
+ m_itu.timer[i].tior = 0x08;
+ m_itu.timer[i].tier = 0xf8;
+ m_itu.timer[i].tsr = 0xf8;
+ m_itu.timer[i].tcnt = 0;
+ m_itu.timer[i].gra = 0xffff;
+ m_itu.timer[i].grb = 0xffff;
+ m_itu.timer[i].bra = 0xffff;
+ m_itu.timer[i].brb = 0xffff;
+ }
+
+ // Programmable Timing Pattern Controller (TPC)
+ m_tpc.tpmr = 0xf0;
+ m_tpc.tpcr = 0xff;
+ m_tpc.nderb = 0;
+ m_tpc.ndera = 0;
+ m_tpc.ndra = 0;
+ m_tpc.ndrb = 0;
+
+ // Watchdog Timer (WDT)
+ m_wdt.tcsr = 0x18;
+ m_wdt.tcnt = 0;
+ m_wdt.rstcsr = 0x3f;
+
+ // Serial Communication Interface (SCI)
+ for (uint32_t i = 0; i < 2; i++)
+ {
+ m_sci[i].smr = 0;
+ m_sci[i].brr = 0xff;
+ m_sci[i].scr = 0;
+ m_sci[i].tsr = 0;
+ m_sci[i].tdr = 0xff;
+ m_sci[i].ssr = 0x84;
+ m_sci[i].ssr_read = 0;
+ m_sci[i].rsr = 0;
+ m_sci[i].rdr = 0;
+ }
+
+ // Pin Function Controller (PFC)
+ m_pfc.paior = 0;
+ m_pfc.pacr1 = 0x3302;
+ m_pfc.pacr2 = 0xff95;
+ m_pfc.pbior = 0;
+ m_pfc.pbcr1 = 0;
+ m_pfc.pbcr2 = 0;
+ m_pfc.padr = 0;
+ m_pfc.pbdr = 0;
+ m_pfc.padr_in = 0;
+ m_pfc.pbdr_in = 0;
+ m_pfc.cascr = 0x5fff;
+ m_pfc.pa_gpio_mask = 0;
+ m_pfc.pb_gpio_mask = 0xffff;
+
+ static constexpr uint16_t PACR1_W_MASK = 0xfffd;
+ static constexpr uint16_t PACR2_W_MASK = 0x55ff;
+ for (int i = 0; i < 16; i++)
+ {
+ int bit = (i & 7) << 1;
+
+ uint16_t data = (i >= 8 ? (m_pfc.pacr1 & PACR1_W_MASK) : (m_pfc.pacr2 & PACR2_W_MASK));
+ uint8_t func = (data >> bit) & 3;
+ m_pfc.pafunc[i] = (data >> bit) & 3;
+ if (func == 0)
+ m_pfc.pa_gpio_mask |= 1 << i;
+ m_pfc.pbfunc[i] = 0;
+ }
+}
+
+uint8_t sh7021_device::read_byte(offs_t offset)
+{
+ const uint32_t area = (offset >> 24) & 7;
+ if (area == 6)
+ m_sh2_state->icount -= ((m_bsc.wcr3 >> 11) & 3) + 1; // Consume cycles specified by A6LW
+ else if (area == 0 || area == 2)
+ m_sh2_state->icount -= ((m_bsc.wcr3 >> 13) & 3) + 1; // Consume cycles specified by A02LW
+
+ return m_program->read_byte(offset & m_am);
+}
+
+uint16_t sh7021_device::read_word(offs_t offset)
+{
+ const uint32_t area = (offset >> 24) & 7;
+ if (area == 6)
+ m_sh2_state->icount -= ((m_bsc.wcr3 >> 11) & 3) + 1; // Consume cycles specified by A6LW
+ else if (area == 0 || area == 2)
+ m_sh2_state->icount -= ((m_bsc.wcr3 >> 13) & 3) + 1; // Consume cycles specified by A02LW
+
+ return m_program->read_word(offset & m_am);
+}
+
+uint32_t sh7021_device::read_long(offs_t offset)
+{
+ const uint32_t area = (offset >> 24) & 7;
+ if (area == 6)
+ m_sh2_state->icount -= ((m_bsc.wcr3 >> 11) & 3) + 1; // Consume cycles specified by A6LW
+ else if (area == 0 || area == 2)
+ m_sh2_state->icount -= ((m_bsc.wcr3 >> 13) & 3) + 1; // Consume cycles specified by A02LW
+
+ return m_program->read_dword(offset & m_am);
+}
+
+uint16_t sh7021_device::decrypted_read_word(offs_t offset)
+{
+ const uint32_t area = (offset >> 24) & 7;
+ if (area == 6)
+ m_sh2_state->icount -= ((m_bsc.wcr3 >> 11) & 3) + 1; // Consume cycles specified by A6LW
+ else if (area == 0 || area == 2)
+ m_sh2_state->icount -= ((m_bsc.wcr3 >> 13) & 3) + 1; // Consume cycles specified by A02LW
+
+ return m_decrypted_program->read_word(offset);
+}
+
+void sh7021_device::write_byte(offs_t offset, uint8_t data)
+{
+ const uint32_t area = (offset >> 24) & 7;
+ if (area == 6)
+ m_sh2_state->icount -= ((m_bsc.wcr3 >> 11) & 3) + 1; // Consume cycles specified by A6LW
+ else if (area == 0 || area == 2)
+ m_sh2_state->icount -= ((m_bsc.wcr3 >> 13) & 3) + 1; // Consume cycles specified by A02LW
+
+ m_program->write_byte(offset & m_am, data);
+}
+
+void sh7021_device::write_word(offs_t offset, uint16_t data)
+{
+ const uint32_t area = (offset >> 24) & 7;
+ if (area == 6)
+ m_sh2_state->icount -= ((m_bsc.wcr3 >> 11) & 3) + 1; // Consume cycles specified by A6LW
+ else if (area == 0 || area == 2)
+ m_sh2_state->icount -= ((m_bsc.wcr3 >> 13) & 3) + 1; // Consume cycles specified by A02LW
+
+ m_program->write_word(offset & m_am, data);
+}
+
+void sh7021_device::write_long(offs_t offset, uint32_t data)
+{
+ const uint32_t area = (offset >> 24) & 7;
+ if (area == 6)
+ m_sh2_state->icount -= ((m_bsc.wcr3 >> 11) & 3) + 1; // Consume cycles specified by A6LW
+ else if (area == 0 || area == 2)
+ m_sh2_state->icount -= ((m_bsc.wcr3 >> 13) & 3) + 1; // Consume cycles specified by A02LW
+
+ m_program->write_dword(offset & m_am, data);
+}
+
+void sh7021_device::recalc_irq()
+{
+ int irq = 0;
+ int vector = -1;
+
+ // Serial IRQs
+ for (uint32_t i = 0; i < 2; ++i)
+ {
+ int sci_level = (i == 1 ? ((m_ipre >> 12) & 0xf) : (m_iprd & 0xf));
+ if (sci_level == 0)
+ {
+ continue;
+ }
+
+ if (BIT(m_sci[i].scr, 7) && BIT(m_sci[i].ssr, 7))
+ {
+ // TxI
+ irq = sci_level;
+ vector = 102 + i * 4;
+ LOGMASKED(LOG_DMA_WR, "SCI Tx interrupt %d is ready, level %d vector %d\n", i, irq, vector);
+ }
+ else if (BIT(m_sci[i].scr, 2) && BIT(m_sci[i].ssr, 2))
+ {
+ // TEI
+ irq = sci_level;
+ vector = 103 + i * 4;
+ LOGMASKED(LOG_DMA_WR, "SCI TE interrupt %d is ready, level %d vector %d\n", i, irq, vector);
+ }
+ }
+
+ // Timer IRQs
+ for (uint32_t i = 0; i < 5; ++i)
+ {
+ if ((m_itu.timer[i].tier & m_itu.timer[i].tsr) & 7)
+ {
+ int level;
+
+ switch (i)
+ {
+ case 0:
+ level = (m_iprc >> 4) & 0xf;
+ break;
+ case 1:
+ level = (m_iprc >> 0) & 0xf;
+ break;
+ case 2:
+ level = (m_iprd >> 12) & 0xf;
+ break;
+ case 3:
+ level = (m_iprd >> 8) & 0xf;
+ break;
+ case 4:
+ level = (m_iprd >> 4) & 0xf;
+ break;
+ }
+
+ if (level == 0)
+ {
+ continue;
+ }
+
+ for (uint32_t j = 0; j < 3; j++)
+ {
+ if (BIT(m_itu.timer[i].tier & m_itu.timer[i].tsr, j))
+ {
+ irq = level;
+ vector = 80 + i * 4 + j;
+ break;
+ }
+ }
+ }
+ }
+
+ if (vector >= 0)
+ {
+ m_sh2_state->internal_irq_level = irq;
+ m_internal_irq_vector = vector;
+ m_test_irq = 1;
+ }
+}
+
+
+// Interrupt Controller (INTC)
+
+uint16_t sh7021_device::intc_ipra_r()
+{
+ if (!machine().side_effects_disabled())
+ LOGMASKED(LOG_INTC_RD, "%s: intc_ipra_r: %04x\n", machine().describe_context(), m_ipra);
+ return m_ipra;
+}
+
+void sh7021_device::intc_ipra_w(offs_t offset, uint16_t data, uint16_t mem_mask)
+{
+ LOGMASKED(LOG_INTC_WR, "%s: intc_ipra_w = %04x & %04x\n", machine().describe_context(), data, mem_mask);
+ COMBINE_DATA(&m_ipra);
+}
+
+uint16_t sh7021_device::intc_iprb_r()
+{
+ if (!machine().side_effects_disabled())
+ LOGMASKED(LOG_INTC_RD, "%s: intc_iprb_r: %04x\n", machine().describe_context(), m_iprb);
+ return m_iprb;
+}
+
+void sh7021_device::intc_iprb_w(offs_t offset, uint16_t data, uint16_t mem_mask)
+{
+ LOGMASKED(LOG_INTC_WR, "%s: intc_iprb_w = %04x & %04x\n", machine().describe_context(), data, mem_mask);
+ COMBINE_DATA(&m_iprb);
+}
+
+uint16_t sh7021_device::intc_iprc_r()
+{
+ if (!machine().side_effects_disabled())
+ LOGMASKED(LOG_INTC_RD, "%s: intc_iprc_r: %04x\n", machine().describe_context(), m_iprc);
+ return m_iprc;
+}
+
+void sh7021_device::intc_iprc_w(offs_t offset, uint16_t data, uint16_t mem_mask)
+{
+ LOGMASKED(LOG_INTC_WR, "%s: intc_iprc_w = %04x & %04x\n", machine().describe_context(), data, mem_mask);
+ COMBINE_DATA(&m_iprc);
+}
+
+uint16_t sh7021_device::intc_iprd_r()
+{
+ if (!machine().side_effects_disabled())
+ LOGMASKED(LOG_INTC_RD, "%s: intc_iprd_r: %04x\n", machine().describe_context(), m_iprd);
+ return m_iprd;
+}
+
+void sh7021_device::intc_iprd_w(offs_t offset, uint16_t data, uint16_t mem_mask)
+{
+ LOGMASKED(LOG_INTC_WR, "%s: intc_iprd_w = %04x & %04x\n", machine().describe_context(), data, mem_mask);
+ COMBINE_DATA(&m_iprd);
+}
+
+uint16_t sh7021_device::intc_ipre_r()
+{
+ if (!machine().side_effects_disabled())
+ LOGMASKED(LOG_INTC_RD, "%s: intc_ipre_r: %04x\n", machine().describe_context(), m_ipre);
+ return m_ipre;
+}
+
+void sh7021_device::intc_ipre_w(offs_t offset, uint16_t data, uint16_t mem_mask)
+{
+ LOGMASKED(LOG_INTC_WR, "%s: intc_ipre_w = %04x & %04x\n", machine().describe_context(), data, mem_mask);
+ COMBINE_DATA(&m_ipre);
+}
+
+uint16_t sh7021_device::intc_icr_r()
+{
+ if (!machine().side_effects_disabled())
+ LOGMASKED(LOG_INTC_RD, "%s: intc_icr_r: %04x\n", machine().describe_context(), m_ipre);
+ return m_icr;
+}
+
+void sh7021_device::intc_icr_w(offs_t offset, uint16_t data, uint16_t mem_mask)
+{
+ LOGMASKED(LOG_INTC_WR, "%s: intc_icr_w = %04x & %04x\n", machine().describe_context(), data, mem_mask);
+ COMBINE_DATA(&m_icr);
+}
+
+
+// User Break Controller (UBC)
+
+uint16_t sh7021_device::ubc_barh_r()
+{
+ if (!machine().side_effects_disabled())
+ LOGMASKED(LOG_UBC_RD, "%s: Break Address Register H, ubc_barh_r: %04x\n", machine().describe_context(), m_ubc.barh);
+ return m_ubc.barh;
+}
+
+void sh7021_device::ubc_barh_w(offs_t offset, uint16_t data, uint16_t mem_mask)
+{
+ LOGMASKED(LOG_UBC_WR, "%s: Break Address Register H, ubc_barh_w = %04x\n", machine().describe_context(), data);
+ COMBINE_DATA(&m_ubc.barh);
+}
+
+uint16_t sh7021_device::ubc_barl_r()
+{
+ if (!machine().side_effects_disabled())
+ LOGMASKED(LOG_UBC_RD, "%s: Break Address Register L, ubc_barl_r: %04x\n", machine().describe_context(), m_ubc.barl);
+ return m_ubc.barl;
+}
+
+void sh7021_device::ubc_barl_w(offs_t offset, uint16_t data, uint16_t mem_mask)
+{
+ LOGMASKED(LOG_UBC_WR, "%s: Break Address Register L, ubc_barl_w = %04x\n", machine().describe_context(), data);
+ COMBINE_DATA(&m_ubc.barl);
+}
+
+uint16_t sh7021_device::ubc_bamrh_r()
+{
+ if (!machine().side_effects_disabled())
+ LOGMASKED(LOG_UBC_RD, "%s: Break Address Mask Register H, ubc_bamrh_r: %04x\n", machine().describe_context(), m_ubc.bamrh);
+ return m_ubc.bamrh;
+}
+
+void sh7021_device::ubc_bamrh_w(offs_t offset, uint16_t data, uint16_t mem_mask)
+{
+ LOGMASKED(LOG_UBC_WR, "%s: Break Address Mask Register H, ubc_bmarh_w = %04x\n", machine().describe_context(), data);
+ COMBINE_DATA(&m_ubc.bamrh);
+}
+
+uint16_t sh7021_device::ubc_bamrl_r()
+{
+ if (!machine().side_effects_disabled())
+ LOGMASKED(LOG_UBC_RD, "%s: Break Address Mask Register L, ubc_bamrl_r: %04x\n", machine().describe_context(), m_ubc.bamrl);
+ return m_ubc.bamrl;
+}
+
+void sh7021_device::ubc_bamrl_w(offs_t offset, uint16_t data, uint16_t mem_mask)
+{
+ LOGMASKED(LOG_UBC_WR, "%s: Break Address Mask Register L, ubc_bmarl_w = %04x\n", machine().describe_context(), data);
+ COMBINE_DATA(&m_ubc.bamrl);
+}
+
+uint16_t sh7021_device::ubc_bbr_r()
+{
+ if (!machine().side_effects_disabled())
+ LOGMASKED(LOG_UBC_RD, "%s: Break Bus Cycle Register, ubc_bbr_r: %04x\n", machine().describe_context(), m_ubc.bbr);
+ return m_ubc.bbr;
+}
+
+void sh7021_device::ubc_bbr_w(offs_t offset, uint16_t data, uint16_t mem_mask)
+{
+ static const char *const CPU_DMA_NAMES[4] = { "No break", "Break on CPU cycles", "Break on DMA cycles", "Break on both CPU and DMA cycles" };
+ static const char *const INSN_DATA_NAMES[4] = { "No break", "Break on instruction fetch cycles", "Break on data access cycles", "Break on both instruction and data cycles" };
+ static const char *const READ_WRITE_NAMES[4] = { "No break", "Break on read cycles", "Break on write cycles", "Break on both read and write cycles" };
+ static const char *const SIZE_NAMES[4] = { "No break", "Break on byte access", "Break on word access", "Break on long word access" };
+ LOGMASKED(LOG_UBC_WR, "%s: Break Bus Cycle Register, ubc_bbr_w = %04x\n", machine().describe_context(), data);
+ LOGMASKED(LOG_UBC_WR, "%s: CPU/DMA Cycle Select: %s\n", machine().describe_context(), CPU_DMA_NAMES[(data >> 6) & 3]);
+ LOGMASKED(LOG_UBC_WR, "%s: Instruction/Data Fetch Select: %s\n", machine().describe_context(), INSN_DATA_NAMES[(data >> 4) & 3]);
+ LOGMASKED(LOG_UBC_WR, "%s: Read/Write Select: %s\n", machine().describe_context(), READ_WRITE_NAMES[(data >> 2) & 3]);
+ LOGMASKED(LOG_UBC_WR, "%s: Operand Size Select: %s\n", machine().describe_context(), SIZE_NAMES[data & 3]);
+ COMBINE_DATA(&m_ubc.bbr);
+}
+
+
+// Bus State Controller (BSC)
+
+uint16_t sh7021_device::bsc_bcr_r()
+{
+ if (!machine().side_effects_disabled())
+ LOGMASKED(LOG_BSC_RD, "%s: Bus Control Register, bsc_bcr_r: %04x\n", machine().describe_context(), m_bsc.bcr);
+ return m_bsc.bcr;
+}
+
+void sh7021_device::bsc_bcr_w(offs_t offset, uint16_t data, uint16_t mem_mask)
+{
+ LOGMASKED(LOG_BSC_WR, "%s: Bus Control Register bsc_bcr_w = %04x & %04x\n", machine().describe_context(), data, mem_mask);
+ LOGMASKED(LOG_BSC_WR, "%s: DRAM Enable: %d\n", machine().describe_context(), BIT(data, 15));
+ LOGMASKED(LOG_BSC_WR, "%s: Multiplexed I/O Enable: %d\n", machine().describe_context(), BIT(data, 14));
+ LOGMASKED(LOG_BSC_WR, "%s: WARP Enable: %d\n", machine().describe_context(), BIT(data, 13));
+ LOGMASKED(LOG_BSC_WR, "%s: /RD High Duty Cycle: %d% of T1 state\n", machine().describe_context(), BIT(data, 12) ? 35 : 50);
+ LOGMASKED(LOG_BSC_WR, "%s: Byte Access Select: %s\n", machine().describe_context(), BIT(data, 11) ? "/LBS, /WR, /HBS enabled" : "/WRH, /WRL, A0 enabled");
+ COMBINE_DATA(&m_bsc.bcr);
+}
+
+uint16_t sh7021_device::bsc_wcr1_r()
+{
+ if (!machine().side_effects_disabled())
+ LOGMASKED(LOG_BSC_RD, "%s: Wait State Control Register 1, bsc_wcr1_r: %04x\n", machine().describe_context(), m_bsc.wcr1);
+ return m_bsc.wcr1;
+}
+
+void sh7021_device::bsc_wcr1_w(offs_t offset, uint16_t data, uint16_t mem_mask)
+{
+ LOGMASKED(LOG_BSC_WR, "%s: Wait State Control Register 1, bsc_wcr1_w = %04x\n", machine().describe_context(), data);
+ COMBINE_DATA(&m_bsc.wcr1);
+}
+
+uint16_t sh7021_device::bsc_wcr2_r()
+{
+ if (!machine().side_effects_disabled())
+ LOGMASKED(LOG_BSC_RD, "%s: Wait State Control Register 2, bsc_wcr2_r: %04x\n", machine().describe_context(), m_bsc.wcr2);
+ return m_bsc.wcr2;
+}
+
+void sh7021_device::bsc_wcr2_w(offs_t offset, uint16_t data, uint16_t mem_mask)
+{
+ LOGMASKED(LOG_BSC_WR, "%s: Wait State Control Register 2, bsc_wcr2_w = %04x & %04x\n", machine().describe_context(), data, mem_mask);
+ COMBINE_DATA(&m_bsc.wcr2);
+}
+
+uint16_t sh7021_device::bsc_wcr3_r()
+{
+ if (!machine().side_effects_disabled())
+ LOGMASKED(LOG_BSC_RD, "%s: Wait State Control Register 3, bsc_wcr3_r: %04x\n", machine().describe_context(), m_bsc.wcr3);
+ return m_bsc.wcr3;
+}
+
+void sh7021_device::bsc_wcr3_w(offs_t offset, uint16_t data, uint16_t mem_mask)
+{
+ LOGMASKED(LOG_BSC_WR, "%s: Wait State Control Register 3, bsc_wcr3_w = %04x & %04x\n", machine().describe_context(), data, mem_mask);
+ COMBINE_DATA(&m_bsc.wcr3);
+}
+
+uint16_t sh7021_device::bsc_dcr_r()
+{
+ if (!machine().side_effects_disabled())
+ LOGMASKED(LOG_BSC_RD, "%s: DRAM Control Register, bsc_dcr_r: %04x\n", machine().describe_context(), m_bsc.dcr);
+ return m_bsc.dcr;
+}
+
+void sh7021_device::bsc_dcr_w(offs_t offset, uint16_t data, uint16_t mem_mask)
+{
+ LOGMASKED(LOG_BSC_WR, "%s: DRAM Control Register, bsc_dcr_w = %04x & %04x\n", machine().describe_context(), data, mem_mask);
+ LOGMASKED(LOG_BSC_WR, "%s: Dual-WE Mode: %d\n", machine().describe_context(), BIT(data, 15));
+ LOGMASKED(LOG_BSC_WR, "%s: RAS Down Mode: %d\n", machine().describe_context(), BIT(data, 14));
+ LOGMASKED(LOG_BSC_WR, "%s: 2-state Precharge: %d\n", machine().describe_context(), BIT(data, 13));
+ LOGMASKED(LOG_BSC_WR, "%s: Burst Enable: %d\n", machine().describe_context(), BIT(data, 12));
+ LOGMASKED(LOG_BSC_WR, "%s: /CAS High Duty Cycle: %d% of Tc state\n", machine().describe_context(), BIT(data, 11) ? 35 : 50);
+ LOGMASKED(LOG_BSC_WR, "%s: Row/Column Multiplex Enable: %d\n", machine().describe_context(), BIT(data, 10));
+ LOGMASKED(LOG_BSC_WR, "%s: Multiplex Shift Count: %d\n", machine().describe_context(), 8 + ((data >> 8) & 3));
+ COMBINE_DATA(&m_bsc.dcr);
+}
+
+uint16_t sh7021_device::bsc_pcr_r()
+{
+ if (!machine().side_effects_disabled())
+ LOGMASKED(LOG_BSC_RD, "%s: Parity Control Register, bsc_pcr_r: %04x\n", machine().describe_context(), m_bsc.pcr);
+ return m_bsc.pcr;
+}
+
+void sh7021_device::bsc_pcr_w(offs_t offset, uint16_t data, uint16_t mem_mask)
+{
+ static const char *const PARITY_CHECK_NAMES[4] =
+ {
+ "Don't Check, Don't Generate",
+ "Check and Generate in DRAM",
+ "Check and Generate in DRAM and Area 2",
+ "Reserved",
+ };
+
+ LOGMASKED(LOG_BSC_WR, "%s: Parity Control Register, bsc_pcr_w = %04x & %04x\n", machine().describe_context(), data, mem_mask);
+ LOGMASKED(LOG_BSC_WR, "%s: Parity Error Clear: %d\n", machine().describe_context(), BIT(data, 15));
+ LOGMASKED(LOG_BSC_WR, "%s: Force Parity Error: %d\n", machine().describe_context(), BIT(data, 14));
+ LOGMASKED(LOG_BSC_WR, "%s: Parity Polarity: %s\n", machine().describe_context(), BIT(data, 13) ? "odd" : "even");
+ LOGMASKED(LOG_BSC_WR, "%s: Parity Check Enable: %s\n", machine().describe_context(), PARITY_CHECK_NAMES[(data >> 11) & 3]);
+ LOGMASKED(LOG_BSC_WR, "%s: Parity Error Clear: %d\n", machine().describe_context(), BIT(data, 15));
+ COMBINE_DATA(&m_bsc.pcr);
+}
+
+uint16_t sh7021_device::bsc_rcr_r()
+{
+ if (!machine().side_effects_disabled())
+ LOGMASKED(LOG_BSC_RD, "%s: Refresh Control Register, bsc_rcr_r: %04x\n", machine().describe_context(), m_bsc.rcr);
+ return m_bsc.rcr;
+}
+
+void sh7021_device::bsc_rcr_w(uint16_t data)
+{
+ if ((data >> 8) != 0x5a)
+ return;
+
+ LOGMASKED(LOG_BSC_WR, "%s: Refresh Control Register, bsc_rcr_w = %02x\n", machine().describe_context(), (uint8_t)data);
+ LOGMASKED(LOG_BSC_WR, "%s: Refresh Control Enable: %d\n", machine().describe_context(), BIT(data, 7));
+ LOGMASKED(LOG_BSC_WR, "%s: Refresh Mode: %s\n", machine().describe_context(), BIT(data, 6) ? "Self-refresh" : "CAS-before-RAS");
+ LOGMASKED(LOG_BSC_WR, "%s: CBR Wait States: %d\n", machine().describe_context(), 1 + ((data >> 4) & 3));
+ m_bsc.rcr = (uint8_t)data;
+}
+
+uint16_t sh7021_device::bsc_rtcsr_r()
+{
+ if (!machine().side_effects_disabled())
+ {
+ LOGMASKED(LOG_BSC_RD, "%s: Refresh Timer Control/Status Register, bsc_rtcsr_r: %04x\n", machine().describe_context(), m_bsc.rtcsr);
+ if (BIT(m_bsc.rtcsr, 7))
+ m_bsc.rtcsr_read = true;
+ }
+ return m_bsc.rtcsr;
+}
+
+void sh7021_device::bsc_rtcsr_w(uint16_t data)
+{
+ if ((data >> 8) != 0xa5)
+ return;
+
+ static const char *const RTCSR_CKS_NAMES[8] =
+ {
+ "Disabled", "/2", "/8", "/32", "/128", "/512", "/2048", "/4096"
+ };
+
+ LOGMASKED(LOG_BSC_WR, "%s: Refresh Timer Control/Status Register, bsc_rcr_w = %02x\n", machine().describe_context(), (uint8_t)data);
+ LOGMASKED(LOG_BSC_WR, "%s: Refresh Control Enable: %d\n", machine().describe_context(), BIT(data, 7));
+ LOGMASKED(LOG_BSC_WR, "%s: Compare Match Interrupt Enable: %d\n", machine().describe_context(), BIT(data, 6));
+ LOGMASKED(LOG_BSC_WR, "%s: Refresh Timer Counter Prescale: %d\n", machine().describe_context(), RTCSR_CKS_NAMES[(data >> 3) & 7]);
+ m_bsc.rtcsr = (m_bsc.rtcsr & 0x80) | (uint8_t)(data & 0x7f);
+ if (m_bsc.rtcsr_read && !BIT(data, 7))
+ {
+ m_bsc.rtcsr_read = false;
+ m_bsc.rtcsr &= 0x7f;
+ }
+}
+
+uint16_t sh7021_device::bsc_rtcnt_r()
+{
+ if (!machine().side_effects_disabled())
+ LOGMASKED(LOG_BSC_RD, "%s: Refresh Timer Count, bsc_rtcnt_r: %04x\n", machine().describe_context(), m_bsc.rtcnt);
+ return m_bsc.rtcnt;
+}
+
+void sh7021_device::bsc_rtcnt_w(uint16_t data)
+{
+ if ((data >> 8) != 0x69)
+ return;
+
+ LOGMASKED(LOG_BSC_WR, "%s: Refresh Timer Count, bsc_rtcnt_w = %02x\n", machine().describe_context(), (uint8_t)data);
+ m_bsc.rtcnt = (uint8_t)data;
+}
+
+uint16_t sh7021_device::bsc_rtcor_r()
+{
+ if (!machine().side_effects_disabled())
+ LOGMASKED(LOG_BSC_RD, "%s: Refresh Time Constant Register, bsc_rtcor_r: %04x\n", machine().describe_context(), m_bsc.rtcor);
+ return m_bsc.rtcor;
+}
+
+void sh7021_device::bsc_rtcor_w(uint16_t data)
+{
+ if ((data >> 8) != 0x96)
+ return;
+
+ LOGMASKED(LOG_BSC_WR, "%s: Refresh Time Constant Register, bsc_rtcor_w = %02x\n", machine().describe_context(), (uint8_t)data);
+ m_bsc.rtcor = (uint8_t)data;
+}
+
+
+// DMA Controller (DMAC)
+
+template uint32_t sh7021_device::dma_sar_r<0>();
+template uint32_t sh7021_device::dma_sar_r<1>();
+template uint32_t sh7021_device::dma_sar_r<2>();
+template uint32_t sh7021_device::dma_sar_r<3>();
+
+template <int Channel>
+uint32_t sh7021_device::dma_sar_r()
+{
+ if (!machine().side_effects_disabled())
+ LOGMASKED(LOG_DMA_RD, "%s: DMA Source Address Register %d, dma_sar_r: %08x\n", machine().describe_context(), Channel, m_dma[Channel].sar);
+ return m_dma[Channel].sar;
+}
+
+template void sh7021_device::dma_sar_w<0>(offs_t offset, uint32_t data, uint32_t mem_mask);
+template void sh7021_device::dma_sar_w<1>(offs_t offset, uint32_t data, uint32_t mem_mask);
+template void sh7021_device::dma_sar_w<2>(offs_t offset, uint32_t data, uint32_t mem_mask);
+template void sh7021_device::dma_sar_w<3>(offs_t offset, uint32_t data, uint32_t mem_mask);
+
+template <int Channel>
+void sh7021_device::dma_sar_w(offs_t offset, uint32_t data, uint32_t mem_mask)
+{
+ LOGMASKED(LOG_DMA_WR, "%s: DMA Source Address Register %d, dma_sar_w = %08x & %08x\n", machine().describe_context(), Channel, data, mem_mask);
+ COMBINE_DATA(&m_dma[Channel].sar);
+}
+
+template uint32_t sh7021_device::dma_dar_r<0>();
+template uint32_t sh7021_device::dma_dar_r<1>();
+template uint32_t sh7021_device::dma_dar_r<2>();
+template uint32_t sh7021_device::dma_dar_r<3>();
+
+template <int Channel>
+uint32_t sh7021_device::dma_dar_r()
+{
+ if (!machine().side_effects_disabled())
+ LOGMASKED(LOG_DMA_RD, "%s: DMA Destination Address Register %d, dma_sar_r: %08x\n", machine().describe_context(), Channel, m_dma[Channel].dar);
+ return m_dma[Channel].dar;
+}
+
+template void sh7021_device::dma_dar_w<0>(offs_t offset, uint32_t data, uint32_t mem_mask);
+template void sh7021_device::dma_dar_w<1>(offs_t offset, uint32_t data, uint32_t mem_mask);
+template void sh7021_device::dma_dar_w<2>(offs_t offset, uint32_t data, uint32_t mem_mask);
+template void sh7021_device::dma_dar_w<3>(offs_t offset, uint32_t data, uint32_t mem_mask);
+
+template <int Channel>
+void sh7021_device::dma_dar_w(offs_t offset, uint32_t data, uint32_t mem_mask)
+{
+ LOGMASKED(LOG_DMA_WR, "%s: DMA Destination Address Register %d, dma_dar_w = %08x & %08x\n", machine().describe_context(), Channel, data, mem_mask);
+ COMBINE_DATA(&m_dma[Channel].dar);
+}
+
+template uint16_t sh7021_device::dma_tcr_r<0>();
+template uint16_t sh7021_device::dma_tcr_r<1>();
+template uint16_t sh7021_device::dma_tcr_r<2>();
+template uint16_t sh7021_device::dma_tcr_r<3>();
+
+template <int Channel>
+uint16_t sh7021_device::dma_tcr_r()
+{
+ if (!machine().side_effects_disabled())
+ LOGMASKED(LOG_DMA_RD, "%s: DMA Transfer Count Register %d, dma_tcr_r: %04x\n", machine().describe_context(), Channel, m_dma[Channel].tcr);
+ return m_dma[Channel].tcr;
+}
+
+template void sh7021_device::dma_tcr_w<0>(offs_t offset, uint16_t data, uint16_t mem_mask);
+template void sh7021_device::dma_tcr_w<1>(offs_t offset, uint16_t data, uint16_t mem_mask);
+template void sh7021_device::dma_tcr_w<2>(offs_t offset, uint16_t data, uint16_t mem_mask);
+template void sh7021_device::dma_tcr_w<3>(offs_t offset, uint16_t data, uint16_t mem_mask);
+
+template <int Channel>
+void sh7021_device::dma_tcr_w(offs_t offset, uint16_t data, uint16_t mem_mask)
+{
+ LOGMASKED(LOG_DMA_WR, "%s: DMA Transfer Count Register %d, dma_tcr_w = %04x & %04x\n", machine().describe_context(), Channel, data, mem_mask);
+ COMBINE_DATA(&m_dma[Channel].tcr);
+}
+
+
+template uint16_t sh7021_device::dma_chcr_r<0>();
+template uint16_t sh7021_device::dma_chcr_r<1>();
+template uint16_t sh7021_device::dma_chcr_r<2>();
+template uint16_t sh7021_device::dma_chcr_r<3>();
+
+template <int Channel>
+uint16_t sh7021_device::dma_chcr_r()
+{
+ if (!machine().side_effects_disabled())
+ LOGMASKED(LOG_DMA_RD, "%s: DMA Channel Control Register %d, dma_chcr_r: %04x\n", machine().describe_context(), Channel, m_dma[Channel].chcr);
+ return m_dma[Channel].chcr;
+}
+
+template void sh7021_device::dma_chcr_w<0>(offs_t offset, uint16_t data, uint16_t mem_mask);
+template void sh7021_device::dma_chcr_w<1>(offs_t offset, uint16_t data, uint16_t mem_mask);
+template void sh7021_device::dma_chcr_w<2>(offs_t offset, uint16_t data, uint16_t mem_mask);
+template void sh7021_device::dma_chcr_w<3>(offs_t offset, uint16_t data, uint16_t mem_mask);
+
+template <int Channel>
+void sh7021_device::dma_chcr_w(offs_t offset, uint16_t data, uint16_t mem_mask)
+{
+ static const char *const ADDR_MODE_NAMES[4] =
+ {
+ "Fixed", "Increment", "Decrement", "Reserved"
+ };
+ static const char *const SOURCE_NAMES[16] =
+ {
+ "/DREQ, Dual-Address Mode",
+ "Reserved (1)",
+ "/DREQ, Memory-to-device",
+ "/DREQ, Device-to-memory",
+ "RXI0 (Serial 0 Receive), Dual-Address Mode",
+ "TXI0 (Serial 0 Transmit), Dual-Address Mode",
+ "RXI1 (Serial 1 Receive), Dual-Address Mode",
+ "TXI1 (Serial 1 Transmit), Dual-Address Mode",
+ "IMIA0 (Timer 0 Capture/Compare-Match), Dual-Address Mode",
+ "IMIA1 (Timer 1 Capture/Compare-Match), Dual-Address Mode",
+ "IMIA2 (Timer 2 Capture/Compare-Match), Dual-Address Mode",
+ "IMIA3 (Timer 3 Capture/Compare-Match), Dual-Address Mode",
+ "Auto-Request, Dual-Address Mode",
+ "Reserved (13)",
+ "Reserved (14)",
+ "Reserved (15)"
+ };
+
+ LOGMASKED(LOG_DMA_WR, "%s: DMA Channel Control Register %d, dma_chcr_w = %04x & %04x\n", machine().describe_context(), Channel, data, mem_mask);
+ LOGMASKED(LOG_DMA_WR, "%s: Dest Address Mode: %s\n", machine().describe_context(), ADDR_MODE_NAMES[data >> 14]);
+ LOGMASKED(LOG_DMA_WR, "%s: Source Address Mode: %s\n", machine().describe_context(), ADDR_MODE_NAMES[(data >> 12) & 3]);
+ LOGMASKED(LOG_DMA_WR, "%s: Resource Select: %s\n", machine().describe_context(), SOURCE_NAMES[(data >> 8) & 15]);
+ LOGMASKED(LOG_DMA_WR, "%s: Acknowledge Bit: DACK output in %s cycle\n", machine().describe_context(), BIT(data, 7) ? "write" : "read");
+ LOGMASKED(LOG_DMA_WR, "%s: Acknowledge Level Bit: DACK active %s\n", machine().describe_context(), BIT(data, 6) ? "low" : "high");
+ LOGMASKED(LOG_DMA_WR, "%s: /DREQ Detect Mode: %s\n", machine().describe_context(), BIT(data, 5) ? "Edge" : "Level");
+ LOGMASKED(LOG_DMA_WR, "%s: Transfer Mode: %s\n", machine().describe_context(), BIT(data, 4) ? "Burst Mode" : "Cycle-Steal");
+ LOGMASKED(LOG_DMA_WR, "%s: Transfer Size: %s\n", machine().describe_context(), BIT(data, 3) ? "Word" : "Byte");
+ LOGMASKED(LOG_DMA_WR, "%s: Interrupt Enable: %d\n", machine().describe_context(), BIT(data, 2));
+ LOGMASKED(LOG_DMA_WR, "%s: Transfer End Clear: %d\n", machine().describe_context(), BIT(data, 1));
+ LOGMASKED(LOG_DMA_WR, "%s: Transfer Enable: %d\n", machine().describe_context(), BIT(data, 0));
+ COMBINE_DATA(&m_dma[Channel].chcr);
+ execute_dma(Channel);
+}
+
+uint16_t sh7021_device::dmaor_r()
+{
+ if (!machine().side_effects_disabled())
+ {
+ LOGMASKED(LOG_DMA_RD, "%s: DMA Operation Register, dmaor_r: %04x\n", machine().describe_context(), m_dmaor);
+ LOGMASKED(LOG_DMA_RD, "%s: Address Error Flag: %d\n", machine().describe_context(), BIT(m_dmaor, 2));
+ LOGMASKED(LOG_DMA_RD, "%s: NMI Flag: %d\n", machine().describe_context(), BIT(m_dmaor, 1));
+ LOGMASKED(LOG_DMA_RD, "%s: DMA Master Enable: %d\n", machine().describe_context(), BIT(m_dmaor, 0));
+ }
+ return m_dmaor;
+}
+
+void sh7021_device::dmaor_w(offs_t offset, uint16_t data, uint16_t mem_mask)
+{
+ static const char *const PRIORITY_NAMES[4] =
+ {
+ "Fixed Priority (0 -> 3 -> 2 -> 1)",
+ "Fixed Priority (1 -> 3 -> 2 -> 0)",
+ "Round-Robin Priority",
+ "External-Pin Round-Robin Priority"
+ };
+ LOGMASKED(LOG_DMA_WR, "%s: DMA Operation Register, dmaor_w = %04x & %04x\n", machine().describe_context(), data, mem_mask);
+ LOGMASKED(LOG_DMA_WR, "%s: Priority Mode: %s\n", machine().describe_context(), PRIORITY_NAMES[(data >> 8) & 3]);
+ LOGMASKED(LOG_DMA_WR, "%s: Address Error Flag: %d\n", machine().describe_context(), BIT(data, 2));
+ LOGMASKED(LOG_DMA_WR, "%s: NMI Flag: %d\n", machine().describe_context(), BIT(data, 1));
+ LOGMASKED(LOG_DMA_WR, "%s: DMA Master Enable: %d\n", machine().describe_context(), BIT(data, 0));
+ COMBINE_DATA(&m_dmaor);
+}
+
+void sh7021_device::execute_dma(int ch)
+{
+ const short dma_word_size[4] = { 0, +1, -1, 0 };
+ uint8_t rs = (m_dma[ch].chcr >> 8) & 0xf; /**< Resource Select bits */
+
+ // channel enable & master enable
+ if ((m_dma[ch].chcr & 1) == 0 || (m_dmaor & 1) == 0)
+ {
+ return;
+ }
+
+ uint8_t dm = (m_dma[ch].chcr >> 14) & 3; /**< Destination Address Mode bits */
+ uint8_t sm = (m_dma[ch].chcr >> 12) & 3; /**< Source Address Mode bits */
+ bool ts = (m_dma[ch].chcr & 8); /**< Transfer Size bit */
+ int src_word_size = dma_word_size[sm] * (ts ? 2 : 1);
+ int dst_word_size = dma_word_size[dm] * (ts ? 2 : 1);
+ uint32_t src_addr = m_dma[ch].sar;
+ uint32_t dst_addr = m_dma[ch].dar;
+ uint32_t count = m_dma[ch].tcr;
+
+ if (count == 0)
+ {
+ count = 0x10000;
+ }
+
+ if (!ts)
+ {
+ //printf("SH7032: DMA byte mode check\n");
+ //printf("DMA%u: S:%08x D:%08x C:%08x CTRL:%04x\n", ch, m_dma[ch].sar, m_dma[ch].dar, m_dma[ch].tcr, m_dma[ch].chcr);
+ //printf("SRC_INC: %d DST_INC: %d\n", src_word_size, dst_word_size);
+ //printf("MODE: %s\n\n", m_dma[ch].chcr & (1 << 4) ? "BURST" : "STEAL");
+ }
+
+ // Fake a a Transmit End Interrupt
+ if (rs == 5 || rs == 7)
+ {
+ int channel = (rs == 5 ? 0 : 1);
+ uint64_t clock_divider = 1 << ((m_sci[channel].smr & 3) << 1);
+ uint64_t char_length = BIT(m_sci[channel].smr, 6) ? 8 : 7;
+ uint64_t stop_bits = BIT(m_sci[channel].smr, 3) ? 2 : 1;
+ attotime transmit_time = attotime::from_ticks(clock_divider * count * (char_length + stop_bits) * (m_sci[channel].brr + 1), clock());
+ m_sci[channel].et->adjust(transmit_time);
+ LOGMASKED(LOG_DMA_WR, "Setting SCI channel %d to elapse in %d ticks (%d * %d * (%d + %d) * %d)\n", channel, clock_divider * count * (char_length + stop_bits) * (m_sci[channel].brr + 1),
+ clock_divider, count, char_length, stop_bits, m_sci[channel].brr + 1);
+ }
+
+ for (int i = 0; i < count; ++i)
+ {
+ if (ts)
+ m_program->write_word(dst_addr & m_am, m_program->read_word(src_addr & m_am));
+ else
+ m_program->write_byte(dst_addr & m_am, m_program->read_byte(src_addr & m_am));
+
+ src_addr += src_word_size;
+ dst_addr += dst_word_size;
+ }
+
+ m_dma[ch].sar = src_addr;
+ m_dma[ch].dar = dst_addr;
+
+ m_dma[ch].chcr |= 2; // Transfer ended
+
+ // TODO: IRQs
+}
+
+void sh7021_device::execute_peripherals(int peripheral_cycles)
+{
+ m_dma_cycles += peripheral_cycles;
+}
+
+// 16-Bit Integrated-Timer Pulse Unit (ITU)
+
+template TIMER_CALLBACK_MEMBER(sh7021_device::sh7021_timer_callback<0>);
+template TIMER_CALLBACK_MEMBER(sh7021_device::sh7021_timer_callback<1>);
+template TIMER_CALLBACK_MEMBER(sh7021_device::sh7021_timer_callback<2>);
+template TIMER_CALLBACK_MEMBER(sh7021_device::sh7021_timer_callback<3>);
+template TIMER_CALLBACK_MEMBER(sh7021_device::sh7021_timer_callback<4>);
+
+template<int Which>
+TIMER_CALLBACK_MEMBER(sh7021_device::sh7021_timer_callback)
+{
+ // TCNT0 and 1 are up-counters
+ //if (Which < 2)
+ {
+ //if (Which == 0)
+ //LOGMASKED(LOG_ITU_WR, "T%d %04x\n", Which, m_itu.timer[Which].tcnt);
+ m_itu.timer[Which].tcnt++;
+
+ if (m_itu.timer[Which].tcnt == 0)
+ {
+ LOGMASKED(LOG_ITU_WR, "Timer %d has overflowed, flagging OVF\n", Which);
+ m_itu.timer[Which].tsr |= 4; // OVF
+ }
+ }
+
+ if (m_itu.timer[Which].tcnt == m_itu.timer[Which].gra)
+ {
+ LOGMASKED(LOG_ITU_WR, "Timer %d count %04x matches GRA %04x, flagging IMFA\n", Which, m_itu.timer[Which].tcnt, m_itu.timer[Which].gra);
+ m_itu.timer[Which].tsr |= 1; // IMFA
+
+ // CCLR[1:0] = 01
+ if (((m_itu.timer[Which].tcr >> 5) & 3) == 1)
+ {
+ LOGMASKED(LOG_ITU_WR, "Timer %d resetting count to 0\n", Which);
+ m_itu.timer[Which].tcnt = 0;
+ }
+ }
+
+ if (m_itu.timer[Which].tcnt == m_itu.timer[Which].grb)
+ {
+ LOGMASKED(LOG_ITU_WR, "Timer %d count %04x matches GRB %04x, flagging IMFB\n", Which, m_itu.timer[Which].tcnt, m_itu.timer[Which].grb);
+ m_itu.timer[Which].tsr |= 2; // IMFB
+
+ // CCLR[1:0] = 10
+ if (((m_itu.timer[Which].tcr >> 5) & 3) == 2)
+ m_itu.timer[Which].tcnt = 0;
+ }
+
+ recalc_irq();
+ //start_timer(Which);
+}
+
+void sh7021_device::start_timer(int i)
+{
+ if (m_itu.timer[i].tcr & 4)
+ fatalerror("external clock source");
+
+ int prescale = 1 << (m_itu.timer[i].tcr & 3);
+
+// printf("Starting timer %u: TCNT:%x GR:%x TCR:%x TI:%x TICK:%f\n", i, m_itu.timer[i].tcnt, m_itu.timer[i].gra, m_itu.timer[i].tcr & 7, m_itu.timer[i].tier, (double)clock()/psc);
+// printf("%d\n", clock());
+ LOGMASKED(LOG_ITU_WR, "Starting Timer %d, prescale %d, clock %d, current count %04x\n", i, prescale, clock(), m_itu.timer[i].tcnt);
+ attotime period = attotime::from_ticks(prescale, clock());
+ m_itu.timer[i].et->adjust(period, i, period);
+}
+
+uint8_t sh7021_device::itu_tstr_r()
+{
+ if (!machine().side_effects_disabled())
+ LOGMASKED(LOG_ITU_RD, "%s: Timer Start Register, itu_tstr_r: %02x\n", machine().describe_context(), m_itu.tstr);
+ return m_itu.tstr | 0x60;
+}
+
+void sh7021_device::itu_tstr_w(uint8_t data)
+{
+ LOGMASKED(LOG_ITU_WR, "%s: Timer Start Register, itu_tstr_w = %02x\n", machine().describe_context(), data);
+
+ // Starts timers
+ const uint8_t newly_enabled = ~m_itu.tstr & data;
+ const uint8_t newly_disabled = m_itu.tstr & ~data;
+ m_itu.tstr = data;
+
+ for (int i = 0; i < 5; ++i)
+ {
+ if (BIT(newly_disabled, i))
+ {
+ LOGMASKED(LOG_ITU_WR, "%s: Timer Start Register, timer %d disabled\n", machine().describe_context(), i);
+ m_itu.timer[i].et->adjust(attotime::never);
+ }
+ else if (BIT(newly_enabled, i))
+ {
+ LOGMASKED(LOG_ITU_WR, "%s: Timer Start Register, timer %d enabled\n", machine().describe_context(), i);
+ start_timer(i);
+ }
+ }
+}
+
+uint8_t sh7021_device::itu_tsnc_r()
+{
+ if (!machine().side_effects_disabled())
+ LOGMASKED(LOG_ITU_RD, "%s: Timer Synchro Register, itu_tsnc_r: %02x\n", machine().describe_context(), m_itu.tsnc);
+ return m_itu.tsnc;
+}
+
+void sh7021_device::itu_tsnc_w(uint8_t data)
+{
+ LOGMASKED(LOG_ITU_WR, "%s: Timer Synchro Register, itu_tsnc_w = %02x\n", machine().describe_context(), data);
+ m_itu.tsnc = data;
+}
+
+uint8_t sh7021_device::itu_tmdr_r()
+{
+ if (!machine().side_effects_disabled())
+ LOGMASKED(LOG_ITU_RD, "%s: Timer Mode Register, itu_tmdr_r: %02x\n", machine().describe_context(), m_itu.tmdr);
+ return m_itu.tmdr;
+}
+
+void sh7021_device::itu_tmdr_w(uint8_t data)
+{
+ LOGMASKED(LOG_ITU_WR, "%s: Timer Mode Register, itu_tmdr_w = %02x\n", machine().describe_context(), data);
+ LOGMASKED(LOG_ITU_WR, "%s: Channel 2 Phase Counting Mode: %d\n", machine().describe_context(), BIT(data, 6));
+ LOGMASKED(LOG_ITU_WR, "%s: Channel 2 Overflow Behavior: %d\n", machine().describe_context(), BIT(data, 5) ? "Set OVF of TSR2 on TCNT2 overflow" : "Set OVF of TSR2 on TCNT2 overflow and underflow");
+ LOGMASKED(LOG_ITU_WR, "%s: Channel 4 PWM Mode: %d\n", machine().describe_context(), BIT(data, 4));
+ LOGMASKED(LOG_ITU_WR, "%s: Channel 3 PWM Mode: %d\n", machine().describe_context(), BIT(data, 3));
+ LOGMASKED(LOG_ITU_WR, "%s: Channel 2 PWM Mode: %d\n", machine().describe_context(), BIT(data, 2));
+ LOGMASKED(LOG_ITU_WR, "%s: Channel 1 PWM Mode: %d\n", machine().describe_context(), BIT(data, 1));
+ LOGMASKED(LOG_ITU_WR, "%s: Channel 0 PWM Mode: %d\n", machine().describe_context(), BIT(data, 0));
+ m_itu.tmdr = data;
+}
+
+uint8_t sh7021_device::itu_tfcr_r()
+{
+ if (!machine().side_effects_disabled())
+ LOGMASKED(LOG_ITU_RD, "%s: Timer Function Control Register, itu_tfcr_r: %02x\n", machine().describe_context(), m_itu.tfcr);
+ return m_itu.tfcr;
+}
+
+void sh7021_device::itu_tfcr_w(uint8_t data)
+{
+ static const char *const COMBO_MODE_NAMES[4] =
+ {
+ "Channel 3 & 4 Normal (0)",
+ "Channel 3 & 4 Normal (1)",
+ "Channel 3 & 4 Together, Complementary PWM",
+ "Channel 3 & 4 Together, Reset-Synced PWM"
+ };
+ LOGMASKED(LOG_ITU_WR, "%s: Timer Function Control Register, itu_tfcr_w = %02x\n", machine().describe_context(), data);
+ LOGMASKED(LOG_ITU_WR, "%s: Combination Mode: %s\n", machine().describe_context(), COMBO_MODE_NAMES[(data >> 4) & 3]);
+ LOGMASKED(LOG_ITU_WR, "%s: Buffer Mode B4: %s\n", machine().describe_context(), BIT(data, 3) ? "GRB4 and BRB4 buffer mode for Ch.4" : "GRB4 normal for Ch.4");
+ LOGMASKED(LOG_ITU_WR, "%s: Buffer Mode A4: %s\n", machine().describe_context(), BIT(data, 2) ? "GRA4 and BRA4 buffer mode for Ch.4" : "GRA4 normal for Ch.4");
+ LOGMASKED(LOG_ITU_WR, "%s: Buffer Mode B3: %s\n", machine().describe_context(), BIT(data, 1) ? "GRB3 and BRB3 buffer mode for Ch.3" : "GRB3 normal for Ch.3");
+ LOGMASKED(LOG_ITU_WR, "%s: Buffer Mode A3: %s\n", machine().describe_context(), BIT(data, 0) ? "GRA3 and BRA3 buffer mode for Ch.3" : "GRA3 normal for Ch.3");
+ m_itu.tfcr = data;
+}
+
+uint8_t sh7021_device::itu_tocr_r()
+{
+ if (!machine().side_effects_disabled())
+ LOGMASKED(LOG_ITU_RD, "%s: Timer Output Control Register, itu_tfcr_r: %02x\n", machine().describe_context(), m_itu.tocr);
+ return m_itu.tocr | 0x7c;
+}
+
+void sh7021_device::itu_tocr_w(uint8_t data)
+{
+ LOGMASKED(LOG_ITU_WR, "%s: Timer Output Control Register, itu_tocr_w = %02x\n", machine().describe_context(), data);
+ LOGMASKED(LOG_ITU_WR, "%s: Output Level Select Ch.4: %s\n", machine().describe_context(), BIT(data, 1) ? "Direct" : "Inverted");
+ LOGMASKED(LOG_ITU_WR, "%s: Output Level Select Ch.3: %s\n", machine().describe_context(), BIT(data, 0) ? "Direct" : "Inverted");
+ m_itu.tocr = data;
+}
+
+template uint8_t sh7021_device::itu_tcr_r<0>();
+template uint8_t sh7021_device::itu_tcr_r<1>();
+template uint8_t sh7021_device::itu_tcr_r<2>();
+template uint8_t sh7021_device::itu_tcr_r<3>();
+template uint8_t sh7021_device::itu_tcr_r<4>();
+
+template <int Channel>
+uint8_t sh7021_device::itu_tcr_r()
+{
+ if (!machine().side_effects_disabled())
+ LOGMASKED(LOG_ITU_RD, "%s: Timer Control Register %d, itu_tcr_r: %02x\n", machine().describe_context(), Channel, m_itu.timer[Channel].tcr);
+ return m_itu.timer[Channel].tcr;
+}
+
+template void sh7021_device::itu_tcr_w<0>(uint8_t data);
+template void sh7021_device::itu_tcr_w<1>(uint8_t data);
+template void sh7021_device::itu_tcr_w<2>(uint8_t data);
+template void sh7021_device::itu_tcr_w<3>(uint8_t data);
+template void sh7021_device::itu_tcr_w<4>(uint8_t data);
+
+template <int Channel>
+void sh7021_device::itu_tcr_w(uint8_t data)
+{
+ static const char *const CCLR_NAMES[4] =
+ {
+ "Don't clear TCNT", "Clear TCNT on GRA match or input capture", "Clear TCNT on GRB match or input capture", "Synced clear"
+ };
+ static const char *const CKEG_NAMES[4] =
+ {
+ "Count rising edges", "Count falling edges", "Count both edges (2)", "Count both edges (3)"
+ };
+ static const char *const TPSC_NAMES[8] =
+ {
+ "/1", "/2", "/4", "/8", "External clock A", "External clock B", "External clock C", "External clock D"
+ };
+
+ LOGMASKED(LOG_ITU_WR, "%s: Timer Control Register %d, itu_tcr_w = %02x\n", machine().describe_context(), Channel, data);
+ LOGMASKED(LOG_ITU_WR, "%s: Counter Clear Mode: %s\n", machine().describe_context(), CCLR_NAMES[(data >> 5) & 3]);
+ LOGMASKED(LOG_ITU_WR, "%s: External-Clock Edge Mode: %s\n", machine().describe_context(), CKEG_NAMES[(data >> 3) & 3]);
+ LOGMASKED(LOG_ITU_WR, "%s: Timer Prescaler Mode: %s\n", machine().describe_context(), TPSC_NAMES[data & 7]);
+ m_itu.timer[Channel].tcr = data;
+}
+
+template uint8_t sh7021_device::itu_tior_r<0>();
+template uint8_t sh7021_device::itu_tior_r<1>();
+template uint8_t sh7021_device::itu_tior_r<2>();
+template uint8_t sh7021_device::itu_tior_r<3>();
+template uint8_t sh7021_device::itu_tior_r<4>();
+
+template <int Channel>
+uint8_t sh7021_device::itu_tior_r()
+{
+ if (!machine().side_effects_disabled())
+ LOGMASKED(LOG_ITU_RD, "%s: Timer I/O Control Register %d, itu_tior_r: %02x\n", machine().describe_context(), Channel, m_itu.timer[Channel].tior);
+ return m_itu.timer[Channel].tior;
+}
+
+template void sh7021_device::itu_tior_w<0>(uint8_t data);
+template void sh7021_device::itu_tior_w<1>(uint8_t data);
+template void sh7021_device::itu_tior_w<2>(uint8_t data);
+template void sh7021_device::itu_tior_w<3>(uint8_t data);
+template void sh7021_device::itu_tior_w<4>(uint8_t data);
+
+template <int Channel>
+void sh7021_device::itu_tior_w(uint8_t data)
+{
+ static const char *const IOB_NAMES[8] =
+ {
+ "Output compare GRB / Compare Match",
+ "Output compare GRB / 0 output at GRB match",
+ "Output compare GRB / 1 output at GRB match",
+ "Output compare GRB / Toggle at GRB match",
+ "Input capture GRB / Capture rising edge",
+ "Input capture GRB / Capture falling edge",
+ "Input capture GRB / Capture both edges (6)",
+ "Input capture GRB / Capture both edges (7)",
+ };
+ static const char *const IOA_NAMES[8] =
+ {
+ "Output compare GRA / Compare Match",
+ "Output compare GRA / 0 output at GRA match",
+ "Output compare GRA / 1 output at GRA match",
+ "Output compare GRA / Toggle at GRA match",
+ "Input capture GRA / Capture rising edge",
+ "Input capture GRA / Capture falling edge",
+ "Input capture GRA / Capture both edges (6)",
+ "Input capture GRA / Capture both edges (7)",
+ };
+
+ LOGMASKED(LOG_ITU_WR, "%s: Timer I/O Control Register %d, itu_tior_w = %02x\n", machine().describe_context(), Channel, data);
+ LOGMASKED(LOG_ITU_WR, "%s: GRB Function: %s\n", machine().describe_context(), IOB_NAMES[(data >> 4) & 7]);
+ LOGMASKED(LOG_ITU_WR, "%s: GRA Function: %s\n", machine().describe_context(), IOA_NAMES[data & 7]);
+ m_itu.timer[Channel].tior = data;
+}
+
+template uint8_t sh7021_device::itu_tier_r<0>();
+template uint8_t sh7021_device::itu_tier_r<1>();
+template uint8_t sh7021_device::itu_tier_r<2>();
+template uint8_t sh7021_device::itu_tier_r<3>();
+template uint8_t sh7021_device::itu_tier_r<4>();
+
+template <int Channel>
+uint8_t sh7021_device::itu_tier_r()
+{
+ if (!machine().side_effects_disabled())
+ LOGMASKED(LOG_ITU_RD, "%s: Timer Interrupt Enable Register %d, itu_tier_r: %02x\n", machine().describe_context(), Channel, m_itu.timer[Channel].tier);
+ return m_itu.timer[Channel].tier;
+}
+
+template void sh7021_device::itu_tier_w<0>(uint8_t data);
+template void sh7021_device::itu_tier_w<1>(uint8_t data);
+template void sh7021_device::itu_tier_w<2>(uint8_t data);
+template void sh7021_device::itu_tier_w<3>(uint8_t data);
+template void sh7021_device::itu_tier_w<4>(uint8_t data);
+
+template <int Channel>
+void sh7021_device::itu_tier_w(uint8_t data)
+{
+ LOGMASKED(LOG_ITU_WR, "%s: Timer Interrupt Enable Register %d, itu_tier_w = %02x\n", machine().describe_context(), Channel, data);
+ LOGMASKED(LOG_ITU_WR, "%s: Enable Overflow Interrupts: %d\n", machine().describe_context(), BIT(data, 2));
+ LOGMASKED(LOG_ITU_WR, "%s: Enable Capture/Compare B Interrupts: %d\n", machine().describe_context(), BIT(data, 1));
+ LOGMASKED(LOG_ITU_WR, "%s: Enable Capture/Compare A Interrupts: %d\n", machine().describe_context(), BIT(data, 0));
+ m_itu.timer[Channel].tier = data;
+}
+
+template uint8_t sh7021_device::itu_tsr_r<0>();
+template uint8_t sh7021_device::itu_tsr_r<1>();
+template uint8_t sh7021_device::itu_tsr_r<2>();
+template uint8_t sh7021_device::itu_tsr_r<3>();
+template uint8_t sh7021_device::itu_tsr_r<4>();
+
+template <int Channel>
+uint8_t sh7021_device::itu_tsr_r()
+{
+ if (!machine().side_effects_disabled())
+ {
+ LOGMASKED(LOG_ITU_RD, "%s: Timer Status Register %d, itu_tsr_r: %02x\n", machine().describe_context(), Channel, m_itu.timer[Channel].tsr);
+ LOGMASKED(LOG_ITU_RD, "%s: Overflow Flag: %d\n", machine().describe_context(), BIT(m_itu.timer[Channel].tsr, 2));
+ LOGMASKED(LOG_ITU_RD, "%s: Compare/Capture B Flag: %d\n", machine().describe_context(), BIT(m_itu.timer[Channel].tsr, 1));
+ LOGMASKED(LOG_ITU_RD, "%s: Compare/Capture A Flag: %d\n", machine().describe_context(), BIT(m_itu.timer[Channel].tsr, 0));
+ }
+ return m_itu.timer[Channel].tsr;
+}
+
+template void sh7021_device::itu_tsr_w<0>(uint8_t data);
+template void sh7021_device::itu_tsr_w<1>(uint8_t data);
+template void sh7021_device::itu_tsr_w<2>(uint8_t data);
+template void sh7021_device::itu_tsr_w<3>(uint8_t data);
+template void sh7021_device::itu_tsr_w<4>(uint8_t data);
+
+template <int Channel>
+void sh7021_device::itu_tsr_w(uint8_t data)
+{
+ LOGMASKED(LOG_ITU_WR, "%s: Timer Status Register %d, itu_tsr_w = %02x\n", machine().describe_context(), Channel, m_itu.timer[Channel].tsr);
+ if (BIT(m_itu.timer[Channel].tsr, 2) && !BIT(data, 2))
+ LOGMASKED(LOG_ITU_WR, "%s: Overflow Clear\n", machine().describe_context());
+ if (BIT(m_itu.timer[Channel].tsr, 1) && !BIT(data, 1))
+ LOGMASKED(LOG_ITU_WR, "%s: Compare/Capture B Clear\n", machine().describe_context());
+ if (BIT(m_itu.timer[Channel].tsr, 0) && !BIT(data, 0))
+ LOGMASKED(LOG_ITU_WR, "%s: Compare/Capture A Clear\n", machine().describe_context());
+ m_itu.timer[Channel].tsr = data;
+}
+
+template uint16_t sh7021_device::itu_tcnt_r<0>();
+template uint16_t sh7021_device::itu_tcnt_r<1>();
+template uint16_t sh7021_device::itu_tcnt_r<2>();
+template uint16_t sh7021_device::itu_tcnt_r<3>();
+template uint16_t sh7021_device::itu_tcnt_r<4>();
+
+template <int Channel>
+uint16_t sh7021_device::itu_tcnt_r()
+{
+ if (!machine().side_effects_disabled())
+ LOGMASKED(LOG_ITU_RD, "%s: Timer Counter %d, itu_tcnt_r: %04x\n", machine().describe_context(), Channel, m_itu.timer[Channel].tcnt);
+ return m_itu.timer[Channel].tcnt;
+}
+
+template void sh7021_device::itu_tcnt_w<0>(offs_t offset, uint16_t data, uint16_t mem_mask);
+template void sh7021_device::itu_tcnt_w<1>(offs_t offset, uint16_t data, uint16_t mem_mask);
+template void sh7021_device::itu_tcnt_w<2>(offs_t offset, uint16_t data, uint16_t mem_mask);
+template void sh7021_device::itu_tcnt_w<3>(offs_t offset, uint16_t data, uint16_t mem_mask);
+template void sh7021_device::itu_tcnt_w<4>(offs_t offset, uint16_t data, uint16_t mem_mask);
+
+template <int Channel>
+void sh7021_device::itu_tcnt_w(offs_t offset, uint16_t data, uint16_t mem_mask)
+{
+ LOGMASKED(LOG_ITU_WR, "%s: Timer Counter %d, itu_tcnt_w = %04x & %04x\n", machine().describe_context(), Channel, data, mem_mask);
+ COMBINE_DATA(&m_itu.timer[Channel].tcnt);
+}
+
+template uint16_t sh7021_device::itu_gra_r<0>();
+template uint16_t sh7021_device::itu_gra_r<1>();
+template uint16_t sh7021_device::itu_gra_r<2>();
+template uint16_t sh7021_device::itu_gra_r<3>();
+template uint16_t sh7021_device::itu_gra_r<4>();
+
+template <int Channel>
+uint16_t sh7021_device::itu_gra_r()
+{
+ if (!machine().side_effects_disabled())
+ LOGMASKED(LOG_ITU_RD, "%s: General Register A %d, itu_gra_r: %04x\n", machine().describe_context(), Channel, m_itu.timer[Channel].gra);
+ return m_itu.timer[Channel].gra;
+}
+
+template void sh7021_device::itu_gra_w<0>(offs_t offset, uint16_t data, uint16_t mem_mask);
+template void sh7021_device::itu_gra_w<1>(offs_t offset, uint16_t data, uint16_t mem_mask);
+template void sh7021_device::itu_gra_w<2>(offs_t offset, uint16_t data, uint16_t mem_mask);
+template void sh7021_device::itu_gra_w<3>(offs_t offset, uint16_t data, uint16_t mem_mask);
+template void sh7021_device::itu_gra_w<4>(offs_t offset, uint16_t data, uint16_t mem_mask);
+
+template <int Channel>
+void sh7021_device::itu_gra_w(offs_t offset, uint16_t data, uint16_t mem_mask)
+{
+ LOGMASKED(LOG_ITU_WR, "%s: General Register A %d, itu_gra_w = %04x\n", machine().describe_context(), Channel, data);
+ COMBINE_DATA(&m_itu.timer[Channel].gra);
+}
+
+template uint16_t sh7021_device::itu_grb_r<0>();
+template uint16_t sh7021_device::itu_grb_r<1>();
+template uint16_t sh7021_device::itu_grb_r<2>();
+template uint16_t sh7021_device::itu_grb_r<3>();
+template uint16_t sh7021_device::itu_grb_r<4>();
+
+template <int Channel>
+uint16_t sh7021_device::itu_grb_r()
+{
+ if (!machine().side_effects_disabled())
+ LOGMASKED(LOG_ITU_RD, "%s: General Register B %d, itu_grb_r: %04x\n", machine().describe_context(), Channel, m_itu.timer[Channel].grb);
+ return m_itu.timer[Channel].grb;
+}
+
+template void sh7021_device::itu_grb_w<0>(offs_t offset, uint16_t data, uint16_t mem_mask);
+template void sh7021_device::itu_grb_w<1>(offs_t offset, uint16_t data, uint16_t mem_mask);
+template void sh7021_device::itu_grb_w<2>(offs_t offset, uint16_t data, uint16_t mem_mask);
+template void sh7021_device::itu_grb_w<3>(offs_t offset, uint16_t data, uint16_t mem_mask);
+template void sh7021_device::itu_grb_w<4>(offs_t offset, uint16_t data, uint16_t mem_mask);
+
+template <int Channel>
+void sh7021_device::itu_grb_w(offs_t offset, uint16_t data, uint16_t mem_mask)
+{
+ LOGMASKED(LOG_ITU_WR, "%s: General Register B %d, itu_grb_w = %04x\n", machine().describe_context(), Channel, data);
+ COMBINE_DATA(&m_itu.timer[Channel].grb);
+}
+
+template uint16_t sh7021_device::itu_bra_r<3>();
+template uint16_t sh7021_device::itu_bra_r<4>();
+
+template <int Channel>
+uint16_t sh7021_device::itu_bra_r()
+{
+ if (!machine().side_effects_disabled())
+ LOGMASKED(LOG_ITU_RD, "%s: Buffer Register A %d, itu_bra_r: %04x\n", machine().describe_context(), Channel, m_itu.timer[Channel].bra);
+ return m_itu.timer[Channel].bra;
+}
+
+template void sh7021_device::itu_bra_w<3>(offs_t offset, uint16_t data, uint16_t mem_mask);
+template void sh7021_device::itu_bra_w<4>(offs_t offset, uint16_t data, uint16_t mem_mask);
+
+template <int Channel>
+void sh7021_device::itu_bra_w(offs_t offset, uint16_t data, uint16_t mem_mask)
+{
+ LOGMASKED(LOG_ITU_WR, "%s: Buffer Register A %d, itu_bra_w = %04x\n", machine().describe_context(), Channel, data);
+ COMBINE_DATA(&m_itu.timer[Channel].bra);
+}
+
+template uint16_t sh7021_device::itu_brb_r<3>();
+template uint16_t sh7021_device::itu_brb_r<4>();
+
+template <int Channel>
+uint16_t sh7021_device::itu_brb_r()
+{
+ if (!machine().side_effects_disabled())
+ LOGMASKED(LOG_ITU_RD, "%s: Buffer Register B %d, itu_brb_r: %04x\n", machine().describe_context(), Channel, m_itu.timer[Channel].brb);
+ return m_itu.timer[Channel].brb;
+}
+
+template void sh7021_device::itu_brb_w<3>(offs_t offset, uint16_t data, uint16_t mem_mask);
+template void sh7021_device::itu_brb_w<4>(offs_t offset, uint16_t data, uint16_t mem_mask);
+
+template <int Channel>
+void sh7021_device::itu_brb_w(offs_t offset, uint16_t data, uint16_t mem_mask)
+{
+ LOGMASKED(LOG_ITU_WR, "%s: Buffer Register B %d, itu_brb_w = %04x\n", machine().describe_context(), Channel, data);
+ COMBINE_DATA(&m_itu.timer[Channel].brb);
+}
+
+
+// Programmable Timing Pattern Controller (TPC)
+
+uint8_t sh7021_device::tpc_tpmr_r()
+{
+ if (!machine().side_effects_disabled())
+ LOGMASKED(LOG_TPC_RD, "%s: TPC Output Mode Register, tpc_tpmr_r: %02x\n", machine().describe_context(), m_tpc.tpmr);
+ return m_tpc.tpmr;
+}
+
+void sh7021_device::tpc_tpmr_w(uint8_t data)
+{
+ LOGMASKED(LOG_TPC_WR, "%s: TPC Output Mode Register, tpc_tpmr_w = %02x\n", machine().describe_context(), data);
+ LOGMASKED(LOG_TPC_WR, "%s: TPC Output Group 3 Operation: %s\n", machine().describe_context(), BIT(data, 3) ? "Non-Overlap Mode (1/0 from A/B)" : "Normal (Compare-Match A)");
+ LOGMASKED(LOG_TPC_WR, "%s: TPC Output Group 2 Operation: %s\n", machine().describe_context(), BIT(data, 2) ? "Non-Overlap Mode (1/0 from A/B)" : "Normal (Compare-Match A)");
+ LOGMASKED(LOG_TPC_WR, "%s: TPC Output Group 1 Operation: %s\n", machine().describe_context(), BIT(data, 1) ? "Non-Overlap Mode (1/0 from A/B)" : "Normal (Compare-Match A)");
+ LOGMASKED(LOG_TPC_WR, "%s: TPC Output Group 0 Operation: %s\n", machine().describe_context(), BIT(data, 0) ? "Non-Overlap Mode (1/0 from A/B)" : "Normal (Compare-Match A)");
+ m_tpc.tpmr = data;
+}
+
+uint8_t sh7021_device::tpc_tpcr_r()
+{
+ if (!machine().side_effects_disabled())
+ LOGMASKED(LOG_TPC_RD, "%s: TPC Output Control Register, tpc_tpcr_r: %02x\n", machine().describe_context(), m_tpc.tpcr);
+ return m_tpc.tpcr;
+}
+
+void sh7021_device::tpc_tpcr_w(uint8_t data)
+{
+ LOGMASKED(LOG_TPC_WR, "%s: TPC Output Control Register, tpc_tpcr_w = %02x\n", machine().describe_context(), data);
+ LOGMASKED(LOG_TPC_WR, "%s: TPC Output Group 3 output triggered by compare-match in ITU channel %d\n", machine().describe_context(), (data >> 6) & 3);
+ LOGMASKED(LOG_TPC_WR, "%s: TPC Output Group 2 output triggered by compare-match in ITU channel %d\n", machine().describe_context(), (data >> 4) & 3);
+ LOGMASKED(LOG_TPC_WR, "%s: TPC Output Group 1 output triggered by compare-match in ITU channel %d\n", machine().describe_context(), (data >> 2) & 3);
+ LOGMASKED(LOG_TPC_WR, "%s: TPC Output Group 0 output triggered by compare-match in ITU channel %d\n", machine().describe_context(), data & 3);
+ m_tpc.tpcr = data;
+}
+
+uint8_t sh7021_device::tpc_ndera_r()
+{
+ if (!machine().side_effects_disabled())
+ LOGMASKED(LOG_TPC_RD, "%s: Next Data Enable Register A, tpc_ndera_r (TP7-0): %02x\n", machine().describe_context(), m_tpc.ndera);
+ return m_tpc.ndera;
+}
+
+void sh7021_device::tpc_ndera_w(uint8_t data)
+{
+ LOGMASKED(LOG_TPC_WR, "%s: Next Data Enable Register A, tpc_ndera_w (TP7-0) = %02x\n", machine().describe_context(), data);
+ m_tpc.ndera = data;
+}
+
+uint8_t sh7021_device::tpc_nderb_r()
+{
+ if (!machine().side_effects_disabled())
+ LOGMASKED(LOG_TPC_RD, "%s: Next Data Enable Register B, tpc_nderb_r (TP15-8): %02x\n", machine().describe_context(), m_tpc.nderb);
+ return m_tpc.nderb;
+}
+
+void sh7021_device::tpc_nderb_w(uint8_t data)
+{
+ LOGMASKED(LOG_TPC_WR, "%s: Next Data Enable Register B, tpc_nderb_w (TP15-8) = %02x\n", machine().describe_context(), data);
+ m_tpc.nderb = data;
+}
+
+uint8_t sh7021_device::tpc_ndra_r()
+{
+ if (!machine().side_effects_disabled())
+ LOGMASKED(LOG_TPC_RD, "%s: Next Data Register A, tpc_ndra_r: %02x\n", machine().describe_context(), 0);//m_tpc.ndra);
+ return 0;//m_tpc.ndra;
+}
+
+void sh7021_device::tpc_ndra_w(uint8_t data)
+{
+ LOGMASKED(LOG_TPC_WR, "%s: Next Data Register A, tpc_ndra_w = %02x\n", machine().describe_context(), data);
+}
+
+uint8_t sh7021_device::tpc_ndra_alt_r()
+{
+ if (!machine().side_effects_disabled())
+ LOGMASKED(LOG_TPC_RD, "%s: Next Data Register A (alt. address), tpc_ndra_alt_r: %02x\n", machine().describe_context(), 0);//m_tpc.ndra);
+ return 0;//m_tpc.ndra;
+}
+
+void sh7021_device::tpc_ndra_alt_w(uint8_t data)
+{
+ LOGMASKED(LOG_TPC_WR, "%s: Next Data Register A (alt. address), tpc_ndra_alt_w = %02x\n", machine().describe_context(), data);
+}
+
+uint8_t sh7021_device::tpc_ndrb_r()
+{
+ if (!machine().side_effects_disabled())
+ LOGMASKED(LOG_TPC_RD, "%s: Next Data Register B, tpc_ndrb_r: %02x\n", machine().describe_context(), 0);//m_tpc.ndrb);
+ return 0;//m_tpc.ndrb;
+}
+
+void sh7021_device::tpc_ndrb_w(uint8_t data)
+{
+ LOGMASKED(LOG_TPC_WR, "%s: Next Data Register B, tpc_ndrb_w = %02x\n", machine().describe_context(), data);
+}
+
+uint8_t sh7021_device::tpc_ndrb_alt_r()
+{
+ if (!machine().side_effects_disabled())
+ LOGMASKED(LOG_TPC_RD, "%s: Next Data Register B (alt. address), tpc_ndrb_alt_r: %02x\n", machine().describe_context(), 0);//m_tpc.ndrb);
+ return 0;//m_tpc.ndrb;
+}
+
+void sh7021_device::tpc_ndrb_alt_w(uint8_t data)
+{
+ LOGMASKED(LOG_TPC_WR, "%s: Next Data Register B (alt. address), tpc_ndrb_alt_w = %02x\n", machine().describe_context(), data);
+}
+
+
+// Watchdog Timer (WDT)
+
+uint8_t sh7021_device::wdt_tcsr_r()
+{
+ return m_wdt.tcsr;
+}
+
+void sh7021_device::wdt_tcsr_w(uint8_t data)
+{
+ m_wdt.tcsr = data;
+}
+
+uint8_t sh7021_device::wdt_tcnt_r()
+{
+ return 0;
+}
+
+void sh7021_device::wdt_tcnt_w(uint8_t data)
+{
+}
+
+uint8_t sh7021_device::wdt_rstcsr_r()
+{
+ return 0;
+}
+
+void sh7021_device::wdt_rstcsr_w(uint8_t data)
+{
+
+}
+
+
+// Serial Communication Interface (SCI)
+
+template TIMER_CALLBACK_MEMBER(sh7021_device::sh7021_sci_callback<0>);
+template TIMER_CALLBACK_MEMBER(sh7021_device::sh7021_sci_callback<1>);
+
+template<int Which>
+TIMER_CALLBACK_MEMBER(sh7021_device::sh7021_sci_callback)
+{
+ LOGMASKED(LOG_DMA_WR, "Setting SCI interrupt on channel %d\n", Which);
+ m_sci[Which].ssr |= (1 << 7) | (1 << 2);
+ recalc_irq();
+}
+
+template uint8_t sh7021_device::sci_smr_r<0>();
+template uint8_t sh7021_device::sci_smr_r<1>();
+
+template <int Channel>
+uint8_t sh7021_device::sci_smr_r()
+{
+ if (!machine().side_effects_disabled())
+ LOGMASKED(LOG_SCI_RD, "%s: Serial Mode Register %d, sci_smr_r: %02x\n", machine().describe_context(), Channel, m_sci[Channel].smr);
+ return m_sci[Channel].smr;
+}
+
+template void sh7021_device::sci_smr_w<0>(uint8_t data);
+template void sh7021_device::sci_smr_w<1>(uint8_t data);
+
+template <int Channel>
+void sh7021_device::sci_smr_w(uint8_t data)
+{
+ LOGMASKED(LOG_SCI_WR, "%s: Serial Mode Register %d, sci_smr_w = %02x\n", machine().describe_context(), Channel, data);
+ LOGMASKED(LOG_SCI_WR, "%s: Communication Mode: %s\n", machine().describe_context(), BIT(data, 7) ? "Clocked synchronous" : "Asynchronous");
+ LOGMASKED(LOG_SCI_WR, "%s: Character Length: %d\n", machine().describe_context(), BIT(data, 6) ? 7 : 8);
+ LOGMASKED(LOG_SCI_WR, "%s: Parity Enable: %d\n", machine().describe_context(), BIT(data, 5));
+ LOGMASKED(LOG_SCI_WR, "%s: Parity Mode: %s\n", machine().describe_context(), BIT(data, 4) ? "Odd" : "Even");
+ LOGMASKED(LOG_SCI_WR, "%s: Stop Bits: %d\n", machine().describe_context(), BIT(data, 3) ? 2 : 1);
+ LOGMASKED(LOG_SCI_WR, "%s: Multiprocessor Mode: %d\n", machine().describe_context(), BIT(data, 2));
+ LOGMASKED(LOG_SCI_WR, "%s: Clock Divider: %d\n", machine().describe_context(), 1 << ((data & 3) * 2));
+ m_sci[Channel].smr = data;
+}
+
+template uint8_t sh7021_device::sci_brr_r<0>();
+template uint8_t sh7021_device::sci_brr_r<1>();
+
+template <int Channel>
+uint8_t sh7021_device::sci_brr_r()
+{
+ if (!machine().side_effects_disabled())
+ LOGMASKED(LOG_SCI_RD, "%s: Bit Rate Register %d, sci_brr_r: %02x\n", machine().describe_context(), Channel, m_sci[Channel].brr);
+ return m_sci[Channel].brr;
+}
+
+template void sh7021_device::sci_brr_w<0>(uint8_t data);
+template void sh7021_device::sci_brr_w<1>(uint8_t data);
+
+template <int Channel>
+void sh7021_device::sci_brr_w(uint8_t data)
+{
+ LOGMASKED(LOG_SCI_WR, "%s: Bit Rate Register %d, sci_brr_w = %02x\n", machine().describe_context(), Channel, data);
+ m_sci[Channel].brr = data;
+}
+
+template uint8_t sh7021_device::sci_scr_r<0>();
+template uint8_t sh7021_device::sci_scr_r<1>();
+
+template <int Channel>
+uint8_t sh7021_device::sci_scr_r()
+{
+ if (!machine().side_effects_disabled())
+ LOGMASKED(LOG_SCI_RD, "%s: Serial Control Register %d, sci_scr_r: %02x\n", machine().describe_context(), Channel, m_sci[Channel].scr);
+ return m_sci[Channel].scr;
+}
+
+template void sh7021_device::sci_scr_w<0>(uint8_t data);
+template void sh7021_device::sci_scr_w<1>(uint8_t data);
+
+template <int Channel>
+void sh7021_device::sci_scr_w(uint8_t data)
+{
+ LOGMASKED(LOG_SCI_WR, "%s: Serial Control Register %d, sci_scr_w = %02x\n", machine().describe_context(), Channel, data);
+ LOGMASKED(LOG_SCI_WR, "%s: Transmit-Empty Interrupt Enable: %d\n", machine().describe_context(), BIT(data, 7));
+ LOGMASKED(LOG_SCI_WR, "%s: Receive-Full Interrupt Enable: %d\n", machine().describe_context(), BIT(data, 6));
+ LOGMASKED(LOG_SCI_WR, "%s: Transmit Enable: %d\n", machine().describe_context(), BIT(data, 5));
+ LOGMASKED(LOG_SCI_WR, "%s: Receive Enable: %d\n", machine().describe_context(), BIT(data, 4));
+ LOGMASKED(LOG_SCI_WR, "%s: Multiprocessor Interrupt Enable: %d\n", machine().describe_context(), BIT(data, 3));
+ LOGMASKED(LOG_SCI_WR, "%s: Transmit-End Interrupt Enable: %d\n", machine().describe_context(), BIT(data, 2));
+ LOGMASKED(LOG_SCI_WR, "%s: Clock Enable Mode: %d%d\n", machine().describe_context(), BIT(data, 1), BIT(data, 0));
+ m_sci[Channel].scr = data;
+}
+
+template uint8_t sh7021_device::sci_tdr_r<0>();
+template uint8_t sh7021_device::sci_tdr_r<1>();
+
+template <int Channel>
+uint8_t sh7021_device::sci_tdr_r()
+{
+ if (!machine().side_effects_disabled())
+ LOGMASKED(LOG_SCI_RD, "%s: Transmit Data Register %d, sci_tdr_r: %02x\n", machine().describe_context(), Channel, m_sci[Channel].tdr);
+ return m_sci[Channel].tdr;
+}
+
+template void sh7021_device::sci_tdr_w<0>(uint8_t data);
+template void sh7021_device::sci_tdr_w<1>(uint8_t data);
+
+template <int Channel>
+void sh7021_device::sci_tdr_w(uint8_t data)
+{
+ LOGMASKED(LOG_SCI_WR, "%s: Transmit Data Register %d, sci_tdr_w = %02x\n", machine().describe_context(), Channel, data);
+ m_sci[Channel].tdr = data;
+}
+
+template uint8_t sh7021_device::sci_ssr_r<0>();
+template uint8_t sh7021_device::sci_ssr_r<1>();
+
+template <int Channel>
+uint8_t sh7021_device::sci_ssr_r()
+{
+ if (!machine().side_effects_disabled())
+ {
+ LOGMASKED(LOG_SCI_RD, "%s: Serial Status Register %d, sci_ssr_r: %02x\n", machine().describe_context(), Channel, m_sci[Channel].ssr);
+ LOGMASKED(LOG_SCI_RD, "%s: Transmit Empty Flag: %d\n", machine().describe_context(), Channel, BIT(m_sci[Channel].ssr, 7));
+ LOGMASKED(LOG_SCI_RD, "%s: Receiver Full Flag: %d\n", machine().describe_context(), Channel, BIT(m_sci[Channel].ssr, 6));
+ LOGMASKED(LOG_SCI_RD, "%s: Overrun Error Flag: %d\n", machine().describe_context(), Channel, BIT(m_sci[Channel].ssr, 5));
+ LOGMASKED(LOG_SCI_RD, "%s: Framing Error Flag: %d\n", machine().describe_context(), Channel, BIT(m_sci[Channel].ssr, 4));
+ LOGMASKED(LOG_SCI_RD, "%s: Parity Error Flag: %d\n", machine().describe_context(), Channel, BIT(m_sci[Channel].ssr, 3));
+ LOGMASKED(LOG_SCI_RD, "%s: Transmit End Flag: %d\n", machine().describe_context(), Channel, BIT(m_sci[Channel].ssr, 2));
+ LOGMASKED(LOG_SCI_RD, "%s: Multiprocessor Bit Flag: %d\n", machine().describe_context(), Channel, BIT(m_sci[Channel].ssr, 1));
+ LOGMASKED(LOG_SCI_RD, "%s: Multiprocessor Bit Transfer Flag: %d\n", machine().describe_context(), Channel, BIT(m_sci[Channel].ssr, 0));
+
+ m_sci[Channel].ssr_read |= m_sci[Channel].ssr & 0xf8;
+ }
+
+ return (m_sci[Channel].ssr & 0xf9) | 0x04;
+}
+
+template void sh7021_device::sci_ssr_w<0>(uint8_t data);
+template void sh7021_device::sci_ssr_w<1>(uint8_t data);
+
+template <int Channel>
+void sh7021_device::sci_ssr_w(uint8_t data)
+{
+ LOGMASKED(LOG_SCI_WR, "%s: Serial Status Register %d, sci_ssr_w = %02x\n", machine().describe_context(), Channel, data);
+ if (!BIT(data, 7) && BIT(m_sci[Channel].ssr, 7) && BIT(m_sci[Channel].ssr_read, 7))
+ {
+ // Clear TDR-Empty Flag and Transmit End Flag
+ m_sci[Channel].ssr_read &= ~(1 << 7);
+ m_sci[Channel].ssr &= ~(1 << 7);
+ m_sci[Channel].ssr &= ~(1 << 2);
+ }
+
+ if (!BIT(data, 6) && BIT(m_sci[Channel].ssr, 6) && BIT(m_sci[Channel].ssr_read, 6))
+ {
+ // Clear RDR-Full Flag
+ m_sci[Channel].ssr_read &= ~(1 << 6);
+ m_sci[Channel].ssr &= ~(1 << 6);
+ }
+
+ if (!BIT(data, 5) && BIT(m_sci[Channel].ssr, 5) && BIT(m_sci[Channel].ssr_read, 5))
+ {
+ // Clear Overrun Error Flag
+ m_sci[Channel].ssr_read &= ~(1 << 5);
+ m_sci[Channel].ssr &= ~(1 << 5);
+ }
+
+ if (!BIT(data, 4) && BIT(m_sci[Channel].ssr, 4) && BIT(m_sci[Channel].ssr_read, 4))
+ {
+ // Clear Framing Error Flag
+ m_sci[Channel].ssr_read &= ~(1 << 4);
+ m_sci[Channel].ssr &= ~(1 << 4);
+ }
+
+ if (!BIT(data, 3) && BIT(m_sci[Channel].ssr, 3) && BIT(m_sci[Channel].ssr_read, 3))
+ {
+ // Clear Parity Error Flag
+ m_sci[Channel].ssr_read &= ~(1 << 3);
+ m_sci[Channel].ssr &= ~(1 << 3);
+ }
+
+ m_sci[Channel].ssr &= 0xfe;
+ m_sci[Channel].ssr |= data & 1;
+}
+
+template uint8_t sh7021_device::sci_rdr_r<0>();
+template uint8_t sh7021_device::sci_rdr_r<1>();
+
+template <int Channel>
+uint8_t sh7021_device::sci_rdr_r()
+{
+ if (!machine().side_effects_disabled())
+ LOGMASKED(LOG_SCI_RD, "%s: Receive Data Register %d, sci_rdr_r: %02x\n", machine().describe_context(), Channel, m_sci[Channel].rdr);
+ return m_sci[Channel].rdr;
+}
+
+
+// Pin Function Controller (PFC)
+
+void sh7021_device::write_padr(uint16_t data)
+{
+ LOGMASKED(LOG_PFC_WR, "%s: Port A Input write: write_padr: %04x\n", machine().describe_context(), data);
+ m_pfc.padr_in = data;
+}
+
+void sh7021_device::write_pbdr(uint16_t data)
+{
+ LOGMASKED(LOG_PFC_WR, "%s: Port B Input write: write_pbdr: %04x\n", machine().describe_context(), data);
+ m_pfc.pbdr_in = data;
+}
+
+template void sh7021_device::write_padr_bit< 0>(int state);
+template void sh7021_device::write_padr_bit< 1>(int state);
+template void sh7021_device::write_padr_bit< 2>(int state);
+template void sh7021_device::write_padr_bit< 3>(int state);
+template void sh7021_device::write_padr_bit< 4>(int state);
+template void sh7021_device::write_padr_bit< 5>(int state);
+template void sh7021_device::write_padr_bit< 6>(int state);
+template void sh7021_device::write_padr_bit< 7>(int state);
+template void sh7021_device::write_padr_bit< 8>(int state);
+template void sh7021_device::write_padr_bit< 9>(int state);
+template void sh7021_device::write_padr_bit<10>(int state);
+template void sh7021_device::write_padr_bit<11>(int state);
+template void sh7021_device::write_padr_bit<12>(int state);
+template void sh7021_device::write_padr_bit<13>(int state);
+template void sh7021_device::write_padr_bit<14>(int state);
+template void sh7021_device::write_padr_bit<15>(int state);
+
+template <int Line>
+void sh7021_device::write_padr_bit(int state)
+{
+ LOGMASKED(LOG_PFC_WR, "%s: Port A Bit %d Input write: write_padr_bit: %d\n", machine().describe_context(), Line, state);
+ m_pfc.padr_in = (m_pfc.padr_in & ~(1 << Line)) | (state << Line);
+}
+
+template void sh7021_device::write_pbdr_bit< 0>(int state);
+template void sh7021_device::write_pbdr_bit< 1>(int state);
+template void sh7021_device::write_pbdr_bit< 2>(int state);
+template void sh7021_device::write_pbdr_bit< 3>(int state);
+template void sh7021_device::write_pbdr_bit< 4>(int state);
+template void sh7021_device::write_pbdr_bit< 5>(int state);
+template void sh7021_device::write_pbdr_bit< 6>(int state);
+template void sh7021_device::write_pbdr_bit< 7>(int state);
+template void sh7021_device::write_pbdr_bit< 8>(int state);
+template void sh7021_device::write_pbdr_bit< 9>(int state);
+template void sh7021_device::write_pbdr_bit<10>(int state);
+template void sh7021_device::write_pbdr_bit<11>(int state);
+template void sh7021_device::write_pbdr_bit<12>(int state);
+template void sh7021_device::write_pbdr_bit<13>(int state);
+template void sh7021_device::write_pbdr_bit<14>(int state);
+template void sh7021_device::write_pbdr_bit<15>(int state);
+
+template <int Line>
+void sh7021_device::write_pbdr_bit(int state)
+{
+ LOGMASKED(LOG_PFC_WR, "%s: Port B Bit %d Input write: write_pbdr_bit: %d\n", machine().describe_context(), Line, state);
+ m_pfc.pbdr_in = (m_pfc.pbdr_in & ~(1 << Line)) | (state << Line);
+}
+
+uint16_t sh7021_device::pfc_paior_r()
+{
+ if (!machine().side_effects_disabled())
+ LOGMASKED(LOG_PFC_RD, "%s: Port A I/O (Direction) Register, pfc_paior_r: %04x\n", machine().describe_context(), m_pfc.paior);
+ return m_pfc.paior;
+}
+
+void sh7021_device::pfc_paior_w(offs_t offset, uint16_t data, uint16_t mem_mask)
+{
+ LOGMASKED(LOG_PFC_WR, "%s: Port A I/O (Direction) Register, pfc_paior_w = %04x & %04x\n", machine().describe_context(), data, mem_mask);
+ COMBINE_DATA(&m_pfc.paior);
+}
+
+uint16_t sh7021_device::pfc_pacr1_r()
+{
+ static constexpr uint16_t PACR1_R_MASK = 0x0002;
+ if (!machine().side_effects_disabled())
+ LOGMASKED(LOG_PFC_RD, "%s: Port A Control Register 1, pfc_pacr1_r: %04x\n", machine().describe_context(), m_pfc.pacr1);
+ return m_pfc.pacr1 | PACR1_R_MASK;
+}
+
+void sh7021_device::pfc_pacr1_w(offs_t offset, uint16_t data, uint16_t mem_mask)
+{
+ static constexpr uint16_t PACR1_W_MASK = 0xfffd;
+ LOGMASKED(LOG_PFC_WR, "%s: Port A Control Register 1, pfc_pacr1_w = %04x & %04x\n", machine().describe_context(), data, mem_mask);
+ COMBINE_DATA(&m_pfc.pacr1);
+ const uint16_t pacr1_masked = m_pfc.pacr1 & PACR1_W_MASK;
+ for (int i = 0; i < 8; i++)
+ {
+ int bit = i << 1;
+ m_pfc.pafunc[8 + i] = (pacr1_masked >> bit) & 3;
+ }
+}
+
+uint16_t sh7021_device::pfc_pacr2_r()
+{
+ static constexpr uint16_t PACR2_R_MASK = 0xaa00;
+ if (!machine().side_effects_disabled())
+ LOGMASKED(LOG_PFC_RD, "%s: Port A Control Register 2, pfc_pacr2_r: %04x\n", machine().describe_context(), m_pfc.pacr2);
+ return m_pfc.pacr2 | PACR2_R_MASK;
+}
+
+void sh7021_device::pfc_pacr2_w(offs_t offset, uint16_t data, uint16_t mem_mask)
+{
+ static constexpr uint16_t PACR2_W_MASK = 0x55ff;
+ LOGMASKED(LOG_PFC_WR, "%s: Port A Control Register 2, pfc_pacr2_w = %04x & %04x\n", machine().describe_context(), data, mem_mask);
+ COMBINE_DATA(&m_pfc.pacr2);
+ const uint16_t pacr2_masked = m_pfc.pacr2 & PACR2_W_MASK;
+ for (int i = 0; i < 8; i++)
+ {
+ int bit = i << 1;
+ m_pfc.pafunc[i] = (pacr2_masked >> bit) & 3;
+ }
+}
+
+uint16_t sh7021_device::pfc_pbior_r()
+{
+ if (!machine().side_effects_disabled())
+ LOGMASKED(LOG_PFC_RD, "%s: Port B I/O (Direction) Register, pfc_pbior_r: %04x\n", machine().describe_context(), m_pfc.pbior);
+ return m_pfc.pbior;
+}
+
+void sh7021_device::pfc_pbior_w(offs_t offset, uint16_t data, uint16_t mem_mask)
+{
+ LOGMASKED(LOG_PFC_WR, "%s: Port B I/O (Direction) Register, pfc_pbior_w = %04x & %04x\n", machine().describe_context(), data, mem_mask);
+ COMBINE_DATA(&m_pfc.pbior);
+}
+
+uint16_t sh7021_device::pfc_pbcr1_r()
+{
+ if (!machine().side_effects_disabled())
+ LOGMASKED(LOG_PFC_RD, "%s: Port B Control Register 1, pfc_pbcr1_r: %04x\n", machine().describe_context(), m_pfc.pbcr1);
+ return m_pfc.pbcr1;
+}
+
+void sh7021_device::pfc_pbcr1_w(offs_t offset, uint16_t data, uint16_t mem_mask)
+{
+ LOGMASKED(LOG_PFC_WR, "%s: Port B Control Register 1, pfc_pbcr1_w = %04x & %04x\n", machine().describe_context(), data, mem_mask);
+ COMBINE_DATA(&m_pfc.pbcr1);
+ for (int i = 0; i < 8; i++)
+ {
+ int bit = i << 1;
+ m_pfc.pbfunc[8 + i] = (m_pfc.pbcr1 >> bit) & 3;
+ }
+}
+
+uint16_t sh7021_device::pfc_pbcr2_r()
+{
+ if (!machine().side_effects_disabled())
+ LOGMASKED(LOG_PFC_RD, "%s: Port B Control Register 2, pfc_pbcr2_r: %04x\n", machine().describe_context(), m_pfc.pbcr2);
+ return m_pfc.pbcr2;
+}
+
+void sh7021_device::pfc_pbcr2_w(offs_t offset, uint16_t data, uint16_t mem_mask)
+{
+ LOGMASKED(LOG_PFC_WR, "%s: Port B Control Register 2, pfc_pbcr2_w = %04x & %04x\n", machine().describe_context(), data, mem_mask);
+ COMBINE_DATA(&m_pfc.pbcr2);
+ for (int i = 0; i < 8; i++)
+ {
+ int bit = i << 1;
+ m_pfc.pbfunc[i] = (m_pfc.pbcr2 >> bit) & 3;
+ }
+}
+
+uint16_t sh7021_device::pfc_padr_r()
+{
+ const uint16_t data = ((m_pfc.padr_in & ~m_pfc.paior) | (m_pfc.padr & m_pfc.paior)) & m_pfc.pa_gpio_mask;
+ if (!machine().side_effects_disabled())
+ LOGMASKED(LOG_PFC_RD, "%s: Port A Data Register, pfc_padr_r: %04x ((%04x & ~%04x) | (%04x & %04x)) & %04x\n", machine().describe_context(), data, m_pfc.padr_in, m_pfc.paior, m_pfc.padr, m_pfc.paior, m_pfc.pa_gpio_mask);
+ return data;
+}
+
+void sh7021_device::pfc_padr_w(offs_t offset, uint16_t data, uint16_t mem_mask)
+{
+ LOGMASKED(LOG_PFC_WR, "%s: Port A Data Register, pfc_padr_w = %04x & %04x\n", machine().describe_context(), data, mem_mask);
+ const uint16_t old = m_pfc.padr;
+ COMBINE_DATA(&m_pfc.padr);
+ const uint16_t changed = m_pfc.padr ^ old;
+
+ uint16_t output_mask = m_pfc.paior & m_pfc.pa_gpio_mask;
+ for (int i = 0; i < 16; i++)
+ {
+ if (BIT(output_mask, i) && BIT(changed, i))
+ {
+ m_pa_bit_out[i](BIT(m_pfc.padr, i));
+ }
+ }
+
+ if (output_mask)
+ {
+ m_pa_out(m_pfc.padr & output_mask, output_mask);
+ }
+}
+
+uint16_t sh7021_device::pfc_pbdr_r()
+{
+ const uint16_t data = ((m_pfc.pbdr_in & ~m_pfc.pbior) | (m_pfc.padr & m_pfc.pbior)) & m_pfc.pa_gpio_mask;
+ if (!machine().side_effects_disabled())
+ LOGMASKED(LOG_PFC_RD, "%s: Port B Data Register, pfc_pbdr_r: %04x\n", machine().describe_context(), data);
+ return data;
+}
+
+void sh7021_device::pfc_pbdr_w(offs_t offset, uint16_t data, uint16_t mem_mask)
+{
+ LOGMASKED(LOG_PFC_WR, "%s: Port B Data Register, pfc_pbdr_w = %04x & %04x\n", machine().describe_context(), data, mem_mask);
+ const uint16_t old = m_pfc.pbdr;
+ COMBINE_DATA(&m_pfc.pbdr);
+ const uint16_t changed = m_pfc.pbdr ^ old;
+
+ uint16_t output_mask = m_pfc.pbior;
+ for (int i = 0; i < 16; i++)
+ {
+ if (m_pfc.pbfunc[i] != 0)
+ {
+ output_mask &= ~(1 << i);
+ }
+ else if (BIT(changed, i))
+ {
+ m_pb_bit_out[i](BIT(m_pfc.pbdr, i));
+ }
+ }
+
+ if (output_mask)
+ {
+ m_pb_out(m_pfc.pbdr & output_mask, output_mask);
+ }
+}
+
+uint16_t sh7021_device::pfc_cascr_r()
+{
+ if (!machine().side_effects_disabled())
+ LOGMASKED(LOG_PFC_RD, "%s: Column Address Strobe Pin Control Register, pfc_cascr_r: %04x\n", machine().describe_context(), m_pfc.cascr);
+ return m_pfc.cascr;
+}
+
+void sh7021_device::pfc_cascr_w(offs_t offset, uint16_t data, uint16_t mem_mask)
+{
+ LOGMASKED(LOG_PFC_WR, "%s: Column Address Strobe Pin Control Register, pfc_cascr_w = %04x & %04x\n", machine().describe_context(), data, mem_mask);
+ COMBINE_DATA(&m_pfc.cascr);
+}
diff --git a/src/devices/cpu/sh/sh7021.h b/src/devices/cpu/sh/sh7021.h
new file mode 100644
index 00000000000..487470ed8b1
--- /dev/null
+++ b/src/devices/cpu/sh/sh7021.h
@@ -0,0 +1,334 @@
+// license:BSD-3-Clause
+// copyright-holders:Ryan Holtz
+/*****************************************************************************
+ *
+ * sh7021.h
+ * Portable Hitachi SH-1 (model SH7021) emulator
+ *
+ *****************************************************************************/
+
+#ifndef MAME_CPU_SH_SH7021_H
+#define MAME_CPU_SH_SH7021_H
+
+#pragma once
+
+#include "sh2.h"
+
+class sh7021_device : public sh2_device
+{
+public:
+ // construction/destruction
+ sh7021_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+ void write_padr(uint16_t data);
+ void write_pbdr(uint16_t data);
+ template <int Line> void write_padr_bit(int state);
+ template <int Line> void write_pbdr_bit(int state);
+
+protected:
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+
+ virtual void execute_run() override;
+
+ void execute_dma(int ch);
+ void execute_peripherals(int peripheral_cycles);
+
+ // Interrupt Controller (INTC)
+ void intc_ipra_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0);
+ uint16_t intc_ipra_r();
+ void intc_iprb_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0);
+ uint16_t intc_iprb_r();
+ void intc_iprc_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0);
+ uint16_t intc_iprc_r();
+ void intc_iprd_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0);
+ uint16_t intc_iprd_r();
+ void intc_ipre_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0);
+ uint16_t intc_ipre_r();
+ void intc_icr_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0);
+ uint16_t intc_icr_r();
+
+ // User Break Controller (UBC)
+ uint16_t ubc_barh_r();
+ void ubc_barh_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0);
+ uint16_t ubc_barl_r();
+ void ubc_barl_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0);
+ uint16_t ubc_bamrh_r();
+ void ubc_bamrh_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0);
+ uint16_t ubc_bamrl_r();
+ void ubc_bamrl_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0);
+ uint16_t ubc_bbr_r();
+ void ubc_bbr_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0);
+
+ // Bus State Controller (BSC)
+ uint16_t bsc_bcr_r();
+ void bsc_bcr_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0);
+ uint16_t bsc_wcr1_r();
+ void bsc_wcr1_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0);
+ uint16_t bsc_wcr2_r();
+ void bsc_wcr2_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0);
+ uint16_t bsc_wcr3_r();
+ void bsc_wcr3_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0);
+ uint16_t bsc_dcr_r();
+ void bsc_dcr_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0);
+ uint16_t bsc_pcr_r();
+ void bsc_pcr_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0);
+ uint16_t bsc_rcr_r();
+ void bsc_rcr_w(uint16_t data);
+ uint16_t bsc_rtcsr_r();
+ void bsc_rtcsr_w(uint16_t data);
+ uint16_t bsc_rtcnt_r();
+ void bsc_rtcnt_w(uint16_t data);
+ uint16_t bsc_rtcor_r();
+ void bsc_rtcor_w(uint16_t data);
+
+ // DMA Controller (DMAC)
+ template <int Channel> uint32_t dma_sar_r();
+ template <int Channel> void dma_sar_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0U);
+ template <int Channel> uint32_t dma_dar_r();
+ template <int Channel> void dma_dar_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0U);
+ template <int Channel> uint16_t dma_tcr_r();
+ template <int Channel> void dma_tcr_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0);
+ template <int Channel> uint16_t dma_chcr_r();
+ template <int Channel> void dma_chcr_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0);
+ uint16_t dmaor_r();
+ void dmaor_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0);
+
+ // 16-Bit Integrated-Timer Pulse Unit (ITU)
+ uint8_t itu_tstr_r();
+ void itu_tstr_w(uint8_t data);
+ uint8_t itu_tsnc_r();
+ void itu_tsnc_w(uint8_t data);
+ uint8_t itu_tmdr_r();
+ void itu_tmdr_w(uint8_t data);
+ uint8_t itu_tfcr_r();
+ void itu_tfcr_w(uint8_t data);
+ uint8_t itu_tocr_r();
+ void itu_tocr_w(uint8_t data);
+
+ template <int Channel> uint8_t itu_tcr_r();
+ template <int Channel> void itu_tcr_w(uint8_t data);
+ template <int Channel> uint8_t itu_tior_r();
+ template <int Channel> void itu_tior_w(uint8_t data);
+ template <int Channel> uint8_t itu_tier_r();
+ template <int Channel> void itu_tier_w(uint8_t data);
+ template <int Channel> uint8_t itu_tsr_r();
+ template <int Channel> void itu_tsr_w(uint8_t data);
+ template <int Channel> uint16_t itu_tcnt_r();
+ template <int Channel> void itu_tcnt_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0);
+ template <int Channel> uint16_t itu_gra_r();
+ template <int Channel> void itu_gra_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0);
+ template <int Channel> uint16_t itu_grb_r();
+ template <int Channel> void itu_grb_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0);
+ template <int Channel> uint16_t itu_bra_r();
+ template <int Channel> void itu_bra_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0);
+ template <int Channel> uint16_t itu_brb_r();
+ template <int Channel> void itu_brb_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0);
+
+ // Programmable Timing Pattern Controller (TPC)
+ uint8_t tpc_tpmr_r();
+ void tpc_tpmr_w(uint8_t data);
+ uint8_t tpc_tpcr_r();
+ void tpc_tpcr_w(uint8_t data);
+ uint8_t tpc_ndera_r();
+ void tpc_ndera_w(uint8_t data);
+ uint8_t tpc_nderb_r();
+ void tpc_nderb_w(uint8_t data);
+ uint8_t tpc_ndra_r();
+ void tpc_ndra_w(uint8_t data);
+ uint8_t tpc_ndra_alt_r();
+ void tpc_ndra_alt_w(uint8_t data);
+ uint8_t tpc_ndrb_r();
+ void tpc_ndrb_w(uint8_t data);
+ uint8_t tpc_ndrb_alt_r();
+ void tpc_ndrb_alt_w(uint8_t data);
+
+ // Watchdog Timer (WDT)
+ uint8_t wdt_tcsr_r(); // TODO: Readable only in 8-bit mode
+ void wdt_tcsr_w(uint8_t data); // TODO: Writable only in 16-bit mode
+ uint8_t wdt_tcnt_r(); // TODO: Readable only in 8-bit mode
+ void wdt_tcnt_w(uint8_t data); // TODO: Writable only in 16-bit mode
+ uint8_t wdt_rstcsr_r();
+ void wdt_rstcsr_w(uint8_t data); // TODO: Writable only in 16-bit mode
+
+ // Serial Communication Interface (SCI)
+ template <int Channel> uint8_t sci_smr_r();
+ template <int Channel> void sci_smr_w(uint8_t data);
+ template <int Channel> uint8_t sci_brr_r();
+ template <int Channel> void sci_brr_w(uint8_t data);
+ template <int Channel> uint8_t sci_scr_r();
+ template <int Channel> void sci_scr_w(uint8_t data);
+ template <int Channel> uint8_t sci_tdr_r();
+ template <int Channel> void sci_tdr_w(uint8_t data);
+ template <int Channel> uint8_t sci_ssr_r();
+ template <int Channel> void sci_ssr_w(uint8_t data);
+ template <int Channel> uint8_t sci_rdr_r();
+
+ // Pin Function Controller (PFC)
+ uint16_t pfc_paior_r();
+ void pfc_paior_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0);
+ uint16_t pfc_pacr1_r();
+ void pfc_pacr1_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0);
+ uint16_t pfc_pacr2_r();
+ void pfc_pacr2_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0);
+ uint16_t pfc_pbior_r();
+ void pfc_pbior_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0);
+ uint16_t pfc_pbcr1_r();
+ void pfc_pbcr1_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0);
+ uint16_t pfc_pbcr2_r();
+ void pfc_pbcr2_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0);
+ uint16_t pfc_padr_r();
+ void pfc_padr_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0);
+ uint16_t pfc_pbdr_r();
+ void pfc_pbdr_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0);
+ uint16_t pfc_cascr_r();
+ void pfc_cascr_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0);
+
+ void internal_map(address_map &map) ATTR_COLD;
+
+ void recalc_irq();
+
+ virtual uint8_t read_byte(offs_t offset) override;
+ virtual uint16_t read_word(offs_t offset) override;
+ virtual uint32_t read_long(offs_t offset) override;
+ virtual uint16_t decrypted_read_word(offs_t offset) override;
+ virtual void write_byte(offs_t offset, uint8_t data) override;
+ virtual void write_word(offs_t offset, uint16_t data) override;
+ virtual void write_long(offs_t offset, uint32_t data) override;
+
+ // Interrupt Controller (INTC)
+ uint16_t m_ipra = 0;
+ uint16_t m_iprb = 0;
+ uint16_t m_iprc = 0;
+ uint16_t m_iprd = 0;
+ uint16_t m_ipre = 0;
+ uint16_t m_icr = 0;
+
+ // User Break Controller (UBC)
+ struct
+ {
+ uint16_t barh = 0;
+ uint16_t barl = 0;
+ uint16_t bamrh = 0;
+ uint16_t bamrl = 0;
+ uint16_t bbr = 0;
+ } m_ubc;
+
+ // Bus State Controller (BSC)
+ struct
+ {
+ uint16_t bcr = 0;
+ uint16_t wcr1 = 0;
+ uint16_t wcr2 = 0;
+ uint16_t wcr3 = 0;
+ uint16_t dcr = 0;
+ uint16_t pcr = 0;
+ uint8_t rcr = 0;
+ uint8_t rtcsr = 0;
+ bool rtcsr_read = false;
+ uint8_t rtcnt = 0;
+ uint8_t rtcor = 0;
+ } m_bsc;
+
+ // DMA Controller (DMAC)
+ struct
+ {
+ uint32_t sar = 0; // Source Address Register
+ uint32_t dar = 0; // Destination Address Register
+ uint16_t tcr = 0; // Transfer Count Register
+ uint16_t chcr = 0; // Channel Control Register
+ } m_dma[4];
+ uint16_t m_dmaor = 0; // DMA Operation Register (status flags)
+ int m_dma_cycles;
+
+ // 16-Bit Integrated-Timer Pulse Unit (ITU)
+ struct
+ {
+ uint8_t tstr = 0;
+ uint8_t tsnc = 0;
+ uint8_t tmdr = 0;
+ uint8_t tfcr = 0;
+ uint8_t tocr = 0;
+
+ struct
+ {
+ uint8_t tcr = 0;
+ uint8_t tior = 0;
+ uint8_t tier = 0;
+ uint8_t tsr = 0;
+ uint16_t tcnt = 0;
+ uint16_t gra = 0;
+ uint16_t grb = 0;
+ uint16_t bra = 0;
+ uint16_t brb = 0;
+ emu_timer *et = nullptr;
+ } timer[5];
+ } m_itu;
+
+ void start_timer(int i);
+
+ template<int which> TIMER_CALLBACK_MEMBER(sh7021_timer_callback);
+ template<int which> TIMER_CALLBACK_MEMBER(sh7021_sci_callback);
+
+ // Programmable Timing Pattern Controller (TPC)
+ struct
+ {
+ uint8_t tpmr = 0;
+ uint8_t tpcr = 0;
+ uint8_t ndera = 0;
+ uint8_t nderb = 0;
+ uint8_t ndra = 0;
+ uint8_t ndrb = 0;
+ } m_tpc;
+
+ // Watchdog Timer (WDT)
+ struct
+ {
+ uint8_t tcsr = 0;
+ uint8_t tcnt = 0;
+ uint8_t rstcsr = 0;
+ } m_wdt;
+
+ // Serial Communication Interface (SCI)
+ struct
+ {
+ uint8_t smr = 0;
+ uint8_t brr = 0;
+ uint8_t scr = 0;
+ uint8_t tsr = 0;
+ uint8_t tdr = 0;
+ uint8_t ssr = 0;
+ uint8_t ssr_read = 0;
+ uint8_t rsr = 0;
+ uint8_t rdr = 0;
+ emu_timer *et = nullptr;
+ } m_sci[2];
+
+ // Pin Function Controller (PFC)
+ struct
+ {
+ uint16_t paior = 0;
+ uint16_t pacr1 = 0;
+ uint16_t pacr2 = 0;
+ uint16_t pbior = 0;
+ uint16_t pbcr1 = 0;
+ uint16_t pbcr2 = 0;
+ uint16_t padr = 0;
+ uint16_t pbdr = 0;
+ uint16_t padr_in = 0;
+ uint16_t pbdr_in = 0;
+ uint16_t cascr = 0;
+ uint8_t pafunc[16];
+ uint8_t pbfunc[16];
+ uint16_t pa_gpio_mask = 0;
+ uint16_t pb_gpio_mask = 0;
+ } m_pfc;
+ devcb_write16 m_pa_out;
+ devcb_write16 m_pb_out;
+ devcb_write_line::array<16> m_pa_bit_out;
+ devcb_write_line::array<16> m_pb_bit_out;
+};
+
+DECLARE_DEVICE_TYPE(SH7021, sh7021_device)
+
+#endif // MAME_CPU_SH_SH7021_H
diff --git a/src/devices/cpu/sh/sh7032.cpp b/src/devices/cpu/sh/sh7032.cpp
new file mode 100644
index 00000000000..9f383816495
--- /dev/null
+++ b/src/devices/cpu/sh/sh7032.cpp
@@ -0,0 +1,43 @@
+// license:BSD-3-Clause
+// copyright-holders:Angelo Salese
+
+#include "emu.h"
+#include "sh7032.h"
+
+DEFINE_DEVICE_TYPE(SH7032, sh7032_device, "sh7032", "Hitachi SH-1 (SH7032)")
+
+
+sh7032_device::sh7032_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : sh2_device(mconfig, SH7032, tag, owner, clock, CPU_TYPE_SH1, address_map_constructor(FUNC(sh7032_device::sh7032_map), this), 28, 0xc7ffffff)
+{
+}
+
+void sh7032_device::device_start()
+{
+ sh2_device::device_start();
+
+ save_item(NAME(m_sh7032_regs));
+}
+
+void sh7032_device::device_reset()
+{
+ sh2_device::device_reset();
+
+ std::fill(std::begin(m_sh7032_regs), std::end(m_sh7032_regs), 0);
+}
+
+void sh7032_device::sh7032_map(address_map &map)
+{
+// fall-back
+ map(0x05fffe00, 0x05ffffff).rw(FUNC(sh7032_device::sh7032_r), FUNC(sh7032_device::sh7032_w)); // SH-7032H internal i/o
+}
+
+uint16_t sh7032_device::sh7032_r(offs_t offset)
+{
+ return m_sh7032_regs[offset];
+}
+
+void sh7032_device::sh7032_w(offs_t offset, uint16_t data, uint16_t mem_mask)
+{
+ COMBINE_DATA(&m_sh7032_regs[offset]);
+}
diff --git a/src/devices/cpu/sh/sh7032.h b/src/devices/cpu/sh/sh7032.h
new file mode 100644
index 00000000000..8608da410d6
--- /dev/null
+++ b/src/devices/cpu/sh/sh7032.h
@@ -0,0 +1,33 @@
+// license:BSD-3-Clause
+// copyright-holders:Angelo Salese
+
+// SH7032, sh1 variant
+
+#ifndef MAME_CPU_SH_SH7032_H
+#define MAME_CPU_SH_SH7032_H
+
+#pragma once
+
+#include "sh2.h"
+
+class sh7032_device : public sh2_device
+{
+public:
+ sh7032_device(const machine_config &mconfig, const char *_tag, device_t *_owner, uint32_t _clock);
+
+protected:
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+
+private:
+ void sh7032_map(address_map &map) ATTR_COLD;
+
+ uint16_t sh7032_r(offs_t offset);
+ void sh7032_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0);
+
+ uint16_t m_sh7032_regs[0x200];
+};
+
+DECLARE_DEVICE_TYPE(SH7032, sh7032_device)
+
+#endif // MAME_CPU_SH_SH7032_H
diff --git a/src/devices/cpu/sh/sh7042.cpp b/src/devices/cpu/sh/sh7042.cpp
new file mode 100644
index 00000000000..9fef06c64ad
--- /dev/null
+++ b/src/devices/cpu/sh/sh7042.cpp
@@ -0,0 +1,505 @@
+// license:BSD-3-Clause
+// copyright-holders:Olivier Galibert
+
+// SH7042, sh2 variant
+
+#include "emu.h"
+#include "sh7042.h"
+
+DEFINE_DEVICE_TYPE(SH7042, sh7042_device, "sh7042", "Hitachi SH-2 (SH7042)")
+DEFINE_DEVICE_TYPE(SH7042A, sh7042a_device, "sh7042a", "Hitachi SH-2 (SH7042A)")
+DEFINE_DEVICE_TYPE(SH7043, sh7043_device, "sh7043", "Hitachi SH-2 (SH7043)")
+DEFINE_DEVICE_TYPE(SH7043A, sh7043a_device, "sh7043a", "Hitachi SH-2 (SH7043A)")
+
+sh7042_device::sh7042_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+ sh7042_device(mconfig, SH7042, tag, owner, clock)
+{
+ m_die_a = false;
+}
+
+sh7042a_device::sh7042a_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+ sh7042_device(mconfig, SH7042A, tag, owner, clock)
+{
+ m_die_a = true;
+}
+
+sh7043_device::sh7043_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+ sh7042_device(mconfig, SH7043, tag, owner, clock)
+{
+ m_die_a = false;
+}
+
+sh7043a_device::sh7043a_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+ sh7042_device(mconfig, SH7043A, tag, owner, clock)
+{
+ m_die_a = true;
+}
+
+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_adc0(*this, "adc0"),
+ m_adc1(*this, "adc1"),
+ m_bsc(*this, "bsc"),
+ m_cmt(*this, "cmt"),
+ m_dmac(*this, "dmac"),
+ m_dmac0(*this, "dmac:0"),
+ m_dmac1(*this, "dmac:1"),
+ m_dmac2(*this, "dmac:2"),
+ m_dmac3(*this, "dmac:3"),
+ m_mtu(*this, "mtu"),
+ m_mtu0(*this, "mtu:0"),
+ m_mtu1(*this, "mtu:1"),
+ m_mtu2(*this, "mtu:2"),
+ m_mtu3(*this, "mtu:3"),
+ m_mtu4(*this, "mtu:4"),
+ 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_sci(*this, "sci%d", 0),
+ m_read_adc(*this, 0),
+ m_sci_tx(*this),
+ m_sci_clk(*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);
+ return 0;
+}
+
+void sh7042_device::device_start()
+{
+ sh2_device::device_start();
+
+ 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::execute_set_input(int irqline, int state)
+{
+ m_intc->set_input(irqline, state);
+}
+
+void sh7042_device::device_reset()
+{
+ sh2_device::device_reset();
+}
+
+
+void sh7042_device::map(address_map &map)
+{
+ map(0xffff81a0, 0xffff81a0).rw(m_sci[0], FUNC(sh_sci_device::smr_r), FUNC(sh_sci_device::smr_w));
+ map(0xffff81a1, 0xffff81a1).rw(m_sci[0], FUNC(sh_sci_device::brr_r), FUNC(sh_sci_device::brr_w));
+ map(0xffff81a2, 0xffff81a2).rw(m_sci[0], FUNC(sh_sci_device::scr_r), FUNC(sh_sci_device::scr_w));
+ map(0xffff81a3, 0xffff81a3).rw(m_sci[0], FUNC(sh_sci_device::tdr_r), FUNC(sh_sci_device::tdr_w));
+ map(0xffff81a4, 0xffff81a4).rw(m_sci[0], FUNC(sh_sci_device::ssr_r), FUNC(sh_sci_device::ssr_w));
+ map(0xffff81a5, 0xffff81a5).r(m_sci[0], FUNC(sh_sci_device::rdr_r));
+ map(0xffff81b0, 0xffff81b0).rw(m_sci[1], FUNC(sh_sci_device::smr_r), FUNC(sh_sci_device::smr_w));
+ map(0xffff81b1, 0xffff81b1).rw(m_sci[1], FUNC(sh_sci_device::brr_r), FUNC(sh_sci_device::brr_w));
+ map(0xffff81b2, 0xffff81b2).rw(m_sci[1], FUNC(sh_sci_device::scr_r), FUNC(sh_sci_device::scr_w));
+ map(0xffff81b3, 0xffff81b3).rw(m_sci[1], FUNC(sh_sci_device::tdr_r), FUNC(sh_sci_device::tdr_w));
+ map(0xffff81b4, 0xffff81b4).rw(m_sci[1], FUNC(sh_sci_device::ssr_r), FUNC(sh_sci_device::ssr_w));
+ map(0xffff81b5, 0xffff81b5).r(m_sci[1], FUNC(sh_sci_device::rdr_r));
+
+ map(0xffff8200, 0xffff8200).rw(m_mtu3, FUNC(sh_mtu_channel_device::tcr_r), FUNC(sh_mtu_channel_device::tcr_w));
+ map(0xffff8201, 0xffff8201).rw(m_mtu4, FUNC(sh_mtu_channel_device::tcr_r), FUNC(sh_mtu_channel_device::tcr_w));
+ map(0xffff8202, 0xffff8202).rw(m_mtu3, FUNC(sh_mtu_channel_device::tmdr_r), FUNC(sh_mtu_channel_device::tmdr_w));
+ map(0xffff8203, 0xffff8203).rw(m_mtu4, FUNC(sh_mtu_channel_device::tmdr_r), FUNC(sh_mtu_channel_device::tmdr_w));
+ map(0xffff8204, 0xffff8205).rw(m_mtu3, FUNC(sh_mtu_channel_device::tior_r), FUNC(sh_mtu_channel_device::tior_w));
+ map(0xffff8206, 0xffff8207).rw(m_mtu4, FUNC(sh_mtu_channel_device::tior_r), FUNC(sh_mtu_channel_device::tior_w));
+ map(0xffff8208, 0xffff8208).rw(m_mtu3, FUNC(sh_mtu_channel_device::tier_r), FUNC(sh_mtu_channel_device::tier_w));
+ map(0xffff8209, 0xffff8209).rw(m_mtu4, FUNC(sh_mtu_channel_device::tier_r), FUNC(sh_mtu_channel_device::tier_w));
+ map(0xffff820a, 0xffff820a).rw(m_mtu, FUNC(sh_mtu_device::toer_r), FUNC(sh_mtu_device::toer_w));
+ map(0xffff820b, 0xffff820b).rw(m_mtu, FUNC(sh_mtu_device::tocr_r), FUNC(sh_mtu_device::tocr_w));
+ map(0xffff820d, 0xffff820d).rw(m_mtu, FUNC(sh_mtu_device::tgcr_r), FUNC(sh_mtu_device::tgcr_w));
+ map(0xffff8210, 0xffff8211).rw(m_mtu3, FUNC(sh_mtu_channel_device::tcnt_r), FUNC(sh_mtu_channel_device::tcnt_w));
+ map(0xffff8212, 0xffff8213).rw(m_mtu4, FUNC(sh_mtu_channel_device::tcnt_r), FUNC(sh_mtu_channel_device::tcnt_w));
+ map(0xffff8214, 0xffff8215).rw(m_mtu, FUNC(sh_mtu_device::tcdr_r), FUNC(sh_mtu_device::tcdr_w));
+ map(0xffff8216, 0xffff8217).rw(m_mtu, FUNC(sh_mtu_device::tddr_r), FUNC(sh_mtu_device::tddr_w));
+ map(0xffff8218, 0xffff821b).rw(m_mtu3, FUNC(sh_mtu_channel_device::tgr_r), FUNC(sh_mtu_channel_device::tgr_w));
+ map(0xffff821c, 0xffff821f).rw(m_mtu4, FUNC(sh_mtu_channel_device::tgr_r), FUNC(sh_mtu_channel_device::tgr_w));
+ map(0xffff8220, 0xffff8221).rw(m_mtu, FUNC(sh_mtu_device::tcnts_r), FUNC(sh_mtu_device::tcnts_w));
+ map(0xffff8222, 0xffff8223).rw(m_mtu, FUNC(sh_mtu_device::tcbr_r), FUNC(sh_mtu_device::tcbr_w));
+ map(0xffff8224, 0xffff8227).rw(m_mtu3, FUNC(sh_mtu_channel_device::tgrc_r), FUNC(sh_mtu_channel_device::tgrc_w));
+ map(0xffff8228, 0xffff822b).rw(m_mtu4, FUNC(sh_mtu_channel_device::tgrc_r), FUNC(sh_mtu_channel_device::tgrc_w));
+ map(0xffff822c, 0xffff822c).rw(m_mtu3, FUNC(sh_mtu_channel_device::tsr_r), FUNC(sh_mtu_channel_device::tsr_w));
+ map(0xffff822d, 0xffff822d).rw(m_mtu4, FUNC(sh_mtu_channel_device::tsr_r), FUNC(sh_mtu_channel_device::tsr_w));
+ map(0xffff8240, 0xffff8240).rw(m_mtu, FUNC(sh_mtu_device::tstr_r), FUNC(sh_mtu_device::tstr_w));
+ map(0xffff8241, 0xffff8241).rw(m_mtu, FUNC(sh_mtu_device::tsyr_r), FUNC(sh_mtu_device::tsyr_w));
+ map(0xffff8260, 0xffff8260).rw(m_mtu0, FUNC(sh_mtu_channel_device::tcr_r), FUNC(sh_mtu_channel_device::tcr_w));
+ map(0xffff8261, 0xffff8261).rw(m_mtu0, FUNC(sh_mtu_channel_device::tmdr_r), FUNC(sh_mtu_channel_device::tmdr_w));
+ map(0xffff8262, 0xffff8263).rw(m_mtu0, FUNC(sh_mtu_channel_device::tior_r), FUNC(sh_mtu_channel_device::tior_w));
+ map(0xffff8264, 0xffff8264).rw(m_mtu0, FUNC(sh_mtu_channel_device::tier_r), FUNC(sh_mtu_channel_device::tier_w));
+ map(0xffff8265, 0xffff8265).rw(m_mtu0, FUNC(sh_mtu_channel_device::tsr_r), FUNC(sh_mtu_channel_device::tsr_w));
+ map(0xffff8266, 0xffff8267).rw(m_mtu0, FUNC(sh_mtu_channel_device::tcnt_r), FUNC(sh_mtu_channel_device::tcnt_w));
+ map(0xffff8268, 0xffff826f).rw(m_mtu0, FUNC(sh_mtu_channel_device::tgr_r), FUNC(sh_mtu_channel_device::tgr_w));
+ map(0xffff8280, 0xffff8280).rw(m_mtu1, FUNC(sh_mtu_channel_device::tcr_r), FUNC(sh_mtu_channel_device::tcr_w));
+ map(0xffff8281, 0xffff8281).rw(m_mtu1, FUNC(sh_mtu_channel_device::tmdr_r), FUNC(sh_mtu_channel_device::tmdr_w));
+ map(0xffff8282, 0xffff8283).rw(m_mtu1, FUNC(sh_mtu_channel_device::tior_r), FUNC(sh_mtu_channel_device::tior_w));
+ map(0xffff8284, 0xffff8284).rw(m_mtu1, FUNC(sh_mtu_channel_device::tier_r), FUNC(sh_mtu_channel_device::tier_w));
+ map(0xffff8285, 0xffff8285).rw(m_mtu1, FUNC(sh_mtu_channel_device::tsr_r), FUNC(sh_mtu_channel_device::tsr_w));
+ map(0xffff8286, 0xffff8287).rw(m_mtu1, FUNC(sh_mtu_channel_device::tcnt_r), FUNC(sh_mtu_channel_device::tcnt_w));
+ map(0xffff8288, 0xffff828b).rw(m_mtu1, FUNC(sh_mtu_channel_device::tgr_r), FUNC(sh_mtu_channel_device::tgr_w));
+ map(0xffff82a0, 0xffff82a0).rw(m_mtu2, FUNC(sh_mtu_channel_device::tcr_r), FUNC(sh_mtu_channel_device::tcr_w));
+ map(0xffff82a1, 0xffff82a1).rw(m_mtu2, FUNC(sh_mtu_channel_device::tmdr_r), FUNC(sh_mtu_channel_device::tmdr_w));
+ map(0xffff82a2, 0xffff82a3).rw(m_mtu2, FUNC(sh_mtu_channel_device::tior_r), FUNC(sh_mtu_channel_device::tior_w));
+ map(0xffff82a4, 0xffff82a4).rw(m_mtu2, FUNC(sh_mtu_channel_device::tier_r), FUNC(sh_mtu_channel_device::tier_w));
+ map(0xffff82a5, 0xffff82a5).rw(m_mtu2, FUNC(sh_mtu_channel_device::tsr_r), FUNC(sh_mtu_channel_device::tsr_w));
+ map(0xffff82a6, 0xffff82a7).rw(m_mtu2, FUNC(sh_mtu_channel_device::tcnt_r), FUNC(sh_mtu_channel_device::tcnt_w));
+ map(0xffff82a8, 0xffff82ab).rw(m_mtu2, FUNC(sh_mtu_channel_device::tgr_r), FUNC(sh_mtu_channel_device::tgr_w));
+
+ 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));
+
+ if(!m_die_a) {
+ map(0xffff83e0, 0xffff83e0).rw(m_adc0, FUNC(sh_adc_device::adcsr_r), FUNC(sh_adc_device::adcsr_w));
+ map(0xffff83e1, 0xffff83e1).rw(m_adc0, FUNC(sh_adc_device::adcr_r), FUNC(sh_adc_device::adcr_w));
+ map(0xffff83f0, 0xffff83ff).r(m_adc0, FUNC(sh_adc_device::addr_r));
+ } else {
+ map(0xffff8400, 0xffff8407).r(m_adc0, FUNC(sh_adc_device::addr_r));
+ map(0xffff8408, 0xffff840f).r(m_adc1, FUNC(sh_adc_device::addr_r));
+ map(0xffff8410, 0xffff8410).rw(m_adc0, FUNC(sh_adc_device::adcsr_r), FUNC(sh_adc_device::adcsr_w));
+ map(0xffff8411, 0xffff8411).rw(m_adc1, FUNC(sh_adc_device::adcsr_r), FUNC(sh_adc_device::adcsr_w));
+ map(0xffff8412, 0xffff8412).rw(m_adc0, FUNC(sh_adc_device::adcr_r), FUNC(sh_adc_device::adcr_w));
+ map(0xffff8413, 0xffff8413).rw(m_adc1, FUNC(sh_adc_device::adcr_r), FUNC(sh_adc_device::adcr_w));
+ }
+
+ map(0xffff8620, 0xffff8621).rw(m_bsc, FUNC(sh_bsc_device::bcr1_r), FUNC(sh_bsc_device::bcr1_w));
+ map(0xffff8622, 0xffff8623).rw(m_bsc, FUNC(sh_bsc_device::bcr2_r), FUNC(sh_bsc_device::bcr2_w));
+ map(0xffff8624, 0xffff8625).rw(m_bsc, FUNC(sh_bsc_device::wcr1_r), FUNC(sh_bsc_device::wcr1_w));
+ map(0xffff8626, 0xffff8627).rw(m_bsc, FUNC(sh_bsc_device::wcr2_r), FUNC(sh_bsc_device::wcr2_w));
+ map(0xffff862a, 0xffff862b).rw(m_bsc, FUNC(sh_bsc_device::dcr_r), FUNC(sh_bsc_device::dcr_w));
+ map(0xffff862c, 0xffff862d).rw(m_bsc, FUNC(sh_bsc_device::rtcsr_r), FUNC(sh_bsc_device::rtcsr_w));
+ map(0xffff862e, 0xffff862f).rw(m_bsc, FUNC(sh_bsc_device::rtcnt_r), FUNC(sh_bsc_device::rtcnt_w));
+ map(0xffff8630, 0xffff8631).rw(m_bsc, FUNC(sh_bsc_device::rtcor_r), FUNC(sh_bsc_device::rtcor_w));
+ map(0xffff86b0, 0xffff86b1).rw(m_dmac, FUNC(sh_dmac_device::dmaor_r), FUNC(sh_dmac_device::dmaor_w));
+ map(0xffff86c0, 0xffff86c3).rw(m_dmac0, FUNC(sh_dmac_channel_device::sar_r), FUNC(sh_dmac_channel_device::sar_w));
+ map(0xffff86c4, 0xffff86c7).rw(m_dmac0, FUNC(sh_dmac_channel_device::dar_r), FUNC(sh_dmac_channel_device::dar_w));
+ map(0xffff86c8, 0xffff86cb).rw(m_dmac0, FUNC(sh_dmac_channel_device::dmatcr_r), FUNC(sh_dmac_channel_device::dmatcr_w));
+ map(0xffff86cc, 0xffff86cf).rw(m_dmac0, FUNC(sh_dmac_channel_device::chcr_r), FUNC(sh_dmac_channel_device::chcr_w));
+ map(0xffff86d0, 0xffff86d3).rw(m_dmac1, FUNC(sh_dmac_channel_device::sar_r), FUNC(sh_dmac_channel_device::sar_w));
+ map(0xffff86d4, 0xffff86d7).rw(m_dmac1, FUNC(sh_dmac_channel_device::dar_r), FUNC(sh_dmac_channel_device::dar_w));
+ map(0xffff86d8, 0xffff86db).rw(m_dmac1, FUNC(sh_dmac_channel_device::dmatcr_r), FUNC(sh_dmac_channel_device::dmatcr_w));
+ map(0xffff86dc, 0xffff86df).rw(m_dmac1, FUNC(sh_dmac_channel_device::chcr_r), FUNC(sh_dmac_channel_device::chcr_w));
+ map(0xffff86e0, 0xffff86e3).rw(m_dmac2, FUNC(sh_dmac_channel_device::sar_r), FUNC(sh_dmac_channel_device::sar_w));
+ map(0xffff86e4, 0xffff86e7).rw(m_dmac2, FUNC(sh_dmac_channel_device::dar_r), FUNC(sh_dmac_channel_device::dar_w));
+ map(0xffff86e8, 0xffff86eb).rw(m_dmac2, FUNC(sh_dmac_channel_device::dmatcr_r), FUNC(sh_dmac_channel_device::dmatcr_w));
+ map(0xffff86ec, 0xffff86ef).rw(m_dmac2, FUNC(sh_dmac_channel_device::chcr_r), FUNC(sh_dmac_channel_device::chcr_w));
+ map(0xffff86f0, 0xffff86f3).rw(m_dmac3, FUNC(sh_dmac_channel_device::sar_r), FUNC(sh_dmac_channel_device::sar_w));
+ map(0xffff86f4, 0xffff86f7).rw(m_dmac3, FUNC(sh_dmac_channel_device::dar_r), FUNC(sh_dmac_channel_device::dar_w));
+ map(0xffff86f8, 0xffff86fb).rw(m_dmac3, FUNC(sh_dmac_channel_device::dmatcr_r), FUNC(sh_dmac_channel_device::dmatcr_w));
+ map(0xffff86fc, 0xffff86ff).rw(m_dmac3, FUNC(sh_dmac_channel_device::chcr_r), FUNC(sh_dmac_channel_device::chcr_w));
+
+ map(0xfffff000, 0xffffffff).ram();
+}
+
+void sh7042_device::device_add_mconfig(machine_config &config)
+{
+ SH_INTC(config, m_intc, *this);
+ if(m_die_a) {
+ SH_ADC_MS(config, m_adc0, *this, m_intc, 0, 136);
+ SH_ADC_MS(config, m_adc1, *this, m_intc, 4, 137);
+ } else
+ SH_ADC_HS(config, m_adc0, *this, m_intc, 136);
+ SH_BSC(config, m_bsc);
+ SH_CMT(config, m_cmt, *this, m_intc, 144, 148);
+ SH_DMAC(config, m_dmac, *this);
+ SH_DMAC_CHANNEL(config, m_dmac0, *this, m_intc);
+ SH_DMAC_CHANNEL(config, m_dmac1, *this, m_intc);
+ SH_DMAC_CHANNEL(config, m_dmac2, *this, m_intc);
+ SH_DMAC_CHANNEL(config, m_dmac3, *this, m_intc);
+ SH_MTU(config, m_mtu, *this, 5);
+ SH_MTU_CHANNEL(config, m_mtu0, *this, 4, 0x60, m_intc, 88,
+ sh_mtu_channel_device::DIV_1,
+ sh_mtu_channel_device::DIV_4,
+ sh_mtu_channel_device::DIV_16,
+ sh_mtu_channel_device::DIV_64,
+ sh_mtu_channel_device::INPUT_A,
+ sh_mtu_channel_device::INPUT_B,
+ sh_mtu_channel_device::INPUT_C,
+ sh_mtu_channel_device::INPUT_D);
+ SH_MTU_CHANNEL(config, m_mtu1, *this, 2, 0x4c, m_intc, 96,
+ sh_mtu_channel_device::DIV_1,
+ sh_mtu_channel_device::DIV_4,
+ sh_mtu_channel_device::DIV_16,
+ sh_mtu_channel_device::DIV_64,
+ sh_mtu_channel_device::INPUT_A,
+ sh_mtu_channel_device::INPUT_B,
+ sh_mtu_channel_device::DIV_256,
+ sh_mtu_channel_device::CHAIN).set_chain(m_mtu2);
+ SH_MTU_CHANNEL(config, m_mtu2, *this, 2, 0x4c, m_intc, 104,
+ sh_mtu_channel_device::DIV_1,
+ sh_mtu_channel_device::DIV_4,
+ sh_mtu_channel_device::DIV_16,
+ sh_mtu_channel_device::DIV_64,
+ sh_mtu_channel_device::INPUT_A,
+ sh_mtu_channel_device::INPUT_B,
+ sh_mtu_channel_device::INPUT_C,
+ sh_mtu_channel_device::DIV_1024);
+ SH_MTU_CHANNEL(config, m_mtu3, *this, 4, 0x60, m_intc, 112,
+ sh_mtu_channel_device::DIV_1,
+ sh_mtu_channel_device::DIV_4,
+ sh_mtu_channel_device::DIV_16,
+ sh_mtu_channel_device::DIV_64,
+ sh_mtu_channel_device::DIV_256,
+ sh_mtu_channel_device::DIV_1024,
+ sh_mtu_channel_device::INPUT_A,
+ sh_mtu_channel_device::INPUT_B);
+ SH_MTU_CHANNEL(config, m_mtu4, *this, 4, 0x60, m_intc, 120,
+ sh_mtu_channel_device::DIV_1,
+ sh_mtu_channel_device::DIV_4,
+ sh_mtu_channel_device::DIV_16,
+ sh_mtu_channel_device::DIV_64,
+ sh_mtu_channel_device::DIV_256,
+ sh_mtu_channel_device::DIV_1024,
+ sh_mtu_channel_device::INPUT_A,
+ sh_mtu_channel_device::INPUT_B);
+ 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);
+ SH_SCI(config, m_sci[0], 0, *this, m_intc, 128, 129, 130, 131);
+ SH_SCI(config, m_sci[1], 1, *this, m_intc, 132, 133, 134, 135);
+
+}
+
+void sh7042_device::internal_update()
+{
+ internal_update(current_cycles());
+}
+
+void sh7042_device::add_event(u64 &event_time, u64 new_event)
+{
+ if(!new_event)
+ return;
+ if(!event_time || event_time > new_event)
+ event_time = new_event;
+}
+
+void sh7042_device::recompute_timer(u64 event_time)
+{
+ 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());
+}
+
+TIMER_CALLBACK_MEMBER(sh7042_device::event_timer_tick)
+{
+ internal_update();
+}
+
+void sh7042_device::internal_update(u64 current_time)
+{
+ u64 event_time = 0;
+
+ add_event(event_time, m_adc0->internal_update(current_time));
+ if(m_adc1)
+ add_event(event_time, m_adc1->internal_update(current_time));
+ add_event(event_time, m_cmt->internal_update(current_time));
+ add_event(event_time, m_mtu0->internal_update(current_time));
+ add_event(event_time, m_mtu1->internal_update(current_time));
+ add_event(event_time, m_mtu2->internal_update(current_time));
+ add_event(event_time, m_mtu3->internal_update(current_time));
+ add_event(event_time, m_mtu4->internal_update(current_time));
+ add_event(event_time, m_sci[0]->internal_update(current_time));
+ add_event(event_time, m_sci[1]->internal_update(current_time));
+
+ recompute_timer(event_time);
+}
+
+u16 sh7042_device::pcf_ah_r()
+{
+ 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);
+}
+
+void sh7042_device::set_internal_interrupt(int level, u32 vector)
+{
+ m_sh2_state->internal_irq_level = level;
+ m_internal_irq_vector = vector;
+ m_test_irq = 1;
+}
+
+void sh7042_device::sh2_exception_internal(const char *message, int irqline, int vector)
+{
+ sh2_device::sh2_exception_internal(message, irqline, vector);
+ m_intc->interrupt_taken(irqline, vector);
+}
diff --git a/src/devices/cpu/sh/sh7042.h b/src/devices/cpu/sh/sh7042.h
new file mode 100644
index 00000000000..dbe2b32f6aa
--- /dev/null
+++ b/src/devices/cpu/sh/sh7042.h
@@ -0,0 +1,190 @@
+// license:BSD-3-Clause
+// copyright-holders:Olivier Galibert
+
+// SH704x, sh2 variant
+
+#ifndef MAME_CPU_SH_SH7042_H
+#define MAME_CPU_SH_SH7042_H
+
+#pragma once
+
+#include "sh2.h"
+#include "sh_intc.h"
+#include "sh_adc.h"
+#include "sh_bsc.h"
+#include "sh_cmt.h"
+#include "sh_dmac.h"
+#include "sh_mtu.h"
+#include "sh_port.h"
+#include "sh_sci.h"
+
+class sh7042_device : public sh2_device
+{
+public:
+ sh7042_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+ template<int Port> auto read_adc() { return m_read_adc[Port].bind(); }
+ template<int Sci> void sci_rx_w(int state) { m_sci[Sci]->do_rx_w(state); }
+ template<int Sci> void sci_clk_w(int state) { m_sci[Sci]->do_clk_w(state); }
+ template<int Sci> auto write_sci_tx() { return m_sci_tx[Sci].bind(); }
+ template<int Sci> auto write_sci_clk() { return m_sci_clk[Sci].bind(); }
+
+ void sci_set_external_clock_period(int sci, const attotime &period) {
+ m_sci[sci].lookup()->do_set_external_clock_period(period);
+ }
+
+ 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()); }
+
+ void set_internal_interrupt(int level, u32 vector);
+
+ void do_sci_tx(int sci, int state) { m_sci_tx[sci](state); }
+ void do_sci_clk(int sci, int state) { m_sci_clk[sci](state); }
+
+protected:
+ const char *m_port16_names;
+ const char *m_port32_names;
+ enum {
+ CSR_ADF = 0x80,
+ CSR_ADIE = 0x40,
+ CSR_ADST = 0x20,
+ CSR_CKS = 0x10,
+ CSR_GRP = 0x08,
+ CSR_CHAN = 0x07
+ };
+
+ enum {
+ CR_PWR = 0x40,
+ CR_TRGS = 0x30,
+ CR_SCAN = 0x08,
+ CR_SIM = 0x04,
+ CR_BUF = 0x03
+ };
+
+ bool m_die_a;
+
+ sh7042_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock);
+
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+ virtual void sh2_exception_internal(const char *message, int irqline, int vector) override;
+ virtual void execute_set_input(int irqline, int state) override;
+
+private:
+ required_device<sh_intc_device> m_intc;
+ required_device<sh_adc_device> m_adc0;
+ optional_device<sh_adc_device> m_adc1;
+ required_device<sh_bsc_device> m_bsc;
+ required_device<sh_cmt_device> m_cmt;
+ required_device<sh_dmac_device> m_dmac;
+ required_device<sh_dmac_channel_device> m_dmac0;
+ required_device<sh_dmac_channel_device> m_dmac1;
+ required_device<sh_dmac_channel_device> m_dmac2;
+ required_device<sh_dmac_channel_device> m_dmac3;
+ required_device<sh_mtu_device> m_mtu;
+ required_device<sh_mtu_channel_device> m_mtu0;
+ required_device<sh_mtu_channel_device> m_mtu1;
+ required_device<sh_mtu_channel_device> m_mtu2;
+ required_device<sh_mtu_channel_device> m_mtu3;
+ required_device<sh_mtu_channel_device> m_mtu4;
+ 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;
+ required_device_array<sh_sci_device, 2> m_sci;
+
+ devcb_read16::array<8> m_read_adc;
+ devcb_write_line::array<2> m_sci_tx, m_sci_clk;
+ 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) ATTR_COLD;
+
+ u16 adc_default(int adc);
+ 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);
+
+ 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 sh7042a_device : public sh7042_device
+{
+public:
+ sh7042a_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+};
+
+class sh7043_device : public sh7042_device
+{
+public:
+ sh7043_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+};
+
+class sh7043a_device : public sh7042_device
+{
+public:
+ sh7043a_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+};
+
+
+DECLARE_DEVICE_TYPE(SH7042, sh7042_device)
+DECLARE_DEVICE_TYPE(SH7042A, sh7042a_device)
+DECLARE_DEVICE_TYPE(SH7043, sh7043_device)
+DECLARE_DEVICE_TYPE(SH7043A, sh7043a_device)
+
+#endif // MAME_CPU_SH_SH7042_H
diff --git a/src/devices/cpu/sh/sh7604.cpp b/src/devices/cpu/sh/sh7604.cpp
new file mode 100644
index 00000000000..8bd1e59970c
--- /dev/null
+++ b/src/devices/cpu/sh/sh7604.cpp
@@ -0,0 +1,1540 @@
+// license:BSD-3-Clause
+// copyright-holders:Juergen Buchmueller, R. Belmont
+/*****************************************************************************
+ *
+ * sh7604.cpp
+ * Portable Hitachi SH-2 (SH7600 family) emulator
+ *
+ * This work is based on <tiraniddo@hotmail.com> C/C++ implementation of
+ * the SH-2 CPU core and was adapted to the MAME CPU core requirements.
+ * Thanks also go to Chuck Mason <chukjr@sundail.net> and Olivier Galibert
+ * <galibert@pobox.com> for letting me peek into their SEMU code :-)
+ *
+ *****************************************************************************/
+/*
+TODO: Test and use sh7604_wdt_device, sh7604_sci_device, and sh7604_bus_device as appropriate
+*/
+
+
+#include "emu.h"
+
+#include "sh7604.h"
+
+//#define VERBOSE 1
+#include "logmacro.h"
+
+
+static constexpr int div_tab[4] = { 3, 5, 7, 0 };
+static constexpr int wdtclk_tab[8] = { 1, 6, 7, 8, 9, 10, 12, 13 };
+
+
+DEFINE_DEVICE_TYPE(SH7604, sh7604_device, "sh2_7604", "Hitachi SH-2 (SH7604)")
+
+
+sh7604_device::sh7604_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : sh2_device(mconfig, SH7604, tag, owner, clock, CPU_TYPE_SH2, address_map_constructor(FUNC(sh7604_device::sh7604_map), this), 32, 0xc7ffffff)
+ , m_test_irq(0), m_internal_irq_vector(0)
+ , m_smr(0), m_brr(0), m_scr(0), m_tdr(0), m_ssr(0)
+ , m_tier(0), m_ftcsr(0), m_frc_tcr(0), m_tocr(0), m_frc(0), m_ocra(0), m_ocrb(0), m_frc_icr(0)
+ , m_ipra(0), m_iprb(0), m_vcra(0), m_vcrb(0), m_vcrc(0), m_vcrd(0), m_vcrwdt(0), m_vcrdiv(0), m_intc_icr(0), m_vecmd(false), m_nmie(false)
+ , m_divu_ovf(false), m_divu_ovfie(false), m_dvsr(0), m_dvdntl(0), m_dvdnth(0)
+ , m_wtcnt(0), m_wtcsr(0), m_rstcsr(0)
+ , m_dmaor(0)
+ , m_sbycr(0), m_ccr(0)
+ , m_bcr1(0), m_bcr2(0), m_wcr(0), m_mcr(0), m_rtcsr(0), m_rtcor(0), m_rtcnt(0)
+ , m_frc_base(0), m_frt_input(0)
+ , m_timer(nullptr), m_wdtimer(nullptr)
+ , m_is_slave(0)
+ , m_dma_kludge_cb(*this)
+ , m_dma_fifo_data_available_cb(*this)
+ , m_ftcsr_read_cb(*this)
+{
+ std::fill(std::begin(m_vcrdma), std::end(m_vcrdma), 0);
+ std::fill(std::begin(m_dma_timer_active), std::end(m_dma_timer_active), 0);
+ std::fill(std::begin(m_dma_irq), std::end(m_dma_irq), 0);
+ std::fill(std::begin(m_active_dma_incs), std::end(m_active_dma_incs), 0);
+ std::fill(std::begin(m_active_dma_incd), std::end(m_active_dma_incd), 0);
+ std::fill(std::begin(m_active_dma_size), std::end(m_active_dma_size), 0);
+ std::fill(std::begin(m_active_dma_steal), std::end(m_active_dma_steal), 0);
+ std::fill(std::begin(m_active_dma_src), std::end(m_active_dma_src), 0);
+ std::fill(std::begin(m_active_dma_dst), std::end(m_active_dma_dst), 0);
+ std::fill(std::begin(m_active_dma_count), std::end(m_active_dma_count), 0);
+ std::fill(std::begin(m_wtcw), std::end(m_wtcw), 0);
+ std::fill(std::begin(m_dma_current_active_timer), std::end(m_dma_current_active_timer), nullptr);
+
+ m_irq_vector.fic = m_irq_vector.foc = m_irq_vector.fov = m_irq_vector.divu = 0;
+ std::fill(std::begin(m_irq_vector.dmac), std::end(m_irq_vector.dmac), 0);
+
+ m_irq_level.frc = m_irq_level.sci = m_irq_level.divu = m_irq_level.dmac = m_irq_level.wdt = 0;
+
+ for (int i = 0; i < 2; i++)
+ m_dmac[i].drcr = m_dmac[i].sar = m_dmac[i].dar = m_dmac[i].tcr = m_dmac[i].chcr = 0;
+}
+
+void sh7604_device::device_start()
+{
+ sh2_device::device_start();
+
+ m_timer = timer_alloc(FUNC(sh7604_device::sh2_timer_callback), this);
+ m_timer->adjust(attotime::never);
+ m_wdtimer = timer_alloc(FUNC(sh7604_device::sh2_wdtimer_callback), this);
+ m_wdtimer->adjust(attotime::never);
+
+ m_dma_current_active_timer[0] = timer_alloc(FUNC(sh7604_device::sh2_dma_current_active_callback), this);
+ m_dma_current_active_timer[0]->adjust(attotime::never);
+
+ m_dma_current_active_timer[1] = timer_alloc(FUNC(sh7604_device::sh2_dma_current_active_callback), this);
+ m_dma_current_active_timer[1]->adjust(attotime::never);
+
+ /* resolve callbacks */
+ m_dma_kludge_cb.resolve();
+ m_dma_fifo_data_available_cb.resolve();
+ m_ftcsr_read_cb.resolve();
+
+ // SCI
+ save_item(NAME(m_smr));
+ save_item(NAME(m_brr));
+ save_item(NAME(m_scr));
+ save_item(NAME(m_tdr));
+ save_item(NAME(m_ssr));
+
+ // FRT / FRC
+ save_item(NAME(m_tier));
+ save_item(NAME(m_ftcsr));
+ save_item(NAME(m_frc_tcr));
+ save_item(NAME(m_tocr));
+ save_item(NAME(m_frc));
+ save_item(NAME(m_ocra));
+ save_item(NAME(m_ocrb));
+ save_item(NAME(m_frc_icr));
+ save_item(NAME(m_frc_base));
+ save_item(NAME(m_frt_input));
+
+ // INTC
+ save_item(NAME(m_irq_level.frc));
+ save_item(NAME(m_irq_level.sci));
+ save_item(NAME(m_irq_level.divu));
+ save_item(NAME(m_irq_level.dmac));
+ save_item(NAME(m_irq_level.wdt));
+ save_item(NAME(m_irq_vector.fic));
+ save_item(NAME(m_irq_vector.foc));
+ save_item(NAME(m_irq_vector.fov));
+ save_item(NAME(m_irq_vector.divu));
+ save_item(NAME(m_irq_vector.dmac));
+
+ save_item(NAME(m_ipra));
+ save_item(NAME(m_iprb));
+ save_item(NAME(m_vcra));
+ save_item(NAME(m_vcrb));
+ save_item(NAME(m_vcrc));
+ save_item(NAME(m_vcrd));
+ save_item(NAME(m_vcrwdt));
+ save_item(NAME(m_vcrdiv));
+ save_item(NAME(m_intc_icr));
+ save_item(NAME(m_vcrdma));
+
+ save_item(NAME(m_vecmd));
+ save_item(NAME(m_nmie));
+
+ // DIVU
+ save_item(NAME(m_divu_ovf));
+ save_item(NAME(m_divu_ovfie));
+ save_item(NAME(m_dvsr));
+ save_item(NAME(m_dvdntl));
+ save_item(NAME(m_dvdnth));
+
+ // WTC
+ save_item(NAME(m_wtcnt));
+ save_item(NAME(m_wtcsr));
+ save_item(NAME(m_rstcsr));
+ save_item(NAME(m_wtcw));
+
+ // DMAC
+ save_item(NAME(m_dmaor));
+ save_item(STRUCT_MEMBER(m_dmac, drcr));
+ save_item(STRUCT_MEMBER(m_dmac, sar));
+ save_item(STRUCT_MEMBER(m_dmac, dar));
+ save_item(STRUCT_MEMBER(m_dmac, tcr));
+ save_item(STRUCT_MEMBER(m_dmac, chcr));
+
+ // misc
+ save_item(NAME(m_sbycr));
+ save_item(NAME(m_ccr));
+
+ // BSC
+ save_item(NAME(m_bcr1));
+ save_item(NAME(m_bcr2));
+ save_item(NAME(m_wcr));
+ save_item(NAME(m_mcr));
+ save_item(NAME(m_rtcsr));
+ save_item(NAME(m_rtcor));
+ save_item(NAME(m_rtcnt));
+}
+
+void sh7604_device::device_reset()
+{
+ sh2_device::device_reset();
+
+ m_frc = 0;
+ m_ocra = 0;
+ m_ocrb = 0;
+ m_frc_icr = 0;
+ m_frc_base = 0;
+ m_frt_input = 0;
+
+ for (int i = 0; i < 2; i++)
+ {
+ m_dma_timer_active[i] = 0;
+ m_dma_irq[i] = 0;
+ m_active_dma_incs[i] = 0;
+ m_active_dma_incd[i] = 0;
+ m_active_dma_size[i] = 0;
+ m_active_dma_steal[i] = 0;
+ m_active_dma_src[i] = 0;
+ m_active_dma_dst[i] = 0;
+ m_active_dma_count[i] = 0;
+ }
+
+ m_wtcnt = 0;
+ m_wtcsr = 0;
+}
+
+void sh7604_device::sh7604_map(address_map &map)
+{
+ map(0x40000000, 0xbfffffff).r(FUNC(sh7604_device::sh2_internal_a5));
+
+// TODO: cps3boot breaks with this enabled. Needs callback
+// map(0xc0000000, 0xc0000fff).ram(); // cache data array
+
+// map(0xe0000000, 0xe00001ff).mirror(0x1ffffe00).rw(FUNC(sh7604_device::sh7604_r), FUNC(sh7604_device::sh7604_w));
+ // TODO: internal map takes way too much resources if mirrored with 0x1ffffe00
+ // we eventually internalize again via trampoline & sh7604_device
+ // Also area 0xffff8000-0xffffbfff is for synchronous DRAM mode,
+ // so this isn't actually a full mirror
+ // SCI
+ map(0xfffffe00, 0xfffffe00).rw(FUNC(sh7604_device::smr_r), FUNC(sh7604_device::smr_w));
+ map(0xfffffe01, 0xfffffe01).rw(FUNC(sh7604_device::brr_r), FUNC(sh7604_device::brr_w));
+ map(0xfffffe02, 0xfffffe02).rw(FUNC(sh7604_device::scr_r), FUNC(sh7604_device::scr_w));
+ map(0xfffffe03, 0xfffffe03).rw(FUNC(sh7604_device::tdr_r), FUNC(sh7604_device::tdr_w));
+ map(0xfffffe04, 0xfffffe04).rw(FUNC(sh7604_device::ssr_r), FUNC(sh7604_device::ssr_w));
+ map(0xfffffe05, 0xfffffe05).r(FUNC(sh7604_device::rdr_r));
+
+ // FRC
+ map(0xfffffe10, 0xfffffe10).rw(FUNC(sh7604_device::tier_r), FUNC(sh7604_device::tier_w));
+ map(0xfffffe11, 0xfffffe11).rw(FUNC(sh7604_device::ftcsr_r), FUNC(sh7604_device::ftcsr_w));
+ map(0xfffffe12, 0xfffffe13).rw(FUNC(sh7604_device::frc_r), FUNC(sh7604_device::frc_w));
+ map(0xfffffe14, 0xfffffe15).rw(FUNC(sh7604_device::ocra_b_r), FUNC(sh7604_device::ocra_b_w));
+ map(0xfffffe16, 0xfffffe16).rw(FUNC(sh7604_device::frc_tcr_r), FUNC(sh7604_device::frc_tcr_w));
+ map(0xfffffe17, 0xfffffe17).rw(FUNC(sh7604_device::tocr_r), FUNC(sh7604_device::tocr_w));
+ map(0xfffffe18, 0xfffffe19).r(FUNC(sh7604_device::frc_icr_r));
+
+ // INTC
+ map(0xfffffe60, 0xfffffe61).rw(FUNC(sh7604_device::iprb_r), FUNC(sh7604_device::iprb_w));
+ map(0xfffffe62, 0xfffffe63).rw(FUNC(sh7604_device::vcra_r), FUNC(sh7604_device::vcra_w));
+ map(0xfffffe64, 0xfffffe65).rw(FUNC(sh7604_device::vcrb_r), FUNC(sh7604_device::vcrb_w));
+ map(0xfffffe66, 0xfffffe67).rw(FUNC(sh7604_device::vcrc_r), FUNC(sh7604_device::vcrc_w));
+ map(0xfffffe68, 0xfffffe69).rw(FUNC(sh7604_device::vcrd_r), FUNC(sh7604_device::vcrd_w));
+
+ map(0xfffffe71, 0xfffffe71).rw(FUNC(sh7604_device::drcr_r<0>), FUNC(sh7604_device::drcr_w<0>));
+ map(0xfffffe72, 0xfffffe72).rw(FUNC(sh7604_device::drcr_r<1>), FUNC(sh7604_device::drcr_w<1>));
+
+ // WTC
+ map(0xfffffe80, 0xfffffe81).rw(FUNC(sh7604_device::wtcnt_r), FUNC(sh7604_device::wtcnt_w));
+ map(0xfffffe82, 0xfffffe83).rw(FUNC(sh7604_device::rstcsr_r), FUNC(sh7604_device::rstcsr_w));
+
+ // standby and cache control
+ map(0xfffffe90, 0xfffffe91).rw(FUNC(sh7604_device::fmr_sbycr_r), FUNC(sh7604_device::fmr_sbycr_w));
+ map(0xfffffe92, 0xfffffe92).rw(FUNC(sh7604_device::ccr_r), FUNC(sh7604_device::ccr_w));
+
+ // INTC second section
+ map(0xfffffee0, 0xfffffee1).rw(FUNC(sh7604_device::intc_icr_r), FUNC(sh7604_device::intc_icr_w));
+ map(0xfffffee2, 0xfffffee3).rw(FUNC(sh7604_device::ipra_r), FUNC(sh7604_device::ipra_w));
+ map(0xfffffee4, 0xfffffee5).rw(FUNC(sh7604_device::vcrwdt_r), FUNC(sh7604_device::vcrwdt_w));
+
+ // DIVU
+ map(0xffffff00, 0xffffff03).rw(FUNC(sh7604_device::dvsr_r), FUNC(sh7604_device::dvsr_w));
+ map(0xffffff04, 0xffffff07).rw(FUNC(sh7604_device::dvdnt_r), FUNC(sh7604_device::dvdnt_w));
+ map(0xffffff08, 0xffffff0b).rw(FUNC(sh7604_device::dvcr_r), FUNC(sh7604_device::dvcr_w));
+ // INTC third section
+ map(0xffffff0c, 0xffffff0f).rw(FUNC(sh7604_device::vcrdiv_r), FUNC(sh7604_device::vcrdiv_w));
+ // DIVU continued (64-bit plus mirrors)
+ map(0xffffff10, 0xffffff13).rw(FUNC(sh7604_device::dvdnth_r), FUNC(sh7604_device::dvdnth_w));
+ map(0xffffff14, 0xffffff17).rw(FUNC(sh7604_device::dvdntl_r), FUNC(sh7604_device::dvdntl_w));
+ map(0xffffff18, 0xffffff1b).r(FUNC(sh7604_device::dvdnth_r));
+ map(0xffffff1c, 0xffffff1f).r(FUNC(sh7604_device::dvdntl_r));
+
+ // DMAC
+ map(0xffffff80, 0xffffff83).rw(FUNC(sh7604_device::sar_r<0>), FUNC(sh7604_device::sar_w<0>));
+ map(0xffffff84, 0xffffff87).rw(FUNC(sh7604_device::dar_r<0>), FUNC(sh7604_device::dar_w<0>));
+ map(0xffffff88, 0xffffff8b).rw(FUNC(sh7604_device::dmac_tcr_r<0>), FUNC(sh7604_device::dmac_tcr_w<0>));
+ map(0xffffff8c, 0xffffff8f).rw(FUNC(sh7604_device::chcr_r<0>), FUNC(sh7604_device::chcr_w<0>));
+
+ map(0xffffff90, 0xffffff93).rw(FUNC(sh7604_device::sar_r<1>), FUNC(sh7604_device::sar_w<1>));
+ map(0xffffff94, 0xffffff97).rw(FUNC(sh7604_device::dar_r<1>), FUNC(sh7604_device::dar_w<1>));
+ map(0xffffff98, 0xffffff9b).rw(FUNC(sh7604_device::dmac_tcr_r<1>), FUNC(sh7604_device::dmac_tcr_w<1>));
+ map(0xffffff9c, 0xffffff9f).rw(FUNC(sh7604_device::chcr_r<1>), FUNC(sh7604_device::chcr_w<1>));
+
+ map(0xffffffa0, 0xffffffa3).rw(FUNC(sh7604_device::vcrdma_r<0>), FUNC(sh7604_device::vcrdma_w<0>));
+ map(0xffffffa8, 0xffffffab).rw(FUNC(sh7604_device::vcrdma_r<1>), FUNC(sh7604_device::vcrdma_w<1>));
+ map(0xffffffb0, 0xffffffb3).rw(FUNC(sh7604_device::dmaor_r), FUNC(sh7604_device::dmaor_w));
+
+ // BSC
+ map(0xffffffe0, 0xffffffe3).rw(FUNC(sh7604_device::bcr1_r), FUNC(sh7604_device::bcr1_w));
+ map(0xffffffe4, 0xffffffe7).rw(FUNC(sh7604_device::bcr2_r), FUNC(sh7604_device::bcr2_w));
+ map(0xffffffe8, 0xffffffeb).rw(FUNC(sh7604_device::wcr_r), FUNC(sh7604_device::wcr_w));
+ map(0xffffffec, 0xffffffef).rw(FUNC(sh7604_device::mcr_r), FUNC(sh7604_device::mcr_w));
+ map(0xfffffff0, 0xfffffff3).rw(FUNC(sh7604_device::rtcsr_r), FUNC(sh7604_device::rtcsr_w));
+ map(0xfffffff4, 0xfffffff7).rw(FUNC(sh7604_device::rtcnt_r), FUNC(sh7604_device::rtcnt_w));
+ map(0xfffffff8, 0xfffffffb).rw(FUNC(sh7604_device::rtcor_r), FUNC(sh7604_device::rtcor_w));
+}
+
+
+void sh7604_device::sh2_exception(const char *message, int irqline)
+{
+ int vector;
+
+ if (irqline != 16)
+ {
+ if (irqline <= ((m_sh2_state->sr >> 4) & 15)) /* If the cpu forbids this interrupt */
+ return;
+
+ // if this is an sh2 internal irq, use its vector
+ if (m_sh2_state->internal_irq_level == irqline)
+ {
+ vector = m_internal_irq_vector;
+ /* avoid spurious irqs with this (TODO: needs a better fix) */
+ m_sh2_state->internal_irq_level = -1;
+ LOG("SH-2 exception #%d (internal vector: $%x) after [%s]\n", irqline, vector, message);
+ }
+ else
+ {
+ if (m_vecmd)
+ {
+ vector = standard_irq_callback(irqline, m_sh2_state->pc);
+ LOG("SH-2 exception #%d (external vector: $%x) after [%s]\n", irqline, vector, message);
+ }
+ else
+ {
+ standard_irq_callback(irqline, m_sh2_state->pc);
+ vector = 64 + irqline/2;
+ LOG("SH-2 exception #%d (autovector: $%x) after [%s]\n", irqline, vector, message);
+ }
+ }
+ }
+ else
+ {
+ vector = 11;
+ LOG("SH-2 nmi exception (autovector: $%x) after [%s]\n", vector, message);
+ }
+
+ sh2_exception_internal(message, irqline, vector);
+}
+
+uint32_t sh7604_device::sh2_internal_a5()
+{
+ return 0xa5a5a5a5;
+}
+
+void sh7604_device::sh2_timer_resync()
+{
+ // TODO: setting 3 is "External clock: count on rising edge"
+ int divider = div_tab[m_frc_tcr & 3];
+ uint64_t cur_time = total_cycles();
+ uint64_t add = (cur_time - m_frc_base) >> divider;
+
+ if (add > 0)
+ {
+ if (divider)
+ m_frc += add;
+
+ m_frc_base = cur_time;
+ }
+}
+
+void sh7604_device::sh2_timer_activate()
+{
+ int max_delta = 0xfffff;
+
+ m_timer->adjust(attotime::never);
+
+ uint16_t frc = m_frc;
+ if (!(m_ftcsr & OCFA))
+ {
+ uint16_t delta = m_ocra - frc;
+ if (delta < max_delta)
+ max_delta = delta;
+ }
+
+ if (!(m_ftcsr & OCFB) && (m_ocra <= m_ocrb || !(m_ftcsr & CCLRA)))
+ {
+ uint16_t delta = m_ocrb - frc;
+ if (delta < max_delta)
+ max_delta = delta;
+ }
+
+ if (!(m_ftcsr & OVF) && !(m_ftcsr & CCLRA))
+ {
+ int delta = 0x10000 - frc;
+ if (delta < max_delta)
+ max_delta = delta;
+ }
+
+ if (max_delta != 0xfffff)
+ {
+ int divider = div_tab[m_frc_tcr & 3];
+ if (divider)
+ {
+ max_delta <<= divider;
+ m_frc_base = total_cycles();
+ m_timer->adjust(cycles_to_attotime(max_delta));
+ }
+ else
+ {
+ logerror("SH2.%s: Timer event in %d cycles of external clock", tag(), max_delta);
+ }
+ }
+}
+
+TIMER_CALLBACK_MEMBER(sh7604_device::sh2_timer_callback)
+{
+ sh2_timer_resync();
+ uint16_t frc = m_frc;
+
+ if (frc == m_ocrb)
+ m_ftcsr |= OCFB;
+
+ if (frc == 0x0000)
+ m_ftcsr |= OVF;
+
+ if (frc == m_ocra)
+ {
+ m_ftcsr |= OCFA;
+
+ if (m_ftcsr & CCLRA)
+ m_frc = 0;
+ }
+
+ sh2_recalc_irq();
+ sh2_timer_activate();
+}
+
+void sh7604_device::sh2_wtcnt_recalc()
+{
+ if (m_wdtimer->expire() != attotime::never)
+ m_wtcnt = 0x100 - (attotime_to_cycles(m_wdtimer->remaining()) >> wdtclk_tab[m_wtcsr & 7]);
+}
+
+void sh7604_device::sh2_wdt_activate()
+{
+ m_wdtimer->adjust(cycles_to_attotime((0x100 - m_wtcnt) << wdtclk_tab[m_wtcsr & 7]));
+}
+
+TIMER_CALLBACK_MEMBER(sh7604_device::sh2_wdtimer_callback)
+{
+ m_wtcnt = 0;
+ if (!(m_wtcsr & 0x40)) // timer mode
+ {
+ m_wtcsr |= 0x80;
+ sh2_recalc_irq();
+ sh2_wdt_activate();
+ }
+ else // watchdog mode
+ {
+ m_rstcsr |= 0x80;
+ // TODO reset and /WDTOVF out
+ }
+}
+
+/*
+ We have to do DMA on a timer (or at least, in chunks) due to the way some systems use it.
+ The 32x is a difficult case, they set the SOURCE of the DMA to a FIFO buffer, which at most
+ can have 8 words in it. Attempting to do an 'instant DMA' in this scenario is impossible
+ because the game is expecting the 68k of the system to feed data into the FIFO at the same
+ time as the SH2 is transfering it out via DMA
+
+ There are two ways we can do this
+
+ a) with a high frequency timer (more accurate, but a large performance hit)
+
+ or
+
+ b) in the CPU_EXECUTE loop
+
+
+ we're currently doing a)
+
+ b) causes problems with ST-V games
+
+*/
+
+
+
+void sh7604_device::sh2_notify_dma_data_available()
+{
+ //printf("call notify\n");
+
+ for (int dmach=0;dmach<2;dmach++)
+ {
+ //printf("m_dma_timer_active[dmach] %04x\n", m_dma_timer_active[dmach]);
+
+ if (m_dma_timer_active[dmach]==2) // 2 = stalled
+ {
+ //printf("resuming stalled dma\n");
+ m_dma_timer_active[dmach]=1;
+ m_dma_current_active_timer[dmach]->adjust(attotime::zero, dmach);
+ }
+ }
+
+}
+
+void sh7604_device::sh2_do_dma(int dmach)
+{
+ if (m_active_dma_count[dmach] > 0)
+ {
+ // process current DMA
+ switch (m_active_dma_size[dmach])
+ {
+ case 0:
+ {
+ // we need to know the src / dest ahead of time without changing them
+ // to allow for the callback to check if we can process the DMA at this
+ // time (we need to know where we're reading / writing to/from)
+
+ uint32_t tempsrc = m_active_dma_src[dmach];
+ if (m_active_dma_incs[dmach] == 2)
+ tempsrc--;
+
+ uint32_t tempdst = m_active_dma_dst[dmach];
+ if (m_active_dma_incd[dmach] == 2)
+ tempdst--;
+
+ if (!m_dma_fifo_data_available_cb.isnull())
+ {
+ int available = m_dma_fifo_data_available_cb(tempsrc, tempdst, 0, m_active_dma_size[dmach]);
+
+ if (!available)
+ {
+ //printf("dma stalled\n");
+ m_dma_timer_active[dmach] = 2; // mark as stalled
+ return;
+ }
+ }
+
+ //schedule next DMA callback
+ m_dma_current_active_timer[dmach]->adjust(cycles_to_attotime(2), dmach);
+
+ uint32_t dmadata = m_program->read_byte(tempsrc);
+ if (!m_dma_kludge_cb.isnull())
+ dmadata = m_dma_kludge_cb(tempsrc, tempdst, dmadata, m_active_dma_size[dmach]);
+ m_program->write_byte(tempdst, dmadata);
+
+ if (m_active_dma_incs[dmach] == 2)
+ m_active_dma_src[dmach]--;
+ if (m_active_dma_incd[dmach] == 2)
+ m_active_dma_dst[dmach]--;
+
+ if (m_active_dma_incs[dmach] == 1)
+ m_active_dma_src[dmach]++;
+ if (m_active_dma_incd[dmach] == 1)
+ m_active_dma_dst[dmach]++;
+
+ m_active_dma_count[dmach]--;
+ break;
+ }
+
+ case 1:
+ {
+ uint32_t tempsrc = m_active_dma_src[dmach];
+ if (m_active_dma_incs[dmach] == 2)
+ tempsrc -= 2;
+
+ uint32_t tempdst = m_active_dma_dst[dmach];
+ if (m_active_dma_incd[dmach] == 2)
+ tempdst -= 2;
+
+ if (!m_dma_fifo_data_available_cb.isnull())
+ {
+ int available = m_dma_fifo_data_available_cb(tempsrc, tempdst, 0, m_active_dma_size[dmach]);
+
+ if (!available)
+ {
+ //printf("dma stalled\n");
+ m_dma_timer_active[dmach] = 2; // mark as stalled
+ return;
+ }
+ }
+
+ //schedule next DMA callback
+ m_dma_current_active_timer[dmach]->adjust(cycles_to_attotime(2), dmach);
+
+ // check: should this really be using read_word_32 / write_word_32?
+ uint32_t dmadata = m_program->read_word(tempsrc);
+ if (!m_dma_kludge_cb.isnull())
+ dmadata = m_dma_kludge_cb(tempsrc, tempdst, dmadata, m_active_dma_size[dmach]);
+ m_program->write_word(tempdst, dmadata);
+
+ if (m_active_dma_incs[dmach] == 2)
+ m_active_dma_src[dmach] -= 2;
+ if (m_active_dma_incd[dmach] == 2)
+ m_active_dma_dst[dmach] -= 2;
+
+ if (m_active_dma_incs[dmach] == 1)
+ m_active_dma_src[dmach] += 2;
+ if (m_active_dma_incd[dmach] == 1)
+ m_active_dma_dst[dmach] += 2;
+
+ m_active_dma_count[dmach]--;
+ break;
+ }
+
+ case 2:
+ {
+ uint32_t tempsrc = m_active_dma_src[dmach];
+ if (m_active_dma_incs[dmach] == 2)
+ tempsrc -= 4;
+
+ uint32_t tempdst = m_active_dma_dst[dmach];
+ if (m_active_dma_incd[dmach] == 2)
+ tempdst -= 4;
+
+ if (!m_dma_fifo_data_available_cb.isnull())
+ {
+ int available = m_dma_fifo_data_available_cb(tempsrc, tempdst, 0, m_active_dma_size[dmach]);
+
+ if (!available)
+ {
+ //printf("dma stalled\n");
+ m_dma_timer_active[dmach] = 2; // mark as stalled
+ return;
+ }
+ }
+
+ //schedule next DMA callback
+ m_dma_current_active_timer[dmach]->adjust(cycles_to_attotime(2), dmach);
+
+ uint32_t dmadata = m_program->read_dword(tempsrc);
+ if (!m_dma_kludge_cb.isnull())
+ dmadata = m_dma_kludge_cb(tempsrc, tempdst, dmadata, m_active_dma_size[dmach]);
+ m_program->write_dword(tempdst, dmadata);
+
+ if (m_active_dma_incs[dmach] == 2)
+ m_active_dma_src[dmach] -= 4;
+ if (m_active_dma_incd[dmach] == 2)
+ m_active_dma_dst[dmach] -= 4;
+
+ if (m_active_dma_incs[dmach] == 1)
+ m_active_dma_src[dmach] += 4;
+ if (m_active_dma_incd[dmach] == 1)
+ m_active_dma_dst[dmach] += 4;
+
+ m_active_dma_count[dmach]--;
+ break;
+ }
+
+ case 3:
+ {
+ // shouldn't this really be 4 calls here instead?
+
+ uint32_t tempsrc = m_active_dma_src[dmach];
+
+ uint32_t tempdst = m_active_dma_dst[dmach];
+ if (m_active_dma_incd[dmach] == 2)
+ tempdst -= 16;
+
+ if (!m_dma_fifo_data_available_cb.isnull())
+ {
+ int available = m_dma_fifo_data_available_cb(tempsrc, tempdst, 0, m_active_dma_size[dmach]);
+
+ if (!available)
+ {
+ //printf("dma stalled\n");
+ m_dma_timer_active[dmach] = 2; // mark as stalled
+ fatalerror("SH2 dma_callback_fifo_data_available == 0 in unsupported mode\n");
+ }
+ }
+
+ //schedule next DMA callback
+ m_dma_current_active_timer[dmach]->adjust(cycles_to_attotime(2), dmach);
+
+ uint32_t dmadata = m_program->read_dword(tempsrc);
+ if (!m_dma_kludge_cb.isnull())
+ dmadata = m_dma_kludge_cb(tempsrc, tempdst, dmadata, m_active_dma_size[dmach]);
+ m_program->write_dword(tempdst, dmadata);
+
+ dmadata = m_program->read_dword(tempsrc + 4);
+ if (!m_dma_kludge_cb.isnull())
+ dmadata = m_dma_kludge_cb(tempsrc, tempdst, dmadata, m_active_dma_size[dmach]);
+ m_program->write_dword(tempdst + 4, dmadata);
+
+ dmadata = m_program->read_dword(tempsrc + 8);
+ if (!m_dma_kludge_cb.isnull())
+ dmadata = m_dma_kludge_cb(tempsrc, tempdst, dmadata, m_active_dma_size[dmach]);
+ m_program->write_dword(tempdst + 8, dmadata);
+
+ dmadata = m_program->read_dword(tempsrc + 12);
+ if (!m_dma_kludge_cb.isnull())
+ dmadata = m_dma_kludge_cb(tempsrc, tempdst, dmadata, m_active_dma_size[dmach]);
+ m_program->write_dword(tempdst + 12, dmadata);
+
+ if (m_active_dma_incd[dmach] == 2)
+ m_active_dma_dst[dmach] -= 16;
+
+ m_active_dma_src[dmach] += 16;
+ if (m_active_dma_incd[dmach] == 1)
+ m_active_dma_dst[dmach] += 16;
+
+ m_active_dma_count[dmach] -= 4;
+ break;
+ }
+ }
+ }
+ else // the dma is complete
+ {
+ // int dma = param & 1;
+
+ // fever soccer uses cycle-stealing mode, resume the CPU now DMA has finished
+ if (m_active_dma_steal[dmach])
+ {
+ resume(SUSPEND_REASON_HALT);
+ }
+
+ LOG("SH2: DMA %d complete\n", dmach);
+ m_dmac[dmach].tcr = 0;
+ m_dmac[dmach].chcr |= 2;
+ m_dma_timer_active[dmach] = 0;
+ m_dma_irq[dmach] |= 1;
+ sh2_recalc_irq();
+
+ }
+}
+
+TIMER_CALLBACK_MEMBER(sh7604_device::sh2_dma_current_active_callback)
+{
+ sh2_do_dma(param & 1);
+}
+
+
+void sh7604_device::sh2_dmac_check(int dmach)
+{
+ if (m_dmac[dmach].chcr & m_dmaor & 1)
+ {
+ if (!m_dma_timer_active[dmach] && !(m_dmac[dmach].chcr & 2))
+ {
+ m_active_dma_incd[dmach] = (m_dmac[dmach].chcr >> 14) & 3;
+ m_active_dma_incs[dmach] = (m_dmac[dmach].chcr >> 12) & 3;
+ m_active_dma_size[dmach] = (m_dmac[dmach].chcr >> 10) & 3;
+ m_active_dma_steal[dmach] = (m_dmac[dmach].chcr & 0x10);
+
+ if (m_active_dma_incd[dmach] == 3 || m_active_dma_incs[dmach] == 3)
+ {
+ LOG("SH2: DMA: bad increment values (%d, %d, %d, %04x)\n", m_active_dma_incd[dmach], m_active_dma_incs[dmach], m_active_dma_size[dmach], m_dmac[dmach].chcr);
+ return;
+ }
+ m_active_dma_src[dmach] = m_dmac[dmach].sar;
+ m_active_dma_dst[dmach] = m_dmac[dmach].dar;
+ m_active_dma_count[dmach] = m_dmac[dmach].tcr;
+ if (!m_active_dma_count[dmach])
+ m_active_dma_count[dmach] = 0x1000000;
+
+ LOG("SH2: DMA %d start %x, %x, %x, %04x, %d, %d, %d\n", dmach, m_active_dma_src[dmach], m_active_dma_dst[dmach], m_active_dma_count[dmach], m_dmac[dmach].chcr, m_active_dma_incs[dmach], m_active_dma_incd[dmach], m_active_dma_size[dmach]);
+
+ m_dma_timer_active[dmach] = 1;
+
+ m_active_dma_src[dmach] &= m_am;
+ m_active_dma_dst[dmach] &= m_am;
+
+ switch (m_active_dma_size[dmach])
+ {
+ case 0:
+ break;
+ case 1:
+ m_active_dma_src[dmach] &= ~1;
+ m_active_dma_dst[dmach] &= ~1;
+ break;
+ case 2:
+ m_active_dma_src[dmach] &= ~3;
+ m_active_dma_dst[dmach] &= ~3;
+ break;
+ case 3:
+ m_active_dma_src[dmach] &= ~3;
+ m_active_dma_dst[dmach] &= ~3;
+ m_active_dma_count[dmach] &= ~3;
+ break;
+ }
+
+ // start DMA timer
+
+ // fever soccer uses cycle-stealing mode, requiring the CPU to be halted
+ if (m_active_dma_steal[dmach])
+ {
+ //printf("cycle stealing DMA\n");
+ suspend(SUSPEND_REASON_HALT, 1);
+ }
+
+ m_dma_current_active_timer[dmach]->adjust(cycles_to_attotime(2), dmach);
+ }
+ }
+ else
+ {
+ if (m_dma_timer_active[dmach])
+ {
+ LOG("SH2: DMA %d cancelled in-flight\n", dmach);
+ //m_dma_complete_timer[dmach]->adjust(attotime::never);
+ m_dma_current_active_timer[dmach]->adjust(attotime::never, dmach);
+
+ m_dma_timer_active[dmach] = 0;
+ }
+ }
+}
+
+/*
+ * SCI
+ */
+// TODO: identical to H8 counterpart
+
+uint8_t sh7604_device::smr_r()
+{
+ return m_smr;
+}
+
+void sh7604_device::smr_w(uint8_t data)
+{
+ m_smr = data;
+}
+
+uint8_t sh7604_device::brr_r()
+{
+ return m_brr;
+}
+
+void sh7604_device::brr_w(uint8_t data)
+{
+ m_brr = data;
+}
+
+uint8_t sh7604_device::scr_r()
+{
+ return m_scr;
+}
+
+void sh7604_device::scr_w(uint8_t data)
+{
+ m_scr = data;
+}
+
+uint8_t sh7604_device::tdr_r()
+{
+ return m_tdr;
+}
+
+void sh7604_device::tdr_w(uint8_t data)
+{
+ m_tdr = data;
+ //printf("%c", data & 0xff);
+}
+
+uint8_t sh7604_device::ssr_r()
+{
+ // 0x84 is needed by EGWord on Saturn to make it to boot for some reason.
+ return m_ssr | 0x84;
+}
+
+void sh7604_device::ssr_w(uint8_t data)
+{
+ m_ssr = data;
+}
+
+uint8_t sh7604_device::rdr_r()
+{
+ return 0;
+}
+
+/*
+ * FRC
+ */
+
+uint8_t sh7604_device::tier_r()
+{
+ return m_tier;
+}
+
+void sh7604_device::tier_w(uint8_t data)
+{
+ sh2_timer_resync();
+ m_tier = data;
+ sh2_timer_activate();
+ sh2_recalc_irq();
+}
+
+uint8_t sh7604_device::ftcsr_r()
+{
+ // TODO: to be tested
+ if (!m_ftcsr_read_cb.isnull())
+ m_ftcsr_read_cb((((m_tier << 24) | (m_ftcsr << 16)) & 0xffff0000) | m_frc);
+
+ return m_ftcsr;
+}
+
+void sh7604_device::ftcsr_w(uint8_t data)
+{
+ uint8_t old = m_ftcsr;
+
+ m_ftcsr = data;
+ sh2_timer_resync();
+ m_ftcsr = (m_ftcsr & ~(ICF | OCFA | OCFB | OVF)) | (old & m_ftcsr & (ICF | OCFA | OCFB | OVF));
+ sh2_timer_activate();
+ sh2_recalc_irq();
+}
+
+uint16_t sh7604_device::frc_r()
+{
+ sh2_timer_resync();
+ return m_frc;
+}
+
+void sh7604_device::frc_w(offs_t offset, uint16_t data, uint16_t mem_mask)
+{
+ sh2_timer_resync();
+ COMBINE_DATA(&m_frc);
+ sh2_timer_activate();
+ sh2_recalc_irq();
+}
+
+uint16_t sh7604_device::ocra_b_r()
+{
+ return (m_tocr & 0x10) ? m_ocrb : m_ocra;
+}
+
+void sh7604_device::ocra_b_w(offs_t offset, uint16_t data, uint16_t mem_mask)
+{
+ sh2_timer_resync();
+ if (m_tocr & 0x10)
+ m_ocrb = (m_ocrb & ~mem_mask) | (data & mem_mask);
+ else
+ m_ocra = (m_ocra & ~mem_mask) | (data & mem_mask);
+ sh2_timer_activate();
+ sh2_recalc_irq();
+}
+
+uint8_t sh7604_device::frc_tcr_r()
+{
+ return m_frc_tcr & 0x83;
+}
+
+void sh7604_device::frc_tcr_w(uint8_t data)
+{
+ sh2_timer_resync();
+ m_frc_tcr = data & 0x83;
+ sh2_timer_activate();
+ sh2_recalc_irq();
+}
+
+uint8_t sh7604_device::tocr_r()
+{
+ return (m_tocr & 0x13) | 0xe0;
+}
+
+void sh7604_device::tocr_w(uint8_t data)
+{
+ sh2_timer_resync();
+ // TODO: output levels A/B (bits 1-0)
+ m_tocr = data & 0x13;
+ sh2_timer_activate();
+ sh2_recalc_irq();
+}
+
+uint16_t sh7604_device::frc_icr_r()
+{
+ return m_frc_icr;
+}
+
+/*
+ * INTC
+ */
+
+uint16_t sh7604_device::intc_icr_r()
+{
+ // TODO: flip meaning based off NMI edge select bit (NMIE)
+ uint16_t nmilv = m_nmi_line_state == ASSERT_LINE ? 0 : 0x8000;
+ return nmilv | (m_intc_icr & 0x0101);
+}
+
+void sh7604_device::intc_icr_w(offs_t offset, uint16_t data, uint16_t mem_mask)
+{
+ COMBINE_DATA(&m_intc_icr);
+ m_nmie = BIT(m_intc_icr, 8);
+ m_vecmd = BIT(m_intc_icr, 0);
+}
+
+uint16_t sh7604_device::ipra_r()
+{
+ return m_ipra & 0xfff0;
+}
+
+void sh7604_device::ipra_w(offs_t offset, uint16_t data, uint16_t mem_mask)
+{
+ COMBINE_DATA(&m_ipra);
+ m_irq_level.divu = (m_ipra >> 12) & 0xf;
+ m_irq_level.dmac = (m_ipra >> 8) & 0xf;
+ m_irq_level.wdt = (m_ipra >> 4) & 0xf;
+ sh2_recalc_irq();
+}
+
+uint16_t sh7604_device::iprb_r()
+{
+ return m_iprb & 0xff00;
+}
+
+void sh7604_device::iprb_w(offs_t offset, uint16_t data, uint16_t mem_mask)
+{
+ COMBINE_DATA(&m_iprb);
+ m_irq_level.sci = (m_iprb >> 12) & 0xf;
+ m_irq_level.frc = (m_iprb >> 8) & 0xf;
+ sh2_recalc_irq();
+}
+
+uint16_t sh7604_device::vcra_r()
+{
+ return m_vcra & 0x7f7f;
+}
+
+void sh7604_device::vcra_w(offs_t offset, uint16_t data, uint16_t mem_mask)
+{
+ COMBINE_DATA(&m_vcra);
+ // ...
+ sh2_recalc_irq();
+}
+
+uint16_t sh7604_device::vcrb_r()
+{
+ return m_vcrb;
+}
+
+void sh7604_device::vcrb_w(offs_t offset, uint16_t data, uint16_t mem_mask)
+{
+ COMBINE_DATA(&m_vcrb);
+ // ...
+ sh2_recalc_irq();
+}
+
+uint16_t sh7604_device::vcrc_r()
+{
+ return m_vcrc & 0x7f7f;
+}
+
+void sh7604_device::vcrc_w(offs_t offset, uint16_t data, uint16_t mem_mask)
+{
+ COMBINE_DATA(&m_vcrc);
+ m_irq_vector.fic = (m_vcrc >> 8) & 0x7f;
+ m_irq_vector.foc = (m_vcrc >> 0) & 0x7f;
+ sh2_recalc_irq();
+}
+
+uint16_t sh7604_device::vcrd_r()
+{
+ return m_vcrd & 0x7f00;
+}
+
+void sh7604_device::vcrd_w(offs_t offset, uint16_t data, uint16_t mem_mask)
+{
+ COMBINE_DATA(&m_vcrd);
+ m_irq_vector.fov = (m_vcrc >> 8) & 0x7f;
+ sh2_recalc_irq();
+}
+
+uint16_t sh7604_device::vcrwdt_r()
+{
+ return m_vcrwdt & 0x7f7f;
+}
+
+void sh7604_device::vcrwdt_w(offs_t offset, uint16_t data, uint16_t mem_mask)
+{
+ COMBINE_DATA(&m_vcrwdt);
+ // ...
+ sh2_recalc_irq();
+}
+
+uint32_t sh7604_device::vcrdiv_r()
+{
+ return m_vcrdiv & 0x7f;
+}
+
+void sh7604_device::vcrdiv_w(offs_t offset, uint32_t data, uint32_t mem_mask)
+{
+ COMBINE_DATA(&m_vcrdiv);
+ // TODO: unemulated, level is seemingly not documented/settable?
+ m_irq_vector.divu = data & 0x7f;
+ sh2_recalc_irq();
+}
+
+/*
+ * DIVU
+ */
+
+uint32_t sh7604_device::dvcr_r()
+{
+ return (m_divu_ovfie ? 2 : 0) | (m_divu_ovf ? 1 : 0);
+}
+
+void sh7604_device::dvcr_w(offs_t offset, uint32_t data, uint32_t mem_mask)
+{
+ if (ACCESSING_BITS_0_7)
+ {
+ if (data & 1)
+ m_divu_ovf = false;
+ if (data & 2)
+ {
+ m_divu_ovfie = BIT(data, 1);
+ if (m_divu_ovfie)
+ LOG("SH2: unemulated DIVU OVF interrupt enable\n");
+ }
+ sh2_recalc_irq();
+ }
+}
+
+uint32_t sh7604_device::dvsr_r()
+{
+ return m_dvsr;
+}
+
+void sh7604_device::dvsr_w(offs_t offset, uint32_t data, uint32_t mem_mask)
+{
+ COMBINE_DATA(&m_dvsr);
+}
+
+uint32_t sh7604_device::dvdnt_r()
+{
+ return m_dvdntl;
+}
+
+void sh7604_device::dvdnt_w(offs_t offset, uint32_t data, uint32_t mem_mask)
+{
+ COMBINE_DATA(&m_dvdntl);
+ int32_t a = m_dvdntl;
+ int32_t b = m_dvsr;
+ LOG("SH2 div32+mod %d/%d\n", a, b);
+ if (b)
+ {
+ m_dvdntl = a / b;
+ m_dvdnth = a % b;
+ }
+ else
+ {
+ m_divu_ovf = true;
+ m_dvdntl = 0x7fffffff;
+ m_dvdnth = 0x7fffffff;
+ sh2_recalc_irq();
+ }
+}
+
+uint32_t sh7604_device::dvdnth_r()
+{
+ return m_dvdnth;
+}
+
+uint32_t sh7604_device::dvdntl_r()
+{
+ return m_dvdntl;
+}
+
+void sh7604_device::dvdnth_w(offs_t offset, uint32_t data, uint32_t mem_mask)
+{
+ COMBINE_DATA(&m_dvdnth);
+}
+
+void sh7604_device::dvdntl_w(offs_t offset, uint32_t data, uint32_t mem_mask)
+{
+ COMBINE_DATA(&m_dvdntl);
+ int64_t a = m_dvdntl | ((uint64_t)m_dvdnth << 32);
+ int64_t b = (int32_t)m_dvsr;
+ LOG("SH2 div64+mod %d/%d\n", a, b);
+ if (b)
+ {
+ int64_t q = a / b;
+ if (q != (int32_t)q)
+ {
+ m_divu_ovf = true;
+ m_dvdntl = 0x7fffffff;
+ m_dvdnth = 0x7fffffff;
+ sh2_recalc_irq();
+ }
+ else
+ {
+ m_dvdntl = q;
+ m_dvdnth = a % b;
+ }
+ }
+ else
+ {
+ m_divu_ovf = true;
+ m_dvdntl = 0x7fffffff;
+ m_dvdnth = 0x7fffffff;
+ sh2_recalc_irq();
+ }
+}
+
+/*
+ * WTC
+ */
+
+uint16_t sh7604_device::wtcnt_r()
+{
+ sh2_wtcnt_recalc();
+ return ((m_wtcsr | 0x18) << 8) | (m_wtcnt & 0xff);
+}
+
+uint16_t sh7604_device::rstcsr_r()
+{
+ return (m_rstcsr & 0xe0) | 0x1f;
+}
+
+void sh7604_device::wtcnt_w(offs_t offset, uint16_t data, uint16_t mem_mask)
+{
+ COMBINE_DATA(&m_wtcw[0]);
+ switch (m_wtcw[0] & 0xff00)
+ {
+ case 0x5a00:
+ m_wtcnt = m_wtcw[0] & 0xff;
+ if (m_wtcsr & 0x20)
+ sh2_wdt_activate();
+ break;
+ case 0xa500:
+ /*
+ WTCSR
+ x--- ---- Overflow in IT mode
+ -x-- ---- Timer mode (0: IT 1: watchdog)
+ --x- ---- Timer enable
+ ---1 1---
+ ---- -xxx Clock select
+ */
+ sh2_wtcnt_recalc();
+ m_wtcsr &= m_wtcw[0] & 0x80;
+ m_wtcsr |= m_wtcw[0] & 0x7f;
+ if (m_wtcsr & 0x20)
+ sh2_wdt_activate();
+ else
+ {
+ m_wtcnt = 0;
+ m_wdtimer->adjust(attotime::never);
+ }
+ sh2_recalc_irq();
+ break;
+ }
+}
+
+void sh7604_device::rstcsr_w(offs_t offset, uint16_t data, uint16_t mem_mask)
+{
+ COMBINE_DATA(&m_wtcw[1]);
+ switch (m_wtcw[1] & 0xff00)
+ {
+ case 0xa500:
+ // clear WOVF flag
+ if ((m_wtcw[1] & 0x80) == 0)
+ m_rstcsr &= 0x7f;
+ break;
+ case 0x5a00:
+ m_rstcsr = (m_rstcsr & 0x80) | (m_wtcw[1] & 0x60);
+ break;
+ }
+}
+
+uint16_t sh7604_device::fmr_sbycr_r()
+{
+ return m_sbycr;
+}
+
+void sh7604_device::fmr_sbycr_w(offs_t offset, uint16_t data, uint16_t mem_mask)
+{
+ switch (mem_mask)
+ {
+ case 0xff00: // FMR 8bit
+ logerror("SH2 set clock multiplier x%d\n", 1 << ((data >> 8) & 3));
+ break;
+ case 0xffff: // FMR 16bit
+ // SH7604 docs says FMR register must be set using 8-bit write, however at practice 16-bit works too.
+ // has been verified for CPS3 custom SH2, SH7604 and SH7095 (clock multiplier feature is not officially documented for SH7095).
+ logerror("SH2 set clock multiplier x%d\n", 1 << (data & 3));
+ break;
+ case 0x00ff: // SBYCR
+ m_sbycr = data;
+ if (data & 0x1f)
+ logerror("SH2 module stop selected %02x\n", data);
+ break;
+ }
+}
+
+uint8_t sh7604_device::ccr_r()
+{
+ return m_ccr & ~0x30;
+}
+
+void sh7604_device::ccr_w(uint8_t data)
+{
+ /*
+ xx-- ---- Way 0/1
+ ---x ---- Cache Purge (CP), write only
+ ---- x--- Two-Way Mode (TW)
+ ---- -x-- Data Replacement Disable (OD)
+ ---- --x- Instruction Replacement Disable (ID)
+ ---- ---x Cache Enable (CE)
+ */
+ m_ccr = data;
+}
+
+uint32_t sh7604_device::bcr1_r()
+{
+ return (m_bcr1 & ~0xe008) | (m_is_slave ? 0x8000 : 0);
+}
+
+void sh7604_device::bcr1_w(offs_t offset, uint32_t data, uint32_t mem_mask)
+{
+ COMBINE_DATA(&m_bcr1);
+}
+
+uint32_t sh7604_device::bcr2_r()
+{
+ return m_bcr2;
+}
+
+void sh7604_device::bcr2_w(offs_t offset, uint32_t data, uint32_t mem_mask)
+{
+ COMBINE_DATA(&m_bcr2);
+}
+
+uint32_t sh7604_device::wcr_r()
+{
+ return m_wcr;
+}
+
+void sh7604_device::wcr_w(offs_t offset, uint32_t data, uint32_t mem_mask)
+{
+ COMBINE_DATA(&m_wcr);
+}
+
+uint32_t sh7604_device::mcr_r()
+{
+ return m_mcr & ~0x103;
+}
+
+void sh7604_device::mcr_w(offs_t offset, uint32_t data, uint32_t mem_mask)
+{
+ COMBINE_DATA(&m_mcr);
+}
+
+uint32_t sh7604_device::rtcsr_r()
+{
+ return m_rtcsr & 0xf8;
+}
+
+void sh7604_device::rtcsr_w(offs_t offset, uint32_t data, uint32_t mem_mask)
+{
+ COMBINE_DATA(&m_rtcsr);
+}
+
+uint32_t sh7604_device::rtcnt_r()
+{
+ return m_rtcnt & 0xff;
+}
+
+void sh7604_device::rtcnt_w(offs_t offset, uint32_t data, uint32_t mem_mask)
+{
+ COMBINE_DATA(&m_rtcnt);
+ m_rtcnt &= 0xff;
+}
+
+uint32_t sh7604_device::rtcor_r()
+{
+ return m_rtcor & 0xff;
+}
+
+void sh7604_device::rtcor_w(offs_t offset, uint32_t data, uint32_t mem_mask)
+{
+ COMBINE_DATA(&m_rtcor);
+ m_rtcor &= 0xff;
+}
+
+void sh7604_device::set_frt_input(int state)
+{
+ if (m_frt_input == state)
+ return;
+
+ m_frt_input = state;
+
+ if (m_frc_tcr & 0x80)
+ {
+ if (state == CLEAR_LINE)
+ return;
+ }
+ else
+ {
+ if (state == ASSERT_LINE)
+ return;
+ }
+
+ sh2_timer_resync();
+ m_frc_icr = m_frc;
+ m_ftcsr |= ICF;
+ //logerror("SH2.%s: ICF activated (%x)\n", tag(), m_sh2_state->pc & AM);
+ sh2_recalc_irq();
+}
+
+void sh7604_device::sh2_recalc_irq()
+{
+ int irq = 0;
+ int vector = -1;
+ int level;
+
+ // Timer irqs
+ if (m_tier & m_ftcsr & (ICF | OCFA | OCFB | OVF))
+ {
+ level = (m_irq_level.frc & 15);
+ if (level > irq)
+ {
+ int mask = m_tier & m_ftcsr;
+ irq = level;
+ if (mask & ICF)
+ vector = m_irq_vector.fic & 0x7f;
+ else if (mask & (OCFA | OCFB))
+ vector = m_irq_vector.foc & 0x7f;
+ else
+ vector = m_irq_vector.fov & 0x7f;
+ }
+ }
+
+ // WDT irqs
+ if (m_wtcsr & 0x80)
+ {
+ level = m_irq_level.wdt & 15;
+ if (level > irq)
+ {
+ irq = level;
+ vector = (m_vcrwdt >> 8) & 0x7f;
+ }
+ }
+
+ // DMA irqs
+ if ((m_dmac[0].chcr & 6) == 6 && m_dma_irq[0])
+ {
+ level = m_irq_level.dmac & 15;
+ if (level > irq)
+ {
+ irq = level;
+ m_dma_irq[0] &= ~1;
+ vector = m_irq_vector.dmac[0] & 0x7f;
+ }
+ }
+ else if ((m_dmac[1].chcr & 6) == 6 && m_dma_irq[1])
+ {
+ level = m_irq_level.dmac & 15;
+ if (level > irq)
+ {
+ irq = level;
+ m_dma_irq[1] &= ~1;
+ vector = m_irq_vector.dmac[1] & 0x7f;
+ }
+ }
+
+ m_sh2_state->internal_irq_level = irq;
+ m_internal_irq_vector = vector;
+ m_test_irq = 1;
+}
+
+/*
+ * DMAC
+ */
+
+template <int Channel>
+uint32_t sh7604_device::vcrdma_r()
+{
+ return m_vcrdma[Channel] & 0x7f;
+}
+
+template <int Channel>
+void sh7604_device::vcrdma_w(offs_t offset, uint32_t data, uint32_t mem_mask)
+{
+ COMBINE_DATA(&m_vcrdma[Channel]);
+ m_irq_vector.dmac[Channel] = m_vcrdma[Channel] & 0x7f;
+ sh2_recalc_irq();
+}
+
+template <int Channel>
+uint8_t sh7604_device::drcr_r()
+{
+ return m_dmac[Channel].drcr & 3;
+}
+
+template <int Channel>
+void sh7604_device::drcr_w(uint8_t data)
+{
+ m_dmac[Channel].drcr = data & 3;
+ sh2_recalc_irq();
+}
+
+template <int Channel>
+uint32_t sh7604_device::sar_r()
+{
+ return m_dmac[Channel].sar;
+}
+
+template <int Channel>
+void sh7604_device::sar_w(offs_t offset, uint32_t data, uint32_t mem_mask)
+{
+ COMBINE_DATA(&m_dmac[Channel].sar);
+}
+
+template <int Channel>
+uint32_t sh7604_device::dar_r()
+{
+ return m_dmac[Channel].dar;
+}
+
+template <int Channel>
+void sh7604_device::dar_w(offs_t offset, uint32_t data, uint32_t mem_mask)
+{
+ COMBINE_DATA(&m_dmac[Channel].dar);
+}
+
+template <int Channel>
+uint32_t sh7604_device::dmac_tcr_r()
+{
+ return m_dmac[Channel].tcr;
+}
+
+template <int Channel>
+void sh7604_device::dmac_tcr_w(offs_t offset, uint32_t data, uint32_t mem_mask)
+{
+ COMBINE_DATA(&m_dmac[Channel].tcr);
+ m_dmac[Channel].tcr &= 0xffffff;
+}
+
+template <int Channel>
+uint32_t sh7604_device::chcr_r()
+{
+ return m_dmac[Channel].chcr;
+}
+
+template <int Channel>
+void sh7604_device::chcr_w(offs_t offset, uint32_t data, uint32_t mem_mask)
+{
+ uint32_t old;
+ old = m_dmac[Channel].chcr;
+ COMBINE_DATA(&m_dmac[Channel].chcr);
+ m_dmac[Channel].chcr = (data & ~2) | (old & m_dmac[Channel].chcr & 2);
+ sh2_dmac_check(Channel);
+}
+
+uint32_t sh7604_device::dmaor_r()
+{
+ return m_dmaor & 0xf;
+}
+
+void sh7604_device::dmaor_w(offs_t offset, uint32_t data, uint32_t mem_mask)
+{
+ if (ACCESSING_BITS_0_7)
+ {
+ uint8_t old = m_dmaor & 0xf;
+ m_dmaor = (data & ~6) | (old & m_dmaor & 6); // TODO: should this be old & data & 6? bug?
+ sh2_dmac_check(0);
+ sh2_dmac_check(1);
+ }
+}
diff --git a/src/devices/cpu/sh/sh7604.h b/src/devices/cpu/sh/sh7604.h
new file mode 100644
index 00000000000..bc0bfcc3330
--- /dev/null
+++ b/src/devices/cpu/sh/sh7604.h
@@ -0,0 +1,264 @@
+// license:BSD-3-Clause
+// copyright-holders:Juergen Buchmueller, R. Belmont
+
+// sh7604, sh2 variant
+
+#ifndef MAME_CPU_SH_SH7604_H
+#define MAME_CPU_SH_SH7604_H
+
+#pragma once
+
+#include "sh2.h"
+
+#define SH2_DMA_KLUDGE_CB(name) int name(uint32_t src, uint32_t dst, uint32_t data, int size)
+#define SH2_DMA_FIFO_DATA_AVAILABLE_CB(name) int name(uint32_t src, uint32_t dst, uint32_t data, int size)
+#define SH2_FTCSR_READ_CB(name) void name(uint32_t data)
+
+
+class sh7604_device : public sh2_device
+{
+public:
+ typedef device_delegate<int (uint32_t src, uint32_t dst, uint32_t data, int size)> dma_kludge_delegate;
+ typedef device_delegate<int (uint32_t src, uint32_t dst, uint32_t data, int size)> dma_fifo_data_available_delegate;
+ typedef device_delegate<void (uint32_t data)> ftcsr_read_delegate;
+
+ sh7604_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+ void set_is_slave(int slave) { m_is_slave = slave; }
+
+ template <typename... T> void set_dma_kludge_callback(T &&... args) { m_dma_kludge_cb.set(std::forward<T>(args)...); }
+
+ template <typename... T> void set_dma_fifo_data_available_callback(T &&... args) { m_dma_fifo_data_available_cb.set(std::forward<T>(args)...); }
+
+ template <typename... T> void set_ftcsr_read_callback(T &&... args) { m_ftcsr_read_cb.set(std::forward<T>(args)...); }
+
+ void sh2_notify_dma_data_available();
+
+protected:
+ sh7604_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock, int cpu_type, address_map_constructor internal_map, int addrlines);
+
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+
+ virtual void sh2_exception(const char *message, int irqline) override;
+
+ uint32_t m_test_irq;
+ int m_internal_irq_vector;
+
+private:
+ enum
+ {
+ ICF = 0x80,
+ OCFA = 0x08,
+ OCFB = 0x04,
+ OVF = 0x02,
+ CCLRA = 0x01
+ };
+
+ void sh7604_map(address_map &map) ATTR_COLD;
+
+ uint32_t sh2_internal_a5();
+
+ // SCI
+ uint8_t smr_r();
+ void smr_w(uint8_t data);
+ uint8_t brr_r();
+ void brr_w(uint8_t data);
+ uint8_t scr_r();
+ void scr_w(uint8_t data);
+ uint8_t tdr_r();
+ void tdr_w(uint8_t data);
+ uint8_t ssr_r();
+ void ssr_w(uint8_t data);
+ uint8_t rdr_r();
+
+ // FRT / FRC
+ uint8_t tier_r();
+ void tier_w(uint8_t data);
+ uint16_t frc_r();
+ void frc_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0);
+ uint8_t ftcsr_r();
+ void ftcsr_w(uint8_t data);
+ uint16_t ocra_b_r();
+ void ocra_b_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0);
+ uint8_t frc_tcr_r();
+ void frc_tcr_w(uint8_t data);
+ uint8_t tocr_r();
+ void tocr_w(uint8_t data);
+ uint16_t frc_icr_r();
+
+ // INTC
+ uint16_t ipra_r();
+ void ipra_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0);
+ uint16_t iprb_r();
+ void iprb_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0);
+ uint16_t vcra_r();
+ void vcra_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0);
+ uint16_t vcrb_r();
+ void vcrb_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0);
+ uint16_t vcrc_r();
+ void vcrc_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0);
+ uint16_t vcrd_r();
+ void vcrd_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0);
+ uint16_t vcrwdt_r();
+ void vcrwdt_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0);
+ uint32_t vcrdiv_r();
+ void vcrdiv_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0);
+ uint16_t intc_icr_r();
+ void intc_icr_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0);
+
+ // DIVU
+ uint32_t dvsr_r();
+ void dvsr_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0);
+ uint32_t dvdnt_r();
+ void dvdnt_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0);
+ uint32_t dvdnth_r();
+ void dvdnth_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0);
+ uint32_t dvdntl_r();
+ void dvdntl_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0);
+
+ uint32_t dvcr_r();
+ void dvcr_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0);
+
+ // DMAC
+ template <int Channel> uint32_t vcrdma_r();
+ template <int Channel> void vcrdma_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0);
+ template <int Channel> uint8_t drcr_r();
+ template <int Channel> void drcr_w(uint8_t data);
+ template <int Channel> uint32_t sar_r();
+ template <int Channel> void sar_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0);
+ template <int Channel> uint32_t dar_r();
+ template <int Channel> void dar_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0);
+ template <int Channel> uint32_t dmac_tcr_r();
+ template <int Channel> void dmac_tcr_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0);
+ template <int Channel> uint32_t chcr_r();
+ template <int Channel> void chcr_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0);
+ uint32_t dmaor_r();
+ void dmaor_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0);
+
+ // WTC
+ uint16_t wtcnt_r();
+ void wtcnt_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0);
+ uint16_t rstcsr_r();
+ void rstcsr_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0);
+
+ // misc
+ uint16_t fmr_sbycr_r();
+ void fmr_sbycr_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0);
+ uint8_t ccr_r();
+ void ccr_w(uint8_t data);
+
+ // BSC
+ uint32_t bcr1_r();
+ void bcr1_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0);
+ uint32_t bcr2_r();
+ void bcr2_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0);
+ uint32_t wcr_r();
+ void wcr_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0);
+ uint32_t mcr_r();
+ void mcr_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0);
+ uint32_t rtcsr_r();
+ void rtcsr_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0);
+ uint32_t rtcor_r();
+ void rtcor_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0);
+ uint32_t rtcnt_r();
+ void rtcnt_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0);
+
+ virtual void set_frt_input(int state) override;
+
+ // SCI
+ uint8_t m_smr, m_brr, m_scr, m_tdr, m_ssr;
+
+ // FRT / FRC
+ uint8_t m_tier, m_ftcsr, m_frc_tcr, m_tocr;
+ uint16_t m_frc;
+ uint16_t m_ocra, m_ocrb, m_frc_icr;
+
+ // INTC
+ struct
+ {
+ uint8_t frc;
+ uint8_t sci;
+ uint8_t divu;
+ uint8_t dmac;
+ uint8_t wdt;
+ } m_irq_level;
+
+ struct
+ {
+ uint8_t fic;
+ uint8_t foc;
+ uint8_t fov;
+ uint8_t divu;
+ uint8_t dmac[2];
+ } m_irq_vector;
+
+ uint16_t m_ipra, m_iprb;
+ uint16_t m_vcra, m_vcrb, m_vcrc, m_vcrd, m_vcrwdt, m_vcrdiv, m_intc_icr, m_vcrdma[2];
+ bool m_vecmd, m_nmie;
+
+ // DIVU
+ bool m_divu_ovf, m_divu_ovfie;
+ uint32_t m_dvsr, m_dvdntl, m_dvdnth;
+
+ // WTC
+ uint8_t m_wtcnt, m_wtcsr;
+ uint8_t m_rstcsr;
+ uint16_t m_wtcw[2];
+
+ // DMAC
+ struct
+ {
+ uint8_t drcr;
+ uint32_t sar;
+ uint32_t dar;
+ uint32_t tcr;
+ uint32_t chcr;
+ } m_dmac[2];
+ uint8_t m_dmaor;
+
+ // misc
+ uint8_t m_sbycr, m_ccr;
+
+ // BSC
+ uint32_t m_bcr1, m_bcr2, m_wcr, m_mcr, m_rtcsr, m_rtcor, m_rtcnt;
+
+ uint64_t m_frc_base;
+
+ int m_frt_input;
+
+ emu_timer *m_timer;
+ emu_timer *m_wdtimer;
+ emu_timer *m_dma_current_active_timer[2];
+ int m_dma_timer_active[2];
+ uint8_t m_dma_irq[2];
+
+ int m_active_dma_incs[2];
+ int m_active_dma_incd[2];
+ int m_active_dma_size[2];
+ int m_active_dma_steal[2];
+ uint32_t m_active_dma_src[2];
+ uint32_t m_active_dma_dst[2];
+ uint32_t m_active_dma_count[2];
+
+ int m_is_slave;
+
+ dma_kludge_delegate m_dma_kludge_cb;
+ dma_fifo_data_available_delegate m_dma_fifo_data_available_cb;
+ ftcsr_read_delegate m_ftcsr_read_cb;
+
+ TIMER_CALLBACK_MEMBER(sh2_timer_callback);
+ TIMER_CALLBACK_MEMBER(sh2_wdtimer_callback);
+ TIMER_CALLBACK_MEMBER(sh2_dma_current_active_callback);
+ void sh2_timer_resync();
+ void sh2_timer_activate();
+ void sh2_wtcnt_recalc();
+ void sh2_wdt_activate();
+ void sh2_do_dma(int dmach);
+ void sh2_dmac_check(int dma);
+ void sh2_recalc_irq();
+};
+
+DECLARE_DEVICE_TYPE(SH7604, sh7604_device)
+
+#endif // MAME_CPU_SH_SH7604_H
diff --git a/src/devices/cpu/sh/sh7604_bus.cpp b/src/devices/cpu/sh/sh7604_bus.cpp
index 4a98ab6130a..8355ccd247a 100644
--- a/src/devices/cpu/sh/sh7604_bus.cpp
+++ b/src/devices/cpu/sh/sh7604_bus.cpp
@@ -30,65 +30,83 @@ DEFINE_DEVICE_TYPE(SH7604_BUS, sh7604_bus_device, "sh7604bus", "SH7604 BUS Contr
// LIVE DEVICE
//**************************************************************************
-READ16_MEMBER(sh7604_bus_device::bus_control_1_r)
+uint16_t sh7604_bus_device::bus_control_1_r()
{
- return (m_bcr1 & 0x1ff7) | (m_is_slave == true ? 0x8000 : 0);
+ return (m_bcr1 & 0x1ff7) | (m_is_slave ? 0x8000 : 0);
}
-WRITE16_MEMBER(sh7604_bus_device::bus_control_1_w)
+void sh7604_bus_device::bus_control_1_w(offs_t offset, uint16_t data, uint16_t mem_mask)
{
COMBINE_DATA(&m_bcr1);
- if(m_bcr1 & 0x1000) // ENDIAN
+ if (m_bcr1 & 0x1000) // ENDIAN
throw emu_fatalerror("%s: enabled little endian for Area 2\n", tag());
- if(m_bcr1 & 0x0800) // PSHR
+ if (m_bcr1 & 0x0800) // PSHR
throw emu_fatalerror("%s: enabled partial space share mode\n", tag());
}
-READ16_MEMBER(sh7604_bus_device::bus_control_2_r) { return m_bcr2 & 0x00fc; }
-WRITE16_MEMBER(sh7604_bus_device::bus_control_2_w)
+uint16_t sh7604_bus_device::bus_control_2_r()
+{
+ return m_bcr2 & 0x00fc;
+}
+
+void sh7604_bus_device::bus_control_2_w(offs_t offset, uint16_t data, uint16_t mem_mask)
{
COMBINE_DATA(&m_bcr2);
- if(m_bcr2 != 0x00fc)
- throw emu_fatalerror("%s: unexpected bus size register set %04x\n", tag(),data);
+ if (m_bcr2 != 0x00fc)
+ throw emu_fatalerror("%s: unexpected bus size register set %04x\n", tag(), data);
}
-READ16_MEMBER(sh7604_bus_device::wait_control_r) { return m_wcr; }
-WRITE16_MEMBER(sh7604_bus_device::wait_control_w) { COMBINE_DATA(&m_wcr); }
+uint16_t sh7604_bus_device::wait_control_r()
+{
+ return m_wcr;
+}
-READ16_MEMBER(sh7604_bus_device::memory_control_r) { return m_mcr & 0xfefc; }
-WRITE16_MEMBER(sh7604_bus_device::memory_control_w) { COMBINE_DATA(&m_mcr); }
+void sh7604_bus_device::wait_control_w(offs_t offset, uint16_t data, uint16_t mem_mask)
+{
+ COMBINE_DATA(&m_wcr);
+}
+
+uint16_t sh7604_bus_device::memory_control_r()
+{
+ return m_mcr & 0xfefc;
+}
+
+void sh7604_bus_device::memory_control_w(offs_t offset, uint16_t data, uint16_t mem_mask)
+{
+ COMBINE_DATA(&m_mcr);
+}
-READ16_MEMBER(sh7604_bus_device::refresh_timer_status_r)
+uint16_t sh7604_bus_device::refresh_timer_status_r()
{
return m_rtcsr & 0x00f8;
}
-WRITE16_MEMBER(sh7604_bus_device::refresh_timer_control_w)
+void sh7604_bus_device::refresh_timer_control_w(offs_t offset, uint16_t data, uint16_t mem_mask)
{
COMBINE_DATA(&m_rtcsr);
- if(m_rtcsr & 0x40)
- throw emu_fatalerror("%s: enabled timer irq register with clock setting = %02x\n",tag(),data & 0x38);
+ if (m_rtcsr & 0x40)
+ throw emu_fatalerror("%s: enabled timer irq register with clock setting = %02x\n", tag(), data & 0x38);
}
-READ16_MEMBER(sh7604_bus_device::refresh_timer_counter_r)
+uint16_t sh7604_bus_device::refresh_timer_counter_r()
{
- throw emu_fatalerror("%s: reading timer counter!\n",tag());
+ throw emu_fatalerror("%s: reading timer counter!\n", tag());
return 0;
}
-WRITE16_MEMBER(sh7604_bus_device::refresh_timer_counter_w)
+void sh7604_bus_device::refresh_timer_counter_w(offs_t offset, uint16_t data, uint16_t mem_mask)
{
- throw emu_fatalerror("%s: writing timer counter %04x\n",tag(),data);
+ throw emu_fatalerror("%s: writing timer counter %04x\n", tag(), data);
//COMBINE_DATA(&m_rtcnt);
}
-READ16_MEMBER(sh7604_bus_device::refresh_timer_constant_r)
+uint16_t sh7604_bus_device::refresh_timer_constant_r()
{
return m_rtcor & 0xff;
}
-WRITE16_MEMBER(sh7604_bus_device::refresh_timer_constant_w)
+void sh7604_bus_device::refresh_timer_constant_w(offs_t offset, uint16_t data, uint16_t mem_mask)
{
COMBINE_DATA(&m_rtcor);
}
@@ -102,7 +120,7 @@ void sh7604_bus_device::bus_regs(address_map &map)
map(0x08, 0x09).rw(FUNC(sh7604_bus_device::refresh_timer_status_r), FUNC(sh7604_bus_device::refresh_timer_control_w));
map(0x0a, 0x0b).rw(FUNC(sh7604_bus_device::refresh_timer_counter_r), FUNC(sh7604_bus_device::refresh_timer_counter_w));
map(0x0c, 0x0d).rw(FUNC(sh7604_bus_device::refresh_timer_constant_r), FUNC(sh7604_bus_device::refresh_timer_constant_w));
-// AM_RANGE(0x0e, 0x0f) unmapped, mirror?
+// map(0x0e, 0x0f) unmapped, mirror?
}
//-------------------------------------------------
@@ -142,22 +160,22 @@ void sh7604_bus_device::device_reset()
// READ/WRITE HANDLERS
//**************************************************************************
-READ32_MEMBER( sh7604_bus_device::read )
+uint32_t sh7604_bus_device::read(address_space &space, offs_t offset)
{
// 16 bit access only, TODO
return space.read_word(offset) & 0xffff;
}
-WRITE32_MEMBER( sh7604_bus_device::write )
+void sh7604_bus_device::write(address_space &space, offs_t offset, uint32_t data, uint32_t mem_mask)
{
// TODO: 8 bit access is invalid
// if accessing bits 16-31, one must write ID = 0xa55a
- if(ACCESSING_BITS_16_31)
+ if (ACCESSING_BITS_16_31)
{
// throw fatalerror if something trips it, presumably the write is going to be ignored
- if((data & 0xffff0000) != 0xa55a0000)
- throw emu_fatalerror("%s: making bus write with ID signature = %04x!\n", tag(),data >> 16);
+ if ((data & 0xffff0000) != 0xa55a0000)
+ throw emu_fatalerror("%s: making bus write with ID signature = %04x!\n", tag(), data >> 16);
}
- space.write_word(offset,data & 0xffff);
+ space.write_word(offset, data & 0xffff);
}
diff --git a/src/devices/cpu/sh/sh7604_bus.h b/src/devices/cpu/sh/sh7604_bus.h
index 672934aa5ae..6400f27cb43 100644
--- a/src/devices/cpu/sh/sh7604_bus.h
+++ b/src/devices/cpu/sh/sh7604_bus.h
@@ -6,8 +6,8 @@
***************************************************************************/
-#ifndef MAME_CPU_SH2_SH7604_BUS_H
-#define MAME_CPU_SH2_SH7604_BUS_H
+#ifndef MAME_CPU_SH_SH7604_BUS_H
+#define MAME_CPU_SH_SH7604_BUS_H
#pragma once
@@ -26,30 +26,30 @@ public:
sh7604_bus_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
// I/O operations
- void bus_regs(address_map &map);
-
- DECLARE_WRITE32_MEMBER( write );
- DECLARE_READ32_MEMBER( read );
- DECLARE_READ16_MEMBER( bus_control_1_r );
- DECLARE_WRITE16_MEMBER( bus_control_1_w );
- DECLARE_READ16_MEMBER( bus_control_2_r );
- DECLARE_WRITE16_MEMBER( bus_control_2_w );
- DECLARE_READ16_MEMBER( wait_control_r );
- DECLARE_WRITE16_MEMBER( wait_control_w );
- DECLARE_READ16_MEMBER( memory_control_r );
- DECLARE_WRITE16_MEMBER( memory_control_w );
- DECLARE_READ16_MEMBER( refresh_timer_status_r );
- DECLARE_WRITE16_MEMBER( refresh_timer_control_w );
- DECLARE_READ16_MEMBER( refresh_timer_counter_r );
- DECLARE_WRITE16_MEMBER( refresh_timer_counter_w );
- DECLARE_READ16_MEMBER( refresh_timer_constant_r );
- DECLARE_WRITE16_MEMBER( refresh_timer_constant_w );
+ void bus_regs(address_map &map) ATTR_COLD;
+
+ void write(address_space &space, offs_t offset, uint32_t data, uint32_t mem_mask = ~0);
+ uint32_t read(address_space &space, offs_t offset);
+ uint16_t bus_control_1_r();
+ void bus_control_1_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0);
+ uint16_t bus_control_2_r();
+ void bus_control_2_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0);
+ uint16_t wait_control_r();
+ void wait_control_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0);
+ uint16_t memory_control_r();
+ void memory_control_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0);
+ uint16_t refresh_timer_status_r();
+ void refresh_timer_control_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0);
+ uint16_t refresh_timer_counter_r();
+ void refresh_timer_counter_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0);
+ uint16_t refresh_timer_constant_r();
+ void refresh_timer_constant_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0);
protected:
// device-level overrides
//virtual void device_validity_check(validity_checker &valid) const;
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
private:
bool m_is_slave;
@@ -67,4 +67,4 @@ private:
// device type definition
DECLARE_DEVICE_TYPE(SH7604_BUS, sh7604_bus_device)
-#endif // MAME_CPU_SH2_SH7604_BUS_H
+#endif // MAME_CPU_SH_SH7604_BUS_H
diff --git a/src/devices/cpu/sh/sh7604_sci.cpp b/src/devices/cpu/sh/sh7604_sci.cpp
index 47b60dd8161..ae3ec5f4620 100644
--- a/src/devices/cpu/sh/sh7604_sci.cpp
+++ b/src/devices/cpu/sh/sh7604_sci.cpp
@@ -29,71 +29,71 @@ DEFINE_DEVICE_TYPE(SH7604_SCI, sh7604_sci_device, "sh7604sci", "SH7604 SCI Contr
// LIVE DEVICE
//**************************************************************************
-READ8_MEMBER(sh7604_sci_device::serial_mode_r)
+uint8_t sh7604_sci_device::serial_mode_r()
{
return m_smr;
}
-WRITE8_MEMBER(sh7604_sci_device::serial_mode_w)
+void sh7604_sci_device::serial_mode_w(uint8_t data)
{
m_smr = data;
- logerror("%s: serial mode set:\n",tag());
- logerror("\tCommunication Mode: %s mode\n",data & 0x80 ? "clocked synchronous" : "asynchronous");
- logerror("\tCharacter Length: %s mode\n",data & 0x40 ? "7-bit" : "8-bit");
- logerror("\tParity Enable: %s\n",data & 0x20 ? "yes" : "no");
- logerror("\tParity Mode: %s\n",data & 0x10 ? "Odd" : "Even");
- logerror("\tStop bits: %s\n",data & 0x08 ? "2" : "1");
- logerror("\tMultiprocessor mode: %s\n",data & 0x04 ? "yes" : "no");
- logerror("\tClock select: clock/%d\n",4 << ((data & 0x03)*2));
+ logerror("%s: serial mode set:\n", tag());
+ logerror("\tCommunication Mode: %s mode\n", data & 0x80 ? "clocked synchronous" : "asynchronous");
+ logerror("\tCharacter Length: %s mode\n", data & 0x40 ? "7-bit" : "8-bit");
+ logerror("\tParity Enable: %s\n", data & 0x20 ? "yes" : "no");
+ logerror("\tParity Mode: %s\n", data & 0x10 ? "Odd" : "Even");
+ logerror("\tStop bits: %s\n", data & 0x08 ? "2" : "1");
+ logerror("\tMultiprocessor mode: %s\n", data & 0x04 ? "yes" : "no");
+ logerror("\tClock select: clock/%d\n", 4 << ((data & 0x03) * 2));
}
-READ8_MEMBER(sh7604_sci_device::serial_control_r)
+uint8_t sh7604_sci_device::serial_control_r()
{
return m_scr;
}
-WRITE8_MEMBER(sh7604_sci_device::serial_control_w)
+void sh7604_sci_device::serial_control_w(uint8_t data)
{
m_scr = data;
- if(data & 0x30)
- throw emu_fatalerror("%s: enabled serial control %02x\n", tag(),data);
+ if (data & 0x30)
+ throw emu_fatalerror("%s: enabled serial control %02x\n", tag(), data);
}
-READ8_MEMBER(sh7604_sci_device::serial_status_r)
+uint8_t sh7604_sci_device::serial_status_r()
{
return m_ssr;
}
-WRITE8_MEMBER(sh7604_sci_device::serial_ack_w)
+void sh7604_sci_device::serial_ack_w(uint8_t data)
{
// TODO: verify this
m_ssr = (m_ssr & 0x06) | (m_ssr & data & 0xf9);
}
-READ8_MEMBER(sh7604_sci_device::bitrate_r )
+uint8_t sh7604_sci_device::bitrate_r()
{
return m_brr;
}
-WRITE8_MEMBER(sh7604_sci_device::bitrate_w )
+void sh7604_sci_device::bitrate_w(uint8_t data)
{
m_brr = data;
}
-READ8_MEMBER(sh7604_sci_device::transmit_data_r)
+uint8_t sh7604_sci_device::transmit_data_r()
{
// ...
return 0;
}
-WRITE8_MEMBER(sh7604_sci_device::transmit_data_w)
+void sh7604_sci_device::transmit_data_w(uint8_t data)
{
// ...
}
-READ8_MEMBER(sh7604_sci_device::receive_data_r)
+uint8_t sh7604_sci_device::receive_data_r()
{
// ...
return 0;
@@ -146,12 +146,12 @@ void sh7604_sci_device::device_reset()
// READ/WRITE HANDLERS
//**************************************************************************
-READ8_MEMBER( sh7604_sci_device::read )
+uint8_t sh7604_sci_device::read(address_space &space, offs_t offset)
{
return space.read_byte(offset);
}
-WRITE8_MEMBER( sh7604_sci_device::write )
+void sh7604_sci_device::write(address_space &space, offs_t offset, uint8_t data)
{
- space.write_byte(offset,data);
+ space.write_byte(offset, data);
}
diff --git a/src/devices/cpu/sh/sh7604_sci.h b/src/devices/cpu/sh/sh7604_sci.h
index a4f12da1275..87748a17a3e 100644
--- a/src/devices/cpu/sh/sh7604_sci.h
+++ b/src/devices/cpu/sh/sh7604_sci.h
@@ -6,8 +6,8 @@
***************************************************************************/
-#ifndef MAME_CPU_SH2_SH7604_SCI_H
-#define MAME_CPU_SH2_SH7604_SCI_H
+#ifndef MAME_CPU_SH_SH7604_SCI_H
+#define MAME_CPU_SH_SH7604_SCI_H
#pragma once
@@ -26,26 +26,27 @@ public:
sh7604_sci_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
// I/O operations
- void sci_regs(address_map &map);
+ void sci_regs(address_map &map) ATTR_COLD;
- DECLARE_WRITE8_MEMBER( write );
- DECLARE_READ8_MEMBER( read );
+ void write(address_space &space, offs_t offset, uint8_t data);
+ uint8_t read(address_space &space, offs_t offset);
- DECLARE_READ8_MEMBER( serial_mode_r );
- DECLARE_WRITE8_MEMBER( serial_mode_w );
- DECLARE_READ8_MEMBER( bitrate_r );
- DECLARE_WRITE8_MEMBER( bitrate_w );
- DECLARE_READ8_MEMBER( serial_control_r );
- DECLARE_WRITE8_MEMBER( serial_control_w );
+ uint8_t serial_mode_r();
+ void serial_mode_w(uint8_t data);
+ uint8_t bitrate_r();
+ void bitrate_w(uint8_t data);
+ uint8_t serial_control_r();
+ void serial_control_w(uint8_t data);
- DECLARE_READ8_MEMBER( transmit_data_r );
- DECLARE_WRITE8_MEMBER( transmit_data_w );
- DECLARE_READ8_MEMBER( serial_status_r );
- DECLARE_WRITE8_MEMBER( serial_ack_w );
- DECLARE_READ8_MEMBER( receive_data_r );
+ uint8_t transmit_data_r();
+ void transmit_data_w(uint8_t data);
+ uint8_t serial_status_r();
+ void serial_ack_w(uint8_t data);
+ uint8_t receive_data_r();
protected:
- enum {
+ enum
+ {
STATUS_MPBT = 1 << 0,
STATUS_MPB = 1 << 1,
STATUS_TEND = 1 << 2,
@@ -58,8 +59,8 @@ protected:
// device-level overrides
// virtual void device_validity_check(validity_checker &valid) const;
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
private:
const address_space_config m_space_config;
@@ -73,4 +74,4 @@ private:
// device type definition
DECLARE_DEVICE_TYPE(SH7604_SCI, sh7604_sci_device)
-#endif // MAME_CPU_SH2_SH7604_SCI_H
+#endif // MAME_CPU_SH_SH7604_SCI_H
diff --git a/src/devices/cpu/sh/sh7604_wdt.cpp b/src/devices/cpu/sh/sh7604_wdt.cpp
index 6dbd27dc3ce..10d7f04c42c 100644
--- a/src/devices/cpu/sh/sh7604_wdt.cpp
+++ b/src/devices/cpu/sh/sh7604_wdt.cpp
@@ -29,10 +29,10 @@ DEFINE_DEVICE_TYPE(SH7604_WDT, sh7604_wdt_device, "sh7604wdt", "SH7604 Watchdog
void sh7604_wdt_device::wdt_regs(address_map &map)
{
-// AM_RANGE(0x00, 0x00) timer control/status
-// AM_RANGE(0x01, 0x01) timer counter
-// AM_RANGE(0x02, 0x02) write only, reset control register
-// AM_RANGE(0x03, 0x03) read status register, write reset status register
+// map(0x00, 0x00) timer control/status
+// map(0x01, 0x01) timer counter
+// map(0x02, 0x02) write only, reset control register
+// map(0x03, 0x03) read status register, write reset status register
}
//-------------------------------------------------
@@ -67,18 +67,18 @@ void sh7604_wdt_device::device_reset()
// READ/WRITE HANDLERS
//**************************************************************************
-READ8_MEMBER( sh7604_wdt_device::read )
+uint8_t sh7604_wdt_device::read(address_space &space, offs_t offset)
{
return space.read_byte(offset);
}
-WRITE16_MEMBER( sh7604_wdt_device::write )
+void sh7604_wdt_device::write(address_space &space, offs_t offset, uint16_t data)
{
uint8_t id_param = data >> 8;
- switch(id_param)
+ switch (id_param)
{
- case 0xa5: space.write_byte(offset*2+0,data & 0xff); break;
- case 0x5a: space.write_byte(offset*2+1,data & 0xff); break;
- default: throw emu_fatalerror("%s: invalid id param write = %02x\n",tag(),id_param);
+ case 0xa5: space.write_byte(offset * 2 + 0, data & 0xff); break;
+ case 0x5a: space.write_byte(offset * 2 + 1, data & 0xff); break;
+ default: throw emu_fatalerror("%s: invalid id param write = %02x\n", tag(), id_param);
}
}
diff --git a/src/devices/cpu/sh/sh7604_wdt.h b/src/devices/cpu/sh/sh7604_wdt.h
index 70490ba8153..88f33b0e9e8 100644
--- a/src/devices/cpu/sh/sh7604_wdt.h
+++ b/src/devices/cpu/sh/sh7604_wdt.h
@@ -6,13 +6,12 @@
***************************************************************************/
-#ifndef MAME_CPU_SH7604_WDT_H
-#define MAME_CPU_SH7604_WDT_H
+#ifndef MAME_CPU_SH_SH7604_WDT_H
+#define MAME_CPU_SH_SH7604_WDT_H
#pragma once
-
//**************************************************************************
// TYPE DEFINITIONS
//**************************************************************************
@@ -26,16 +25,16 @@ public:
sh7604_wdt_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
// I/O operations
- void wdt_regs(address_map &map);
+ void wdt_regs(address_map &map) ATTR_COLD;
- DECLARE_WRITE16_MEMBER( write );
- DECLARE_READ8_MEMBER( read );
+ void write(address_space &space, offs_t offset, uint16_t data);
+ uint8_t read(address_space &space, offs_t offset);
protected:
// device-level overrides
// virtual void device_validity_check(validity_checker &valid) const;
- virtual void device_start() override;
- virtual void device_reset() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
private:
const address_space_config m_space_config;
};
@@ -44,4 +43,4 @@ private:
// device type definition
DECLARE_DEVICE_TYPE(SH7604_WDT, sh7604_wdt_device)
-#endif // MAME_CPU_SH7604_WDT_H
+#endif // MAME_CPU_SH_SH7604_WDT_H
diff --git a/src/devices/cpu/sh/sh_adc.cpp b/src/devices/cpu/sh/sh_adc.cpp
new file mode 100644
index 00000000000..282e994254a
--- /dev/null
+++ b/src/devices/cpu/sh/sh_adc.cpp
@@ -0,0 +1,342 @@
+// 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_MS, sh_adc_ms_device, "sh_adc_ms", "SH2/704x ADC (medium speed)")
+DEFINE_DEVICE_TYPE(SH_ADC_HS, sh_adc_hs_device, "sh_adc_hs", "SH2/704x ADC (high speed)")
+
+sh_adc_device::sh_adc_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock) :
+ device_t(mconfig, type, 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_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)
+{
+}
+
+sh_adc_ms_device::sh_adc_ms_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) :
+ sh_adc_device(mconfig, SH_ADC_MS, tag, owner, clock)
+{
+ m_is_hs = false;
+ m_port_base = 0;
+ m_port_mask = 3;
+ m_port_shift = 6;
+ m_analog_powered = true;
+}
+
+sh_adc_hs_device::sh_adc_hs_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) :
+ sh_adc_device(mconfig, SH_ADC_HS, tag, owner, clock)
+{
+ m_is_hs = true;
+ m_port_base = 0;
+ m_port_mask = 7;
+ m_port_shift = 0;
+ m_analog_powered = false;
+}
+
+
+u16 sh_adc_device::addr_r(offs_t offset)
+{
+ return m_addr[offset] << m_port_shift;
+}
+
+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 & (0x70 | m_port_mask)) | (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_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_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 + m_port_base);
+}
+
+void sh_adc_device::commit_value(int reg, int buffer)
+{
+ 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()
+{
+ if(m_is_hs) {
+ m_trigger = 1 << ((m_adcr >> 4) & 3);
+ m_analog_power_control = !(m_adcr & 0x40);
+
+ m_mode = ACTIVE | (m_adcr & 0x08 ? REPEAT : 0);
+
+ if(m_adcr & 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;
+
+ } else {
+ m_trigger = T_SOFT;
+
+ m_mode = ACTIVE;
+
+ if(m_adcsr & 0x08) {
+ m_mode |= ROTATE;
+ m_start_channel = 0;
+ m_end_channel = m_adcsr & 3;
+ } else
+ m_start_channel = m_end_channel = m_adcsr & 3;
+ }
+}
+
+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..d9e8236f09b
--- /dev/null
+++ b/src/devices/cpu/sh/sh_adc.h
@@ -0,0 +1,124 @@
+// 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:
+ 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:
+ sh_adc_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock);
+
+ required_device<sh7042_device> m_cpu;
+ required_device<sh_intc_device> m_intc;
+ int m_port_base, m_port_mask, m_port_shift;
+ int m_intc_vector;
+ bool m_is_hs;
+
+ 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 ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+
+ 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);
+};
+
+class sh_adc_ms_device : public sh_adc_device {
+public:
+ sh_adc_ms_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock = 0);
+
+ template<typename T, typename U> sh_adc_ms_device(const machine_config &mconfig, const char *tag, device_t *owner,
+ T &&cpu, U &&intc, int port_base, int vect) :
+ sh_adc_ms_device(mconfig, tag, owner)
+ {
+ m_cpu.set_tag(std::forward<T>(cpu));
+ m_intc.set_tag(std::forward<U>(intc));
+ m_is_hs = false;
+ m_port_base = port_base;
+ m_intc_vector = vect;
+ }
+};
+
+class sh_adc_hs_device : public sh_adc_device {
+public:
+ sh_adc_hs_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock = 0);
+
+ template<typename T, typename U> sh_adc_hs_device(const machine_config &mconfig, const char *tag, device_t *owner,
+ T &&cpu, U &&intc, int vect) :
+ sh_adc_hs_device(mconfig, tag, owner)
+ {
+ m_cpu.set_tag(std::forward<T>(cpu));
+ m_intc.set_tag(std::forward<U>(intc));
+ m_intc_vector = vect;
+ }
+};
+
+DECLARE_DEVICE_TYPE(SH_ADC_MS, sh_adc_ms_device)
+DECLARE_DEVICE_TYPE(SH_ADC_HS, sh_adc_hs_device)
+
+#endif // MAME_CPU_SH_SH_ADC_H
diff --git a/src/devices/cpu/sh/sh_bsc.cpp b/src/devices/cpu/sh/sh_bsc.cpp
new file mode 100644
index 00000000000..1151b220928
--- /dev/null
+++ b/src/devices/cpu/sh/sh_bsc.cpp
@@ -0,0 +1,139 @@
+// license:BSD-3-Clause
+// copyright-holders:Olivier Galibert
+/***************************************************************************
+
+ sh_bsc.h
+
+ SH DMA controller
+
+***************************************************************************/
+
+#include "emu.h"
+#include "sh_bsc.h"
+
+DEFINE_DEVICE_TYPE(SH_BSC, sh_bsc_device, "sh_bsc", "SH Bus State Controller")
+
+sh_bsc_device::sh_bsc_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) :
+ device_t(mconfig, SH_BSC, tag, owner, clock)
+{
+}
+
+void sh_bsc_device::device_start()
+{
+ save_item(NAME(m_bcr1));
+ save_item(NAME(m_bcr2));
+ save_item(NAME(m_wcr1));
+ save_item(NAME(m_wcr2));
+ save_item(NAME(m_dcr));
+ save_item(NAME(m_rtcsr));
+ save_item(NAME(m_rtcnt));
+ save_item(NAME(m_rtcor));
+}
+
+void sh_bsc_device::device_reset()
+{
+ m_bcr1 = 0x200f;
+ m_bcr2 = 0xffff;
+ m_wcr1 = 0xffff;
+ m_wcr2 = 0x000f;
+ m_dcr = 0;
+ m_rtcsr = 0;
+ m_rtcnt = 0;
+ m_rtcor = 0;
+}
+
+u16 sh_bsc_device::bcr1_r()
+{
+ logerror("bcr1_r\n");
+ return m_bcr1;
+}
+
+void sh_bsc_device::bcr1_w(offs_t, u16 data, u16 mem_mask)
+{
+ COMBINE_DATA(&m_bcr1);
+ logerror("bcr1_w %04x\n", m_bcr1);
+}
+
+u16 sh_bsc_device::bcr2_r()
+{
+ logerror("bcr2_r\n");
+ return m_bcr2;
+}
+
+void sh_bsc_device::bcr2_w(offs_t, u16 data, u16 mem_mask)
+{
+ COMBINE_DATA(&m_bcr2);
+ logerror("bcr2_w %04x\n", m_bcr2);
+}
+
+u16 sh_bsc_device::wcr1_r()
+{
+ logerror("wcr1_r\n");
+ return m_wcr1;
+}
+
+void sh_bsc_device::wcr1_w(offs_t, u16 data, u16 mem_mask)
+{
+ COMBINE_DATA(&m_wcr1);
+ logerror("wcr1_w %04x\n", m_wcr1);
+}
+
+u16 sh_bsc_device::wcr2_r()
+{
+ logerror("wcr2_r\n");
+ return m_wcr2;
+}
+
+void sh_bsc_device::wcr2_w(offs_t, u16 data, u16 mem_mask)
+{
+ COMBINE_DATA(&m_wcr2);
+ logerror("wcr2_w %04x\n", m_wcr2);
+}
+
+u16 sh_bsc_device::dcr_r()
+{
+ logerror("dcr_r\n");
+ return m_dcr;
+}
+
+void sh_bsc_device::dcr_w(offs_t, u16 data, u16 mem_mask)
+{
+ COMBINE_DATA(&m_dcr);
+ logerror("dcr_w %04x\n", m_dcr);
+}
+
+u16 sh_bsc_device::rtcsr_r()
+{
+ logerror("rtcsr_r\n");
+ return m_rtcsr;
+}
+
+void sh_bsc_device::rtcsr_w(offs_t, u16 data, u16 mem_mask)
+{
+ COMBINE_DATA(&m_rtcsr);
+ logerror("rtcsr_w %04x\n", m_rtcsr);
+}
+
+u16 sh_bsc_device::rtcnt_r()
+{
+ logerror("rtcnt_r\n");
+ return m_rtcnt;
+}
+
+void sh_bsc_device::rtcnt_w(offs_t, u16 data, u16 mem_mask)
+{
+ COMBINE_DATA(&m_rtcnt);
+ logerror("rtcnt_w %04x\n", m_rtcnt);
+}
+
+u16 sh_bsc_device::rtcor_r()
+{
+ logerror("rtcor_r\n");
+ return m_rtcor;
+}
+
+void sh_bsc_device::rtcor_w(offs_t, u16 data, u16 mem_mask)
+{
+ COMBINE_DATA(&m_rtcor);
+ logerror("rtcor_w %04x\n", m_rtcor);
+}
diff --git a/src/devices/cpu/sh/sh_bsc.h b/src/devices/cpu/sh/sh_bsc.h
new file mode 100644
index 00000000000..f1c78916cf7
--- /dev/null
+++ b/src/devices/cpu/sh/sh_bsc.h
@@ -0,0 +1,47 @@
+// license:BSD-3-Clause
+// copyright-holders:Olivier Galibert
+/***************************************************************************
+
+ sh_bsc.h
+
+ SH Bus State Controller
+
+***************************************************************************/
+
+#ifndef MAME_CPU_SH_SH_BSC_H
+#define MAME_CPU_SH_SH_BSC_H
+
+#pragma once
+
+class sh_bsc_device : public device_t {
+public:
+ sh_bsc_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock = 0);
+
+ u16 bcr1_r();
+ void bcr1_w(offs_t, u16 data, u16 mem_mask);
+ u16 bcr2_r();
+ void bcr2_w(offs_t, u16 data, u16 mem_mask);
+ u16 wcr1_r();
+ void wcr1_w(offs_t, u16 data, u16 mem_mask);
+ u16 wcr2_r();
+ void wcr2_w(offs_t, u16 data, u16 mem_mask);
+ u16 dcr_r();
+ void dcr_w(offs_t, u16 data, u16 mem_mask);
+ u16 rtcsr_r();
+ void rtcsr_w(offs_t, u16 data, u16 mem_mask);
+ u16 rtcnt_r();
+ void rtcnt_w(offs_t, u16 data, u16 mem_mask);
+ u16 rtcor_r();
+ void rtcor_w(offs_t, u16 data, u16 mem_mask);
+
+
+protected:
+ u16 m_bcr1, m_bcr2, m_wcr1, m_wcr2, m_dcr, m_rtcsr, m_rtcnt, m_rtcor;
+
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+};
+
+DECLARE_DEVICE_TYPE(SH_BSC, sh_bsc_device)
+
+#endif
diff --git a/src/devices/cpu/sh/sh_cmt.cpp b/src/devices/cpu/sh/sh_cmt.cpp
new file mode 100644
index 00000000000..74b7299a53b
--- /dev/null
+++ b/src/devices/cpu/sh/sh_cmt.cpp
@@ -0,0 +1,202 @@
+// 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()
+{
+ save_item(NAME(m_next_event));
+ save_item(NAME(m_str));
+ save_item(NAME(m_csr));
+ save_item(NAME(m_cnt));
+ save_item(NAME(m_cor));
+
+}
+
+void sh_cmt_device::device_reset()
+{
+ std::fill(m_next_event.begin(), m_next_event.end(), 0);
+ m_str = 0;
+ std::fill(m_csr.begin(), m_csr.end(), 0);
+ std::fill(m_cnt.begin(), m_cnt.end(), 0);
+ std::fill(m_cor.begin(), m_cor.end(), 0xffff);
+}
+
+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);
+ 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());
+ COMBINE_DATA(&m_csr[reg]);
+}
+
+void sh_cmt_device::cnt_w(int reg, u16 data, u16 mem_mask)
+{
+ COMBINE_DATA(&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]);
+ 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));
+ if(m_next_event[clk]) {
+ 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..4451e90e3ef
--- /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 ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+
+ 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_dasm.cpp b/src/devices/cpu/sh/sh_dasm.cpp
index a2e6dd67496..016d3022708 100644
--- a/src/devices/cpu/sh/sh_dasm.cpp
+++ b/src/devices/cpu/sh/sh_dasm.cpp
@@ -3,12 +3,11 @@
#include "emu.h"
#include "sh_dasm.h"
-#define SIGNX8(x) (((int32_t)(x) << 24) >> 24)
-#define SIGNX12(x) (((int32_t)(x) << 20) >> 20)
#define Rn ((opcode>>8)&15)
#define Rm ((opcode>>4)&15)
-const char *const sh_disassembler::regname[16] = {
+const char *const sh_disassembler::regname[16] =
+{
"R0", "R1", "R2", "R3", "R4", "R5", "R6", "R7",
"R8", "R9", "R10","R11","R12","R13","R14",
// The old SH2 dasm used 'SP' here, the old SH4 used 'R15'
@@ -19,7 +18,7 @@ const char *const sh_disassembler::regname[16] = {
uint32_t sh_disassembler::op0000(std::ostream &stream, uint32_t pc, uint16_t opcode)
{
uint32_t flags = 0;
- switch(opcode & 0x3f)
+ switch (opcode & 0x3f)
{
case 0x02:
util::stream_format(stream, "STC SR,%s", regname[Rn]);
@@ -38,7 +37,7 @@ uint32_t sh_disassembler::op0000(std::ostream &stream, uint32_t pc, uint16_t opc
break;
case 0x0B:
stream << "RTS";
- flags = STEP_OUT;
+ flags = STEP_OUT | step_over_extra(1);
break;
case 0x12:
util::stream_format(stream, "STS GBR,%s", regname[Rn]);
@@ -72,10 +71,10 @@ uint32_t sh_disassembler::op0000(std::ostream &stream, uint32_t pc, uint16_t opc
break;
case 0x2B:
stream << "RTE";
- flags = STEP_OUT;
+ flags = STEP_OUT | step_over_extra(1);
break;
default:
- switch(opcode & 15)
+ switch (opcode & 15)
{
case 0:
util::stream_format(stream, "?????? $%04X", opcode);
@@ -123,7 +122,7 @@ uint32_t sh_disassembler::op0000(std::ostream &stream, uint32_t pc, uint16_t opc
util::stream_format(stream, "MOV.L @(R0,%s),%s", regname[Rm], regname[Rn]);
break;
case 15:
- util::stream_format(stream, "MAC.L @%s+,@%s+", regname[Rn], regname[Rm]);
+ util::stream_format(stream, "MAC.L @%s+,@%s+", regname[Rm], regname[Rn]);
break;
}
}
@@ -251,7 +250,7 @@ uint32_t sh_disassembler::op0011(std::ostream &stream, uint32_t pc, uint16_t opc
uint32_t sh_disassembler::op0100(std::ostream &stream, uint32_t pc, uint16_t opcode)
{
uint32_t flags = 0;
- switch(opcode & 0x3F)
+ switch (opcode & 0x3F)
{
case 0x00:
util::stream_format(stream, "SHLL %s", regname[Rn]);
@@ -386,7 +385,7 @@ uint32_t sh_disassembler::op0101(std::ostream &stream, uint32_t pc, uint16_t opc
uint32_t sh_disassembler::op0110(std::ostream &stream, uint32_t pc, uint16_t opcode)
{
- switch(opcode & 0xF)
+ switch (opcode & 0xF)
{
case 0x00:
util::stream_format(stream, "MOV.B @%s,%s", regname[Rm], regname[Rn]);
@@ -448,7 +447,7 @@ uint32_t sh_disassembler::op0111(std::ostream &stream, uint32_t pc, uint16_t opc
uint32_t sh_disassembler::op1000(std::ostream &stream, uint32_t pc, uint16_t opcode)
{
- switch((opcode >> 8) & 15)
+ switch ((opcode >> 8) & 15)
{
case 0:
util::stream_format(stream, "MOV.B R0,@($%02X,%s)", (opcode & 15), regname[Rm]);
@@ -466,17 +465,17 @@ uint32_t sh_disassembler::op1000(std::ostream &stream, uint32_t pc, uint16_t opc
util::stream_format(stream, "CMP/EQ #$%02X,R0", (opcode & 0xff));
break;
case 9:
- util::stream_format(stream, "BT $%08X", pc + SIGNX8(opcode & 0xff) * 2 + 2);
- break;
+ util::stream_format(stream, "BT $%08X", pc + int8_t(opcode & 0xff) * 2 + 2);
+ return STEP_COND;
case 11:
- util::stream_format(stream, "BF $%08X", pc + SIGNX8(opcode & 0xff) * 2 + 2);
- break;
+ util::stream_format(stream, "BF $%08X", pc + int8_t(opcode & 0xff) * 2 + 2);
+ return STEP_COND;
case 13:
- util::stream_format(stream, "BTS $%08X", pc + SIGNX8(opcode & 0xff) * 2 + 2);
- break;
+ util::stream_format(stream, "BTS $%08X", pc + int8_t(opcode & 0xff) * 2 + 2);
+ return STEP_COND | step_over_extra(1);
case 15:
- util::stream_format(stream, "BFS $%08X", pc + SIGNX8(opcode & 0xff) * 2 + 2);
- break;
+ util::stream_format(stream, "BFS $%08X", pc + int8_t(opcode & 0xff) * 2 + 2);
+ return STEP_COND | step_over_extra(1);
default :
util::stream_format(stream, "invalid $%04X", opcode);
}
@@ -491,20 +490,20 @@ uint32_t sh_disassembler::op1001(std::ostream &stream, uint32_t pc, uint16_t opc
uint32_t sh_disassembler::op1010(std::ostream &stream, uint32_t pc, uint16_t opcode)
{
- util::stream_format(stream, "BRA $%08X", SIGNX12(opcode & 0xfff) * 2 + pc + 2);
+ util::stream_format(stream, "BRA $%08X", util::sext(opcode & 0xfff, 12) * 2 + pc + 2);
return 0;
}
uint32_t sh_disassembler::op1011(std::ostream &stream, uint32_t pc, uint16_t opcode)
{
- util::stream_format(stream, "BSR $%08X", SIGNX12(opcode & 0xfff) * 2 + pc + 2);
+ util::stream_format(stream, "BSR $%08X", util::sext(opcode & 0xfff, 12) * 2 + pc + 2);
return STEP_OVER | step_over_extra(1);
}
uint32_t sh_disassembler::op1100(std::ostream &stream, uint32_t pc, uint16_t opcode)
{
uint32_t flags = 0;
- switch((opcode >> 8) & 15)
+ switch ((opcode >> 8) & 15)
{
case 0:
util::stream_format(stream, "MOV.B R0,@($%02X,GBR)", opcode & 0xff);
@@ -591,7 +590,8 @@ uint32_t sh_disassembler::op0000_sh34(std::ostream &stream, uint32_t pc, uint16_
util::stream_format(stream, "?????? $%04X", opcode);
break;
case 0x2:
- if (opcode & 0x80) {
+ if (opcode & 0x80)
+ {
util::stream_format(stream, "STC %s_BANK,%s", regname[(Rm) & 7], regname[Rn]);
return flags;
}
@@ -708,14 +708,14 @@ uint32_t sh_disassembler::op0000_sh34(std::ostream &stream, uint32_t pc, uint16_
{
case 0x00:
stream << "RTS";
- flags = STEP_OUT;
+ flags = STEP_OUT | step_over_extra(1);
break;
case 0x10:
stream << "SLEEP";
break;
case 0x20:
stream << "RTE";
- flags = STEP_OUT;
+ flags = STEP_OUT | step_over_extra(1);
break;
}
break;
@@ -796,7 +796,8 @@ uint32_t sh_disassembler::op0100_sh34(std::ostream &stream, uint32_t pc, uint16_
}
break;
case 0x3:
- if (opcode & 0x80) {
+ if (opcode & 0x80)
+ {
util::stream_format(stream, "STC.L %s_BANK,@-%s", regname[(Rm) & 7],regname[Rn]);
return flags;
}
@@ -868,7 +869,8 @@ uint32_t sh_disassembler::op0100_sh34(std::ostream &stream, uint32_t pc, uint16_
}
break;
case 0x7:
- if (opcode & 0x80) {
+ if (opcode & 0x80)
+ {
util::stream_format(stream, "LDC.L @%s+,%s_BANK", regname[Rn],regname[(Rm) & 7]);
return flags;
}
@@ -964,7 +966,8 @@ uint32_t sh_disassembler::op0100_sh34(std::ostream &stream, uint32_t pc, uint16_
util::stream_format(stream, "SHLD %s,%s", regname[Rm], regname[Rn]);
break;
case 0xE:
- if (opcode & 0x80) {
+ if (opcode & 0x80)
+ {
util::stream_format(stream, "LDC %s,%s_BANK", regname[Rn],regname[(Rm) & 7]);
return flags;
}
@@ -1081,8 +1084,10 @@ uint32_t sh_disassembler::op1111_sh34(std::ostream &stream, uint32_t pc, uint16_
util::stream_format(stream, "FIPR FV%d, FV%d", (Rn & 3) << 2, Rn & 12);
break;
case 0xF0:
- if (opcode & 0x100) {
- if (opcode & 0x200) {
+ if (opcode & 0x100)
+ {
+ if (opcode & 0x200)
+ {
switch (opcode & 0xC00)
{
case 0x000:
@@ -1095,10 +1100,14 @@ uint32_t sh_disassembler::op1111_sh34(std::ostream &stream, uint32_t pc, uint16_
util::stream_format(stream, "Funknown $%04X", opcode);
break;
}
- } else {
+ }
+ else
+ {
util::stream_format(stream, "FTRV XMTRX, FV%d", Rn & 12);
}
- } else {
+ }
+ else
+ {
util::stream_format(stream, "FSCA FPUL, F%s", regname[Rn & 14]);
}
break;
diff --git a/src/devices/cpu/sh/sh_dasm.h b/src/devices/cpu/sh/sh_dasm.h
index 52d6b2eb723..2b29187ee73 100644
--- a/src/devices/cpu/sh/sh_dasm.h
+++ b/src/devices/cpu/sh/sh_dasm.h
@@ -1,8 +1,8 @@
// license:BSD-3-Clause
// copyright-holders:Juergen Buchmueller, R. Belmont
-#ifndef MAME_CPU_SH_SHDASM_H
-#define MAME_CPU_SH_SHDASM_H
+#ifndef MAME_CPU_SH_SH_DASM_H
+#define MAME_CPU_SH_SH_DASM_H
#pragma once
@@ -42,4 +42,4 @@ private:
bool m_is_sh34;
};
-#endif
+#endif // MAME_CPU_SH_SH_DASM_H
diff --git a/src/devices/cpu/sh/sh_dmac.cpp b/src/devices/cpu/sh/sh_dmac.cpp
new file mode 100644
index 00000000000..39775445ba9
--- /dev/null
+++ b/src/devices/cpu/sh/sh_dmac.cpp
@@ -0,0 +1,115 @@
+// license:BSD-3-Clause
+// copyright-holders:Olivier Galibert
+/***************************************************************************
+
+ sh_dmac.h
+
+ SH DMA controller
+
+***************************************************************************/
+
+#include "emu.h"
+#include "sh_dmac.h"
+#include "sh7042.h"
+
+DEFINE_DEVICE_TYPE(SH_DMAC, sh_dmac_device, "sh_dmac", "SH DMA controller")
+DEFINE_DEVICE_TYPE(SH_DMAC_CHANNEL, sh_dmac_channel_device, "sh_dmac_channel", "SH DMA controller channel")
+
+sh_dmac_device::sh_dmac_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) :
+ device_t(mconfig, SH_DMAC, tag, owner, clock),
+ m_cpu(*this, finder_base::DUMMY_TAG)
+{
+}
+
+void sh_dmac_device::device_start()
+{
+ save_item(NAME(m_dmaor));
+}
+
+void sh_dmac_device::device_reset()
+{
+ m_dmaor = 0;
+}
+
+u16 sh_dmac_device::dmaor_r()
+{
+ logerror("dmaor_r\n");
+ return m_dmaor;
+}
+
+void sh_dmac_device::dmaor_w(offs_t, u16 data, u16 mem_mask)
+{
+ COMBINE_DATA(&m_dmaor);
+ logerror("dmaor_w %04x\n", m_dmaor);
+}
+
+sh_dmac_channel_device::sh_dmac_channel_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) :
+ device_t(mconfig, SH_DMAC_CHANNEL, tag, owner, clock),
+ m_cpu(*this, finder_base::DUMMY_TAG),
+ m_intc(*this, finder_base::DUMMY_TAG)
+{
+}
+
+void sh_dmac_channel_device::device_start()
+{
+ save_item(NAME(m_sar));
+ save_item(NAME(m_dar));
+ save_item(NAME(m_dmatcr));
+ save_item(NAME(m_chcr));
+}
+
+void sh_dmac_channel_device::device_reset()
+{
+ m_sar = 0;
+ m_dar = 0;
+ m_dmatcr = 0;
+ m_chcr = 0;
+}
+
+u32 sh_dmac_channel_device::sar_r()
+{
+ logerror("sar_r\n");
+ return m_sar;
+}
+
+void sh_dmac_channel_device::sar_w(offs_t, u32 data, u32 mem_mask)
+{
+ COMBINE_DATA(&m_sar);
+ logerror("sar_w %08x\n", m_sar);
+}
+
+u32 sh_dmac_channel_device::dar_r()
+{
+ logerror("dar_r\n");
+ return m_dar;
+}
+
+void sh_dmac_channel_device::dar_w(offs_t, u32 data, u32 mem_mask)
+{
+ COMBINE_DATA(&m_dar);
+ logerror("dar_w %08x\n", m_dar);
+}
+
+u32 sh_dmac_channel_device::dmatcr_r()
+{
+ logerror("dmatcr_r\n");
+ return m_dmatcr;
+}
+
+void sh_dmac_channel_device::dmatcr_w(offs_t, u32 data, u32 mem_mask)
+{
+ COMBINE_DATA(&m_dmatcr);
+ logerror("dmatcr_w %08x\n", m_dmatcr);
+}
+
+u32 sh_dmac_channel_device::chcr_r()
+{
+ logerror("chcr_r\n");
+ return m_chcr;
+}
+
+void sh_dmac_channel_device::chcr_w(offs_t, u32 data, u32 mem_mask)
+{
+ COMBINE_DATA(&m_chcr);
+ logerror("chcr_w %08x\n", m_chcr);
+}
diff --git a/src/devices/cpu/sh/sh_dmac.h b/src/devices/cpu/sh/sh_dmac.h
new file mode 100644
index 00000000000..3c8436df0d8
--- /dev/null
+++ b/src/devices/cpu/sh/sh_dmac.h
@@ -0,0 +1,79 @@
+// license:BSD-3-Clause
+// copyright-holders:Olivier Galibert
+/***************************************************************************
+
+ sh_dmac.h
+
+ SH DMA controller
+
+***************************************************************************/
+
+#ifndef MAME_CPU_SH_SH_DMAC_H
+#define MAME_CPU_SH_SH_DMAC_H
+
+#pragma once
+
+// To generalize eventually
+class sh7042_device;
+class sh_intc_device;
+
+class sh_dmac_device : public device_t {
+public:
+ sh_dmac_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock = 0);
+
+ template <typename T> sh_dmac_device(const machine_config &mconfig, const char *tag, device_t *owner, T &&cpu)
+ : sh_dmac_device(mconfig, tag, owner)
+ {
+ set_info(cpu);
+ }
+
+ template<typename T> void set_info(T &&cpu) { m_cpu.set_tag(std::forward<T>(cpu)); }
+
+ u16 dmaor_r();
+ void dmaor_w(offs_t, u16 data, u16 mem_mask);
+
+
+protected:
+ required_device<sh7042_device> m_cpu;
+
+ u16 m_dmaor;
+
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+};
+
+class sh_dmac_channel_device : public device_t {
+public:
+ sh_dmac_channel_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock = 0);
+
+ template <typename T, typename U> sh_dmac_channel_device(const machine_config &mconfig, const char *tag, device_t *owner, T &&cpu, U &&intc)
+ : sh_dmac_channel_device(mconfig, tag, owner)
+ {
+ set_info(cpu, intc);
+ }
+
+ template<typename T, typename U> void set_info(T &&cpu, U &&intc) { m_cpu.set_tag(std::forward<T>(cpu)); m_intc.set_tag(std::forward<U>(intc)); }
+
+ u32 sar_r();
+ void sar_w(offs_t, u32 data, u32 mem_mask);
+ u32 dar_r();
+ void dar_w(offs_t, u32 data, u32 mem_mask);
+ u32 dmatcr_r();
+ void dmatcr_w(offs_t, u32 data, u32 mem_mask);
+ u32 chcr_r();
+ void chcr_w(offs_t, u32 data, u32 mem_mask);
+
+protected:
+ required_device<sh7042_device> m_cpu;
+ required_device<sh_intc_device> m_intc;
+
+ u32 m_sar, m_dar, m_dmatcr, m_chcr;
+
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+};
+
+DECLARE_DEVICE_TYPE(SH_DMAC, sh_dmac_device)
+DECLARE_DEVICE_TYPE(SH_DMAC_CHANNEL, sh_dmac_channel_device)
+
+#endif
diff --git a/src/devices/cpu/sh/sh_fe.cpp b/src/devices/cpu/sh/sh_fe.cpp
index efee8bf506f..5e803b8ee00 100644
--- a/src/devices/cpu/sh/sh_fe.cpp
+++ b/src/devices/cpu/sh/sh_fe.cpp
@@ -2,7 +2,7 @@
// copyright-holders:David Haywood, R. Belmont
/***************************************************************************
- sh_fe.c
+ sh_fe.cpp
Front end for SH recompiler
@@ -10,7 +10,6 @@
#include "emu.h"
#include "sh2.h"
-#include "sh2comn.h"
#include "cpu/drcfe.h"
@@ -51,7 +50,7 @@ bool sh_frontend::describe(opcode_desc &desc, const opcode_desc *prev)
return describe_group_0(desc, prev, opcode);
case 1: // MOVLS4
- desc.regin[0] |= REGFLAG_R(Rn) | REGFLAG_R(Rm);
+ desc.regin[0] |= REGFLAG_R(REG_N) | REGFLAG_R(REG_M);
desc.flags |= OPFLAG_WRITES_MEMORY;
return true;
@@ -65,8 +64,8 @@ bool sh_frontend::describe(opcode_desc &desc, const opcode_desc *prev)
return describe_group_4(desc, prev, opcode);
case 5: // MOVLL4
- desc.regin[0] |= REGFLAG_R(Rm);
- desc.regout[0] |= REGFLAG_R(Rn);
+ desc.regin[0] |= REGFLAG_R(REG_M);
+ desc.regout[0] |= REGFLAG_R(REG_N);
desc.flags |= OPFLAG_READS_MEMORY;
return true;
@@ -74,24 +73,24 @@ bool sh_frontend::describe(opcode_desc &desc, const opcode_desc *prev)
return describe_group_6(desc, prev, opcode);
case 7: // ADDI
- desc.regin[0] |= REGFLAG_R(Rn);
- desc.regout[0] |= REGFLAG_R(Rn);
+ desc.regin[0] |= REGFLAG_R(REG_N);
+ desc.regout[0] |= REGFLAG_R(REG_N);
return true;
case 8:
return describe_group_8(desc, prev, opcode);
case 9: // MOVWI
- desc.regout[0] |= REGFLAG_R(Rn);
+ desc.regout[0] |= REGFLAG_R(REG_N);
desc.flags |= OPFLAG_READS_MEMORY;
return true;
case 11: // BSR
desc.regout[1] |= REGFLAG_PR;
- // (intentional fallthrough - BSR is BRA with the addition of PR = the return address)
+ [[fallthrough]]; // BSR is BRA with the addition of PR = the return address
case 10: // BRA
{
- int32_t disp = ((int32_t)opcode << 20) >> 20;
+ int32_t disp = util::sext(opcode, 12);
desc.flags |= OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE;
desc.targetpc = (desc.pc + 2) + disp * 2 + 2;
@@ -104,12 +103,12 @@ bool sh_frontend::describe(opcode_desc &desc, const opcode_desc *prev)
return describe_group_12(desc, prev, opcode);
case 13: // MOVLI
- desc.regout[0] |= REGFLAG_R(Rn);
+ desc.regout[0] |= REGFLAG_R(REG_N);
desc.flags |= OPFLAG_READS_MEMORY;
return true;
case 14: // MOVI
- desc.regout[0] |= REGFLAG_R(Rn);
+ desc.regout[0] |= REGFLAG_R(REG_N);
return true;
case 15: // NOP
@@ -127,7 +126,7 @@ bool sh_frontend::describe_group_2(opcode_desc &desc, const opcode_desc *prev, u
case 0: // MOVBS(Rm, Rn);
case 1: // MOVWS(Rm, Rn);
case 2: // MOVLS(Rm, Rn);
- desc.regin[0] |= REGFLAG_R(Rm) | REGFLAG_R(Rn);
+ desc.regin[0] |= REGFLAG_R(REG_M) | REGFLAG_R(REG_N);
desc.flags |= OPFLAG_WRITES_MEMORY;
return true;
@@ -138,28 +137,28 @@ bool sh_frontend::describe_group_2(opcode_desc &desc, const opcode_desc *prev, u
case 5: // MOVWM(Rm, Rn);
case 6: // MOVLM(Rm, Rn);
case 13: // XTRCT(Rm, Rn);
- desc.regin[0] |= REGFLAG_R(Rm) | REGFLAG_R(Rn);
- desc.regout[0] |= REGFLAG_R(Rn);
+ desc.regin[0] |= REGFLAG_R(REG_M) | REGFLAG_R(REG_N);
+ desc.regout[0] |= REGFLAG_R(REG_N);
desc.flags |= OPFLAG_WRITES_MEMORY;
return true;
case 7: // DIV0S(Rm, Rn);
case 8: // TST(Rm, Rn);
case 12: // CMPSTR(Rm, Rn);
- desc.regin[0] |= REGFLAG_R(Rm) | REGFLAG_R(Rn);
+ desc.regin[0] |= REGFLAG_R(REG_M) | REGFLAG_R(REG_N);
desc.regout[1] |= REGFLAG_SR;
return true;
case 9: // AND(Rm, Rn);
case 10: // XOR(Rm, Rn);
case 11: // OR(Rm, Rn);
- desc.regin[0] |= REGFLAG_R(Rm) | REGFLAG_R(Rn);
- desc.regout[0] |= REGFLAG_R(Rn);
+ desc.regin[0] |= REGFLAG_R(REG_M) | REGFLAG_R(REG_N);
+ desc.regout[0] |= REGFLAG_R(REG_N);
return true;
case 14: // MULU(Rm, Rn);
case 15: // MULS(Rm, Rn);
- desc.regin[0] |= REGFLAG_R(Rm) | REGFLAG_R(Rn);
+ desc.regin[0] |= REGFLAG_R(REG_M) | REGFLAG_R(REG_N);
desc.regout[1] |= REGFLAG_MACL | REGFLAG_MACH;
desc.cycles = 2;
return true;
@@ -177,7 +176,7 @@ bool sh_frontend::describe_group_3(opcode_desc &desc, const opcode_desc *prev, u
case 3: // CMPGE(Rm, Rn);
case 6: // CMPHI(Rm, Rn);
case 7: // CMPGT(Rm, Rn);
- desc.regin[0] |= REGFLAG_R(Rm) | REGFLAG_R(Rn);
+ desc.regin[0] |= REGFLAG_R(REG_M) | REGFLAG_R(REG_N);
desc.regout[1] |= REGFLAG_SR;
return true;
@@ -186,31 +185,31 @@ bool sh_frontend::describe_group_3(opcode_desc &desc, const opcode_desc *prev, u
return true;
case 4: // DIV1(Rm, Rn);
- desc.regin[0] |= REGFLAG_R(Rm) | REGFLAG_R(Rn);
- desc.regout[0] |= REGFLAG_R(Rn);
+ desc.regin[0] |= REGFLAG_R(REG_M) | REGFLAG_R(REG_N);
+ desc.regout[0] |= REGFLAG_R(REG_N);
desc.regout[1] |= REGFLAG_SR;
return true;
case 5: // DMULU(Rm, Rn);
case 13: // DMULS(Rm, Rn);
- desc.regin[0] |= REGFLAG_R(Rm) | REGFLAG_R(Rn);
+ desc.regin[0] |= REGFLAG_R(REG_M) | REGFLAG_R(REG_N);
desc.regout[1] |= REGFLAG_MACL | REGFLAG_MACH;
desc.cycles = 2;
return true;
case 8: // SUB(Rm, Rn);
case 12: // ADD(Rm, Rn);
- desc.regin[0] |= REGFLAG_R(Rm) | REGFLAG_R(Rn);
- desc.regout[0] |= REGFLAG_R(Rn);
+ desc.regin[0] |= REGFLAG_R(REG_M) | REGFLAG_R(REG_N);
+ desc.regout[0] |= REGFLAG_R(REG_N);
return true;
case 10: // SUBC(Rm, Rn);
case 11: // SUBV(Rm, Rn);
case 14: // ADDC(Rm, Rn);
case 15: // ADDV(Rm, Rn);
- desc.regin[0] |= REGFLAG_R(Rm) | REGFLAG_R(Rn);
+ desc.regin[0] |= REGFLAG_R(REG_M) | REGFLAG_R(REG_N);
desc.regin[1] |= REGFLAG_SR;
- desc.regout[0] |= REGFLAG_R(Rn);
+ desc.regout[0] |= REGFLAG_R(REG_N);
desc.regout[1] |= REGFLAG_SR;
return true;
}
@@ -233,26 +232,26 @@ bool sh_frontend::describe_group_6(opcode_desc &desc, const opcode_desc *prev, u
case 13: // EXTUW(Rm, Rn);
case 14: // EXTSB(Rm, Rn);
case 15: // EXTSW(Rm, Rn);
- desc.regin[0] |= REGFLAG_R(Rm);
- desc.regout[0] |= REGFLAG_R(Rn);
+ desc.regin[0] |= REGFLAG_R(REG_M);
+ desc.regout[0] |= REGFLAG_R(REG_N);
return true;
case 4: // MOVBP(Rm, Rn);
case 5: // MOVWP(Rm, Rn);
case 6: // MOVLP(Rm, Rn);
- desc.regin[0] |= REGFLAG_R(Rm) | REGFLAG_R(Rn);
- desc.regout[0] |= REGFLAG_R(Rn);
+ desc.regin[0] |= REGFLAG_R(REG_M) | REGFLAG_R(REG_N);
+ desc.regout[0] |= REGFLAG_R(REG_N);
desc.flags |= OPFLAG_READS_MEMORY;
return true;
case 8: // SWAPB(Rm, Rn);
- desc.regin[0] |= REGFLAG_R(Rm) | REGFLAG_R(Rn);
- desc.regout[0] |= REGFLAG_R(Rn);
+ desc.regin[0] |= REGFLAG_R(REG_M) | REGFLAG_R(REG_N);
+ desc.regout[0] |= REGFLAG_R(REG_N);
return true;
case 10: // NEGC(Rm, Rn);
- desc.regin[0] |= REGFLAG_R(Rm);
- desc.regout[0] |= REGFLAG_R(Rn);
+ desc.regin[0] |= REGFLAG_R(REG_M);
+ desc.regout[0] |= REGFLAG_R(REG_N);
desc.regout[1] |= REGFLAG_SR;
return true;
}
@@ -263,49 +262,49 @@ bool sh_frontend::describe_group_8(opcode_desc &desc, const opcode_desc *prev, u
{
int32_t disp;
- switch ( opcode & (15<<8) )
+ switch (opcode & (15 << 8))
{
case 0 << 8: // MOVBS4(opcode & 0x0f, Rm);
case 1 << 8: // MOVWS4(opcode & 0x0f, Rm);
- desc.regin[0] |= REGFLAG_R(Rm) | REGFLAG_R(0);
+ desc.regin[0] |= REGFLAG_R(REG_M) | REGFLAG_R(0);
desc.flags |= OPFLAG_WRITES_MEMORY;
return true;
- case 2<< 8: // NOP();
- case 3<< 8: // NOP();
- case 6<< 8: // NOP();
- case 7<< 8: // NOP();
- case 10<< 8: // NOP();
- case 12<< 8: // NOP();
- case 14<< 8: // NOP();
+ case 2 << 8: // NOP();
+ case 3 << 8: // NOP();
+ case 6 << 8: // NOP();
+ case 7 << 8: // NOP();
+ case 10 << 8: // NOP();
+ case 12 << 8: // NOP();
+ case 14 << 8: // NOP();
return true;
- case 4<< 8: // MOVBL4(Rm, opcode & 0x0f);
- case 5<< 8: // MOVWL4(Rm, opcode & 0x0f);
- desc.regin[0] |= REGFLAG_R(Rm);
+ case 4 << 8: // MOVBL4(Rm, opcode & 0x0f);
+ case 5 << 8: // MOVWL4(Rm, opcode & 0x0f);
+ desc.regin[0] |= REGFLAG_R(REG_M);
desc.regout[0] |= REGFLAG_R(0);
desc.flags |= OPFLAG_READS_MEMORY;
return true;
- case 8<< 8: // CMPIM(opcode & 0xff);
- desc.regin[0] |= REGFLAG_R(Rm);
+ case 8 << 8: // CMPIM(opcode & 0xff);
+ desc.regin[0] |= REGFLAG_R(REG_M);
desc.regin[1] |= REGFLAG_SR;
desc.regout[1] |= REGFLAG_SR;
return true;
- case 9<< 8: // BT(opcode & 0xff);
- case 11<< 8: // BF(opcode & 0xff);
+ case 9 << 8: // BT(opcode & 0xff);
+ case 11 << 8: // BF(opcode & 0xff);
desc.flags |= OPFLAG_IS_CONDITIONAL_BRANCH;
desc.cycles = 3;
- disp = ((int32_t)opcode << 24) >> 24;
+ disp = util::sext(opcode, 8);
desc.targetpc = (desc.pc + 2) + disp * 2 + 2;
return true;
- case 13<< 8: // BTS(opcode & 0xff);
- case 15<< 8: // BFS(opcode & 0xff);
+ case 13 << 8: // BTS(opcode & 0xff);
+ case 15 << 8: // BFS(opcode & 0xff);
desc.flags |= OPFLAG_IS_CONDITIONAL_BRANCH;
desc.cycles = 2;
- disp = ((int32_t)opcode << 24) >> 24;
+ disp = util::sext(opcode, 8);
desc.targetpc = (desc.pc + 2) + disp * 2 + 2;
desc.delayslots = 1;
return true;
@@ -318,14 +317,14 @@ bool sh_frontend::describe_group_12(opcode_desc &desc, const opcode_desc *prev,
{
switch (opcode & (15<<8))
{
- case 0<<8: // MOVBSG(opcode & 0xff);
- case 1<<8: // MOVWSG(opcode & 0xff);
- case 2<<8: // MOVLSG(opcode & 0xff);
+ case 0 << 8: // MOVBSG(opcode & 0xff);
+ case 1 << 8: // MOVWSG(opcode & 0xff);
+ case 2 << 8: // MOVLSG(opcode & 0xff);
desc.regin[0] |= REGFLAG_R(0);
desc.flags |= OPFLAG_WRITES_MEMORY;
return true;
- case 3<<8: // TRAPA(opcode & 0xff);
+ case 3 << 8: // TRAPA(opcode & 0xff);
desc.regin[0] |= REGFLAG_R(15);
desc.regin[1] |= REGFLAG_VBR;
desc.regout[0] |= REGFLAG_R(15);
@@ -334,31 +333,31 @@ bool sh_frontend::describe_group_12(opcode_desc &desc, const opcode_desc *prev,
desc.flags |= OPFLAG_READS_MEMORY | OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE;
return true;
- case 4<<8: // MOVBLG(opcode & 0xff);
- case 5<<8: // MOVWLG(opcode & 0xff);
- case 6<<8: // MOVLLG(opcode & 0xff);
- case 7<<8: // MOVA(opcode & 0xff);
+ case 4 << 8: // MOVBLG(opcode & 0xff);
+ case 5 << 8: // MOVWLG(opcode & 0xff);
+ case 6 << 8: // MOVLLG(opcode & 0xff);
+ case 7 << 8: // MOVA(opcode & 0xff);
desc.regout[0] |= REGFLAG_R(0);
desc.flags |= OPFLAG_READS_MEMORY;
return true;
- case 8<<8: // TSTI(opcode & 0xff);
+ case 8 << 8: // TSTI(opcode & 0xff);
desc.regin[0] |= REGFLAG_R(0);
desc.regin[1] |= REGFLAG_SR;
desc.regout[1] |= REGFLAG_SR;
return true;
- case 9<<8: // ANDI(opcode & 0xff);
- case 10<<8: // XORI(opcode & 0xff);
- case 11<<8: // ORI(opcode & 0xff);
+ case 9 << 8: // ANDI(opcode & 0xff);
+ case 10 << 8: // XORI(opcode & 0xff);
+ case 11 << 8: // ORI(opcode & 0xff);
desc.regin[0] |= REGFLAG_R(0);
desc.regout[0] |= REGFLAG_R(0);
return true;
- case 12<<8: // TSTM(opcode & 0xff);
- case 13<<8: // ANDM(opcode & 0xff);
- case 14<<8: // XORM(opcode & 0xff);
- case 15<<8: // ORM(opcode & 0xff);
+ case 12 << 8: // TSTM(opcode & 0xff);
+ case 13 << 8: // ANDM(opcode & 0xff);
+ case 14 << 8: // XORM(opcode & 0xff);
+ case 15 << 8: // ORM(opcode & 0xff);
desc.regin[0] |= REGFLAG_R(0);
desc.regin[1] |= REGFLAG_SR | REGFLAG_GBR;
desc.regout[1] |= REGFLAG_SR;
@@ -394,7 +393,7 @@ bool sh_frontend::describe_group_0(opcode_desc &desc, const opcode_desc *prev, u
return true;
case 0x02: // STCSR(Rn);
- desc.regout[0] |= REGFLAG_R(Rn);
+ desc.regout[0] |= REGFLAG_R(REG_N);
return true;
case 0x03: // BSRF(Rn);
@@ -418,7 +417,7 @@ bool sh_frontend::describe_group_0(opcode_desc &desc, const opcode_desc *prev, u
case 0x34: // MOVBS0(Rm, Rn);
case 0x35: // MOVWS0(Rm, Rn);
case 0x36: // MOVLS0(Rm, Rn);
- desc.regin[0] |= REGFLAG_R(Rm) | REGFLAG_R(Rn) | REGFLAG_R(0);
+ desc.regin[0] |= REGFLAG_R(REG_M) | REGFLAG_R(REG_N) | REGFLAG_R(0);
desc.flags |= OPFLAG_READS_MEMORY;
return true;
@@ -426,7 +425,7 @@ bool sh_frontend::describe_group_0(opcode_desc &desc, const opcode_desc *prev, u
case 0x17: // MULL(Rm, Rn);
case 0x27: // MULL(Rm, Rn);
case 0x37: // MULL(Rm, Rn);
- desc.regin[0] |= REGFLAG_R(Rn) | REGFLAG_R(Rm);
+ desc.regin[0] |= REGFLAG_R(REG_N) | REGFLAG_R(REG_M);
desc.regout[1] |= REGFLAG_MACL;
desc.cycles = 2;
return true;
@@ -436,7 +435,7 @@ bool sh_frontend::describe_group_0(opcode_desc &desc, const opcode_desc *prev, u
return true;
case 0x0a: // STSMACH(Rn);
- desc.regout[0] |= REGFLAG_R(Rn);
+ desc.regout[0] |= REGFLAG_R(REG_N);
desc.regout[1] |= REGFLAG_MACH;
return true;
@@ -462,8 +461,8 @@ bool sh_frontend::describe_group_0(opcode_desc &desc, const opcode_desc *prev, u
case 0x3c: // MOVBL0(Rm, Rn);
case 0x3d: // MOVWL0(Rm, Rn);
case 0x3e: // MOVLL0(Rm, Rn);
- desc.regin[0] |= REGFLAG_R(Rm) | REGFLAG_R(0);
- desc.regout[0] |= REGFLAG_R(Rn);
+ desc.regin[0] |= REGFLAG_R(REG_M) | REGFLAG_R(0);
+ desc.regout[0] |= REGFLAG_R(REG_N);
desc.flags |= OPFLAG_READS_MEMORY;
return true;
@@ -471,13 +470,13 @@ bool sh_frontend::describe_group_0(opcode_desc &desc, const opcode_desc *prev, u
case 0x1f: // MAC_L(Rm, Rn);
case 0x2f: // MAC_L(Rm, Rn);
case 0x3f: // MAC_L(Rm, Rn);
- desc.regin[0] |= REGFLAG_R(Rm) | REGFLAG_R(Rn);
+ desc.regin[0] |= REGFLAG_R(REG_M) | REGFLAG_R(REG_N);
desc.regout[1] |= REGFLAG_MACL | REGFLAG_MACH;
desc.cycles = 3;
return true;
case 0x12: // STCGBR(Rn);
- desc.regout[0] |= REGFLAG_R(Rn);
+ desc.regout[0] |= REGFLAG_R(REG_N);
desc.regin[1] |= REGFLAG_GBR;
return true;
@@ -491,7 +490,7 @@ bool sh_frontend::describe_group_0(opcode_desc &desc, const opcode_desc *prev, u
case 0x1a: // STSMACL(Rn);
desc.regin[1] |= REGFLAG_MACL;
- desc.regout[0] |= REGFLAG_R(Rn);
+ desc.regout[0] |= REGFLAG_R(REG_N);
return true;
case 0x1b: // SLEEP();
@@ -499,12 +498,12 @@ bool sh_frontend::describe_group_0(opcode_desc &desc, const opcode_desc *prev, u
return true;
case 0x22: // STCVBR(Rn);
- desc.regin[0] |= REGFLAG_R(Rn);
+ desc.regin[0] |= REGFLAG_R(REG_N);
desc.regout[1] |= REGFLAG_VBR;
return true;
case 0x23: // BRAF(Rn);
- desc.regin[0] |= REGFLAG_R(Rm);
+ desc.regin[0] |= REGFLAG_R(REG_M);
desc.flags |= OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE;
desc.targetpc = BRANCH_TARGET_DYNAMIC;
desc.delayslots = 1;
@@ -517,12 +516,12 @@ bool sh_frontend::describe_group_0(opcode_desc &desc, const opcode_desc *prev, u
case 0x29: // MOVT(Rn);
desc.regin[1] |= REGFLAG_SR;
- desc.regout[0] |= REGFLAG_R(Rn);
+ desc.regout[0] |= REGFLAG_R(REG_N);
return true;
case 0x2a: // STSPR(Rn);
desc.regin[1] |= REGFLAG_PR;
- desc.regout[0] |= REGFLAG_R(Rn);
+ desc.regout[0] |= REGFLAG_R(REG_N);
return true;
case 0x2b: // RTE();
@@ -549,35 +548,35 @@ bool sh_frontend::describe_group_4(opcode_desc &desc, const opcode_desc *prev, u
case 0x01: // SHLR(Rn);
case 0x04: // ROTL(Rn);
case 0x05: // ROTR(Rn);
- desc.regin[0] |= REGFLAG_R(Rn);
- desc.regout[0] |= REGFLAG_R(Rn);
+ desc.regin[0] |= REGFLAG_R(REG_N);
+ desc.regout[0] |= REGFLAG_R(REG_N);
desc.regout[1] |= REGFLAG_SR;
return true;
case 0x02: // STSMMACH(Rn);
- desc.regin[0] |= REGFLAG_R(Rn);
+ desc.regin[0] |= REGFLAG_R(REG_N);
desc.regin[1] |= REGFLAG_MACH;
- desc.regout[0] |= REGFLAG_R(Rn);
+ desc.regout[0] |= REGFLAG_R(REG_N);
desc.flags |= OPFLAG_WRITES_MEMORY;
return true;
case 0x03: // STCMSR(Rn);
- desc.regin[0] |= REGFLAG_R(Rn);
- desc.regout[0] |= REGFLAG_R(Rn);
+ desc.regin[0] |= REGFLAG_R(REG_N);
+ desc.regout[0] |= REGFLAG_R(REG_N);
desc.cycles = 2;
desc.flags |= OPFLAG_WRITES_MEMORY;
return true;
case 0x06: // LDSMMACH(Rn);
- desc.regin[0] |= REGFLAG_R(Rn);
- desc.regout[0] |= REGFLAG_R(Rn);
+ desc.regin[0] |= REGFLAG_R(REG_N);
+ desc.regout[0] |= REGFLAG_R(REG_N);
desc.regout[1] |= REGFLAG_MACH;
desc.flags |= OPFLAG_READS_MEMORY;
return true;
case 0x07: // LDCMSR(Rn);
- desc.regin[0] |= REGFLAG_R(Rn);
- desc.regout[0] |= REGFLAG_R(Rn);
+ desc.regin[0] |= REGFLAG_R(REG_N);
+ desc.regout[0] |= REGFLAG_R(REG_N);
desc.regout[1] |= REGFLAG_SR;
desc.cycles = 3;
desc.flags |= OPFLAG_READS_MEMORY | OPFLAG_CAN_EXPOSE_EXTERNAL_INT | OPFLAG_END_SEQUENCE;
@@ -589,17 +588,17 @@ bool sh_frontend::describe_group_4(opcode_desc &desc, const opcode_desc *prev, u
case 0x19: // SHLR8(Rn);
case 0x28: // SHLL16(Rn);
case 0x29: // SHLR16(Rn);
- desc.regin[0] |= REGFLAG_R(Rn);
- desc.regout[0] |= REGFLAG_R(Rn);
+ desc.regin[0] |= REGFLAG_R(REG_N);
+ desc.regout[0] |= REGFLAG_R(REG_N);
return true;
case 0x0a: // LDSMACH(Rn);
- desc.regin[0] |= REGFLAG_R(Rn);
+ desc.regin[0] |= REGFLAG_R(REG_N);
desc.regout[1] |= REGFLAG_MACH;
return true;
case 0x0b: // JSR(Rn);
- desc.regin[0] |= REGFLAG_R(Rn);
+ desc.regin[0] |= REGFLAG_R(REG_N);
desc.regout[1] |= REGFLAG_PR;
desc.flags |= OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE;
desc.targetpc = BRANCH_TARGET_DYNAMIC;
@@ -607,7 +606,7 @@ bool sh_frontend::describe_group_4(opcode_desc &desc, const opcode_desc *prev, u
return true;
case 0x0e: // LDCSR(Rn);
- desc.regin[0] |= REGFLAG_R(Rn);
+ desc.regin[0] |= REGFLAG_R(REG_N);
desc.regout[1] |= REGFLAG_SR;
desc.flags |= OPFLAG_CAN_EXPOSE_EXTERNAL_INT | OPFLAG_END_SEQUENCE;
return true;
@@ -616,62 +615,62 @@ bool sh_frontend::describe_group_4(opcode_desc &desc, const opcode_desc *prev, u
case 0x1f: // MAC_W(Rm, Rn);
case 0x2f: // MAC_W(Rm, Rn);
case 0x3f: // MAC_W(Rm, Rn);
- desc.regin[0] |= REGFLAG_R(Rm) | REGFLAG_R(Rn);
+ desc.regin[0] |= REGFLAG_R(REG_M) | REGFLAG_R(REG_N);
desc.regin[1] |= REGFLAG_MACL | REGFLAG_MACH;
- desc.regout[0] |= REGFLAG_R(Rm) | REGFLAG_R(Rn);
+ desc.regout[0] |= REGFLAG_R(REG_M) | REGFLAG_R(REG_N);
desc.regout[1] |= REGFLAG_MACL | REGFLAG_MACH;
desc.cycles = 3;
return true;
case 0x10: // DT(Rn);
- desc.regin[0] |= REGFLAG_R(Rn);
+ desc.regin[0] |= REGFLAG_R(REG_N);
desc.regin[1] |= REGFLAG_SR;
- desc.regout[0] |= REGFLAG_R(Rn);
+ desc.regout[0] |= REGFLAG_R(REG_N);
desc.regout[1] |= REGFLAG_SR;
return true;
case 0x11: // CMPPZ(Rn);
case 0x15: // CMPPL(Rn);
- desc.regin[0] |= REGFLAG_R(Rn);
+ desc.regin[0] |= REGFLAG_R(REG_N);
desc.regin[1] |= REGFLAG_SR;
desc.regout[1] |= REGFLAG_SR;
return true;
case 0x12: // STSMMACL(Rn);
- desc.regin[0] |= REGFLAG_R(Rn);
+ desc.regin[0] |= REGFLAG_R(REG_N);
desc.regin[1] |= REGFLAG_MACL;
- desc.regout[0] |= REGFLAG_R(Rn);
+ desc.regout[0] |= REGFLAG_R(REG_N);
desc.flags |= OPFLAG_WRITES_MEMORY;
return true;
case 0x13: // STCMGBR(Rn);
- desc.regin[0] |= REGFLAG_R(Rn);
+ desc.regin[0] |= REGFLAG_R(REG_N);
desc.regin[1] |= REGFLAG_GBR;
- desc.regout[0] |= REGFLAG_R(Rn);
+ desc.regout[0] |= REGFLAG_R(REG_N);
desc.flags |= OPFLAG_WRITES_MEMORY;
return true;
case 0x16: // LDSMMACL(Rn);
- desc.regin[0] |= REGFLAG_R(Rm) | REGFLAG_R(Rn);
- desc.regout[0] |= REGFLAG_R(Rm) | REGFLAG_R(Rn);
+ desc.regin[0] |= REGFLAG_R(REG_M) | REGFLAG_R(REG_N);
+ desc.regout[0] |= REGFLAG_R(REG_M) | REGFLAG_R(REG_N);
desc.regout[1] |= REGFLAG_MACL;
desc.flags |= OPFLAG_READS_MEMORY;
return true;
case 0x17: // LDCMGBR(Rn);
- desc.regin[0] |= REGFLAG_R(Rn);
- desc.regout[0] |= REGFLAG_R(Rn);
+ desc.regin[0] |= REGFLAG_R(REG_N);
+ desc.regout[0] |= REGFLAG_R(REG_N);
desc.regout[1] |= REGFLAG_GBR;
desc.flags |= OPFLAG_READS_MEMORY;
return true;
case 0x1a: // LDSMACL(Rn);
- desc.regin[0] |= REGFLAG_R(Rn);
+ desc.regin[0] |= REGFLAG_R(REG_N);
desc.regout[1] |= REGFLAG_MACL;
return true;
case 0x1b: // TAS(Rn);
- desc.regin[0] |= REGFLAG_R(Rn);
+ desc.regin[0] |= REGFLAG_R(REG_N);
desc.regin[1] |= REGFLAG_SR;
desc.regout[1] |= REGFLAG_SR;
desc.cycles = 4;
@@ -679,67 +678,67 @@ bool sh_frontend::describe_group_4(opcode_desc &desc, const opcode_desc *prev, u
return true;
case 0x1e: // LDCGBR(Rn);
- desc.regin[0] |= REGFLAG_R(Rn);
+ desc.regin[0] |= REGFLAG_R(REG_N);
desc.regout[1] |= REGFLAG_GBR;
return true;
case 0x20: // SHAL(Rn);
case 0x21: // SHAR(Rn);
- desc.regin[0] |= REGFLAG_R(Rn);
- desc.regout[0] |= REGFLAG_R(Rn);
+ desc.regin[0] |= REGFLAG_R(REG_N);
+ desc.regout[0] |= REGFLAG_R(REG_N);
desc.regout[1] |= REGFLAG_SR;
return true;
case 0x22: // STSMPR(Rn);
- desc.regin[0] |= REGFLAG_R(Rn);
+ desc.regin[0] |= REGFLAG_R(REG_N);
desc.regin[1] |= REGFLAG_PR;
- desc.regout[0] |= REGFLAG_R(Rn);
+ desc.regout[0] |= REGFLAG_R(REG_N);
desc.flags |= OPFLAG_WRITES_MEMORY;
return true;
case 0x23: // STCMVBR(Rn);
- desc.regin[0] |= REGFLAG_R(Rn);
+ desc.regin[0] |= REGFLAG_R(REG_N);
desc.regin[1] |= REGFLAG_VBR;
- desc.regout[0] |= REGFLAG_R(Rn);
+ desc.regout[0] |= REGFLAG_R(REG_N);
desc.flags |= OPFLAG_WRITES_MEMORY;
return true;
case 0x24: // ROTCL(Rn);
case 0x25: // ROTCR(Rn);
- desc.regin[0] |= REGFLAG_R(Rn);
+ desc.regin[0] |= REGFLAG_R(REG_N);
desc.regin[1] |= REGFLAG_SR;
- desc.regout[0] |= REGFLAG_R(Rn);
+ desc.regout[0] |= REGFLAG_R(REG_N);
desc.regout[1] |= REGFLAG_SR;
return true;
case 0x26: // LDSMPR(Rn);
- desc.regin[0] |= REGFLAG_R(Rn);
- desc.regout[0] |= REGFLAG_R(Rn);
+ desc.regin[0] |= REGFLAG_R(REG_N);
+ desc.regout[0] |= REGFLAG_R(REG_N);
desc.regout[1] |= REGFLAG_PR;
desc.flags |= OPFLAG_READS_MEMORY;
return true;
case 0x27: // LDCMVBR(Rn);
- desc.regin[0] |= REGFLAG_R(Rn);
- desc.regout[0] |= REGFLAG_R(Rn);
+ desc.regin[0] |= REGFLAG_R(REG_N);
+ desc.regout[0] |= REGFLAG_R(REG_N);
desc.regout[1] |= REGFLAG_VBR;
desc.flags |= OPFLAG_READS_MEMORY;
return true;
case 0x2a: // LDSPR(Rn);
- desc.regin[0] |= REGFLAG_R(Rn);
+ desc.regin[0] |= REGFLAG_R(REG_N);
desc.regout[1] |= REGFLAG_PR;
return true;
case 0x2b: // JMP(Rm);
- desc.regin[0] |= REGFLAG_R(Rm);
+ desc.regin[0] |= REGFLAG_R(REG_M);
desc.flags |= OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE;
desc.targetpc = BRANCH_TARGET_DYNAMIC;
desc.delayslots = 1;
return true;
case 0x2e: // LDCVBR(Rn);
- desc.regin[0] |= REGFLAG_R(Rn);
+ desc.regin[0] |= REGFLAG_R(REG_N);
desc.regout[1] |= REGFLAG_VBR;
return true;
diff --git a/src/devices/cpu/sh/sh_intc.cpp b/src/devices/cpu/sh/sh_intc.cpp
new file mode 100644
index 00000000000..989cc8d62a1
--- /dev/null
+++ b/src/devices/cpu/sh/sh_intc.cpp
@@ -0,0 +1,151 @@
+// 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")
+
+const u8 sh_intc_device::pribit[0x100] = {
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 8, 8, 8, 9, 9, 9, 9,
+ 10, 10, 10, 10, 11, 11, 11, 11, 12, 12, 12, 12, 13, 13, 13, 13,
+ 14, 14, 14, 14, 15, 15, 15, 15, 16, 16, 16, 16, 17, 17, 17, 17,
+ 18, 18, 18, 18, 19, 19, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21,
+ 22, 22, 22, 22, 23, 23, 23, 23, 24, 24, 24, 24, 25, 25, 25, 25,
+ 26, 26, 26, 26, 27, 27, 27, 27, 28, 28, 28, 28, 29, 29, 29, 29,
+ 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
+ 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
+ 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
+ 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
+ 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
+ 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
+};
+
+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()
+{
+ save_item(NAME(m_ipr));
+ save_item(NAME(m_icr));
+ save_item(NAME(m_isr));
+ save_item(NAME(m_pending));
+ save_item(NAME(m_lines));
+
+ std::fill(m_ipr.begin(), m_ipr.end(), 0);
+ m_isr = 0;
+ m_icr = 0;
+ m_lines = 0;
+}
+
+void sh_intc_device::device_reset()
+{
+ std::fill(m_pending.begin(), m_pending.end(), 0);
+}
+
+void sh_intc_device::interrupt_taken(int irqline, int vector)
+{
+ // Don't clear an external interrupt which is level and still active
+ if(vector < 64 || vector >= 72 || BIT(m_icr, 7-(vector & 7)) || !BIT(m_lines, vector & 7))
+ m_pending[vector >> 5] &= ~(1 << (vector & 31));
+
+ update_irq();
+}
+
+void sh_intc_device::update_irq()
+{
+ int best_level = -1;
+ int best_vector = 0;
+
+ for(u32 bv = 64/32; bv != 160/32; bv ++) {
+ if(!m_pending[bv])
+ continue;
+ for(u32 iv = 0; iv != 32; iv++) {
+ if(!BIT(m_pending[bv], iv))
+ continue;
+ u32 vector = bv*32 + iv;
+ u32 slot = pribit[vector];
+ u32 shift = 12-4*(slot & 3);
+ int level = (m_ipr[slot >> 2] >> shift) & 15;
+ if(level > best_level) {
+ best_level = level;
+ best_vector = vector;
+ }
+ }
+ }
+ m_cpu->set_internal_interrupt(best_level, best_vector);
+}
+
+void sh_intc_device::internal_interrupt(int vector)
+{
+ m_pending[vector >> 5] |= 1 << (vector & 31);
+ update_irq();
+}
+
+void sh_intc_device::set_input(int inputnum, int state)
+{
+ if(BIT(m_lines, inputnum) == state)
+ return;
+ if(BIT(m_icr, 7-inputnum)) {
+ // Level interrupt
+ if(state)
+ m_pending[64 >> 5] |= 1 << inputnum;
+ else
+ m_pending[64 >> 5] &= ~(1 << inputnum);
+ } else {
+ // Edge interrupt
+ if(state)
+ m_pending[64 >> 5] |= 1 << inputnum;
+ }
+ update_irq();
+}
+
+u16 sh_intc_device::icr_r()
+{
+ return m_icr;
+}
+
+void sh_intc_device::icr_w(offs_t, u16 data, u16 mem_mask)
+{
+ COMBINE_DATA(&m_icr);
+ logerror("icr_w %04x @ %04x\n", data, mem_mask);
+}
+
+u16 sh_intc_device::isr_r()
+{
+ return m_isr;
+}
+
+void sh_intc_device::isr_w(offs_t, u16 data, u16 mem_mask)
+{
+ COMBINE_DATA(&m_isr);
+ logerror("isr_w %04x @ %04x\n", data, mem_mask);
+}
+
+u16 sh_intc_device::ipr_r(offs_t offset)
+{
+ return m_ipr[offset];
+}
+
+void sh_intc_device::ipr_w(offs_t offset, u16 data, u16 mem_mask)
+{
+ COMBINE_DATA(&m_ipr[offset]);
+ 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..9a743f4e778
--- /dev/null
+++ b/src/devices/cpu/sh/sh_intc.h
@@ -0,0 +1,58 @@
+// 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));
+ }
+
+ void interrupt_taken(int irqline, 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:
+ static const u8 pribit[256];
+
+ std::array<u32, 8> m_pending;
+ std::array<u16, 8> m_ipr;
+
+ u16 m_isr, m_icr;
+
+ u8 m_lines;
+
+ required_device<sh7042_device> m_cpu;
+
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+
+ void update_irq();
+};
+
+DECLARE_DEVICE_TYPE(SH_INTC, sh_intc_device)
+
+#endif // MAME_CPU_SH_SH_INTC_H
diff --git a/src/devices/cpu/sh/sh_mtu.cpp b/src/devices/cpu/sh/sh_mtu.cpp
new file mode 100644
index 00000000000..532a47da5a8
--- /dev/null
+++ b/src/devices/cpu/sh/sh_mtu.cpp
@@ -0,0 +1,529 @@
+// license:BSD-3-Clause
+// copyright-holders:Olivier Galibert
+/***************************************************************************
+
+ sh_mtu.h
+
+ SH DMA controller
+
+***************************************************************************/
+
+#include "emu.h"
+#include "sh_mtu.h"
+#include "sh7042.h"
+
+#define V 1
+
+DEFINE_DEVICE_TYPE(SH_MTU, sh_mtu_device, "sh_mtu", "SH Multifuntion timer pulse unit")
+DEFINE_DEVICE_TYPE(SH_MTU_CHANNEL, sh_mtu_channel_device, "sh_mtu_channel", "SH Multifuntion timer pulse unit channel")
+
+sh_mtu_device::sh_mtu_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) :
+ device_t(mconfig, SH_MTU, tag, owner, clock),
+ m_cpu(*this, finder_base::DUMMY_TAG),
+ m_timer_channel(*this, "%u", 0)
+{
+}
+
+void sh_mtu_device::device_start()
+{
+ save_item(NAME(m_tstr));
+ save_item(NAME(m_tsyr));
+ save_item(NAME(m_toer));
+ save_item(NAME(m_tocr));
+ save_item(NAME(m_tgcr));
+ save_item(NAME(m_tcdr));
+ save_item(NAME(m_tddr));
+ save_item(NAME(m_tcnts));
+ save_item(NAME(m_tcbr));
+}
+
+void sh_mtu_device::device_reset()
+{
+ m_tstr = 0;
+ m_tsyr = 0;
+ m_toer = 0xc0;
+ m_tocr = 0;
+ m_tgcr = 0x80;
+ m_tcdr = 0xffff;
+ m_tddr = 0xffff;
+ m_tcnts = 0;
+ m_tcbr = 0xffff;
+}
+
+u8 sh_mtu_device::tstr_r()
+{
+ logerror("tstr_r\n");
+ return m_tstr;
+}
+
+void sh_mtu_device::tstr_w(u8 data)
+{
+ m_tstr = data;
+ logerror("tstr_w %02x\n", m_tstr);
+ // To generalize
+ m_timer_channel[0]->set_enable(BIT(m_tstr, 0));
+ m_timer_channel[1]->set_enable(BIT(m_tstr, 1));
+ m_timer_channel[2]->set_enable(BIT(m_tstr, 2));
+ m_timer_channel[3]->set_enable(BIT(m_tstr, 6));
+ m_timer_channel[4]->set_enable(BIT(m_tstr, 7));
+}
+
+u8 sh_mtu_device::tsyr_r()
+{
+ logerror("tsyr_r\n");
+ return m_tsyr;
+}
+
+void sh_mtu_device::tsyr_w(u8 data)
+{
+ m_tsyr = data;
+ logerror("tsyr_w %02x\n", m_tsyr);
+}
+
+u8 sh_mtu_device::toer_r()
+{
+ logerror("toer_r\n");
+ return m_toer;
+}
+
+void sh_mtu_device::toer_w(u8 data)
+{
+ m_toer = data;
+ logerror("toer_w %02x\n", m_toer);
+}
+
+u8 sh_mtu_device::tocr_r()
+{
+ logerror("tocr_r\n");
+ return m_tocr;
+}
+
+void sh_mtu_device::tocr_w(u8 data)
+{
+ m_tocr = data;
+ logerror("tocr_w %02x\n", m_tocr);
+}
+
+u8 sh_mtu_device::tgcr_r()
+{
+ logerror("tgcr_r\n");
+ return m_tgcr;
+}
+
+void sh_mtu_device::tgcr_w(u8 data)
+{
+ m_tgcr = data;
+ logerror("tgcr_w %02x\n", m_tgcr);
+}
+
+u16 sh_mtu_device::tcdr_r()
+{
+ logerror("tcdr_r\n");
+ return m_tcdr;
+}
+
+void sh_mtu_device::tcdr_w(offs_t, u16 data, u16 mem_mask)
+{
+ COMBINE_DATA(&m_tcdr);
+ logerror("tcdr_w %04x\n", m_tcdr);
+}
+
+u16 sh_mtu_device::tddr_r()
+{
+ logerror("tddr_r\n");
+ return m_tddr;
+}
+
+void sh_mtu_device::tddr_w(offs_t, u16 data, u16 mem_mask)
+{
+ COMBINE_DATA(&m_tddr);
+ logerror("tddr_w %04x\n", m_tddr);
+}
+
+u16 sh_mtu_device::tcnts_r()
+{
+ logerror("tcnts_r\n");
+ return m_tcnts;
+}
+
+void sh_mtu_device::tcnts_w(offs_t, u16 data, u16 mem_mask)
+{
+ COMBINE_DATA(&m_tcnts);
+ logerror("tcnts_w %04x\n", m_tcnts);
+}
+
+u16 sh_mtu_device::tcbr_r()
+{
+ logerror("tcbr_r\n");
+ return m_tcbr;
+}
+
+void sh_mtu_device::tcbr_w(offs_t, u16 data, u16 mem_mask)
+{
+ COMBINE_DATA(&m_tcbr);
+ logerror("tcbr_w %04x\n", m_tcbr);
+}
+
+sh_mtu_channel_device::sh_mtu_channel_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) :
+ device_t(mconfig, SH_MTU_CHANNEL, tag, owner, clock),
+ m_cpu(*this, finder_base::DUMMY_TAG),
+ m_intc(*this, finder_base::DUMMY_TAG),
+ m_chained_timer(*this, finder_base::DUMMY_TAG)
+{
+}
+
+void sh_mtu_channel_device::device_start()
+{
+ m_channel_active = false;
+ device_reset();
+
+ save_item(NAME(m_tgr_count));
+ save_item(NAME(m_tbr_count));
+ save_item(NAME(m_tgr_clearing));
+ save_item(NAME(m_tcr));
+ save_item(NAME(m_tmdr));
+ save_item(NAME(m_tior));
+ save_item(NAME(m_tier));
+ save_item(NAME(m_tsr));
+ save_item(NAME(m_clock_type));
+ save_item(NAME(m_clock_divider));
+ save_item(NAME(m_tcnt));
+ save_item(NAME(m_tgr));
+ save_item(NAME(m_last_clock_update));
+ save_item(NAME(m_event_time));
+ save_item(NAME(m_phase));
+ save_item(NAME(m_counter_cycle));
+ save_item(NAME(m_counter_incrementing));
+ save_item(NAME(m_channel_active));
+
+ m_tsr = 0xc0;
+}
+
+void sh_mtu_channel_device::device_reset()
+{
+ // Don't touch channel_active here, top level device handles it.
+
+ m_tbr_count = 0;
+ m_tgr_clearing = TGR_CLEAR_NONE;
+ m_tcr = 0;
+ m_tmdr = 0xc0;
+ m_tior = 0;
+ m_tier = 0x40 & m_tier_mask;
+ m_clock_type = DIV_1;
+ m_clock_divider = 0;
+ m_tcnt = 0;
+ std::fill(m_tgr.begin(), m_tgr.end(), 0xffff);
+ m_last_clock_update = 0;
+ m_event_time = 0;
+ m_phase = 0;
+ m_counter_cycle = 1;
+ m_counter_incrementing = true;
+}
+
+u8 sh_mtu_channel_device::tcr_r()
+{
+ return m_tcr;
+}
+
+void sh_mtu_channel_device::tcr_w(u8 data)
+{
+ update_counter();
+ m_tcr = data;
+ logerror("tcr_w %02x\n", m_tcr);
+ switch(m_tcr & 0x60) {
+ case 0x00:
+ m_tgr_clearing = TGR_CLEAR_NONE;
+ if(V>=1) logerror("No automatic tcnt clearing\n");
+ break;
+ case 0x20: case 0x40: {
+ m_tgr_clearing = m_tcr & 0x20 ? 0 : 1;
+ if(m_tgr_count > 2 && (m_tcr & 0x80))
+ m_tgr_clearing += 2;
+ if(V>=1) logerror("Auto-clear on tgr%c\n", 'a'+m_tgr_clearing);
+ break;
+ }
+ case 0x60:
+ m_tgr_clearing = TGR_CLEAR_EXT;
+ if(V>=1) logerror("External sync clear\n");
+ break;
+ }
+
+ int count_type = m_count_types[m_tcr & 7];
+ if(count_type >= DIV_1 && m_clock_type <= DIV_4) {
+ m_clock_type = DIV_1;
+ m_clock_divider = count_type - DIV_1;
+ if(V>=1) logerror("clock divider %d (%d)\n", m_clock_divider, 1 << m_clock_divider);
+ if(!m_clock_divider)
+ m_phase = 0;
+ else {
+ switch(m_tcr & 0x18) {
+ case 0x00:
+ m_phase = 0;
+ if(V>=1) logerror("Phase 0\n");
+ break;
+ case 0x08:
+ m_phase = 1 << (m_clock_divider-1);
+ if(V>=1) logerror("Phase 180\n");
+ break;
+ case 0x10: case 0x18:
+ m_phase = 0;
+ m_clock_divider--;
+ if(V>=1) logerror("Phase 0+180\n");
+ break;
+ }
+ }
+
+ } else if(count_type == CHAIN) {
+ m_clock_type = CHAIN;
+ m_clock_divider = 0;
+ m_phase = 0;
+ if(V>=1) logerror("chained timer\n");
+
+ } else if(count_type >= INPUT_A && count_type <= INPUT_D) {
+ m_clock_type = count_type;
+ m_clock_divider = 0;
+ m_phase = 0;
+ if(V>=1) logerror("counting input %c\n", 'a'+count_type-INPUT_A);
+ }
+ recalc_event();
+}
+
+u8 sh_mtu_channel_device::tmdr_r()
+{
+ return m_tmdr;
+}
+
+void sh_mtu_channel_device::tmdr_w(u8 data)
+{
+ m_tmdr = data;
+ logerror("tmdr_w %02x\n", m_tmdr);
+}
+
+u8 sh_mtu_channel_device::tior_r()
+{
+ return m_tior;
+}
+
+void sh_mtu_channel_device::tior_w(u8 data)
+{
+ m_tior = data;
+}
+
+u8 sh_mtu_channel_device::tier_r()
+{
+ return m_tier;
+}
+
+void sh_mtu_channel_device::tier_w(u8 data)
+{
+ update_counter();
+ m_tier = data;
+ if(0)
+ logerror("irq %c%c%c%c%c%c\n",
+ m_tier & IRQ_A ? 'a' : '.',
+ m_tier & IRQ_B ? 'b' : '.',
+ m_tier & IRQ_C ? 'c' : '.',
+ m_tier & IRQ_D ? 'd' : '.',
+ m_tier & IRQ_V ? 'v' : '.',
+ m_tier & IRQ_U ? 'u' : '.');
+ recalc_event();
+}
+
+u8 sh_mtu_channel_device::tsr_r()
+{
+ return m_tsr;
+}
+
+void sh_mtu_channel_device::tsr_w(u8 data)
+{
+ update_counter();
+ m_tsr = (data & 0x80) | (m_tsr & ~data & 0x7f);
+ recalc_event();
+}
+
+u16 sh_mtu_channel_device::tcnt_r()
+{
+ if(!machine().side_effects_disabled())
+ update_counter();
+ // Need to implement phase counting for the rotary controller on the psr540
+ if(m_tmdr & 0xf)
+ return 0;
+ return m_tcnt;
+}
+
+void sh_mtu_channel_device::tcnt_w(offs_t, u16 data, u16 mem_mask)
+{
+ update_counter();
+ COMBINE_DATA(&m_tcnt);
+ recalc_event();
+}
+
+u16 sh_mtu_channel_device::tgr_r(offs_t reg)
+{
+ return m_tgr[reg];
+}
+
+void sh_mtu_channel_device::tgr_w(offs_t reg, u16 data, u16 mem_mask)
+{
+ update_counter();
+ COMBINE_DATA(&m_tgr[reg]);
+ recalc_event();
+}
+
+u16 sh_mtu_channel_device::tgrc_r(offs_t reg)
+{
+ return tgr_r(reg + 2);
+}
+
+void sh_mtu_channel_device::tgrc_w(offs_t reg, u16 data, u16 mem_mask)
+{
+ tgr_w(reg + 2, data, mem_mask);
+}
+
+void sh_mtu_channel_device::set_enable(bool enable)
+{
+ update_counter();
+ m_channel_active = enable;
+ if(enable)
+ logerror("enabled\n");
+ else
+ logerror("disabled\n");
+ recalc_event();
+}
+
+u64 sh_mtu_channel_device::internal_update(u64 current_time)
+{
+ while(m_event_time && current_time >= m_event_time) {
+ update_counter(m_event_time);
+ recalc_event(m_event_time);
+ }
+
+ return m_event_time;
+}
+
+void sh_mtu_channel_device::recalc_event(u64 cur_time)
+{
+ if(!m_channel_active) {
+ m_event_time = 0;
+ return;
+ }
+
+ bool update_cpu = cur_time == 0;
+ u64 old_event_time = m_event_time;
+
+ if(m_clock_type != DIV_1) {
+ m_event_time = 0;
+ if(old_event_time && update_cpu)
+ m_cpu->internal_update();
+
+ return;
+ }
+
+ if(!cur_time)
+ cur_time = m_cpu->current_cycles();
+
+ if(m_counter_incrementing) {
+ u32 event_delay = 0xffffffff;
+ if(m_tgr_clearing >= 0)
+ m_counter_cycle = m_tgr[m_tgr_clearing] + 1;
+ else
+ m_counter_cycle = 0x10000;
+ if((m_tier & IRQ_V && m_interrupt[4] != -1) && (m_counter_cycle == 0x10000 || m_tcnt >= m_counter_cycle))
+ event_delay = 0x10000 - m_tcnt;
+
+ for(int i = 0; i < m_tgr_count; i++)
+ if(BIT(m_tier, i) && m_interrupt[i] != -1) {
+ u32 new_delay = 0xffffffff;
+ u16 cmp = m_tgr[i] + 1;
+ if(cmp > m_tcnt) {
+ if(m_tcnt >= m_counter_cycle || cmp <= m_counter_cycle)
+ new_delay = cmp - m_tcnt;
+ } else if(cmp <= m_counter_cycle) {
+ if(m_tcnt < m_counter_cycle)
+ new_delay = (m_counter_cycle - m_tcnt) + cmp;
+ else
+ new_delay = (0x10000 - m_tcnt) + cmp;
+ }
+
+ if(event_delay > new_delay)
+ event_delay = new_delay;
+ }
+ if(event_delay != 0xffffffff)
+ m_event_time = ((((cur_time + (1ULL << m_clock_divider) - m_phase) >> m_clock_divider) + event_delay - 1) << m_clock_divider) + m_phase;
+ else
+ m_event_time = 0;
+ } else {
+ logerror("decrementing counter\n");
+ exit(1);
+ }
+
+ if(old_event_time != m_event_time && update_cpu)
+ m_cpu->internal_update();
+}
+
+void sh_mtu_channel_device::update_counter(u64 cur_time)
+{
+ if(m_clock_type != DIV_1)
+ return;
+
+ if(!cur_time)
+ cur_time = m_cpu->current_cycles();
+
+ if(!m_channel_active) {
+ m_last_clock_update = cur_time;
+ return;
+ }
+
+ u64 base_time = m_last_clock_update;
+ m_last_clock_update = cur_time;
+ u64 new_time = cur_time;
+ if(m_clock_divider) {
+ base_time = (base_time + m_phase) >> m_clock_divider;
+ new_time = (new_time + m_phase) >> m_clock_divider;
+ }
+ if(new_time == base_time)
+ return;
+
+ if(m_counter_incrementing) {
+ u16 prev = m_tcnt;
+ u64 delta = new_time - base_time;
+ u64 tt = m_tcnt + delta;
+
+ if(prev >= m_counter_cycle) {
+ if(tt >= 0x10000)
+ m_tcnt = (tt - 0x10000) % m_counter_cycle;
+ else
+ m_tcnt = tt;
+ } else
+ m_tcnt = tt % m_counter_cycle;
+
+ for(int i = 0; i < m_tgr_count; i++) {
+ u16 cmp = m_tgr[i] + 1;
+ bool match = m_tcnt == cmp || (tt == cmp && tt == m_counter_cycle);
+ if(!match) {
+ // Need to do additional checks here for software that polls the flags with interrupts disabled, since recalc_event only schedules IRQ events.
+ if(prev >= m_counter_cycle)
+ match = (cmp > prev && tt >= cmp) || (cmp <= m_counter_cycle && m_tcnt < m_counter_cycle && (delta - (0x10000 - prev)) >= cmp);
+ else if(cmp <= m_counter_cycle)
+ match = delta >= m_counter_cycle || (prev < cmp && tt >= cmp) || (m_tcnt <= prev && m_tcnt >= cmp);
+
+ if(match && BIT(m_tier, i) && m_interrupt[i] != -1)
+ logerror("update_counter unexpected TGR %d IRQ\n", i);
+ }
+
+ if(match) {
+ m_tsr |= 1 << i;
+ if(BIT(m_tier, i) && m_interrupt[i] != -1)
+ m_intc->internal_interrupt(m_interrupt[i]);
+ }
+ }
+ if(tt >= 0x10000 && (m_counter_cycle == 0x10000 || prev >= m_counter_cycle)) {
+ m_tsr |= IRQ_V;
+ if(m_tier & IRQ_V && m_interrupt[4] != -1)
+ m_intc->internal_interrupt(m_interrupt[4]);
+ }
+ } else {
+ logerror("decrementing counter\n");
+ exit(1);
+ }
+}
diff --git a/src/devices/cpu/sh/sh_mtu.h b/src/devices/cpu/sh/sh_mtu.h
new file mode 100644
index 00000000000..7d1a9be9d6e
--- /dev/null
+++ b/src/devices/cpu/sh/sh_mtu.h
@@ -0,0 +1,182 @@
+// license:BSD-3-Clause
+// copyright-holders:Olivier Galibert
+/***************************************************************************
+
+ sh_mtu.h
+
+ SH Multifunction timer pulse unit
+
+***************************************************************************/
+
+#ifndef MAME_CPU_SH_SH_MTU_H
+#define MAME_CPU_SH_SH_MTU_H
+
+#pragma once
+
+// To generalize eventually
+class sh7042_device;
+class sh_intc_device;
+
+class sh_mtu_channel_device : public device_t {
+public:
+ enum {
+ CHAIN,
+ INPUT_A,
+ INPUT_B,
+ INPUT_C,
+ INPUT_D,
+ DIV_1,
+ DIV_2,
+ DIV_4,
+ DIV_8,
+ DIV_16,
+ DIV_32,
+ DIV_64,
+ DIV_128,
+ DIV_256,
+ DIV_512,
+ DIV_1024,
+ DIV_2048,
+ DIV_4096
+ };
+
+ enum {
+ TGR_CLEAR_NONE = -1,
+ TGR_CLEAR_EXT = -2
+ };
+
+ enum {
+ IRQ_A = 0x01,
+ IRQ_B = 0x02,
+ IRQ_C = 0x04,
+ IRQ_D = 0x08,
+ IRQ_V = 0x10,
+ IRQ_U = 0x20,
+ IRQ_E = 0x80
+ };
+
+ sh_mtu_channel_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock = 0);
+
+ template <typename T, typename U> sh_mtu_channel_device(const machine_config &mconfig, const char *tag, device_t *owner, T &&cpu, int tgr_count, int tier_mask, U &&intc, int irq_base,
+ int t0, int t1, int t2, int t3, int t4, int t5, int t6, int t7)
+ : sh_mtu_channel_device(mconfig, tag, owner)
+ {
+ set_info(cpu, intc);
+ m_tgr_count = tgr_count;
+ m_tbr_count = 0;
+ m_tier_mask = tier_mask;
+
+ m_interrupt[0] = irq_base;
+ m_interrupt[1] = irq_base + 1;
+ m_interrupt[2] = tier_mask & 0x04 ? -1 : irq_base + 2;
+ m_interrupt[3] = tier_mask & 0x08 ? -1 : irq_base + 3;
+ m_interrupt[4] = irq_base + 4;
+ m_interrupt[5] = tier_mask & 0x20 ? -1 : irq_base + 5;
+
+ m_count_types[0] = t0;
+ m_count_types[1] = t1;
+ m_count_types[2] = t2;
+ m_count_types[3] = t3;
+ m_count_types[4] = t4;
+ m_count_types[5] = t5;
+ m_count_types[6] = t6;
+ m_count_types[7] = t7;
+ }
+
+ template<typename T, typename U> void set_info(T &&cpu, U &&intc) { m_cpu.set_tag(std::forward<T>(cpu)); m_intc.set_tag(std::forward<U>(intc)); }
+ template<typename T> void set_chain(T &&chain) { m_chained_timer.set_tag(std::forward<T>(chain)); }
+
+ u8 tcr_r();
+ void tcr_w(u8 data);
+ u8 tmdr_r();
+ void tmdr_w(u8 data);
+ u8 tior_r();
+ void tior_w(u8 data);
+ u8 tier_r();
+ void tier_w(u8 data);
+ u8 tsr_r();
+ void tsr_w(u8 data);
+ u16 tcnt_r();
+ void tcnt_w(offs_t, u16 data, u16 mem_mask);
+ u16 tgr_r(offs_t reg);
+ void tgr_w(offs_t reg, u16 data, u16 mem_mask);
+ u16 tgrc_r(offs_t reg);
+ void tgrc_w(offs_t reg, u16 data, u16 mem_mask);
+
+ void set_enable(bool enable);
+ u64 internal_update(u64 current_time);
+
+protected:
+ required_device<sh7042_device> m_cpu;
+ required_device<sh_intc_device> m_intc;
+ optional_device<sh_mtu_channel_device> m_chained_timer;
+ int m_interrupt[6];
+ u8 m_tier_mask;
+
+ int m_tgr_count, m_tbr_count;
+ int m_tgr_clearing;
+ u8 m_tcr, m_tmdr, m_tior, m_tier, m_tsr;
+ int m_clock_type, m_clock_divider;
+ u16 m_tcnt;
+ std::array<u16, 4> m_tgr;
+ u64 m_last_clock_update, m_event_time;
+ u32 m_phase, m_counter_cycle;
+ bool m_counter_incrementing;
+ bool m_channel_active;
+ std::array<int, 8> m_count_types;
+
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+ void update_counter(u64 cur_time = 0);
+ void recalc_event(u64 cur_time = 0);
+};
+
+class sh_mtu_device : public device_t {
+public:
+ sh_mtu_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock = 0);
+
+ template <typename T> sh_mtu_device(const machine_config &mconfig, const char *tag, device_t *owner, T &&cpu, int timer_count)
+ : sh_mtu_device(mconfig, tag, owner)
+ {
+ set_info(cpu);
+ m_timer_count = timer_count;
+ }
+
+ template<typename T> void set_info(T &&cpu) { m_cpu.set_tag(std::forward<T>(cpu)); }
+
+ u8 tstr_r();
+ void tstr_w(u8 data);
+ u8 tsyr_r();
+ void tsyr_w(u8 data);
+ u8 toer_r();
+ void toer_w(u8 data);
+ u8 tocr_r();
+ void tocr_w(u8 data);
+ u8 tgcr_r();
+ void tgcr_w(u8 data);
+ u16 tcdr_r();
+ void tcdr_w(offs_t, u16 data, u16 mem_mask);
+ u16 tddr_r();
+ void tddr_w(offs_t, u16 data, u16 mem_mask);
+ u16 tcnts_r();
+ void tcnts_w(offs_t, u16 data, u16 mem_mask);
+ u16 tcbr_r();
+ void tcbr_w(offs_t, u16 data, u16 mem_mask);
+
+protected:
+ required_device<sh7042_device> m_cpu;
+ required_device_array<sh_mtu_channel_device, 5> m_timer_channel;
+
+ int m_timer_count;
+
+ u8 m_tstr, m_tsyr, m_toer, m_tocr, m_tgcr;
+ u16 m_tcdr, m_tddr, m_tcnts, m_tcbr;
+
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+};
+
+DECLARE_DEVICE_TYPE(SH_MTU, sh_mtu_device)
+DECLARE_DEVICE_TYPE(SH_MTU_CHANNEL, sh_mtu_channel_device)
+
+#endif
diff --git a/src/devices/cpu/sh/sh_port.cpp b/src/devices/cpu/sh/sh_port.cpp
new file mode 100644
index 00000000000..2cf5735826b
--- /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..45f7d14feaf
--- /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 ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+};
+
+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 ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+};
+
+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/devices/cpu/sh/sh_sci.cpp b/src/devices/cpu/sh/sh_sci.cpp
new file mode 100644
index 00000000000..edb35d84489
--- /dev/null
+++ b/src/devices/cpu/sh/sh_sci.cpp
@@ -0,0 +1,765 @@
+// license:BSD-3-Clause
+// copyright-holders:Olivier Galibert
+
+#include "emu.h"
+#include "sh_sci.h"
+#include "sh7042.h"
+#include "sh_intc.h"
+
+#define LOG_REGS (1 << 1U) // Register writes
+#define LOG_RREGS (1 << 2U) // Register reads
+#define LOG_RATE (1 << 3U) // Bitrate setting
+#define LOG_DATA (1 << 4U) // Bytes transmitted
+#define LOG_CLOCK (1 << 5U) // Clock and transmission start/stop
+#define LOG_STATE (1 << 6U) // State machine states
+#define LOG_TICK (1 << 7U) // Clock ticks
+
+#define VERBOSE (LOG_DATA|LOG_RATE)
+
+#include "logmacro.h"
+
+DEFINE_DEVICE_TYPE(SH_SCI, sh_sci_device, "sh_sci", "SH Serial Communications Interface")
+
+
+// Clocking:
+// Async mode:
+// The circuit wants 16 events per bit.
+// * Internal clocking: the cpu clock is divided by one of (1, 4, 16, 64) from the cks field of smr
+// then by (brr+1) then by 2.
+// * External clocking: the external clock is supposed to be 16*bitrate.
+// Sync mode:
+// The circuit wants 2 events per bit, a positive and a negative edge.
+// * Internal clocking: the cpu clock is divided by one of (1, 4, 16, 64) from the cks field of smr
+// then by (brr+1) then by 2. Events are then interpreted has been alternatively positive and
+// negative (e.g. another divide-by-two, sync-wise).
+// * External clocking: the external clock is supposed to be at bitrate, both edges are used.
+//
+// Synchronization:
+// Async mode:
+// Both modes use a 4-bits counter incremented on every event (16/bit).
+//
+// * Transmit sets the counter to 0 at transmit start. Output data line changes value
+// on counter == 0. If the clock output is required, clk=1 outside of transmit,
+// clk=0 on counter==0, clk=1 on counter==8.
+//
+// * Receive sets the counter to 0 when the data line initially goes down (start bit)
+// Output line is read on counter==8. It is unknown whether the counter is reset
+// on every data line level change.
+//
+// Sync mode:
+// * Transmit changes the data line on negative edges, the clock line, following positive and
+// negative edge definition, is output as long as transmit is active and is otherwise 1.
+//
+// * Receive reads the data line on positive edges.
+//
+// Framing:
+// Async mode: 1 bit of start at 0, 7 or 8 bits of data, nothing or 1 bit of parity or 1 bit of multiprocessing, 1 or 2 bits of stop at 1.
+// Sync mode: 8 bits of data.
+//
+// Multiprocessing bit is an extra bit which value can be set on transmit in bit zero of ssr.
+// On receive when zero the byte is dropped.
+
+
+const char *const sh_sci_device::state_names[] = { "idle", "start", "bit", "parity", "stop", "last-tick" };
+
+sh_sci_device::sh_sci_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) :
+ device_t(mconfig, SH_SCI, tag, owner, clock),
+ m_cpu(*this, finder_base::DUMMY_TAG),
+ m_intc(*this, finder_base::DUMMY_TAG),
+ m_external_to_internal_ratio(0), m_internal_to_external_ratio(0), m_id(0), m_eri_int(0), m_rxi_int(0), m_txi_int(0), m_tei_int(0),
+ m_tx_state(0), m_rx_state(0), m_tx_bit(0), m_rx_bit(0), m_clock_state(0), m_tx_parity(0), m_rx_parity(0), m_tx_clock_counter(0), m_rx_clock_counter(0),
+ m_clock_mode(INTERNAL_ASYNC), m_ext_clock_value(false), m_rx_value(true),
+ m_rdr(0), m_tdr(0), m_smr(0), m_scr(0), m_ssr(0), m_brr(0), m_rsr(0), m_tsr(0), m_clock_event(0), m_divider(0)
+{
+ m_external_clock_period = attotime::never;
+}
+
+void sh_sci_device::do_set_external_clock_period(const attotime &period)
+{
+ m_external_clock_period = period;
+}
+
+void sh_sci_device::smr_w(u8 data)
+{
+ m_smr = data;
+
+ LOGMASKED(LOG_REGS, "smr_w %02x %s %c%c%c%s /%d (%06x)\n", data,
+ data & SMR_CA ? "sync" : "async",
+ data & SMR_CHR ? '7' : '8',
+ data & SMR_PE ? data & SMR_OE ? 'o' : 'e' : 'n',
+ data & SMR_STOP ? '2' : '1',
+ data & SMR_MP ? " mp" : "",
+ 1 << 2*(data & SMR_CKS),
+ m_cpu->pc());
+
+ clock_update();
+}
+
+u8 sh_sci_device::smr_r()
+{
+ LOGMASKED(LOG_RREGS, "smr_r %02x (%06x)\n", m_smr, m_cpu->pc());
+ return m_smr;
+}
+
+void sh_sci_device::brr_w(u8 data)
+{
+ m_brr = data;
+ LOGMASKED(LOG_REGS, "brr_w %02x (%06x)\n", m_brr, m_cpu->pc());
+ clock_update();
+}
+
+u8 sh_sci_device::brr_r()
+{
+ LOGMASKED(LOG_RREGS, "brr_r %02x (%06x)\n", m_brr, m_cpu->pc());
+ return m_brr;
+}
+
+bool sh_sci_device::is_sync_start() const
+{
+ return (m_smr & SMR_CA) && ((m_scr & (SCR_TE|SCR_RE)) == (SCR_TE|SCR_RE));
+}
+
+bool sh_sci_device::has_recv_error() const
+{
+ return m_ssr & (SSR_ORER|SSR_PER|SSR_FER);
+}
+
+void sh_sci_device::scr_w(u8 data)
+{
+ LOGMASKED(LOG_REGS, "scr_w %02x%s%s%s%s%s%s clk=%d (%06x)\n", data,
+ data & SCR_TIE ? " txi" : "",
+ data & SCR_RIE ? " rxi" : "",
+ data & SCR_TE ? " tx" : "",
+ data & SCR_RE ? " rx" : "",
+ data & SCR_MPIE ? " mpi" : "",
+ data & SCR_TEIE ? " tei" : "",
+ data & SCR_CKE,
+ m_cpu->pc());
+
+ u8 delta = m_scr ^ data;
+ m_scr = data;
+ clock_update();
+
+ if((delta & SCR_RE) && !(m_scr & SCR_RE)) {
+ m_rx_state = ST_IDLE;
+ clock_stop(CLK_RX);
+ }
+
+ if((delta & SCR_RE) && (m_scr & SCR_RE) && m_rx_state == ST_IDLE && !has_recv_error() && !is_sync_start())
+ rx_start();
+ if((delta & SCR_TIE) && (m_scr & SCR_TIE) && (m_ssr & SSR_TDRE))
+ m_intc->internal_interrupt(m_txi_int);
+ if((delta & SCR_TEIE) && (m_scr & SCR_TEIE) && (m_ssr & SSR_TEND))
+ m_intc->internal_interrupt(m_tei_int);
+ if((delta & SCR_RIE) && (m_scr & SCR_RIE) && (m_ssr & SSR_RDRF))
+ m_intc->internal_interrupt(m_rxi_int);
+ if((delta & SCR_RIE) && (m_scr & SCR_RIE) && has_recv_error())
+ m_intc->internal_interrupt(m_eri_int);
+}
+
+u8 sh_sci_device::scr_r()
+{
+ LOGMASKED(LOG_RREGS, "scr_r %02x (%06x)\n", m_scr, m_cpu->pc());
+ return m_scr;
+}
+
+void sh_sci_device::tdr_w(u8 data)
+{
+ LOGMASKED(LOG_REGS, "tdr_w %02x (%06x)\n", data, m_cpu->pc());
+ m_tdr = data;
+#if 0
+ if(m_cpu->access_is_dma()) {
+ m_ssr &= ~SSR_TDRE;
+ if(m_tx_state == ST_IDLE)
+ tx_start();
+ }
+#endif
+}
+
+u8 sh_sci_device::tdr_r()
+{
+ LOGMASKED(LOG_RREGS, "tdr_r %02x (%06x)\n", m_tdr, m_cpu->pc());
+ return m_tdr;
+}
+
+void sh_sci_device::ssr_w(u8 data)
+{
+ if(!(m_scr & SCR_TE)) {
+ data |= SSR_TDRE;
+ m_ssr |= SSR_TDRE;
+ }
+ if((m_ssr & SSR_TDRE) && !(data & SSR_TDRE))
+ m_ssr &= ~SSR_TEND;
+ m_ssr = ((m_ssr & ~SSR_MPBT) | (data & SSR_MPBT)) & (data | (SSR_TEND|SSR_MPB|SSR_MPBT));
+ LOGMASKED(LOG_REGS, "ssr_w %02x -> %02x (%06x)\n", data, m_ssr, m_cpu->pc());
+
+ if(m_tx_state == ST_IDLE && !(m_ssr & SSR_TDRE))
+ tx_start();
+
+ if((m_scr & SCR_RE) && m_rx_state == ST_IDLE && !has_recv_error() && !is_sync_start())
+ rx_start();
+}
+
+u8 sh_sci_device::ssr_r()
+{
+ LOGMASKED(LOG_RREGS, "ssr_r %02x (%06x)\n", m_ssr, m_cpu->pc());
+ return m_ssr;
+}
+
+u8 sh_sci_device::rdr_r()
+{
+ LOGMASKED(LOG_RREGS, "rdr_r %02x (%06x)\n", m_rdr, m_cpu->pc());
+
+#if 0
+ if(!machine().side_effects_disabled() && m_cpu->access_is_dma())
+ m_ssr &= ~SSR_RDRF;
+#endif
+ return m_rdr;
+}
+
+void sh_sci_device::scmr_w(u8 data)
+{
+ LOGMASKED(LOG_REGS, "scmr_w %02x (%06x)\n", data, m_cpu->pc());
+}
+
+u8 sh_sci_device::scmr_r()
+{
+ LOGMASKED(LOG_RREGS, "scmr_r (%06x)\n", m_cpu->pc());
+ return 0x00;
+}
+
+void sh_sci_device::clock_update()
+{
+ m_divider = 2 << (2*(m_smr & SMR_CKS));
+ m_divider *= m_brr+1;
+
+ if(m_smr & SMR_CA) {
+ if(m_scr & SCR_CKE1)
+ m_clock_mode = EXTERNAL_SYNC;
+ else
+ m_clock_mode = INTERNAL_SYNC_OUT;
+ } else {
+ if(m_scr & SCR_CKE1)
+ m_clock_mode = EXTERNAL_ASYNC;
+ else if(m_scr & SCR_CKE0)
+ m_clock_mode = INTERNAL_ASYNC_OUT;
+ else
+ m_clock_mode = INTERNAL_ASYNC;
+ }
+
+ if(m_clock_mode == EXTERNAL_ASYNC && !m_external_clock_period.is_never())
+ m_clock_mode = EXTERNAL_RATE_ASYNC;
+ if(m_clock_mode == EXTERNAL_SYNC && !m_external_clock_period.is_never())
+ m_clock_mode = EXTERNAL_RATE_SYNC;
+
+ if(VERBOSE & LOG_RATE) {
+ std::string new_message;
+ switch(m_clock_mode) {
+ case INTERNAL_ASYNC:
+ new_message = util::string_format("clock internal at %d Hz, async, bitrate %d bps\n", int(m_cpu->clock() / m_divider), int(m_cpu->clock() / (m_divider*16)));
+ break;
+ case INTERNAL_ASYNC_OUT:
+ new_message = util::string_format("clock internal at %d Hz, async, bitrate %d bps, output\n", int(m_cpu->clock() / m_divider), int(m_cpu->clock() / (m_divider*16)));
+ break;
+ case EXTERNAL_ASYNC:
+ new_message = "clock external, async\n";
+ break;
+ case EXTERNAL_RATE_ASYNC:
+ new_message = util::string_format("clock external at %d Hz, async, bitrate %d bps\n", int(m_cpu->clock()*m_internal_to_external_ratio), int(m_cpu->clock()*m_internal_to_external_ratio/16));
+ break;
+ case INTERNAL_SYNC_OUT:
+ new_message = util::string_format("clock internal at %d Hz, sync, output\n", int(m_cpu->clock() / (m_divider*2)));
+ break;
+ case EXTERNAL_SYNC:
+ new_message = "clock external, sync\n";
+ break;
+ case EXTERNAL_RATE_SYNC:
+ new_message = util::string_format("clock external at %d Hz, sync\n", int(m_cpu->clock()*m_internal_to_external_ratio));
+ break;
+ }
+ if(new_message != m_last_clock_message) {
+ (LOG_OUTPUT_FUNC)(new_message);
+ m_last_clock_message = std::move(new_message);
+ }
+ }
+}
+
+void sh_sci_device::device_start()
+{
+ if(m_external_clock_period.is_never()) {
+ m_internal_to_external_ratio = 0;
+ m_external_to_internal_ratio = 0;
+ } else {
+ m_external_to_internal_ratio = (m_external_clock_period*m_cpu->clock()).as_double();
+ m_internal_to_external_ratio = 1/m_external_to_internal_ratio;
+ }
+
+ save_item(NAME(m_tx_state));
+ save_item(NAME(m_rx_state));
+ save_item(NAME(m_tx_bit));
+ save_item(NAME(m_rx_bit));
+ save_item(NAME(m_clock_state));
+ save_item(NAME(m_tx_parity));
+ save_item(NAME(m_rx_parity));
+ save_item(NAME(m_tx_clock_counter));
+ save_item(NAME(m_rx_clock_counter));
+ save_item(NAME(m_clock_mode));
+ save_item(NAME(m_ext_clock_value));
+ save_item(NAME(m_rx_value));
+
+ save_item(NAME(m_rdr));
+ save_item(NAME(m_tdr));
+ save_item(NAME(m_smr));
+ save_item(NAME(m_scr));
+ save_item(NAME(m_ssr));
+ save_item(NAME(m_brr));
+ save_item(NAME(m_rsr));
+ save_item(NAME(m_tsr));
+ save_item(NAME(m_clock_event));
+ save_item(NAME(m_clock_step));
+ save_item(NAME(m_divider));
+}
+
+void sh_sci_device::device_reset()
+{
+ m_rdr = 0x00;
+ m_tdr = 0xff;
+ m_smr = 0x00;
+ m_scr = 0x00;
+ m_ssr = 0x84;
+ m_brr = 0xff;
+ m_rsr = 0x00;
+ m_tsr = 0xff;
+ m_rx_bit = 0;
+ m_tx_bit = 0;
+ m_tx_state = ST_IDLE;
+ m_rx_state = ST_IDLE;
+ m_clock_state = 0;
+ m_clock_mode = INTERNAL_ASYNC;
+ m_clock_event = 0;
+ clock_update();
+ m_ext_clock_value = true;
+ m_tx_clock_counter = 0;
+ m_rx_clock_counter = 0;
+ m_cpu->do_sci_clk(m_id, 1);
+ m_cpu->do_sci_tx(m_id, 1);
+}
+
+TIMER_CALLBACK_MEMBER(sh_sci_device::sync_tick)
+{
+ // Used only to force system-wide syncs
+}
+
+void sh_sci_device::do_rx_w(int state)
+{
+#if 0
+ if(m_cpu->standby()) {
+ m_rx_value = state;
+ return;
+ }
+#endif
+
+ if(state != m_rx_value && (m_clock_state & CLK_RX))
+ if(m_rx_clock_counter == 1 || m_rx_clock_counter == 15)
+ m_rx_clock_counter = 0;
+
+ m_rx_value = state;
+ if(!m_rx_value && !(m_clock_state & CLK_RX) && m_rx_state != ST_IDLE)
+ clock_start(CLK_RX);
+}
+
+void sh_sci_device::do_clk_w(int state)
+{
+ if(m_ext_clock_value == state)
+ return;
+
+ m_ext_clock_value = state;
+ if(!m_clock_state /* || m_cpu->standby() */)
+ return;
+
+ if(m_clock_mode == EXTERNAL_ASYNC) {
+ if(m_clock_state & CLK_TX)
+ tx_async_tick();
+ if(m_clock_state & CLK_RX)
+ rx_async_tick();
+ } else if(m_clock_mode == EXTERNAL_SYNC) {
+ if(m_clock_state & CLK_TX)
+ tx_sync_tick();
+ if(m_clock_state & CLK_RX)
+ rx_sync_tick();
+ }
+}
+
+u64 sh_sci_device::internal_update(u64 current_time)
+{
+ if(!m_clock_event || current_time < m_clock_event)
+ return m_clock_event;
+
+ if(m_clock_mode == INTERNAL_ASYNC || m_clock_mode == INTERNAL_ASYNC_OUT || m_clock_mode == EXTERNAL_RATE_ASYNC) {
+ if(m_clock_state & CLK_TX)
+ tx_async_tick();
+ if(m_clock_state & CLK_RX)
+ rx_async_tick();
+ } else if(m_clock_mode == INTERNAL_SYNC_OUT || m_clock_mode == EXTERNAL_RATE_SYNC) {
+ if(m_clock_state & CLK_TX)
+ tx_sync_tick();
+ if(m_clock_state & CLK_RX)
+ rx_sync_tick();
+ }
+
+ if(m_clock_state) {
+ if(m_clock_step)
+ m_clock_event += m_clock_step;
+ else if(m_clock_mode == EXTERNAL_RATE_ASYNC || m_clock_mode == EXTERNAL_RATE_SYNC)
+ m_clock_event = u64(u64(m_clock_event * m_internal_to_external_ratio + 1) * m_external_to_internal_ratio + 1);
+ else
+ m_clock_event = 0;
+
+ if(m_clock_event)
+ m_cpu->internal_update();
+
+ } else if(!m_clock_state) {
+ m_clock_event = 0;
+ if(m_clock_mode == INTERNAL_ASYNC_OUT || m_clock_mode == INTERNAL_SYNC_OUT)
+ m_cpu->do_sci_clk(m_id, 1);
+ }
+
+ return m_clock_event;
+}
+
+void sh_sci_device::clock_start(int mode)
+{
+ // Happens when back-to-back
+ if(m_clock_state & mode)
+ return;
+
+ if(mode == CLK_TX)
+ m_tx_clock_counter = 15;
+ else
+ m_rx_clock_counter = 15;
+
+ m_clock_state |= mode;
+ if(m_clock_state != mode)
+ return;
+
+ m_clock_step = 0;
+
+ switch(m_clock_mode) {
+ case INTERNAL_ASYNC:
+ case INTERNAL_ASYNC_OUT:
+ case INTERNAL_SYNC_OUT: {
+ LOGMASKED(LOG_CLOCK, "Starting internal clock\n");
+ m_clock_step = m_divider;
+ u64 now = m_cpu->current_cycles();
+ m_clock_event = (now / m_clock_step + 1) * m_clock_step;
+ m_cpu->internal_update();
+ break;
+ }
+
+ case EXTERNAL_RATE_ASYNC:
+ case EXTERNAL_RATE_SYNC: {
+ LOGMASKED(LOG_CLOCK, "Simulating external clock\n", m_clock_mode == EXTERNAL_RATE_ASYNC ? "async" : "sync");
+ u64 now = m_cpu->current_cycles();
+ m_clock_event = u64(u64(now * m_internal_to_external_ratio + 1) * m_external_to_internal_ratio + 1);
+ m_cpu->internal_update();
+ break;
+ }
+
+ case EXTERNAL_ASYNC:
+ case EXTERNAL_SYNC:
+ LOGMASKED(LOG_CLOCK, "Waiting for external clock\n");
+ break;
+ }
+}
+
+void sh_sci_device::clock_stop(int mode)
+{
+ m_clock_state &= ~mode;
+ if(!m_clock_state) {
+ m_clock_event = 0;
+ m_clock_step = 0;
+ LOGMASKED(LOG_CLOCK, "Stopping clocks\n");
+ }
+ m_cpu->internal_update();
+}
+
+void sh_sci_device::tx_start()
+{
+ m_ssr |= SSR_TDRE;
+ m_tsr = m_tdr;
+ m_tx_parity = m_smr & SMR_OE ? 0 : 1;
+ LOGMASKED(LOG_DATA, "start transmit %02x '%c'\n", m_tsr, m_tsr >= 32 && m_tsr < 127 ? m_tsr : '.');
+ if(m_scr & SCR_TIE)
+ m_intc->internal_interrupt(m_txi_int);
+ if(m_smr & SMR_CA) {
+ m_tx_state = ST_BIT;
+ m_tx_bit = 8;
+ } else {
+ m_tx_state = ST_START;
+ m_tx_bit = 1;
+ }
+ clock_start(CLK_TX);
+ if(m_rx_state == ST_IDLE && !has_recv_error() && is_sync_start())
+ rx_start();
+}
+
+void sh_sci_device::tx_async_tick()
+{
+ m_tx_clock_counter = (m_tx_clock_counter + 1) & 15;
+ LOGMASKED(LOG_TICK, "tx_async_tick %x\n", m_tx_clock_counter);
+ if(m_tx_clock_counter == 0) {
+ tx_async_step();
+
+ if(m_clock_mode == INTERNAL_ASYNC_OUT)
+ m_cpu->do_sci_clk(m_id, 0);
+
+ } else if(m_tx_clock_counter == 8 && m_clock_mode == INTERNAL_ASYNC_OUT)
+ m_cpu->do_sci_clk(m_id, 1);
+}
+
+void sh_sci_device::tx_async_step()
+{
+ LOGMASKED(LOG_STATE, "tx_async_step state=%s bit=%d\n", state_names[m_tx_state], m_tx_bit);
+ switch(m_tx_state) {
+ case ST_START:
+ m_cpu->do_sci_tx(m_id, false);
+ assert(m_tx_bit == 1);
+ m_tx_state = ST_BIT;
+ m_tx_bit = m_smr & SMR_CHR ? 7 : 8;
+ break;
+
+ case ST_BIT:
+ m_tx_parity ^= (m_tsr & 1);
+ m_cpu->do_sci_tx(m_id, m_tsr & 1);
+ m_tsr >>= 1;
+ m_tx_bit--;
+ if(!m_tx_bit) {
+ if(m_smr & SMR_CA) {
+ if(!(m_ssr & SSR_TDRE))
+ tx_start();
+ else {
+ m_tx_state = ST_LAST_TICK;
+ m_tx_bit = 0;
+ }
+ } else if(m_smr & SMR_PE) {
+ m_tx_state = ST_PARITY;
+ m_tx_bit = 1;
+ } else {
+ m_tx_state = ST_STOP;
+ m_tx_bit = m_smr & SMR_STOP ? 2 : 1;
+ }
+ }
+ break;
+
+ case ST_PARITY:
+ m_cpu->do_sci_tx(m_id, m_tx_parity);
+ assert(m_tx_bit == 1);
+ m_tx_state = ST_STOP;
+ m_tx_bit = m_smr & SMR_STOP ? 2 : 1;
+ break;
+
+ case ST_STOP:
+ m_cpu->do_sci_tx(m_id, true);
+ m_tx_bit--;
+ if(!m_tx_bit) {
+ if(!(m_ssr & SSR_TDRE))
+ tx_start();
+ else {
+ m_tx_state = ST_LAST_TICK;
+ m_tx_bit = 0;
+ }
+ }
+ break;
+
+ case ST_LAST_TICK:
+ m_tx_state = ST_IDLE;
+ m_tx_bit = 0;
+ clock_stop(CLK_TX);
+ m_cpu->do_sci_tx(m_id, 1);
+ m_ssr |= SSR_TEND;
+ if(m_scr & SCR_TEIE)
+ m_intc->internal_interrupt(m_tei_int);
+
+ // if there's more to send, start the transmitter
+ if((m_scr & SCR_TE) && !(m_ssr & SSR_TDRE))
+ tx_start();
+ break;
+
+ default:
+ abort();
+ }
+ LOGMASKED(LOG_STATE, " -> state=%s bit=%d\n", state_names[m_tx_state], m_tx_bit);
+}
+
+void sh_sci_device::tx_sync_tick()
+{
+ m_tx_clock_counter = (m_tx_clock_counter + 1) & 1;
+ LOGMASKED(LOG_TICK, "tx_sync_tick %x\n", m_tx_clock_counter);
+ if(m_tx_clock_counter == 0) {
+ tx_sync_step();
+
+ if(m_clock_mode == INTERNAL_SYNC_OUT && m_tx_state != ST_IDLE)
+ m_cpu->do_sci_clk(m_id, 0);
+
+ } else if(m_tx_clock_counter == 1 && m_clock_mode == INTERNAL_SYNC_OUT)
+ m_cpu->do_sci_clk(m_id, 1);
+}
+
+void sh_sci_device::tx_sync_step()
+{
+ LOGMASKED(LOG_STATE, "tx_sync_step bit=%d\n", m_tx_bit);
+ if(!m_tx_bit) {
+ m_tx_state = ST_IDLE;
+ clock_stop(CLK_TX);
+ m_cpu->do_sci_tx(m_id, 1);
+ m_ssr |= SSR_TEND;
+ if(m_scr & SCR_TEIE)
+ m_intc->internal_interrupt(m_tei_int);
+
+ // if there's more to send, start the transmitter
+ if((m_scr & SCR_TE) && !(m_ssr & SSR_TDRE))
+ tx_start();
+ } else {
+ m_cpu->do_sci_tx(m_id, m_tsr & 1);
+ m_tsr >>= 1;
+ m_tx_bit--;
+ }
+}
+
+void sh_sci_device::rx_start()
+{
+ m_rx_parity = m_smr & SMR_OE ? 0 : 1;
+ m_rsr = 0x00;
+ LOGMASKED(LOG_STATE, "start receive\n");
+ if(m_smr & SMR_CA) {
+ m_rx_state = ST_BIT;
+ m_rx_bit = 8;
+ clock_start(CLK_RX);
+ } else {
+ m_rx_state = ST_START;
+ m_rx_bit = 1;
+ if(!m_rx_value)
+ clock_start(CLK_RX);
+ }
+}
+
+void sh_sci_device::rx_done()
+{
+ if(!(m_ssr & SSR_FER)) {
+ if((m_smr & SMR_PE) && m_rx_parity) {
+ m_ssr |= SSR_PER;
+ LOGMASKED(LOG_DATA, "Receive parity error\n");
+ } else if(m_ssr & SSR_RDRF) {
+ m_ssr |= SSR_ORER;
+ LOGMASKED(LOG_DATA, "Receive overrun\n");
+ } else {
+ m_ssr |= SSR_RDRF;
+ LOGMASKED(LOG_DATA, "Received %02x '%c'\n", m_rsr, m_rsr >= 32 && m_rsr < 127 ? m_rsr : '.');
+ m_rdr = m_rsr;
+ }
+ }
+ if(m_scr & SCR_RIE) {
+ if(has_recv_error())
+ m_intc->internal_interrupt(m_eri_int);
+ else
+ m_intc->internal_interrupt(m_rxi_int);
+ }
+ if((m_scr & SCR_RE) && !has_recv_error() && !is_sync_start())
+ rx_start();
+ else {
+ clock_stop(CLK_RX);
+ m_rx_state = ST_IDLE;
+ }
+}
+
+void sh_sci_device::rx_async_tick()
+{
+ m_rx_clock_counter = (m_rx_clock_counter + 1) & 15;
+ LOGMASKED(LOG_TICK, "rx_async_tick %x\n", m_rx_clock_counter);
+ if(m_rx_clock_counter == 8)
+ rx_async_step();
+}
+
+void sh_sci_device::rx_async_step()
+{
+ LOGMASKED(LOG_STATE, "rx_async_step state=%s bit=%d\n", state_names[m_rx_state], m_rx_bit);
+ switch(m_rx_state) {
+ case ST_START:
+ if(m_rx_value) {
+ clock_stop(CLK_RX);
+ break;
+ }
+ m_rx_state = ST_BIT;
+ m_rx_bit = m_smr & SMR_CHR ? 7 : 8;
+ break;
+
+ case ST_BIT:
+ m_rx_parity ^= m_rx_value;
+ m_rsr >>= 1;
+ if(m_rx_value) {
+ m_rx_parity = !m_rx_parity;
+ m_rsr |= (m_smr & (SMR_CA|SMR_CHR)) == SMR_CHR ? 0x40 : 0x80;
+ }
+ m_rx_bit--;
+ if(!m_rx_bit) {
+ if(m_smr & SMR_CA)
+ rx_done();
+ else if(m_smr & SMR_PE) {
+ m_rx_state = ST_PARITY;
+ m_rx_bit = 1;
+ } else {
+ m_rx_state = ST_STOP;
+ m_rx_bit = 1; // Always 1 on rx
+ }
+ }
+ break;
+
+ case ST_PARITY:
+ m_rx_parity ^= m_rx_value;
+ assert(m_rx_bit == 1);
+ m_rx_state = ST_STOP;
+ m_rx_bit = 1;
+ break;
+
+ case ST_STOP:
+ assert(m_rx_bit == 1);
+ if(!m_rx_value)
+ m_ssr |= SSR_FER;
+ else if((m_smr & SMR_PE) && m_rx_parity)
+ m_ssr |= SSR_PER;
+ rx_done();
+ break;
+
+ default:
+ abort();
+ }
+ LOGMASKED(LOG_STATE, " -> state=%s, bit=%d\n", state_names[m_rx_state], m_rx_bit);
+}
+
+void sh_sci_device::rx_sync_tick()
+{
+ m_rx_clock_counter = (m_rx_clock_counter + 1) & 1;
+ LOGMASKED(LOG_TICK, "rx_sync_tick %x\n", m_rx_clock_counter);
+
+ if(m_rx_clock_counter == 0 && m_clock_mode == INTERNAL_SYNC_OUT)
+ m_cpu->do_sci_clk(m_id, 0);
+
+ else if(m_rx_clock_counter == 1) {
+ if(m_clock_mode == INTERNAL_SYNC_OUT)
+ m_cpu->do_sci_clk(m_id, 1);
+
+ rx_sync_step();
+ }
+}
+
+void sh_sci_device::rx_sync_step()
+{
+ LOGMASKED(LOG_STATE, "rx_sync_step bit=%d\n", m_rx_value);
+ m_rsr >>= 1;
+ if(m_rx_value)
+ m_rsr |= 0x80;
+ m_rx_bit--;
+
+ if(!m_rx_bit)
+ rx_done();
+}
diff --git a/src/devices/cpu/sh/sh_sci.h b/src/devices/cpu/sh/sh_sci.h
new file mode 100644
index 00000000000..3c36a346254
--- /dev/null
+++ b/src/devices/cpu/sh/sh_sci.h
@@ -0,0 +1,151 @@
+// license:BSD-3-Clause
+// copyright-holders:Olivier Galibert
+/***************************************************************************
+
+ sh_sci.h
+
+ SH Serial Communications Interface
+
+
+***************************************************************************/
+
+#ifndef MAME_CPU_SH_SH_SCI_H
+#define MAME_CPU_SH_SH_SCI_H
+
+#pragma once
+
+class sh7042_device;
+class sh_intc_device;
+
+class sh_sci_device : public device_t {
+public:
+ sh_sci_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+ template<typename T, typename U> sh_sci_device(const machine_config &mconfig, const char *tag, device_t *owner, int id, T &&cpu, U &&intc, int eri, int rxi, int txi, int tei)
+ : sh_sci_device(mconfig, tag, owner, 0)
+ {
+ m_cpu.set_tag(std::forward<T>(cpu));
+ m_intc.set_tag(std::forward<U>(intc));
+ m_id = id;
+ m_eri_int = eri;
+ m_rxi_int = rxi;
+ m_txi_int = txi;
+ m_tei_int = tei;
+ }
+
+ void do_set_external_clock_period(const attotime &_period);
+
+ void smr_w(u8 data);
+ u8 smr_r();
+ void brr_w(u8 data);
+ u8 brr_r();
+ void scr_w(u8 data);
+ u8 scr_r();
+ void tdr_w(u8 data);
+ u8 tdr_r();
+ void ssr_w(u8 data);
+ u8 ssr_r();
+ u8 rdr_r();
+ void scmr_w(u8 data);
+ u8 scmr_r();
+
+ void do_rx_w(int state);
+ void do_clk_w(int state);
+
+ u64 internal_update(u64 current_time);
+
+protected:
+ enum {
+ ST_IDLE, ST_START, ST_BIT, ST_PARITY, ST_STOP, ST_LAST_TICK
+ };
+
+ static const char *const state_names[];
+
+ enum {
+ CLK_TX = 1,
+ CLK_RX = 2
+ };
+
+ enum {
+ INTERNAL_ASYNC,
+ INTERNAL_ASYNC_OUT,
+ EXTERNAL_ASYNC,
+ EXTERNAL_RATE_ASYNC,
+ INTERNAL_SYNC_OUT,
+ EXTERNAL_SYNC,
+ EXTERNAL_RATE_SYNC
+ };
+
+ enum {
+ SMR_CA = 0x80,
+ SMR_CHR = 0x40,
+ SMR_PE = 0x20,
+ SMR_OE = 0x10,
+ SMR_STOP = 0x08,
+ SMR_MP = 0x04,
+ SMR_CKS = 0x03,
+
+ SCR_TIE = 0x80,
+ SCR_RIE = 0x40,
+ SCR_TE = 0x20,
+ SCR_RE = 0x10,
+ SCR_MPIE = 0x08,
+ SCR_TEIE = 0x04,
+ SCR_CKE = 0x03,
+ SCR_CKE1 = 0x02,
+ SCR_CKE0 = 0x01,
+
+ SSR_TDRE = 0x80,
+ SSR_RDRF = 0x40,
+ SSR_ORER = 0x20,
+ SSR_FER = 0x10,
+ SSR_PER = 0x08,
+ SSR_TEND = 0x04,
+ SSR_MPB = 0x02,
+ SSR_MPBT = 0x01
+ };
+
+ required_device<sh7042_device> m_cpu;
+ required_device<sh_intc_device> m_intc;
+ attotime m_external_clock_period;
+ double m_external_to_internal_ratio, m_internal_to_external_ratio;
+
+ int m_id, m_eri_int, m_rxi_int, m_txi_int, m_tei_int;
+
+ int m_tx_state, m_rx_state, m_tx_bit, m_rx_bit, m_clock_state, m_tx_parity, m_rx_parity, m_tx_clock_counter, m_rx_clock_counter;
+ u32 m_clock_mode;
+ bool m_ext_clock_value, m_rx_value;
+
+ u8 m_rdr, m_tdr, m_smr, m_scr, m_ssr, m_brr, m_rsr, m_tsr;
+ u64 m_clock_event, m_clock_step, m_divider;
+
+ std::string m_last_clock_message;
+
+ void device_start() override ATTR_COLD;
+ void device_reset() override ATTR_COLD;
+
+ TIMER_CALLBACK_MEMBER(sync_tick);
+
+ void clock_start(int mode);
+ void clock_stop(int mode);
+ void clock_update();
+
+ void tx_start();
+ void tx_async_tick();
+ void tx_async_step();
+ void tx_sync_tick();
+ void tx_sync_step();
+
+ void rx_start();
+ void rx_done();
+ void rx_async_tick();
+ void rx_async_step();
+ void rx_sync_tick();
+ void rx_sync_step();
+
+ bool is_sync_start() const;
+ bool has_recv_error() const;
+};
+
+DECLARE_DEVICE_TYPE(SH_SCI, sh_sci_device)
+
+#endif // MAME_CPU_SH_SH_SCI_H