diff options
Diffstat (limited to 'src/devices/cpu/sh')
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 |