diff options
Diffstat (limited to 'src/devices/cpu/sh')
-rw-r--r-- | src/devices/cpu/sh/sh.cpp | 4322 | ||||
-rw-r--r-- | src/devices/cpu/sh/sh.h | 469 | ||||
-rw-r--r-- | src/devices/cpu/sh/sh2.cpp | 2536 | ||||
-rw-r--r-- | src/devices/cpu/sh/sh2.h | 366 | ||||
-rw-r--r-- | src/devices/cpu/sh/sh2comn.cpp | 27 | ||||
-rw-r--r-- | src/devices/cpu/sh/sh2comn.h | 36 | ||||
-rw-r--r-- | src/devices/cpu/sh/sh2dasm.cpp | 610 | ||||
-rw-r--r-- | src/devices/cpu/sh/sh2drc.cpp | 2982 | ||||
-rw-r--r-- | src/devices/cpu/sh/sh2fe.cpp | 739 | ||||
-rw-r--r-- | src/devices/cpu/sh/sh3comn.cpp | 144 | ||||
-rw-r--r-- | src/devices/cpu/sh/sh4.cpp | 5093 | ||||
-rw-r--r-- | src/devices/cpu/sh/sh4.h | 593 | ||||
-rw-r--r-- | src/devices/cpu/sh/sh4comn.cpp | 115 | ||||
-rw-r--r-- | src/devices/cpu/sh/sh4comn.h | 108 | ||||
-rw-r--r-- | src/devices/cpu/sh/sh4dmac.cpp | 12 | ||||
-rw-r--r-- | src/devices/cpu/sh/sh4fe.cpp | 317 | ||||
-rw-r--r-- | src/devices/cpu/sh/sh_dasm.cpp (renamed from src/devices/cpu/sh/sh4dasm.cpp) | 987 | ||||
-rw-r--r-- | src/devices/cpu/sh/sh_dasm.h | 45 | ||||
-rw-r--r-- | src/devices/cpu/sh/sh_fe.cpp | 772 |
19 files changed, 9593 insertions, 10680 deletions
diff --git a/src/devices/cpu/sh/sh.cpp b/src/devices/cpu/sh/sh.cpp new file mode 100644 index 00000000000..f89f260c322 --- /dev/null +++ b/src/devices/cpu/sh/sh.cpp @@ -0,0 +1,4322 @@ +// license:BSD-3-Clause +// copyright-holders:David Haywood + +#include "emu.h" +#include "sh.h" +#include "sh_dasm.h" + +void sh_common_execution::device_start() +{ + /* allocate the implementation-specific state from the full cache */ + m_sh2_state = (internal_sh2_state *)m_cache.alloc_near(sizeof(internal_sh2_state)); + + save_item(NAME(m_sh2_state->pc)); + save_item(NAME(m_sh2_state->sr)); + save_item(NAME(m_sh2_state->pr)); + save_item(NAME(m_sh2_state->gbr)); + save_item(NAME(m_sh2_state->vbr)); + save_item(NAME(m_sh2_state->mach)); + save_item(NAME(m_sh2_state->macl)); + save_item(NAME(m_sh2_state->r)); + save_item(NAME(m_sh2_state->ea)); + save_item(NAME(m_sh2_state->m_delay)); + save_item(NAME(m_sh2_state->pending_irq)); + save_item(NAME(m_sh2_state->pending_nmi)); + save_item(NAME(m_sh2_state->irqline)); + save_item(NAME(m_sh2_state->evec)); + save_item(NAME(m_sh2_state->irqsr)); + save_item(NAME(m_sh2_state->target)); + save_item(NAME(m_sh2_state->internal_irq_level)); + save_item(NAME(m_sh2_state->sleep_mode)); + save_item(NAME(m_sh2_state->icount)); + + m_sh2_state->pc = 0; + m_sh2_state->pr = 0; + m_sh2_state->sr = 0; + m_sh2_state->gbr = 0; + m_sh2_state->vbr = 0; + m_sh2_state->mach = 0; + m_sh2_state->macl = 0; + memset(m_sh2_state->r, 0, sizeof(m_sh2_state->r)); + m_sh2_state->ea = 0; + m_sh2_state->m_delay = 0; + m_sh2_state->pending_irq = 0; + m_sh2_state->pending_nmi = 0; + m_sh2_state->irqline = 0; + m_sh2_state->evec = 0; + m_sh2_state->irqsr = 0; + m_sh2_state->target = 0; + m_sh2_state->internal_irq_level = 0; + m_sh2_state->icount = 0; + m_sh2_state->sleep_mode = 0; + m_sh2_state->arg0 = 0; + + state_add(SH4_PC, "PC", m_sh2_state->pc).formatstr("%08X").callimport(); + state_add(SH_SR, "SR", m_sh2_state->sr).formatstr("%08X").callimport(); + state_add(SH4_PR, "PR", m_sh2_state->pr).formatstr("%08X"); + state_add(SH4_GBR, "GBR", m_sh2_state->gbr).formatstr("%08X"); + state_add(SH4_VBR, "VBR", m_sh2_state->vbr).formatstr("%08X"); + state_add(SH4_MACH, "MACH", m_sh2_state->mach).formatstr("%08X"); + state_add(SH4_MACL, "MACL", m_sh2_state->macl).formatstr("%08X"); + state_add(SH4_R0, "R0", m_sh2_state->r[0]).formatstr("%08X"); + state_add(SH4_R1, "R1", m_sh2_state->r[1]).formatstr("%08X"); + state_add(SH4_R2, "R2", m_sh2_state->r[2]).formatstr("%08X"); + state_add(SH4_R3, "R3", m_sh2_state->r[3]).formatstr("%08X"); + state_add(SH4_R4, "R4", m_sh2_state->r[4]).formatstr("%08X"); + state_add(SH4_R5, "R5", m_sh2_state->r[5]).formatstr("%08X"); + state_add(SH4_R6, "R6", m_sh2_state->r[6]).formatstr("%08X"); + state_add(SH4_R7, "R7", m_sh2_state->r[7]).formatstr("%08X"); + state_add(SH4_R8, "R8", m_sh2_state->r[8]).formatstr("%08X"); + state_add(SH4_R9, "R9", m_sh2_state->r[9]).formatstr("%08X"); + state_add(SH4_R10, "R10", m_sh2_state->r[10]).formatstr("%08X"); + state_add(SH4_R11, "R11", m_sh2_state->r[11]).formatstr("%08X"); + state_add(SH4_R12, "R12", m_sh2_state->r[12]).formatstr("%08X"); + state_add(SH4_R13, "R13", m_sh2_state->r[13]).formatstr("%08X"); + state_add(SH4_R14, "R14", m_sh2_state->r[14]).formatstr("%08X"); + 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(STATE_GENFLAGS, "GENFLAGS", m_sh2_state->sr).formatstr("%20s").noshow(); + + m_icountptr = &m_sh2_state->icount; + + m_program = &space(AS_PROGRAM); +} + + +void sh_common_execution::drc_start() +{ + /* DRC helpers */ + memset(m_pcflushes, 0, sizeof(m_pcflushes)); + + m_fastram_select = 0; + memset(m_fastram, 0, sizeof(m_fastram)); + + /* reset per-driver pcflushes */ + m_pcfsel = 0; + + /* initialize the UML generator */ + uint32_t flags = 0; + m_drcuml = std::make_unique<drcuml_state>(*this, m_cache, flags, 1, 32, 1); + + /* add symbols for our stuff */ + m_drcuml->symbol_add(&m_sh2_state->pc, sizeof(m_sh2_state->pc), "pc"); + m_drcuml->symbol_add(&m_sh2_state->icount, sizeof(m_sh2_state->icount), "icount"); + for (int regnum = 0; regnum < 16; regnum++) + { + char buf[10]; + sprintf(buf, "r%d", regnum); + m_drcuml->symbol_add(&m_sh2_state->r[regnum], sizeof(m_sh2_state->r[regnum]), buf); + } + m_drcuml->symbol_add(&m_sh2_state->pr, sizeof(m_sh2_state->pr), "pr"); + m_drcuml->symbol_add(&m_sh2_state->sr, sizeof(m_sh2_state->sr), "sr"); + m_drcuml->symbol_add(&m_sh2_state->gbr, sizeof(m_sh2_state->gbr), "gbr"); + m_drcuml->symbol_add(&m_sh2_state->vbr, sizeof(m_sh2_state->vbr), "vbr"); + m_drcuml->symbol_add(&m_sh2_state->macl, sizeof(m_sh2_state->macl), "macl"); + m_drcuml->symbol_add(&m_sh2_state->mach, sizeof(m_sh2_state->macl), "mach"); + + /* initialize the front-end helper */ + init_drc_frontend(); + + /* compute the register parameters */ + for (int regnum = 0; regnum < 16; regnum++) + { + m_regmap[regnum] = uml::mem(&m_sh2_state->r[regnum]); + } + + /* if we have registers to spare, assign r0, r1, r2 to leftovers */ + /* WARNING: do not use synthetic registers that are mapped here! */ + if (!DISABLE_FAST_REGISTERS) + { + drcbe_info beinfo; + m_drcuml->get_backend_info(beinfo); + if (beinfo.direct_iregs > 4) + { + m_regmap[0] = uml::I4; + } + if (beinfo.direct_iregs > 5) + { + m_regmap[1] = uml::I5; + } + if (beinfo.direct_iregs > 6) + { + m_regmap[2] = uml::I6; + } + } + + /* mark the cache dirty so it is updated on next execute */ + m_cache_dirty = true; + + save_item(NAME(m_pcfsel)); + //save_item(NAME(m_maxpcfsel)); + save_item(NAME(m_pcflushes)); +} + +/* code cycles t-bit + * 0011 nnnn mmmm 1100 1 - + * ADD Rm,Rn + */ +void sh_common_execution::ADD(uint32_t m, uint32_t n) +{ + m_sh2_state->r[n] += m_sh2_state->r[m]; +} + +/* code cycles t-bit + * 0111 nnnn iiii iiii 1 - + * ADD #imm,Rn + */ +void sh_common_execution::ADDI(uint32_t i, uint32_t n) +{ + m_sh2_state->r[n] += (int32_t)(int16_t)(int8_t)i; +} + +/* code cycles t-bit + * 0011 nnnn mmmm 1110 1 carry + * ADDC Rm,Rn + */ +void sh_common_execution::ADDC(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]; + m_sh2_state->r[n] = tmp1 + (m_sh2_state->sr & SH_T); + if (tmp0 > tmp1) + m_sh2_state->sr |= SH_T; + else + m_sh2_state->sr &= ~SH_T; + if (tmp1 > m_sh2_state->r[n]) + m_sh2_state->sr |= SH_T; +} + +/* code cycles t-bit + * 0011 nnnn mmmm 1111 1 overflow + * ADDV Rm,Rn + */ +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; + 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; + ans += dest; + if (src == 0 || src == 2) + { + if (ans == 1) + m_sh2_state->sr |= SH_T; + else + m_sh2_state->sr &= ~SH_T; + } + else + m_sh2_state->sr &= ~SH_T; +} + +/* code cycles t-bit + * 0010 nnnn mmmm 1001 1 - + * AND Rm,Rn + */ +void sh_common_execution::AND(uint32_t m, uint32_t n) +{ + m_sh2_state->r[n] &= m_sh2_state->r[m]; +} + +/* code cycles t-bit + * 1100 1001 iiii iiii 1 - + * AND #imm,R0 + */ +void sh_common_execution::ANDI(uint32_t i) +{ + m_sh2_state->r[0] &= i; +} + +/* code cycles t-bit + * 1100 1101 iiii iiii 1 - + * AND.B #imm,@(R0,GBR) + */ +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 ); + m_sh2_state->icount -= 2; +} + +/* code cycles t-bit + * 1000 1011 dddd dddd 3/1 - + * BF disp8 + */ +void sh_common_execution::BF(uint32_t d) +{ + if ((m_sh2_state->sr & SH_T) == 0) + { + int32_t disp = ((int32_t)d << 24) >> 24; + m_sh2_state->pc = m_sh2_state->ea = m_sh2_state->pc + disp * 2 + 2; + m_sh2_state->icount -= 2; + } +} + +/* code cycles t-bit + * 1000 1111 dddd dddd 3/1 - + * BFS disp8 + */ +void sh_common_execution::BFS(uint32_t d) +{ + if ((m_sh2_state->sr & SH_T) == 0) + { + int32_t disp = ((int32_t)d << 24) >> 24; + m_sh2_state->m_delay = m_sh2_state->ea = m_sh2_state->pc + disp * 2 + 2; + m_sh2_state->icount--; + } +} + +/* code cycles t-bit + * 1010 dddd dddd dddd 2 - + * BRA disp12 + */ +void sh_common_execution::BRA(uint32_t d) +{ + int32_t disp = ((int32_t)d << 20) >> 20; + +#if BUSY_LOOP_HACKS + if (disp == -2) + { + uint32_t next_opcode = RW(m_sh2_state->pc & AM); + /* BRA $ + * NOP + */ + if (next_opcode == 0x0009) + m_sh2_state->icount %= 3; /* cycles for BRA $ and NOP taken (3) */ + } +#endif + m_sh2_state->m_delay = m_sh2_state->ea = m_sh2_state->pc + disp * 2 + 2; + m_sh2_state->icount--; +} + +/* code cycles t-bit + * 0000 mmmm 0010 0011 2 - + * BRAF Rm + */ +void sh_common_execution::BRAF(uint32_t m) +{ + m_sh2_state->m_delay = m_sh2_state->pc + m_sh2_state->r[m] + 2; + m_sh2_state->icount--; +} + +/* code cycles t-bit + * 1011 dddd dddd dddd 2 - + * BSR disp12 + */ +void sh_common_execution::BSR(uint32_t d) +{ + int32_t disp = ((int32_t)d << 20) >> 20; + + 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; + m_sh2_state->icount--; +} + +/* code cycles t-bit + * 0000 mmmm 0000 0011 2 - + * BSRF Rm + */ +void sh_common_execution::BSRF(uint32_t m) +{ + m_sh2_state->pr = m_sh2_state->pc + 2; + m_sh2_state->m_delay = m_sh2_state->pc + m_sh2_state->r[m] + 2; + m_sh2_state->icount--; +} + +/* code cycles t-bit + * 1000 1001 dddd dddd 3/1 - + * BT disp8 + */ +void sh_common_execution::BT(uint32_t d) +{ + if ((m_sh2_state->sr & SH_T) != 0) + { + int32_t disp = ((int32_t)d << 24) >> 24; + m_sh2_state->pc = m_sh2_state->ea = m_sh2_state->pc + disp * 2 + 2; + m_sh2_state->icount -= 2; + } +} + +/* code cycles t-bit + * 1000 1101 dddd dddd 2/1 - + * BTS disp8 + */ +void sh_common_execution::BTS(uint32_t d) +{ + if ((m_sh2_state->sr & SH_T) != 0) + { + int32_t disp = ((int32_t)d << 24) >> 24; + m_sh2_state->m_delay = m_sh2_state->ea = m_sh2_state->pc + disp * 2 + 2; + m_sh2_state->icount--; + } +} + +/* code cycles t-bit + * 0000 0000 0010 1000 1 - + * CLRMAC + */ +void sh_common_execution::CLRMAC() +{ + m_sh2_state->mach = 0; + m_sh2_state->macl = 0; +} + +/* code cycles t-bit + * 0000 0000 0000 1000 1 - + * CLRT + */ +void sh_common_execution::CLRT() +{ + m_sh2_state->sr &= ~SH_T; +} + +/* code cycles t-bit + * 0011 nnnn mmmm 0000 1 comparison result + * CMP_EQ Rm,Rn + */ +void sh_common_execution::CMPEQ(uint32_t m, uint32_t n) +{ + if (m_sh2_state->r[n] == m_sh2_state->r[m]) + m_sh2_state->sr |= SH_T; + else + m_sh2_state->sr &= ~SH_T; +} + +/* code cycles t-bit + * 0011 nnnn mmmm 0011 1 comparison result + * CMP_GE Rm,Rn + */ +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]) + m_sh2_state->sr |= SH_T; + else + m_sh2_state->sr &= ~SH_T; +} + +/* code cycles t-bit + * 0011 nnnn mmmm 0111 1 comparison result + * CMP_GT Rm,Rn + */ +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]) + m_sh2_state->sr |= SH_T; + else + m_sh2_state->sr &= ~SH_T; +} + +/* code cycles t-bit + * 0011 nnnn mmmm 0110 1 comparison result + * CMP_HI Rm,Rn + */ +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]) + m_sh2_state->sr |= SH_T; + else + m_sh2_state->sr &= ~SH_T; +} + +/* code cycles t-bit + * 0011 nnnn mmmm 0010 1 comparison result + * CMP_HS Rm,Rn + */ +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]) + m_sh2_state->sr |= SH_T; + else + m_sh2_state->sr &= ~SH_T; +} + +/* code cycles t-bit + * 0100 nnnn 0001 0101 1 comparison result + * CMP_PL Rn + */ +void sh_common_execution::CMPPL(uint32_t n) +{ + if ((int32_t) m_sh2_state->r[n] > 0) + m_sh2_state->sr |= SH_T; + else + m_sh2_state->sr &= ~SH_T; +} + +/* code cycles t-bit + * 0100 nnnn 0001 0001 1 comparison result + * CMP_PZ Rn + */ +void sh_common_execution::CMPPZ(uint32_t n) +{ + if ((int32_t) m_sh2_state->r[n] >= 0) + m_sh2_state->sr |= SH_T; + else + m_sh2_state->sr &= ~SH_T; +} + +/* code cycles t-bit + * 0010 nnnn mmmm 1100 1 comparison result + * CMP_STR Rm,Rn + */ +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) + m_sh2_state->sr &= ~SH_T; + else + m_sh2_state->sr |= SH_T; +} + +/* code cycles t-bit + * 1000 1000 iiii iiii 1 comparison result + * CMP/EQ #imm,R0 + */ +void sh_common_execution::CMPIM(uint32_t i) +{ + uint32_t imm = (uint32_t)(int32_t)(int16_t)(int8_t)i; + + if (m_sh2_state->r[0] == imm) + m_sh2_state->sr |= SH_T; + else + m_sh2_state->sr &= ~SH_T; +} + +/* code cycles t-bit + * 0010 nnnn mmmm 0111 1 calculation result + * DIV0S Rm,Rn + */ +void sh_common_execution::DIV0S(uint32_t m, uint32_t n) +{ + if ((m_sh2_state->r[n] & 0x80000000) == 0) + m_sh2_state->sr &= ~SH_Q; + else + m_sh2_state->sr |= SH_Q; + if ((m_sh2_state->r[m] & 0x80000000) == 0) + 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) + m_sh2_state->sr |= SH_T; + else + m_sh2_state->sr &= ~SH_T; +} + +/* code cycles t-bit + * 0000 0000 0001 1001 1 0 + * DIV0U + */ +void sh_common_execution::DIV0U() +{ + m_sh2_state->sr &= ~(SH_M | SH_Q | SH_T); +} + +/* code cycles t-bit + * 0011 nnnn mmmm 0100 1 calculation result + * DIV1 Rm,Rn + */ +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; + if (0x80000000 & m_sh2_state->r[n]) + m_sh2_state->sr |= SH_Q; + else + m_sh2_state->sr &= ~SH_Q; + + m_sh2_state->r[n] = (m_sh2_state->r[n] << 1) | (m_sh2_state->sr & SH_T); + + if (!old_q) + { + if (!(m_sh2_state->sr & SH_M)) + { + tmp0 = 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) + m_sh2_state->sr |= SH_Q; + else + m_sh2_state->sr &= ~SH_Q; + else + if(m_sh2_state->r[n] > tmp0) + m_sh2_state->sr &= ~SH_Q; + else + m_sh2_state->sr |= SH_Q; + } + else + { + tmp0 = 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) + m_sh2_state->sr &= ~SH_Q; + else + m_sh2_state->sr |= SH_Q; + } + else + { + if(m_sh2_state->r[n] < tmp0) + m_sh2_state->sr |= SH_Q; + else + m_sh2_state->sr &= ~SH_Q; + } + } + } + else + { + if (!(m_sh2_state->sr & SH_M)) + { + tmp0 = 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) + m_sh2_state->sr |= SH_Q; + else + m_sh2_state->sr &= ~SH_Q; + else + if(m_sh2_state->r[n] < tmp0) + m_sh2_state->sr &= ~SH_Q; + else + m_sh2_state->sr |= SH_Q; + } + else + { + tmp0 = 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) + m_sh2_state->sr &= ~SH_Q; + else + m_sh2_state->sr |= SH_Q; + else + if(m_sh2_state->r[n] > tmp0) + 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 */ + m_sh2_state->sr |= SH_T; + else + m_sh2_state->sr &= ~SH_T; +} + +/* 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; + + 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) + { + Res2 = ~Res2; + if (Res0 == 0) + Res2++; + else + Res0 = (~Res0) + 1; + } + 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; + m_sh2_state->icount--; +} + +/* DT Rn */ +void sh_common_execution::DT(uint32_t n) +{ + m_sh2_state->r[n]--; + if (m_sh2_state->r[n] == 0) + m_sh2_state->sr |= SH_T; + else + m_sh2_state->sr &= ~SH_T; +#if BUSY_LOOP_HACKS + { + uint32_t next_opcode = RW(m_sh2_state->pc & AM); + /* DT Rn + * BF $-2 + */ + if (next_opcode == 0x8bfd) + { + while (m_sh2_state->r[n] > 1 && m_sh2_state->icount > 4) + { + m_sh2_state->r[n]--; + m_sh2_state->icount -= 4; /* cycles for DT (1) and BF taken (3) */ + } + } + } +#endif +} + +/* 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; +} + +/* 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; +} + +/* EXTU.B Rm,Rn */ +void sh_common_execution::EXTUB(uint32_t m, uint32_t n) +{ + m_sh2_state->r[n] = m_sh2_state->r[m] & 0x000000ff; +} + +/* EXTU.W Rm,Rn */ +void sh_common_execution::EXTUW(uint32_t m, uint32_t n) +{ + m_sh2_state->r[n] = m_sh2_state->r[m] & 0x0000ffff; +} + +/* JMP @Rm */ +void sh_common_execution::JMP(uint32_t m) +{ + m_sh2_state->m_delay = m_sh2_state->ea = m_sh2_state->r[m]; + //m_sh2_state->icount--; // not in SH4 implementation? +} + +/* JSR @Rm */ +void sh_common_execution::JSR(uint32_t m) +{ + m_sh2_state->pr = m_sh2_state->pc + 2; + m_sh2_state->m_delay = m_sh2_state->ea = m_sh2_state->r[m]; + m_sh2_state->icount--; +} + +/* LDC Rm,GBR */ +void sh_common_execution::LDCGBR(uint32_t m) +{ + m_sh2_state->gbr = m_sh2_state->r[m]; +} + +/* LDC Rm,VBR */ +void sh_common_execution::LDCVBR(uint32_t m) +{ + m_sh2_state->vbr = m_sh2_state->r[m]; +} + +/* LDC.L @Rm+,GBR */ +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->r[m] += 4; + m_sh2_state->icount -= 2; +} + +/* LDC.L @Rm+,VBR */ +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->r[m] += 4; + m_sh2_state->icount -= 2; +} + +/* LDS Rm,MACH */ +void sh_common_execution::LDSMACH(uint32_t m) +{ + m_sh2_state->mach = m_sh2_state->r[m]; +} + +/* LDS Rm,MACL */ +void sh_common_execution::LDSMACL(uint32_t m) +{ + m_sh2_state->macl = m_sh2_state->r[m]; +} + +/* LDS Rm,PR */ +void sh_common_execution::LDSPR(uint32_t m) +{ + m_sh2_state->pr = m_sh2_state->r[m]; +} + +/* LDS.L @Rm+,MACH */ +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->r[m] += 4; +} + +/* LDS.L @Rm+,MACL */ +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->r[m] += 4; +} + +/* LDS.L @Rm+,PR */ +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->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] ); + m_sh2_state->r[n] += 4; + tempm = (int32_t) RL( m_sh2_state->r[m] ); + m_sh2_state->r[m] += 4; + if ((int32_t) (tempn ^ tempm) < 0) + fnLmL = -1; + else + fnLmL = 0; + 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) + { + Res2 = ~Res2; + if (Res0 == 0) + Res2++; + else + 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)) + { + Res2 = 0x00008000; + Res0 = 0x00000000; + } + else if (((int32_t) Res2 > 0) && (Res2 > 0x00007fff)) + { + Res2 = 0x00007fff; + Res0 = 0xffffffff; + } + 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; + } + m_sh2_state->icount -= 2; +} + +/* 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] ); + m_sh2_state->r[n] += 2; + tempm = (int32_t) RW( 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; + m_sh2_state->macl += tempm; + if ((int32_t) m_sh2_state->macl >= 0) + ans = 0; + else + ans = 1; + ans += 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; + } + } + else + { + m_sh2_state->mach += tempn; + if (templ > m_sh2_state->macl) + m_sh2_state->mach += 1; + } + m_sh2_state->icount -= 2; +} + +/* MOV Rm,Rn */ +void sh_common_execution::MOV(uint32_t m, uint32_t n) +{ + m_sh2_state->r[n] = m_sh2_state->r[m]; +} + +/* MOV.B Rm,@Rn */ +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); +} + +/* 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); +} + +/* 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] ); +} + +/* 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 ); +} + +/* 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 ); +} + +/* 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 ); +} + +/* 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; + + m_sh2_state->r[n] -= 1; + WB( 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; + + m_sh2_state->r[n] -= 2; + WW( m_sh2_state->r[n], data ); +} + +/* MOV.L Rm,@-Rn */ +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 ); +} + +/* 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] ); + if (n != m) + m_sh2_state->r[m] += 1; +} + +/* 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] ); + if (n != m) + m_sh2_state->r[m] += 2; +} + +/* 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] ); + if (n != m) + m_sh2_state->r[m] += 4; +} + +/* MOV.B Rm,@(R0,Rn) */ +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 ); +} + +/* 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 ); +} + +/* 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] ); +} + +/* 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 ); +} + +/* 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 ); +} + +/* 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 ); +} + +/* 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; +} + +/* MOV.W @(disp8,PC),Rn */ +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 ); +} + +/* MOV.L @(disp8,PC),Rn */ +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 ); +} + +/* MOV.B @(disp8,GBR),R0 */ +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 ); +} + +/* MOV.W @(disp8,GBR),R0 */ +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 ); +} + +/* MOV.L @(disp8,GBR),R0 */ +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 ); +} + +/* MOV.B R0,@(disp8,GBR) */ +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 ); +} + +/* MOV.W R0,@(disp8,GBR) */ +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 ); +} + +/* MOV.L R0,@(disp8,GBR) */ +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] ); +} + +/* MOV.B R0,@(disp4,Rn) */ +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 ); +} + +/* MOV.W R0,@(disp4,Rn) */ +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 ); +} + +/* MOV.L Rm,@(disp4,Rn) */ +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] ); +} + +/* MOV.B @(disp4,Rm),R0 */ +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 ); +} + +/* MOV.W @(disp4,Rm),R0 */ +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 ); +} + +/* MOV.L @(disp4,Rm),Rn */ +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 ); +} + +/* MOVA @(disp8,PC),R0 */ +void sh_common_execution::MOVA(uint32_t d) +{ + uint32_t disp = d & 0xff; + m_sh2_state->ea = ((m_sh2_state->pc + 2) & ~3) + disp * 4; + m_sh2_state->r[0] = m_sh2_state->ea; +} + +/* MOVT Rn */ +void sh_common_execution::MOVT(uint32_t n) +{ + m_sh2_state->r[n] = m_sh2_state->sr & SH_T; +} + +/* MUL.L Rm,Rn */ +void sh_common_execution::MULL(uint32_t m, uint32_t n) +{ + m_sh2_state->macl = m_sh2_state->r[n] * m_sh2_state->r[m]; + m_sh2_state->icount--; +} + +/* 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]; +} + +/* 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]; +} + +/* NEG Rm,Rn */ +void sh_common_execution::NEG(uint32_t m, uint32_t n) +{ + m_sh2_state->r[n] = 0 - m_sh2_state->r[m]; +} + +/* NEGC Rm,Rn */ +void sh_common_execution::NEGC(uint32_t m, uint32_t n) +{ + uint32_t temp; + + 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; + else + m_sh2_state->sr &= ~SH_T; +} + +/* NOP */ +void sh_common_execution::NOP(void) +{ +} + +/* NOT Rm,Rn */ +void sh_common_execution::NOT(uint32_t m, uint32_t n) +{ + m_sh2_state->r[n] = ~m_sh2_state->r[m]; +} + +/* OR Rm,Rn */ +void sh_common_execution::OR(uint32_t m, uint32_t n) +{ + m_sh2_state->r[n] |= m_sh2_state->r[m]; +} + +/* OR #imm,R0 */ +void sh_common_execution::ORI(uint32_t i) +{ + m_sh2_state->r[0] |= i; + m_sh2_state->icount -= 2; // not in SH2 implementation? +} + +/* 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? +} + +/* ROTCL Rn */ +void sh_common_execution::ROTCL(uint32_t n) +{ + uint32_t temp; + + 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; +} + +/* ROTCR Rn */ +void sh_common_execution::ROTCR(uint32_t n) +{ + uint32_t temp; + temp = (m_sh2_state->sr & SH_T) << 31; + if (m_sh2_state->r[n] & SH_T) + m_sh2_state->sr |= SH_T; + else + m_sh2_state->sr &= ~SH_T; + m_sh2_state->r[n] = (m_sh2_state->r[n] >> 1) | temp; +} + +/* ROTL Rn */ +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); +} + +/* 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); +} + +/* RTS */ +void sh_common_execution::RTS() +{ + m_sh2_state->m_delay = m_sh2_state->ea = m_sh2_state->pr; + m_sh2_state->icount--; +} + +/* SETT */ +void sh_common_execution::SETT() +{ + m_sh2_state->sr |= SH_T; +} + +/* SHAL Rn (same as SHLL) */ +void sh_common_execution::SHAL(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] <<= 1; +} + +/* SHAR Rn */ +void sh_common_execution::SHAR(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] = (uint32_t)((int32_t)m_sh2_state->r[n] >> 1); +} + +/* SHLL Rn (same as SHAL) */ +void sh_common_execution::SHLL(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] <<= 1; +} + +/* SHLL2 Rn */ +void sh_common_execution::SHLL2(uint32_t n) +{ + m_sh2_state->r[n] <<= 2; +} + +/* SHLL8 Rn */ +void sh_common_execution::SHLL8(uint32_t n) +{ + m_sh2_state->r[n] <<= 8; +} + +/* SHLL16 Rn */ +void sh_common_execution::SHLL16(uint32_t n) +{ + m_sh2_state->r[n] <<= 16; +} + +/* SHLR Rn */ +void sh_common_execution::SHLR(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] >>= 1; +} + +/* SHLR2 Rn */ +void sh_common_execution::SHLR2(uint32_t n) +{ + m_sh2_state->r[n] >>= 2; +} + +/* SHLR8 Rn */ +void sh_common_execution::SHLR8(uint32_t n) +{ + m_sh2_state->r[n] >>= 8; +} + +/* SHLR16 Rn */ +void sh_common_execution::SHLR16(uint32_t n) +{ + m_sh2_state->r[n] >>= 16; +} + + +/* STC SR,Rn */ +void sh_common_execution::STCSR(uint32_t n) +{ + m_sh2_state->r[n] = m_sh2_state->sr; +} + +/* STC GBR,Rn */ +void sh_common_execution::STCGBR(uint32_t n) +{ + m_sh2_state->r[n] = m_sh2_state->gbr; +} + +/* STC VBR,Rn */ +void sh_common_execution::STCVBR(uint32_t n) +{ + m_sh2_state->r[n] = m_sh2_state->vbr; +} + +/* STC.L SR,@-Rn */ +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 ); + m_sh2_state->icount--; +} + +/* STC.L GBR,@-Rn */ +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 ); + m_sh2_state->icount--; +} + +/* STC.L VBR,@-Rn */ +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 ); + m_sh2_state->icount--; +} + +/* STS MACH,Rn */ +void sh_common_execution::STSMACH(uint32_t n) +{ + m_sh2_state->r[n] = m_sh2_state->mach; +} + +/* STS MACL,Rn */ +void sh_common_execution::STSMACL(uint32_t n) +{ + m_sh2_state->r[n] = m_sh2_state->macl; +} + +/* STS PR,Rn */ +void sh_common_execution::STSPR(uint32_t n) +{ + m_sh2_state->r[n] = m_sh2_state->pr; +} + +/* STS.L MACH,@-Rn */ +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 ); +} + +/* STS.L MACL,@-Rn */ +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 ); +} + +/* STS.L PR,@-Rn */ +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 ); +} + +/* SUB Rm,Rn */ +void sh_common_execution::SUB(uint32_t m, uint32_t n) +{ + m_sh2_state->r[n] -= m_sh2_state->r[m]; +} + +/* 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]; + m_sh2_state->r[n] = tmp1 - (m_sh2_state->sr & SH_T); + if (tmp0 < tmp1) + m_sh2_state->sr |= SH_T; + else + m_sh2_state->sr &= ~SH_T; + if (tmp1 < m_sh2_state->r[n]) + m_sh2_state->sr |= SH_T; +} + +/* 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; + 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; + ans += dest; + if (src == 1) + { + if (ans == 1) + m_sh2_state->sr |= SH_T; + else + m_sh2_state->sr &= ~SH_T; + } + else + m_sh2_state->sr &= ~SH_T; +} + +/* 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; +} + +/* 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; + 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 ); + 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 ); + m_sh2_state->icount -= 3; +} + +/* TST Rm,Rn */ +void sh_common_execution::TST(uint32_t m, uint32_t n) +{ + if ((m_sh2_state->r[n] & m_sh2_state->r[m]) == 0) + m_sh2_state->sr |= SH_T; + else + m_sh2_state->sr &= ~SH_T; +} + +/* TST #imm,R0 */ +void sh_common_execution::TSTI(uint32_t i) +{ + uint32_t imm = i & 0xff; + + if ((imm & m_sh2_state->r[0]) == 0) + m_sh2_state->sr |= SH_T; + else + m_sh2_state->sr &= ~SH_T; +} + +/* TST.B #imm,@(R0,GBR) */ +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) + m_sh2_state->sr |= SH_T; + else + m_sh2_state->sr &= ~SH_T; + m_sh2_state->icount -= 2; +} + +/* XOR Rm,Rn */ +void sh_common_execution::XOR(uint32_t m, uint32_t n) +{ + m_sh2_state->r[n] ^= m_sh2_state->r[m]; +} + +/* XOR #imm,R0 */ +void sh_common_execution::XORI(uint32_t i) +{ + uint32_t imm = i & 0xff; + m_sh2_state->r[0] ^= imm; +} + +/* 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 ); + 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; +} + +/* SLEEP */ +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) + m_sh2_state->pc -= 2; + m_sh2_state->icount -= 2; + /* Wait_for_exception; */ + if(m_sh2_state->sleep_mode == 0) + m_sh2_state->sleep_mode = 1; + else if(m_sh2_state->sleep_mode == 2) + m_sh2_state->sleep_mode = 0; +} + +/* Common dispatch */ + +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; + } +} + +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; + } +} + +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; + } +} + +void sh_common_execution::op1000(uint16_t opcode) +{ + switch ( opcode & (15<<8) ) + { + 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; + } +} + + +void sh_common_execution::op1100(uint16_t opcode) +{ + switch (opcode & (15<<8)) + { + 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; + } +} + +// SH4 cases fall through to here too +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) + { + 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; + } +} + +// SH4 cases fall through to here too +void sh_common_execution::execute_one_4000(uint16_t opcode) +{ + // 0f always the same, others differ + + 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; + + } +} + +void sh_common_execution::execute_one(const uint16_t opcode) +{ + switch(opcode & 0xf000) + { + 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; + } +} + +// DRC / UML related +void cfunc_unimplemented(void *param) { ((sh_common_execution *)param)->func_unimplemented(); } +void cfunc_MAC_W(void *param) { ((sh_common_execution *)param)->func_MAC_W(); } +void cfunc_MAC_L(void *param) { ((sh_common_execution *)param)->func_MAC_L(); } +void cfunc_DIV1(void *param) { ((sh_common_execution *)param)->func_DIV1(); } +void cfunc_ADDV(void *param) { ((sh_common_execution *)param)->func_ADDV(); } +void cfunc_SUBV(void *param) { ((sh_common_execution *)param)->func_SUBV(); } +void cfunc_printf_probe(void *param) { ((sh_common_execution *)param)->func_printf_probe(); } + +/*------------------------------------------------- + sh2drc_add_fastram - add a new fastram + region +-------------------------------------------------*/ + +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)) + { + m_fastram[m_fastram_select].start = start; + m_fastram[m_fastram_select].end = end; + m_fastram[m_fastram_select].readonly = readonly; + m_fastram[m_fastram_select].base = base; + m_fastram_select++; + } +} + +using namespace uml; + +/*************************************************************************** + INLINE FUNCTIONS +***************************************************************************/ + +/*------------------------------------------------- + epc - compute the exception PC from a + descriptor +-------------------------------------------------*/ + +uint32_t sh_common_execution::epc(const opcode_desc *desc) +{ + return (desc->flags & OPFLAG_IN_DELAY_SLOT) ? (desc->pc - 1) : desc->pc; +} + +/*------------------------------------------------- + alloc_handle - allocate a handle if not + already allocated +-------------------------------------------------*/ + +void sh_common_execution::alloc_handle(drcuml_state *drcuml, code_handle **handleptr, const char *name) +{ + if (*handleptr == nullptr) + *handleptr = drcuml->handle_alloc(name); +} + +/*------------------------------------------------- + load_fast_iregs - load any fast integer + registers +-------------------------------------------------*/ + +void sh_common_execution::load_fast_iregs(drcuml_block *block) +{ + int regnum; + + for (regnum = 0; regnum < ARRAY_LENGTH(m_regmap); regnum++) + { + if (m_regmap[regnum].is_int_register()) + { + UML_MOV(block, uml::parameter::make_ireg(m_regmap[regnum].ireg()), mem(&m_sh2_state->r[regnum])); + } + } +} + + +/*------------------------------------------------- + save_fast_iregs - save any fast integer + registers +-------------------------------------------------*/ + +void sh_common_execution::save_fast_iregs(drcuml_block *block) +{ + int regnum; + + for (regnum = 0; regnum < ARRAY_LENGTH(m_regmap); regnum++) + { + if (m_regmap[regnum].is_int_register()) + { + UML_MOV(block, mem(&m_sh2_state->r[regnum]), uml::parameter::make_ireg(m_regmap[regnum].ireg())); + } + } +} + + +/*------------------------------------------------- + log_desc_flags_to_string - generate a string + representing the instruction description + flags +-------------------------------------------------*/ + +const char *sh_common_execution::log_desc_flags_to_string(uint32_t flags) +{ + static char tempbuf[30]; + char *dest = tempbuf; + + /* branches */ + if (flags & OPFLAG_IS_UNCONDITIONAL_BRANCH) + *dest++ = 'U'; + else if (flags & OPFLAG_IS_CONDITIONAL_BRANCH) + *dest++ = 'C'; + else + *dest++ = '.'; + + /* intrablock branches */ + *dest++ = (flags & OPFLAG_INTRABLOCK_BRANCH) ? 'i' : '.'; + + /* branch targets */ + *dest++ = (flags & OPFLAG_IS_BRANCH_TARGET) ? 'B' : '.'; + + /* delay slots */ + *dest++ = (flags & OPFLAG_IN_DELAY_SLOT) ? 'D' : '.'; + + /* exceptions */ + if (flags & OPFLAG_WILL_CAUSE_EXCEPTION) + *dest++ = 'E'; + else if (flags & OPFLAG_CAN_CAUSE_EXCEPTION) + *dest++ = 'e'; + else + *dest++ = '.'; + + /* read/write */ + if (flags & OPFLAG_READS_MEMORY) + *dest++ = 'R'; + else if (flags & OPFLAG_WRITES_MEMORY) + *dest++ = 'W'; + else + *dest++ = '.'; + + /* TLB validation */ + *dest++ = (flags & OPFLAG_VALIDATE_TLB) ? 'V' : '.'; + + /* TLB modification */ + *dest++ = (flags & OPFLAG_MODIFIES_TRANSLATION) ? 'T' : '.'; + + /* redispatch */ + *dest++ = (flags & OPFLAG_REDISPATCH) ? 'R' : '.'; + return tempbuf; +} + + +/*------------------------------------------------- + log_register_list - log a list of GPR registers +-------------------------------------------------*/ + +void sh_common_execution::log_register_list(drcuml_state *drcuml, const char *string, const uint32_t *reglist, const uint32_t *regnostarlist) +{ + int count = 0; + int regnum; + + /* skip if nothing */ + if (reglist[0] == 0 && reglist[1] == 0 && reglist[2] == 0) + return; + + drcuml->log_printf("[%s:", string); + + for (regnum = 0; regnum < 16; regnum++) + { + if (reglist[0] & REGFLAG_R(regnum)) + { + drcuml->log_printf("%sr%d", (count++ == 0) ? "" : ",", regnum); + if (regnostarlist != nullptr && !(regnostarlist[0] & REGFLAG_R(regnum))) + drcuml->log_printf("*"); + } + } + + if (reglist[1] & REGFLAG_PR) + { + drcuml->log_printf("%spr", (count++ == 0) ? "" : ","); + if (regnostarlist != nullptr && !(regnostarlist[1] & REGFLAG_PR)) + drcuml->log_printf("*"); + } + + if (reglist[1] & REGFLAG_SR) + { + drcuml->log_printf("%ssr", (count++ == 0) ? "" : ","); + if (regnostarlist != nullptr && !(regnostarlist[1] & REGFLAG_SR)) + drcuml->log_printf("*"); + } + + if (reglist[1] & REGFLAG_MACL) + { + drcuml->log_printf("%smacl", (count++ == 0) ? "" : ","); + if (regnostarlist != nullptr && !(regnostarlist[1] & REGFLAG_MACL)) + drcuml->log_printf("*"); + } + + if (reglist[1] & REGFLAG_MACH) + { + drcuml->log_printf("%smach", (count++ == 0) ? "" : ","); + if (regnostarlist != nullptr && !(regnostarlist[1] & REGFLAG_MACH)) + drcuml->log_printf("*"); + } + + if (reglist[1] & REGFLAG_GBR) + { + drcuml->log_printf("%sgbr", (count++ == 0) ? "" : ","); + if (regnostarlist != nullptr && !(regnostarlist[1] & REGFLAG_GBR)) + drcuml->log_printf("*"); + } + + if (reglist[1] & REGFLAG_VBR) + { + drcuml->log_printf("%svbr", (count++ == 0) ? "" : ","); + if (regnostarlist != nullptr && !(regnostarlist[1] & REGFLAG_VBR)) + drcuml->log_printf("*"); + } + + drcuml->log_printf("] "); +} + +/*------------------------------------------------- + log_opcode_desc - log a list of descriptions +-------------------------------------------------*/ + +void sh_common_execution::log_opcode_desc(drcuml_state *drcuml, const opcode_desc *desclist, int indent) +{ + /* open the file, creating it if necessary */ + if (indent == 0) + drcuml->log_printf("\nDescriptor list @ %08X\n", desclist->pc); + + /* output each descriptor */ + for ( ; desclist != nullptr; desclist = desclist->next()) + { + std::ostringstream stream; + + /* disassemle the current instruction and output it to the log */ + if (drcuml->logging() || drcuml->logging_native()) + { + if (desclist->flags & OPFLAG_VIRTUAL_NOOP) + stream << "<virtual nop>"; + else + { + sh_disassembler sh2d(false); + sh2d.dasm_one(stream, desclist->pc, desclist->opptr.w[0]); + } + } + else + stream << "???"; + drcuml->log_printf("%08X [%08X] t:%08X f:%s: %-30s", desclist->pc, desclist->physpc, desclist->targetpc, log_desc_flags_to_string(desclist->flags), stream.str().c_str()); + + /* output register states */ + log_register_list(drcuml, "use", desclist->regin, nullptr); + log_register_list(drcuml, "mod", desclist->regout, desclist->regreq); + drcuml->log_printf("\n"); + + /* if we have a delay slot, output it recursively */ + if (desclist->delay.first() != nullptr) + log_opcode_desc(drcuml, desclist->delay.first(), indent + 1); + + /* at the end of a sequence add a dividing line */ + if (desclist->flags & OPFLAG_END_SEQUENCE) + drcuml->log_printf("-----\n"); + } +} + +/*------------------------------------------------- + log_add_disasm_comment - add a comment + including disassembly of an SH2 instruction +-------------------------------------------------*/ + +void sh_common_execution::log_add_disasm_comment(drcuml_block *block, uint32_t pc, uint32_t op) +{ + if (m_drcuml->logging()) + { + sh_disassembler sh2d(false); + std::ostringstream stream; + sh2d.dasm_one(stream, pc, op); + block->append_comment("%08X: %s", pc, stream.str().c_str()); + } +} + + +/*------------------------------------------------- + code_flush_cache - flush the cache and + regenerate static code +-------------------------------------------------*/ + +void sh_common_execution::code_flush_cache() +{ + drcuml_state *drcuml = m_drcuml.get(); + + /* empty the transient cache contents */ + drcuml->reset(); + + try + { + /* generate the entry point and out-of-cycles handlers */ + static_generate_nocode_handler(); + static_generate_out_of_cycles(); + static_generate_entry_point(); + + /* add subroutines for memory accesses */ + static_generate_memory_accessor(1, false, "read8", &m_read8); + static_generate_memory_accessor(1, true, "write8", &m_write8); + static_generate_memory_accessor(2, false, "read16", &m_read16); + static_generate_memory_accessor(2, true, "write16", &m_write16); + static_generate_memory_accessor(4, false, "read32", &m_read32); + static_generate_memory_accessor(4, true, "write32", &m_write32); + } + catch (drcuml_block::abort_compilation &) + { + fatalerror("Unable to generate SH2 static code\n"); + } + + m_cache_dirty = false; +} + +/* Execute cycles - returns number of cycles actually run */ +void sh_common_execution::execute_run_drc() +{ + drcuml_state *drcuml = m_drcuml.get(); + int execute_result; + + /* reset the cache if dirty */ + if (m_cache_dirty) + code_flush_cache(); + + /* execute */ + do + { + /* run as much as we can */ + execute_result = drcuml->execute(*m_entry); + + /* if we need to recompile, do it */ + if (execute_result == EXECUTE_MISSING_CODE) + { + code_compile_block(0, m_sh2_state->pc); + } + else if (execute_result == EXECUTE_UNMAPPED_CODE) + { + fatalerror("Attempted to execute unmapped code at PC=%08X\n", m_sh2_state->pc); + } + else if (execute_result == EXECUTE_RESET_CACHE) + { + code_flush_cache(); + } + } while (execute_result != EXECUTE_OUT_OF_CYCLES); +} + + +/*------------------------------------------------- + code_compile_block - compile a block of the + given mode at the specified pc +-------------------------------------------------*/ + +void sh_common_execution::code_compile_block(uint8_t mode, offs_t pc) +{ + drcuml_state *drcuml = m_drcuml.get(); + compiler_state compiler = { 0 }; + const opcode_desc *seqhead, *seqlast; + const opcode_desc *desclist; + bool override = false; + drcuml_block *block; + + g_profiler.start(PROFILER_DRC_COMPILE); + + /* get a description of this sequence */ + desclist = get_desclist(pc); + + if (drcuml->logging() || drcuml->logging_native()) + log_opcode_desc(drcuml, desclist, 0); + + bool succeeded = false; + while (!succeeded) + { + try + { + /* start the block */ + block = drcuml->begin_block(4096); + + /* loop until we get through all instruction sequences */ + for (seqhead = desclist; seqhead != nullptr; seqhead = seqlast->next()) + { + const opcode_desc *curdesc; + uint32_t nextpc; + + /* add a code log entry */ + if (drcuml->logging()) + block->append_comment("-------------------------"); // comment + + /* determine the last instruction in this sequence */ + for (seqlast = seqhead; seqlast != nullptr; seqlast = seqlast->next()) + if (seqlast->flags & OPFLAG_END_SEQUENCE) + break; + assert(seqlast != nullptr); + + /* if we don't have a hash for this mode/pc, or if we are overriding all, add one */ + if (override || !drcuml->hash_exists(mode, seqhead->pc)) + UML_HASH(block, mode, seqhead->pc); // hash mode,pc + + /* if we already have a hash, and this is the first sequence, assume that we */ + /* are recompiling due to being out of sync and allow future overrides */ + else if (seqhead == desclist) + { + override = true; + UML_HASH(block, mode, seqhead->pc); // hash mode,pc + } + + /* otherwise, redispatch to that fixed PC and skip the rest of the processing */ + else + { + UML_LABEL(block, seqhead->pc | 0x80000000); // label seqhead->pc | 0x80000000 + UML_HASHJMP(block, 0, seqhead->pc, *m_nocode); + // hashjmp <mode>,seqhead->pc,nocode + continue; + } + + /* validate this code block if we're not pointing into ROM */ + if (m_program->get_write_ptr(seqhead->physpc) != nullptr) + generate_checksum_block(block, &compiler, seqhead, seqlast); + + /* label this instruction, if it may be jumped to locally */ + if (seqhead->flags & OPFLAG_IS_BRANCH_TARGET) + { + UML_LABEL(block, seqhead->pc | 0x80000000); // label seqhead->pc | 0x80000000 + } + + /* iterate over instructions in the sequence and compile them */ + for (curdesc = seqhead; curdesc != seqlast->next(); curdesc = curdesc->next()) + { + generate_sequence_instruction(block, &compiler, curdesc, 0xffffffff); + } + + /* if we need to return to the start, do it */ + if (seqlast->flags & OPFLAG_RETURN_TO_START) + { + nextpc = pc; + } + /* otherwise we just go to the next instruction */ + else + { + nextpc = seqlast->pc + (seqlast->skipslots + 1) * 2; + } + + /* count off cycles and go there */ + generate_update_cycles(block, &compiler, nextpc, true); // <subtract cycles> + + /* SH2 has no modes */ + if (seqlast->next() == nullptr || seqlast->next()->pc != nextpc) + { + UML_HASHJMP(block, 0, nextpc, *m_nocode); + } + // hashjmp <mode>,nextpc,nocode + } + + /* end the sequence */ + block->end(); + g_profiler.stop(); + succeeded = true; + } + catch (drcuml_block::abort_compilation &) + { + code_flush_cache(); + } + } +} + + +/*------------------------------------------------- + static_generate_nocode_handler - generate an + exception handler for "out of code" +-------------------------------------------------*/ + +void sh_common_execution::static_generate_nocode_handler() +{ + drcuml_state *drcuml = m_drcuml.get(); + drcuml_block *block; + + /* begin generating */ + block = drcuml->begin_block(10); + + /* generate a hash jump via the current mode and PC */ + alloc_handle(drcuml, &m_nocode, "nocode"); + UML_HANDLE(block, *m_nocode); // handle nocode + UML_GETEXP(block, I0); // getexp i0 + UML_MOV(block, mem(&m_sh2_state->pc), I0); // mov [pc],i0 + save_fast_iregs(block); + UML_EXIT(block, EXECUTE_MISSING_CODE); // exit EXECUTE_MISSING_CODE + + block->end(); +} + + +/*------------------------------------------------- + static_generate_out_of_cycles - generate an + out of cycles exception handler +-------------------------------------------------*/ + +void sh_common_execution::static_generate_out_of_cycles() +{ + drcuml_state *drcuml = m_drcuml.get(); + drcuml_block *block; + + /* begin generating */ + block = drcuml->begin_block(10); + + /* generate a hash jump via the current mode and PC */ + alloc_handle(drcuml, &m_out_of_cycles, "out_of_cycles"); + UML_HANDLE(block, *m_out_of_cycles); // handle out_of_cycles + UML_GETEXP(block, I0); // getexp i0 + UML_MOV(block, mem(&m_sh2_state->pc), I0); // mov <pc>,i0 + save_fast_iregs(block); + UML_EXIT(block, EXECUTE_OUT_OF_CYCLES); // exit EXECUTE_OUT_OF_CYCLES + + block->end(); +} + +/*------------------------------------------------- + generate_checksum_block - generate code to + validate a sequence of opcodes +-------------------------------------------------*/ + +void sh_common_execution::generate_checksum_block(drcuml_block *block, compiler_state *compiler, const opcode_desc *seqhead, const opcode_desc *seqlast) +{ + const opcode_desc *curdesc; + if (m_drcuml->logging()) + block->append_comment("[Validation for %08X]", seqhead->pc); // comment + + /* loose verify or single instruction: just compare and fail */ + if (!(m_drcoptions & SH2DRC_STRICT_VERIFY) || seqhead->next() == nullptr) + { + if (!(seqhead->flags & OPFLAG_VIRTUAL_NOOP)) + { + void *base; + if (m_xor == 0) base = m_direct->read_ptr(seqhead->physpc, SH2_CODE_XOR(0)); + else if (m_xor == 1) base = m_direct->read_ptr(seqhead->physpc, SH34LE_CODE_XOR(0)); + else base = m_direct->read_ptr(seqhead->physpc, SH34BE_CODE_XOR(0)); + + UML_LOAD(block, I0, base, 0, SIZE_WORD, SCALE_x2); // load i0,base,word + UML_CMP(block, I0, seqhead->opptr.w[0]); // cmp i0,*opptr + UML_EXHc(block, COND_NE, *m_nocode, epc(seqhead)); // exne nocode,seqhead->pc + } + } + + /* full verification; sum up everything */ + else + { + uint32_t sum = 0; + void *base; + if (m_xor == 0) base = m_direct->read_ptr(seqhead->physpc, SH2_CODE_XOR(0)); + else if (m_xor == 1) base = m_direct->read_ptr(seqhead->physpc, SH34LE_CODE_XOR(0)); + else base = m_direct->read_ptr(seqhead->physpc, SH34BE_CODE_XOR(0)); + + UML_LOAD(block, I0, base, 0, SIZE_WORD, SCALE_x4); // load i0,base,word + sum += seqhead->opptr.w[0]; + for (curdesc = seqhead->next(); curdesc != seqlast->next(); curdesc = curdesc->next()) + if (!(curdesc->flags & OPFLAG_VIRTUAL_NOOP)) + { + if (m_xor == 0) base = m_direct->read_ptr(curdesc->physpc, SH2_CODE_XOR(0)); + else if (m_xor == 1) base = m_direct->read_ptr(curdesc->physpc, SH34LE_CODE_XOR(0)); + else base = m_direct->read_ptr(curdesc->physpc, SH34BE_CODE_XOR(0)); + + UML_LOAD(block, I1, base, 0, SIZE_WORD, SCALE_x2); // load i1,*opptr,word + UML_ADD(block, I0, I0, I1); // add i0,i0,i1 + sum += curdesc->opptr.w[0]; + } + UML_CMP(block, I0, sum); // cmp i0,sum + UML_EXHc(block, COND_NE, *m_nocode, epc(seqhead)); // exne nocode,seqhead->pc + } +} + + + +/*------------------------------------------------- + generate_sequence_instruction - generate code + for a single instruction in a sequence +-------------------------------------------------*/ + +void sh_common_execution::generate_sequence_instruction(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, uint32_t ovrpc) +{ + offs_t expc; + + /* add an entry for the log */ + if (m_drcuml->logging() && !(desc->flags & OPFLAG_VIRTUAL_NOOP)) + log_add_disasm_comment(block, desc->pc, desc->opptr.w[0]); + + /* set the PC map variable */ + expc = (desc->flags & OPFLAG_IN_DELAY_SLOT) ? desc->pc - 1 : desc->pc; + UML_MAPVAR(block, MAPVAR_PC, expc); // mapvar PC,expc + + /* accumulate total cycles */ + compiler->cycles += desc->cycles; + + /* update the icount map variable */ + UML_MAPVAR(block, MAPVAR_CYCLES, compiler->cycles); // mapvar CYCLES,compiler->cycles + + /* if we want a probe, add it here */ + if (desc->pc == PROBE_ADDRESS) + { + UML_MOV(block, mem(&m_sh2_state->pc), desc->pc); // mov [pc],desc->pc + UML_CALLC(block, cfunc_printf_probe, this); // callc cfunc_printf_probe,sh2 + } + + /* if we are debugging, call the debugger */ + if ((machine().debug_flags & DEBUG_FLAG_ENABLED) != 0) + { + UML_MOV(block, mem(&m_sh2_state->pc), desc->pc); // mov [pc],desc->pc + save_fast_iregs(block); + UML_DEBUG(block, desc->pc); // debug desc->pc + } + else // not debug, see what other reasons there are for flushing the PC + { + if (m_drcoptions & SH2DRC_FLUSH_PC) // always flush? + { + UML_MOV(block, mem(&m_sh2_state->pc), desc->pc); // mov m_sh2_state->pc, desc->pc + } + else // check for driver-selected flushes + { + int pcflush; + + for (pcflush = 0; pcflush < m_pcfsel; pcflush++) + { + if (desc->pc == m_pcflushes[pcflush]) + { + UML_MOV(block, mem(&m_sh2_state->pc), desc->pc); // mov m_sh2_state->pc, desc->pc + } + } + } + } + + + /* if we hit an unmapped address, fatal error */ + if (desc->flags & OPFLAG_COMPILER_UNMAPPED) + { + UML_MOV(block, mem(&m_sh2_state->pc), desc->pc); // mov [pc],desc->pc + save_fast_iregs(block); + UML_EXIT(block, EXECUTE_UNMAPPED_CODE); // exit EXECUTE_UNMAPPED_CODE + } + + /* if this is an invalid opcode, die */ + if (desc->flags & OPFLAG_INVALID_OPCODE) + { + fatalerror("SH2DRC: invalid opcode!\n"); + } + + /* otherwise, unless this is a virtual no-op, it's a regular instruction */ + else if (!(desc->flags & OPFLAG_VIRTUAL_NOOP)) + { + /* compile the instruction */ + if (!generate_opcode(block, compiler, desc, ovrpc)) + { + // handle an illegal op + UML_MOV(block, mem(&m_sh2_state->pc), desc->pc); // mov [pc],desc->pc + UML_MOV(block, mem(&m_sh2_state->arg0), desc->opptr.w[0]); // mov [arg0],opcode + UML_CALLC(block, cfunc_unimplemented, this); // callc cfunc_unimplemented + } + } +} + +/*------------------------------------------------------------------ + generate_delay_slot +------------------------------------------------------------------*/ + +void sh_common_execution::generate_delay_slot(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, uint32_t ovrpc) +{ + compiler_state compiler_temp = *compiler; + + /* compile the delay slot using temporary compiler state */ + assert(desc->delay.first() != nullptr); + generate_sequence_instruction(block, &compiler_temp, desc->delay.first(), ovrpc); // <next instruction> + + /* update the label */ + compiler->labelnum = compiler_temp.labelnum; +} + +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 &= m_am; + m_sh2_state->irqsr = m_sh2_state->sr; + // claim it's an NMI, because it pretty much is + m_sh2_state->pending_nmi = 1; +} + +void sh_common_execution::func_MAC_W() +{ + uint16_t opcode; + int n, m; + + // recover the opcode + opcode = m_sh2_state->arg0; + + // extract the operands + n = Rn; + m = Rm; + + MAC_W(m, n); +} + + +void sh_common_execution::func_MAC_L() +{ + uint16_t opcode; + int n, m; + + // recover the opcode + opcode = m_sh2_state->arg0; + + // extract the operands + n = Rn; + m = Rm; + + MAC_L(m, n); +} + + +void sh_common_execution::func_DIV1() +{ + uint16_t opcode; + int n, m; + + // recover the opcode + opcode = m_sh2_state->arg0; + + // extract the operands + n = Rn; + m = Rm; + + DIV1(m, n); +} + + +void sh_common_execution::func_ADDV() +{ + uint16_t opcode; + int n, m; + + // recover the opcode + opcode = m_sh2_state->arg0; + + // extract the operands + n = Rn; + m = Rm; + + ADDV(m, n); +} + + +void sh_common_execution::func_SUBV() +{ + uint16_t opcode; + int n, m; + + // recover the opcode + opcode = m_sh2_state->arg0; + + // extract the operands + n = Rn; + m = Rm; + + SUBV(m, n); +} + + +void sh_common_execution::func_printf_probe() +{ + uint32_t pc = m_sh2_state->pc; + + printf(" PC=%08X r0=%08X r1=%08X r2=%08X\n", + pc, + (uint32_t)m_sh2_state->r[0], + (uint32_t)m_sh2_state->r[1], + (uint32_t)m_sh2_state->r[2]); + printf(" r3=%08X r4=%08X r5=%08X r6=%08X\n", + (uint32_t)m_sh2_state->r[3], + (uint32_t)m_sh2_state->r[4], + (uint32_t)m_sh2_state->r[5], + (uint32_t)m_sh2_state->r[6]); + printf(" r7=%08X r8=%08X r9=%08X r10=%08X\n", + (uint32_t)m_sh2_state->r[7], + (uint32_t)m_sh2_state->r[8], + (uint32_t)m_sh2_state->r[9], + (uint32_t)m_sh2_state->r[10]); + printf(" r11=%08X r12=%08X r13=%08X r14=%08X\n", + (uint32_t)m_sh2_state->r[11], + (uint32_t)m_sh2_state->r[12], + (uint32_t)m_sh2_state->r[13], + (uint32_t)m_sh2_state->r[14]); + printf(" r15=%08X macl=%08X mach=%08X gbr=%08X\n", + (uint32_t)m_sh2_state->r[15], + (uint32_t)m_sh2_state->macl, + (uint32_t)m_sh2_state->mach, + (uint32_t)m_sh2_state->gbr); + printf(" evec %x irqsr %x pc=%08x\n", + (uint32_t)m_sh2_state->evec, + (uint32_t)m_sh2_state->irqsr, (uint32_t)m_sh2_state->pc); +} + +/*------------------------------------------------- + generate_opcode - generate code for a specific + opcode +-------------------------------------------------*/ + +bool sh_common_execution::generate_opcode(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, uint32_t ovrpc) +{ + uint32_t scratch, scratch2; + int32_t disp; + uint16_t opcode = desc->opptr.w[0]; + uint8_t opswitch = opcode >> 12; + int in_delay_slot = ((desc->flags & OPFLAG_IN_DELAY_SLOT) != 0); + + //printf("generating %04x\n", opcode); + + switch (opswitch) + { + case 0: + return generate_group_0(block, compiler, desc, opcode, in_delay_slot, ovrpc); + + 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 + SETEA(0); // set ea for debug + UML_CALLH(block, *m_write32); + + if (!in_delay_slot) + generate_update_cycles(block, compiler, desc->pc + 2, true); + return true; + + case 2: + return generate_group_2(block, compiler, desc, opcode, in_delay_slot, ovrpc); + case 3: + return generate_group_3(block, compiler, desc, opcode, ovrpc); + case 4: + return generate_group_4(block, compiler, desc, opcode, in_delay_slot, ovrpc); + + case 5: // MOVLL4 + scratch = (opcode & 0x0f) * 4; + UML_ADD(block, I0, R32(Rm), 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 + + if (!in_delay_slot) + generate_update_cycles(block, compiler, desc->pc + 2, true); + return true; + + case 6: + return generate_group_6(block, compiler, desc, opcode, in_delay_slot, ovrpc); + + 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 + return true; + + case 8: + return generate_group_8(block, compiler, desc, opcode, in_delay_slot, ovrpc); + + 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 + } + else + { + scratch2 = (uint32_t)(int32_t)(int16_t) RW(scratch); + UML_MOV(block, R32(Rn), scratch2); // mov Rn, scratch2 + } + + if (!in_delay_slot) + generate_update_cycles(block, compiler, desc->pc + 2, true); + return true; + + case 10: // BRA + disp = ((int32_t)opcode << 20) >> 20; + 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); + + generate_update_cycles(block, compiler, m_sh2_state->ea, true); // <subtract cycles> + UML_HASHJMP(block, 0, m_sh2_state->ea, *m_nocode); // hashjmp m_sh2_state->ea + return true; + + case 11: // BSR + // panicstr @ 403da22 relies on the delay slot clobbering the PR set by a BSR, so + // 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; + 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); + + generate_update_cycles(block, compiler, m_sh2_state->ea, true); // <subtract cycles> + UML_HASHJMP(block, 0, m_sh2_state->ea, *m_nocode); // hashjmp m_sh2_state->ea + return true; + + case 12: + return generate_group_12(block, compiler, desc, opcode, in_delay_slot, ovrpc); + + case 13: // MOVLI + if (ovrpc == 0xffffffff) + { + scratch = ((desc->pc + 4) & ~3) + ((opcode & 0xff) * 4); + } + else + { + scratch = ((ovrpc + 4) & ~3) + ((opcode & 0xff) * 4); + } + + if (m_drcoptions & SH2DRC_STRICT_PCREL) + { + 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 + } + else + { + scratch2 = RL(scratch); + UML_MOV(block, R32(Rn), scratch2); // mov Rn, scratch2 + } + + if (!in_delay_slot) + generate_update_cycles(block, compiler, desc->pc + 2, true); + return true; + + case 14: // MOVI + scratch = opcode & 0xff; + scratch2 = (uint32_t)(int32_t)(int16_t)(int8_t)scratch; + UML_MOV(block, R32(Rn), scratch2); + return true; + + case 15: + return generate_group_15(block, compiler, desc, opcode, in_delay_slot, ovrpc); + } + + return false; +} + +bool sh_common_execution::generate_group_15(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, uint16_t opcode, int in_delay_slot, uint32_t ovrpc) +{ + // no ops here on sh1/2 + return false; +} + +bool sh_common_execution::generate_group_2(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, uint16_t opcode, int in_delay_slot, uint32_t ovrpc) +{ + 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_CALLH(block, *m_write8); + + if (!in_delay_slot) + generate_update_cycles(block, compiler, desc->pc + 2, true); + 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_CALLH(block, *m_write16); + + if (!in_delay_slot) + generate_update_cycles(block, compiler, desc->pc + 2, true); + 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_CALLH(block, *m_write32); + + if (!in_delay_slot) + generate_update_cycles(block, compiler, desc->pc + 2, true); + return true; + + case 3: + 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_CALLH(block, *m_write8); // call write8 + + if (!in_delay_slot) + generate_update_cycles(block, compiler, desc->pc + 2, true); + 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_CALLH(block, *m_write16); // call write16 + + if (!in_delay_slot) + generate_update_cycles(block, compiler, desc->pc + 2, true); + 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_CALLH(block, *m_write32); // call write32 + + if (!in_delay_slot) + generate_update_cycles(block, compiler, desc->pc + 2, true); + return true; + + case 13: // XTRCT(Rm, Rn); + UML_SHL(block, I0, R32(Rm), 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_AND(block, I1, I1, 0xffff); // and r1, r1, #0x0000ffff + + UML_OR(block, R32(Rn), 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_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_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_TEST(block, I1, 0x80000000); // test r1, #0x80000000 + UML_JMPc(block, COND_Z, compiler->labelnum); // jz labelnum + + UML_OR(block, I0, I0, SH_T); // or r0, r0, T + UML_LABEL(block, compiler->labelnum++); // labelnum: + UML_MOV(block, mem(&m_sh2_state->sr), I0); // mov sr, r0 + return true; + + 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_JMPc(block, COND_NZ, compiler->labelnum); // jnz compiler->labelnum + + UML_OR(block, I0, I0, SH_T); // or r0, r0, T + UML_LABEL(block, compiler->labelnum++); // desc->pc: + + UML_MOV(block, mem(&m_sh2_state->sr), I0); // mov m_sh2_state->sr, r0 + return true; + + case 12: // CMPSTR(Rm, Rn); + UML_XOR(block, I0, R32(Rn), R32(Rm)); // 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 + + UML_SHR(block, I2, I0, 16); // shr r2, r0, #16 (HL) + UML_AND(block, I2, I2, 0xff); // and r2, r2, #0xff + + UML_SHR(block, I3, I0, 8); // shr r3, r0, #8 (LH) + UML_AND(block, I3, I3, 0xff); // and r3, r3, #0xff + + UML_AND(block, I7, I0, 0xff); // and r7, r0, #0xff (LL) + + UML_AND(block, mem(&m_sh2_state->sr), mem(&m_sh2_state->sr), ~SH_T); // and sr, sr, ~T (clear the T bit) + + UML_CMP(block, I1, 0); // cmp r1, #0 + UML_JMPc(block, COND_Z, compiler->labelnum); // jnz labelnum + UML_CMP(block, I2, 0); // cmp r2, #0 + UML_JMPc(block, COND_Z, compiler->labelnum); // jnz labelnum + UML_CMP(block, I3, 0); // cmp r3, #0 + UML_JMPc(block, COND_Z, compiler->labelnum); // jnz labelnum + UML_CMP(block, I7, 0); // cmp r7, #0 + UML_JMPc(block, COND_NZ, compiler->labelnum+1); // jnz labelnum + + UML_LABEL(block, compiler->labelnum++); // labelnum: + UML_OR(block, mem(&m_sh2_state->sr), mem(&m_sh2_state->sr), SH_T); // or sr, sr, T + + UML_LABEL(block, compiler->labelnum++); // labelnum+1: + return true; + + case 9: // AND(Rm, Rn); + UML_AND(block, R32(Rn), R32(Rn), R32(Rm)); // and Rn, Rn, Rm + return true; + + case 10: // XOR(Rm, Rn); + UML_XOR(block, R32(Rn), R32(Rn), R32(Rm)); // xor Rn, Rn, Rm + return true; + + case 11: // OR(Rm, Rn); + UML_OR(block, R32(Rn), R32(Rn), R32(Rm)); // 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_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_MULS(block, mem(&m_sh2_state->macl), mem(&m_sh2_state->ea), I0, I1); // muls macl, ea, r0, r1 + return true; + } + + return false; +} + + +bool sh_common_execution::generate_group_3(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, uint16_t opcode, uint32_t ovrpc) +{ + switch (opcode & 15) + { + case 0: // CMPEQ(Rm, Rn); (equality) + UML_CMP(block, R32(Rn), R32(Rm)); // 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_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_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_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_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; + + case 1: + case 9: + return false; + + case 4: // DIV1(Rm, Rn); + save_fast_iregs(block); + UML_MOV(block, mem(&m_sh2_state->arg0), desc->opptr.w[0]); + UML_CALLC(block, cfunc_DIV1, this); + load_fast_iregs(block); + return true; + + 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)); + return true; + } + break; + + 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)); + return true; + } + break; + + case 8: // SUB(Rm, Rn); + UML_SUB(block, R32(Rn), R32(Rn), R32(Rm)); // sub Rn, Rn, Rm + return true; + + case 12: // ADD(Rm, Rn); + UML_ADD(block, R32(Rn), R32(Rn), R32(Rm)); // 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_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; + + case 11: // SUBV(Rm, Rn); + save_fast_iregs(block); + UML_MOV(block, mem(&m_sh2_state->arg0), desc->opptr.w[0]); + UML_CALLC(block, cfunc_SUBV, this); + load_fast_iregs(block); + return true; + + 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_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; + + case 15: // ADDV(Rm, Rn); + save_fast_iregs(block); + UML_MOV(block, mem(&m_sh2_state->arg0), desc->opptr.w[0]); + UML_CALLC(block, cfunc_ADDV, this); + load_fast_iregs(block); + return true; + } + return false; +} + + +bool sh_common_execution::generate_group_6(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, uint16_t opcode, int in_delay_slot, uint32_t ovrpc) +{ + switch (opcode & 15) + { + case 0: // MOVBL(Rm, Rn); + UML_MOV(block, I0, R32(Rm)); // 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 + + 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 + SETEA(0); // debug: ea = r0 + UML_CALLH(block, *m_read16); // call read16 + UML_SEXT(block, R32(Rn), 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 + SETEA(0); // debug: ea = r0 + UML_CALLH(block, *m_read32); // call read32 + UML_MOV(block, R32(Rn), 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 + return true; + + case 7: // NOT(Rm, Rn); + UML_XOR(block, R32(Rn), R32(Rm), 0xffffffff); // xor Rn, Rm, 0xffffffff + return true; + + case 9: // SWAPW(Rm, Rn); + UML_ROL(block, R32(Rn), R32(Rm), 16); // rol Rn, Rm, 16 + return true; + + case 11: // NEG(Rm, Rn); + UML_SUB(block, R32(Rn), 0, R32(Rm)); // sub Rn, 0, Rm + return true; + + case 12: // EXTUB(Rm, Rn); + UML_AND(block, R32(Rn), R32(Rm), 0x000000ff); // and Rn, Rm, 0xff + return true; + + case 13: // EXTUW(Rm, Rn); + UML_AND(block, R32(Rn), R32(Rm), 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 + return true; + + case 15: // EXTSW(Rm, Rn); + UML_SEXT(block, R32(Rn), R32(Rm), SIZE_WORD); // sext Rn, Rm, WORD + return true; + + case 4: // MOVBP(Rm, Rn); + UML_MOV(block, I0, R32(Rm)); // mov r0, Rm + UML_CALLH(block, *m_read8); // call read8 + UML_SEXT(block, R32(Rn), I0, SIZE_BYTE); // sext Rn, r0, BYTE + + if (Rm != Rn) + UML_ADD(block, R32(Rm), R32(Rm), 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_CALLH(block, *m_read16); // call read16 + UML_SEXT(block, R32(Rn), I0, SIZE_WORD); // sext Rn, r0, WORD + + if (Rm != Rn) + UML_ADD(block, R32(Rm), R32(Rm), 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_CALLH(block, *m_read32); // call read32 + UML_MOV(block, R32(Rn), I0); // mov Rn, r0 + + if (Rm != Rn) + UML_ADD(block, R32(Rm), R32(Rm), 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_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 + 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_JMPc(block, COND_NC, compiler->labelnum); // jnc labelnum + + UML_OR(block, mem(&m_sh2_state->sr), mem(&m_sh2_state->sr), SH_T); // or sr, sr, T + + UML_LABEL(block, compiler->labelnum++); // labelnum: + + return true; + } + + return false; +} + +bool sh_common_execution::generate_group_8(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, uint16_t opcode, int in_delay_slot, uint32_t ovrpc) +{ + int32_t disp; + uint32_t udisp; + code_label templabel; + + switch ( opcode & (15<<8) ) + { + case 0 << 8: // MOVBS4(opcode & 0x0f, Rm); + udisp = (opcode & 0x0f); + UML_ADD(block, I0, R32(Rm), udisp); // add r0, Rm, udisp + UML_MOV(block, I1, R32(0)); // mov r1, R0 + UML_CALLH(block, *m_write8); // call write8 + + if (!in_delay_slot) + generate_update_cycles(block, compiler, desc->pc + 2, true); + return true; + + case 1 << 8: // MOVWS4(opcode & 0x0f, Rm); + udisp = (opcode & 0x0f) * 2; + UML_ADD(block, I0, R32(Rm), udisp); // add r0, Rm, udisp + UML_MOV(block, I1, R32(0)); // mov r1, R0 + UML_CALLH(block, *m_write16); // call write16 + + if (!in_delay_slot) + 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: + return false; + + case 4<< 8: // MOVBL4(Rm, opcode & 0x0f); + udisp = opcode & 0x0f; + UML_ADD(block, I0, R32(Rm), 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 + + if (!in_delay_slot) + generate_update_cycles(block, compiler, desc->pc + 2, true); + return true; + + case 5<< 8: // MOVWL4(Rm, opcode & 0x0f); + udisp = (opcode & 0x0f)*2; + UML_ADD(block, I0, R32(Rm), 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 + + if (!in_delay_slot) + generate_update_cycles(block, compiler, desc->pc + 2, true); + return true; + + case 8<< 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 + UML_CMP(block, I1, R32(0)); // cmp r1, R0 + UML_JMPc(block, COND_NZ, compiler->labelnum); // jnz compiler->labelnum (if negative) + + UML_OR(block, I0, I0, SH_T); // or r0, r0, T + + UML_LABEL(block, compiler->labelnum++); // labelnum: + UML_MOV(block, mem(&m_sh2_state->sr), I0); // mov m_sh2_state->sr, r0 + return true; + + case 9<< 8: // 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; + 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> + UML_HASHJMP(block, 0, m_sh2_state->ea, *m_nocode); // jmp m_sh2_state->ea + + UML_LABEL(block, compiler->labelnum++); // labelnum: + return true; + + case 11<< 8: // 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; + 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> + UML_HASHJMP(block, 0, m_sh2_state->ea, *m_nocode); // jmp m_sh2_state->ea + + UML_LABEL(block, compiler->labelnum++); // labelnum: + return true; + + case 13<< 8: // 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; + m_sh2_state->ea = (desc->pc + 2) + disp * 2 + 2; // m_sh2_state->ea = destination + + templabel = compiler->labelnum; // save our label + compiler->labelnum++; // make sure the delay slot doesn't use it + generate_delay_slot(block, compiler, desc, m_sh2_state->ea-2); + + generate_update_cycles(block, compiler, m_sh2_state->ea, true); // <subtract cycles> + UML_HASHJMP(block, 0, m_sh2_state->ea, *m_nocode); // jmp m_sh2_state->ea + + UML_LABEL(block, templabel); // labelnum: + return true; + } + break; + + case 15<< 8: // 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; + m_sh2_state->ea = (desc->pc + 2) + disp * 2 + 2; // m_sh2_state->ea = destination + + templabel = compiler->labelnum; // save our label + compiler->labelnum++; // make sure the delay slot doesn't use it + generate_delay_slot(block, compiler, desc, m_sh2_state->ea-2); // delay slot only if the branch is taken + + generate_update_cycles(block, compiler, m_sh2_state->ea, true); // <subtract cycles> + UML_HASHJMP(block, 0, m_sh2_state->ea, *m_nocode); // jmp m_sh2_state->ea + + UML_LABEL(block, templabel); // labelnum: + return true; + } + break; + } + + return false; +} + +bool sh_common_execution::generate_group_12_TRAPA(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, uint16_t opcode, int in_delay_slot, uint32_t ovrpc) +{ + uint32_t scratch = (opcode & 0xff) * 4; + UML_ADD(block, mem(&m_sh2_state->ea), mem(&m_sh2_state->vbr), scratch); // add ea, vbr, scratch + + UML_SUB(block, R32(15), R32(15), 4); // sub R15, R15, #4 + UML_MOV(block, I0, R32(15)); // mov r0, R15 + UML_MOV(block, I1, mem(&m_sh2_state->sr)); // mov r1, sr + UML_CALLH(block, *m_write32); // write32 + + UML_SUB(block, R32(15), R32(15), 4); // sub R15, R15, #4 + UML_MOV(block, I0, R32(15)); // mov r0, R15 + UML_MOV(block, I1, desc->pc + 2); // mov r1, pc+2 + UML_CALLH(block, *m_write32); // write32 + + UML_MOV(block, I0, mem(&m_sh2_state->ea)); // mov r0, ea + UML_CALLH(block, *m_read32); // read32 + UML_HASHJMP(block, 0, I0, *m_nocode); // jmp (r0) + + return true; +} + +bool sh_common_execution::generate_group_12(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, uint16_t opcode, int in_delay_slot, uint32_t ovrpc) +{ + uint32_t scratch; + + switch (opcode & (15<<8)) + { + case 0<<8: // 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 + UML_CALLH(block, *m_write8); // call write8 + + if (!in_delay_slot) + generate_update_cycles(block, compiler, desc->pc + 2, true); + return true; + + case 1<<8: // 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 + UML_CALLH(block, *m_write16); // call write16 + + if (!in_delay_slot) + generate_update_cycles(block, compiler, desc->pc + 2, true); + return true; + + case 2<<8: // 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 + UML_CALLH(block, *m_write32); // call write32 + + if (!in_delay_slot) + generate_update_cycles(block, compiler, desc->pc + 2, true); + return true; + + case 3<<8: // TRAPA(opcode & 0xff); + return generate_group_12_TRAPA(block, compiler, desc, opcode, in_delay_slot, ovrpc); + + case 4<<8: // 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 + UML_SEXT(block, R32(0), I0, SIZE_BYTE); // sext R0, r0, BYTE + + if (!in_delay_slot) + generate_update_cycles(block, compiler, desc->pc + 2, true); + return true; + + case 5<<8: // 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 + UML_SEXT(block, R32(0), I0, SIZE_WORD); // sext R0, r0, WORD + + if (!in_delay_slot) + generate_update_cycles(block, compiler, desc->pc + 2, true); + return true; + + case 6<<8: // 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 + UML_MOV(block, R32(0), I0); // mov R0, r0 + + if (!in_delay_slot) + generate_update_cycles(block, compiler, desc->pc + 2, true); + return true; + + case 7<<8: // 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); + 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) + UML_AND(block, I0, R32(0), scratch); // and r0, R0, scratch + UML_CMP(block, I0, 0); // cmp r0, #0 + UML_JMPc(block, COND_NZ, compiler->labelnum); // jnz labelnum + + UML_OR(block, mem(&m_sh2_state->sr), mem(&m_sh2_state->sr), SH_T); // or sr, sr, T + + UML_LABEL(block, compiler->labelnum++); // labelnum: + return true; + + case 9<<8: // 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); + UML_XOR(block, R32(0), R32(0), opcode & 0xff); // xor r0, r0, opcode & 0xff + return true; + + case 11<<8: // 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); + 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 + + UML_AND(block, I0, I0, opcode & 0xff); + UML_CMP(block, I0, 0); // cmp r0, #0 + UML_JMPc(block, COND_NZ, compiler->labelnum); // jnz labelnum + + UML_OR(block, mem(&m_sh2_state->sr), mem(&m_sh2_state->sr), SH_T); // or sr, sr, T + + UML_LABEL(block, compiler->labelnum++); // labelnum: + return true; + + case 13<<8: // ANDM(opcode & 0xff); + UML_ADD(block, I0, R32(0), mem(&m_sh2_state->gbr)); // add r0, R0, gbr + UML_CALLH(block, *m_read8); // read8 + + UML_AND(block, I1, I0, opcode&0xff); // and r1, r0, #opcode&0xff + UML_ADD(block, I0, R32(0), mem(&m_sh2_state->gbr)); // add r0, R0, gbr + SETEA(0); + UML_CALLH(block, *m_write8); // write8 + return true; + + case 14<<8: // XORM(opcode & 0xff); + UML_ADD(block, I0, R32(0), mem(&m_sh2_state->gbr)); // add r0, R0, gbr + UML_CALLH(block, *m_read8); // read8 + + UML_XOR(block, I1, I0, opcode&0xff); // xor r1, r0, #opcode&0xff + UML_ADD(block, I0, R32(0), mem(&m_sh2_state->gbr)); // add r0, R0, gbr + SETEA(0); + UML_CALLH(block, *m_write8); // write8 + return true; + + case 15<<8: // ORM(opcode & 0xff); + UML_ADD(block, I0, R32(0), mem(&m_sh2_state->gbr)); // add r0, R0, gbr + UML_CALLH(block, *m_read8); // read8 + + UML_OR(block, I1, I0, opcode&0xff); // or r1, r0, #opcode&0xff + UML_ADD(block, I0, R32(0), mem(&m_sh2_state->gbr)); // add r0, R0, gbr + SETEA(0); + UML_CALLH(block, *m_write8); // write8 + return true; + } + + return false; +} + +bool sh_common_execution::generate_group_0_RTE(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, uint16_t opcode, int in_delay_slot, uint32_t ovrpc) +{ + generate_delay_slot(block, compiler, desc, 0xffffffff); + + UML_MOV(block, I0, R32(15)); // mov r0, R15 + UML_CALLH(block, *m_read32); // call read32 + UML_MOV(block, mem(&m_sh2_state->pc), I0); // mov pc, r0 + UML_ADD(block, R32(15), R32(15), 4); // add R15, R15, #4 + + UML_MOV(block, I0, R32(15)); // mov r0, R15 + UML_CALLH(block, *m_read32); // call read32 + UML_MOV(block, mem(&m_sh2_state->sr), I0); // mov sr, r0 + UML_ADD(block, R32(15), R32(15), 4); // add R15, R15, #4 + + compiler->checkints = true; + UML_MOV(block, mem(&m_sh2_state->ea), mem(&m_sh2_state->pc)); // mov ea, pc + generate_update_cycles(block, compiler, mem(&m_sh2_state->ea), true); // <subtract cycles> + UML_HASHJMP(block, 0, mem(&m_sh2_state->pc), *m_nocode); // and jump to the "resume PC" + + return true; +} + + +bool sh_common_execution::generate_group_0(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, uint16_t opcode, int in_delay_slot, uint32_t ovrpc) +{ + switch (opcode & 0x3F) + { + case 0x00: // these are all illegal + case 0x01: + case 0x10: + case 0x11: + case 0x13: + case 0x20: + case 0x21: + case 0x30: + case 0x31: + case 0x32: + case 0x33: + case 0x38: + case 0x39: + case 0x3a: + case 0x3b: + return false; + + case 0x09: // NOP(); + return true; + + case 0x02: // STCSR(Rn); + UML_MOV(block, R32(Rn), 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), mem(&m_sh2_state->target), desc->pc); // add target, target, pc + + // 32x Cosmic Carnage @ 6002cb0 relies on the delay slot + // clobbering the calculated PR, so do it first + UML_ADD(block, mem(&m_sh2_state->pr), desc->pc, 4); // add m_pr, desc->pc, #4 (skip the current insn & delay slot) + + generate_delay_slot(block, compiler, desc, m_sh2_state->target); + + generate_update_cycles(block, compiler, mem(&m_sh2_state->target), true); // <subtract cycles> + UML_HASHJMP(block, 0, mem(&m_sh2_state->target), *m_nocode); // jmp target + return true; + } + break; + + case 0x04: // MOVBS0(Rm, Rn); + 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_CALLH(block, *m_write8); // call write8 + + if (!in_delay_slot) + generate_update_cycles(block, compiler, desc->pc + 2, true); + return true; + + case 0x05: // MOVWS0(Rm, Rn); + 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_CALLH(block, *m_write16); // call write16 + + if (!in_delay_slot) + generate_update_cycles(block, compiler, desc->pc + 2, true); + return true; + + case 0x06: // MOVLS0(Rm, Rn); + 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_CALLH(block, *m_write32); // call write32 + + if (!in_delay_slot) + generate_update_cycles(block, compiler, desc->pc + 2, true); + return true; + + case 0x07: // MULL(Rm, Rn); + case 0x17: // MULL(Rm, Rn); + case 0x27: // MULL(Rm, Rn); + 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 + return true; + } + break; + + case 0x08: // CLRT(); + UML_AND(block, mem(&m_sh2_state->sr), mem(&m_sh2_state->sr), ~SH_T); // and r0, sr, ~T (clear the T bit) + return true; + + case 0x0a: // STSMACH(Rn); + UML_MOV(block, R32(Rn), mem(&m_sh2_state->mach)); // mov Rn, mach + return true; + + case 0x0b: // RTS(); + UML_MOV(block, mem(&m_sh2_state->target), mem(&m_sh2_state->pr)); // mov target, pr (in case of d-slot shenanigans) + + generate_delay_slot(block, compiler, desc, m_sh2_state->target); + + generate_update_cycles(block, compiler, mem(&m_sh2_state->target), true); // <subtract cycles> + UML_HASHJMP(block, 0, mem(&m_sh2_state->target), *m_nocode); + return true; + + case 0x0c: // MOVBL0(Rm, Rn); + 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_CALLH(block, *m_read8); // call read8 + UML_SEXT(block, R32(Rn), I0, SIZE_BYTE); // sext Rn, r0, BYTE + + if (!in_delay_slot) + generate_update_cycles(block, compiler, desc->pc + 2, true); + return true; + + case 0x0d: // MOVWL0(Rm, Rn); + 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_CALLH(block, *m_read16); // call read16 + UML_SEXT(block, R32(Rn), I0, SIZE_WORD); // sext Rn, r0, WORD + + if (!in_delay_slot) + generate_update_cycles(block, compiler, desc->pc + 2, true); + return true; + + case 0x0e: // MOVLL0(Rm, Rn); + 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_CALLH(block, *m_read32); // call read32 + UML_MOV(block, R32(Rn), I0); // mov Rn, r0 + + if (!in_delay_slot) + generate_update_cycles(block, compiler, desc->pc + 2, true); + return true; + + case 0x0f: // MAC_L(Rm, Rn); + case 0x1f: // MAC_L(Rm, Rn); + case 0x2f: // MAC_L(Rm, Rn); + case 0x3f: // MAC_L(Rm, Rn); + if (m_cpu_type > CPU_TYPE_SH1) + { + save_fast_iregs(block); + UML_MOV(block, mem(&m_sh2_state->arg0), desc->opptr.w[0]); + UML_CALLC(block, cfunc_MAC_L, this); + load_fast_iregs(block); + return true; + } + break; + + case 0x12: // STCGBR(Rn); + UML_MOV(block, R32(Rn), mem(&m_sh2_state->gbr)); // mov Rn, gbr + return true; + + case 0x18: // SETT(); + UML_OR(block, mem(&m_sh2_state->sr), mem(&m_sh2_state->sr), SH_T); // or sr, sr, T + return true; + + case 0x19: // DIV0U(); + UML_AND(block, mem(&m_sh2_state->sr), mem(&m_sh2_state->sr), ~(SH_M|SH_Q|SH_T)); // and sr, sr, ~(M|Q|T) + return true; + + case 0x1a: // STSMACL(Rn); + UML_MOV(block, R32(Rn), mem(&m_sh2_state->macl)); // mov Rn, macl + return true; + + case 0x1b: // SLEEP(); + UML_MOV(block, I0, mem(&m_sh2_state->sleep_mode)); // mov i0, sleep_mode + UML_CMP(block, I0, 0x2); // cmp i0, #2 + UML_JMPc(block, COND_E, compiler->labelnum); // beq labelnum + // sleep mode != 2 + UML_MOV(block, mem(&m_sh2_state->sleep_mode), 0x1); // mov sleep_mode, #1 + generate_update_cycles(block, compiler, desc->pc, true); // repeat this insn + UML_JMP(block, compiler->labelnum+1); // jmp labelnum+1 + + UML_LABEL(block, compiler->labelnum++); // labelnum: + // sleep_mode == 2 + UML_MOV(block, mem(&m_sh2_state->sleep_mode), 0x0); // sleep_mode = 0 + generate_update_cycles(block, compiler, desc->pc+2, true); // go to next insn + + UML_LABEL(block, compiler->labelnum++); // labelnum+1: + return true; + + case 0x22: // STCVBR(Rn); + UML_MOV(block, R32(Rn), 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 + + generate_delay_slot(block, compiler, desc, m_sh2_state->target); + + generate_update_cycles(block, compiler, mem(&m_sh2_state->target), true); // <subtract cycles> + UML_HASHJMP(block, 0, mem(&m_sh2_state->target), *m_nocode); // jmp target + return true; + } + break; + + case 0x28: // CLRMAC(); + UML_MOV(block, mem(&m_sh2_state->macl), 0); // mov macl, #0 + UML_MOV(block, mem(&m_sh2_state->mach), 0); // mov mach, #0 + return true; + + case 0x29: // MOVT(Rn); + UML_AND(block, R32(Rn), 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 + return true; + + case 0x2b: // RTE(); + return generate_group_0_RTE(block, compiler, desc, opcode, in_delay_slot, ovrpc); + } + + return false; +} + +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_AND(block, I0, I0, SH_FLAGS); // and r0, r0, FLAGS + UML_MOV(block, mem(&m_sh2_state->sr), I0); + + compiler->checkints = true; + return true; +} + +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 + SETEA(0); + UML_CALLH(block, *m_read32); // call read32 + UML_ADD(block, R32(Rn), R32(Rn), 4); // add Rn, #4 + UML_MOV(block, mem(&m_sh2_state->sr), I0); // mov sr, r0 + + compiler->checkints = true; + if (!in_delay_slot) + generate_update_cycles(block, compiler, desc->pc + 2, true); + return true; +} + +bool sh_common_execution::generate_group_4(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, uint16_t opcode, int in_delay_slot, uint32_t ovrpc) +{ + switch (opcode & 0x3F) + { + case 0x00: // SHLL(Rn); + UML_SHL(block, R32(Rn), R32(Rn), 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_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_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_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_MOV(block, I1, mem(&m_sh2_state->mach)); // mov r1, mach + SETEA(0); // set ea for debug + UML_CALLH(block, *m_write32); // call write32 + + if (!in_delay_slot) + generate_update_cycles(block, compiler, desc->pc + 2, true); + 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_MOV(block, I1, mem(&m_sh2_state->sr)); // mov r1, sr + SETEA(0); // set ea for debug + UML_CALLH(block, *m_write32); // call write32 + + if (!in_delay_slot) + generate_update_cycles(block, compiler, desc->pc + 2, true); + return true; + + case 0x06: // LDSMMACH(Rn); + UML_MOV(block, I0, R32(Rn)); // mov r0, Rn + SETEA(0); + UML_CALLH(block, *m_read32); // call read32 + UML_ADD(block, R32(Rn), R32(Rn), 4); // add Rn, #4 + UML_MOV(block, mem(&m_sh2_state->mach), I0); // mov mach, r0 + + if (!in_delay_slot) + generate_update_cycles(block, compiler, desc->pc + 2, true); + return true; + + case 0x07: // LDCMSR(Rn); + 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); + return true; + + case 0x09: // SHLR2(Rn); + UML_SHR(block, R32(Rn), R32(Rn), 2); + return true; + + case 0x18: // SHLL8(Rn); + UML_SHL(block, R32(Rn), R32(Rn), 8); + return true; + + case 0x19: // SHLR8(Rn); + UML_SHR(block, R32(Rn), R32(Rn), 8); + return true; + + case 0x28: // SHLL16(Rn); + UML_SHL(block, R32(Rn), R32(Rn), 16); + return true; + + case 0x29: // SHLR16(Rn); + UML_SHR(block, R32(Rn), R32(Rn), 16); + return true; + + case 0x0a: // LDSMACH(Rn); + UML_MOV(block, mem(&m_sh2_state->mach), R32(Rn)); // mov mach, Rn + return true; + + case 0x0b: // JSR(Rn); + UML_MOV(block, mem(&m_sh2_state->target), R32(Rn)); // 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) + + generate_delay_slot(block, compiler, desc, m_sh2_state->target-4); + + generate_update_cycles(block, compiler, mem(&m_sh2_state->target), true); // <subtract cycles> + UML_HASHJMP(block, 0, mem(&m_sh2_state->target), *m_nocode); // and do the jump + return true; + + case 0x0e: // LDCSR(Rn); + return generate_group_4_LDCSR(block, compiler, desc, opcode, in_delay_slot, ovrpc); + + case 0x0f: // MAC_W(Rm, Rn); + case 0x1f: // MAC_W(Rm, Rn); + case 0x2f: // MAC_W(Rm, Rn); + case 0x3f: // MAC_W(Rm, Rn); + save_fast_iregs(block); + UML_MOV(block, mem(&m_sh2_state->arg0), desc->opptr.w[0]); + UML_CALLC(block, cfunc_MAC_W, this); + load_fast_iregs(block); + return true; + + case 0x10: // DT(Rn); + 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_JMPc(block, COND_NZ, compiler->labelnum); // jz compiler->labelnum + + UML_OR(block, I0, I0, SH_T); // or r0, r0, T + UML_LABEL(block, compiler->labelnum++); // desc->pc: + + UML_MOV(block, mem(&m_sh2_state->sr), I0); // mov m_sh2_state->sr, r0 + return true; + } + break; + + 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_JMPc(block, COND_S, compiler->labelnum); // js compiler->labelnum (if negative) + + UML_OR(block, I0, I0, SH_T); // or r0, r0, T + UML_LABEL(block, compiler->labelnum++); // desc->pc: + + UML_MOV(block, mem(&m_sh2_state->sr), I0); // mov m_sh2_state->sr, r0 + return true; + + 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_JMPc(block, COND_S, compiler->labelnum); // js compiler->labelnum (if negative) + UML_JMPc(block, COND_Z, compiler->labelnum); // jz compiler->labelnum (if zero) + + UML_OR(block, I0, I0, SH_T); // or r0, r0, T + + UML_LABEL(block, compiler->labelnum++); // desc->pc: + UML_MOV(block, mem(&m_sh2_state->sr), I0); // mov m_sh2_state->sr, r0 + 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_MOV(block, I1, mem(&m_sh2_state->macl)); // mov r1, macl + SETEA(0); // set ea for debug + UML_CALLH(block, *m_write32); // call write32 + + if (!in_delay_slot) + generate_update_cycles(block, compiler, desc->pc + 2, true); + 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_MOV(block, I1, mem(&m_sh2_state->gbr)); // mov r1, gbr + SETEA(0); // set ea for debug + UML_CALLH(block, *m_write32); // call write32 + + if (!in_delay_slot) + generate_update_cycles(block, compiler, desc->pc + 2, true); + return true; + + case 0x16: // LDSMMACL(Rn); + UML_MOV(block, I0, R32(Rn)); // mov r0, Rn + SETEA(0); + UML_CALLH(block, *m_read32); // call read32 + UML_ADD(block, R32(Rn), R32(Rn), 4); // add Rn, #4 + UML_MOV(block, mem(&m_sh2_state->macl), I0); // mov macl, r0 + + if (!in_delay_slot) + generate_update_cycles(block, compiler, desc->pc + 2, true); + return true; + + case 0x17: // LDCMGBR(Rn); + UML_MOV(block, I0, R32(Rn)); // mov r0, Rn + SETEA(0); + UML_CALLH(block, *m_read32); // call read32 + UML_ADD(block, R32(Rn), R32(Rn), 4); // add Rn, #4 + UML_MOV(block, mem(&m_sh2_state->gbr), I0); // mov gbr, r0 + + if (!in_delay_slot) + generate_update_cycles(block, compiler, desc->pc + 2, true); + return true; + + case 0x1a: // LDSMACL(Rn); + UML_MOV(block, mem(&m_sh2_state->macl), R32(Rn)); // mov macl, Rn + return true; + + case 0x1b: // TAS(Rn); + UML_MOV(block, I0, R32(Rn)); // mov r0, Rn + SETEA(0); + UML_CALLH(block, *m_read8); // call read8 + + UML_AND(block, mem(&m_sh2_state->sr), mem(&m_sh2_state->sr), ~SH_T); // and sr, sr, ~T + + UML_CMP(block, I0, 0); // cmp r0, #0 + UML_JMPc(block, COND_NZ, compiler->labelnum); // jnz labelnum + + UML_OR(block, mem(&m_sh2_state->sr), mem(&m_sh2_state->sr), SH_T); // or sr, sr, T + + UML_LABEL(block, compiler->labelnum++); // labelnum: + + UML_OR(block, I1, I0, 0x80); // or r1, r0, #0x80 + + UML_MOV(block, I0, R32(Rn)); // mov r0, Rn + UML_CALLH(block, *m_write8); // write the value back + + if (!in_delay_slot) + generate_update_cycles(block, compiler, desc->pc + 2, true); + return true; + + case 0x1e: // LDCGBR(Rn); + UML_MOV(block, mem(&m_sh2_state->gbr), R32(Rn)); // 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_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 + 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_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 + 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 + SETEA(0); + UML_MOV(block, I1, mem(&m_sh2_state->pr)); // mov r1, pr + UML_CALLH(block, *m_write32); // call write32 + + if (!in_delay_slot) + generate_update_cycles(block, compiler, desc->pc + 2, true); + 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 + SETEA(0); + UML_MOV(block, I1, mem(&m_sh2_state->vbr)); // mov r1, vbr + UML_CALLH(block, *m_write32); // call write32 + + if (!in_delay_slot) + generate_update_cycles(block, compiler, desc->pc + 2, true); + return true; + + 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_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_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 + 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 + + 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 + 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 + + 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 + return true; + + case 0x2b: // JMP(Rn); + UML_MOV(block, mem(&m_sh2_state->target), R32(Rn)); // mov target, Rn + + generate_delay_slot(block, compiler, desc, m_sh2_state->target); + + generate_update_cycles(block, compiler, mem(&m_sh2_state->target), true); // <subtract cycles> + UML_HASHJMP(block, 0, mem(&m_sh2_state->target), *m_nocode); // jmp (target) + return true; + + case 0x2e: // LDCVBR(Rn); + UML_MOV(block, mem(&m_sh2_state->vbr), R32(Rn)); // mov vbr, Rn + return true; + + case 0x0c: + case 0x0d: + case 0x14: + case 0x1c: + case 0x1d: + case 0x2c: + case 0x2d: + case 0x30: + case 0x31: + case 0x32: + case 0x33: + case 0x34: + case 0x35: + case 0x36: + case 0x37: + case 0x38: + case 0x39: + case 0x3a: + case 0x3b: + case 0x3c: + case 0x3d: + case 0x3e: + return false; + } + + return false; +} + + +/*************************************************************************** + CORE CALLBACKS +***************************************************************************/ + +/*------------------------------------------------- + sh2drc_set_options - configure DRC options +-------------------------------------------------*/ + +void sh_common_execution::sh2drc_set_options(uint32_t options) +{ + if (!allow_drc()) return; + m_drcoptions = options; +} + + +/*------------------------------------------------- + sh2drc_add_pcflush - add a new address where + the PC must be flushed for speedups to work +-------------------------------------------------*/ + +void sh_common_execution::sh2drc_add_pcflush(offs_t address) +{ + if (!allow_drc()) return; + + if (m_pcfsel < ARRAY_LENGTH(m_pcflushes)) + m_pcflushes[m_pcfsel++] = address; +} diff --git a/src/devices/cpu/sh/sh.h b/src/devices/cpu/sh/sh.h new file mode 100644 index 00000000000..1e41d74385b --- /dev/null +++ b/src/devices/cpu/sh/sh.h @@ -0,0 +1,469 @@ +// license:BSD-3-Clause +// copyright-holders:David Haywood + +#ifndef MAME_CPU_SH_SH_H +#define MAME_CPU_SH_SH_H + +#pragma once + +#include "cpu/drcfe.h" +#include "cpu/drcuml.h" +#include "cpu/drcumlsh.h" + +/*************************************************************************** + DEBUGGING +**************************************************************************/ + +#define DISABLE_FAST_REGISTERS (0) // set to 1 to turn off usage of register caching +#define SINGLE_INSTRUCTION_MODE (0) + +#define SET_EA (0) // makes slower but "shows work" in the EA fake register like the interpreter + +#if SET_EA +#define SETEA(x) UML_MOV(block, mem(&m_sh2_state->ea), ireg(x)) +#else +#define SETEA(x) +#endif + +/*************************************************************************** + CONSTANTS +***************************************************************************/ + +/* speed up delay loops, bail out of tight loops (can cause timer issues) */ +#define BUSY_LOOP_HACKS 0 + +/* compilation boundaries -- how far back/forward does the analysis extend? */ +#define COMPILE_BACKWARDS_BYTES 64 +#define COMPILE_FORWARDS_BYTES 256 +#define COMPILE_MAX_INSTRUCTIONS ((COMPILE_BACKWARDS_BYTES/2) + (COMPILE_FORWARDS_BYTES/2)) +#define COMPILE_MAX_SEQUENCE 64 + +#define SH2DRC_STRICT_VERIFY 0x0001 /* verify all instructions */ +#define SH2DRC_FLUSH_PC 0x0002 /* flush the PC value before each memory access */ +#define SH2DRC_STRICT_PCREL 0x0004 /* do actual loads on MOVLI/MOVWI instead of collapsing to immediates */ + +#define SH2DRC_COMPATIBLE_OPTIONS (SH2DRC_STRICT_VERIFY | SH2DRC_FLUSH_PC | SH2DRC_STRICT_PCREL) +#define SH2DRC_FASTEST_OPTIONS (0) + +/* size of the execution code cache */ +#define CACHE_SIZE (32 * 1024 * 1024) + +#define SH2_MAX_FASTRAM 4 + +/* map variables */ +#define MAPVAR_PC M0 +#define MAPVAR_CYCLES M1 + +/* exit codes */ +#define EXECUTE_OUT_OF_CYCLES 0 +#define EXECUTE_MISSING_CODE 1 +#define EXECUTE_UNMAPPED_CODE 2 +#define EXECUTE_RESET_CACHE 3 + +#define PROBE_ADDRESS ~0 + +#define CPU_TYPE_SH1 (0) +#define CPU_TYPE_SH2 (1) +#define CPU_TYPE_SH3 (2) +#define CPU_TYPE_SH4 (3) + +#define Rn ((opcode>>8)&15) +#define Rm ((opcode>>4)&15) + +/* Bits in SR */ +#define SH_T 0x00000001 +#define SH_S 0x00000002 +#define SH_I 0x000000f0 +#define SH_Q 0x00000100 +#define SH_M 0x00000200 + +#define SH_FLAGS (SH_M|SH_Q|SH_I|SH_S|SH_T) + +#define REGFLAG_R(n) (1 << (n)) + +/* register flags 1 */ +#define REGFLAG_PR (1 << 0) +#define REGFLAG_MACL (1 << 1) +#define REGFLAG_MACH (1 << 2) +#define REGFLAG_GBR (1 << 3) +#define REGFLAG_VBR (1 << 4) +#define REGFLAG_SR (1 << 5) + +/*************************************************************************** + 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 R32(reg) m_regmap[reg] + +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 +}; + +class sh_common_execution : public cpu_device +{ + +public: + sh_common_execution(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock, endianness_t endianness, address_map_constructor internal) + : cpu_device(mconfig, type, tag, owner, clock) + , m_sh2_state(nullptr) + , m_cache(CACHE_SIZE + sizeof(internal_sh2_state)) + , m_drcuml(nullptr) + , m_drcoptions(0) + , m_entry(nullptr) + , m_read8(nullptr) + , m_write8(nullptr) + , m_read16(nullptr) + , m_write16(nullptr) + , m_read32(nullptr) + , m_write32(nullptr) + , m_interrupt(nullptr) + , m_nocode(nullptr) + , m_out_of_cycles(nullptr) + , m_xor(0) + { } + + // Data that needs to be stored close to the generated DRC code + struct internal_sh2_state + { + uint32_t pc; + uint32_t pr; + uint32_t sr; + uint32_t mach; + uint32_t macl; + uint32_t r[16]; + uint32_t ea; + + uint32_t pending_irq; + uint32_t pending_nmi; + int32_t irqline; + uint32_t evec; // exception vector for DRC + uint32_t irqsr; // IRQ-time old SR for DRC + uint32_t target; // target for jmp/jsr/etc so the delay slot can't kill it + int internal_irq_level; + int icount; + uint8_t sleep_mode; + uint32_t arg0; /* print_debug argument 1 */ + uint32_t arg1; + uint32_t gbr; + uint32_t vbr; + + uint32_t m_delay; + }; + + 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; + +protected: + + void ADD(uint32_t m, uint32_t n); + void ADDI(uint32_t i, uint32_t n); + void ADDC(uint32_t m, uint32_t n); + void ADDV(uint32_t m, uint32_t n); + void AND(uint32_t m, uint32_t n); + void ANDI(uint32_t i); + void ANDM(uint32_t i); + void BF(uint32_t d); + void BFS(uint32_t d); + void BRA(uint32_t d); + void BRAF(uint32_t m); + void BSR(uint32_t d); + void BSRF(uint32_t m); + void BT(uint32_t d); + void BTS(uint32_t d); + void CLRMAC(); + void CLRT(); + void CMPEQ(uint32_t m, uint32_t n); + void CMPGE(uint32_t m, uint32_t n); + void CMPGT(uint32_t m, uint32_t n); + void CMPHI(uint32_t m, uint32_t n); + void CMPHS(uint32_t m, uint32_t n); + void CMPPL(uint32_t n); + void CMPPZ(uint32_t n); + void CMPSTR(uint32_t m, uint32_t n); + void CMPIM(uint32_t i); + void DIV0S(uint32_t m, uint32_t n); + void DIV0U(); + void DIV1(uint32_t m, uint32_t n); + void DMULS(uint32_t m, uint32_t n); + void DMULU(uint32_t m, uint32_t n); + void DT(uint32_t n); + void EXTSB(uint32_t m, uint32_t n); + void EXTSW(uint32_t m, uint32_t n); + void EXTUB(uint32_t m, uint32_t n); + void EXTUW(uint32_t m, uint32_t n); + void JMP(uint32_t m); + void JSR(uint32_t m); + void LDCGBR(uint32_t m); + void LDCVBR(uint32_t m); + void LDCMGBR(uint32_t m); + void LDCMVBR(uint32_t m); + void LDSMACH(uint32_t m); + void LDSMACL(uint32_t m); + void LDSPR(uint32_t m); + void LDSMMACH(uint32_t m); + void LDSMMACL(uint32_t m); + void LDSMPR(uint32_t m); + void MAC_L(uint32_t m, uint32_t n); + void MAC_W(uint32_t m, uint32_t n); + void MOV(uint32_t m, uint32_t n); + void MOVBS(uint32_t m, uint32_t n); + void MOVWS(uint32_t m, uint32_t n); + void MOVLS(uint32_t m, uint32_t n); + void MOVBL(uint32_t m, uint32_t n); + void MOVWL(uint32_t m, uint32_t n); + void MOVLL(uint32_t m, uint32_t n); + void MOVBM(uint32_t m, uint32_t n); + void MOVWM(uint32_t m, uint32_t n); + void MOVLM(uint32_t m, uint32_t n); + void MOVBP(uint32_t m, uint32_t n); + void MOVWP(uint32_t m, uint32_t n); + void MOVLP(uint32_t m, uint32_t n); + void MOVBS0(uint32_t m, uint32_t n); + void MOVWS0(uint32_t m, uint32_t n); + void MOVLS0(uint32_t m, uint32_t n); + void MOVBL0(uint32_t m, uint32_t n); + void MOVWL0(uint32_t m, uint32_t n); + void MOVLL0(uint32_t m, uint32_t n); + void MOVI(uint32_t i, uint32_t n); + void MOVWI(uint32_t d, uint32_t n); + void MOVLI(uint32_t d, uint32_t n); + void MOVBLG(uint32_t d); + void MOVWLG(uint32_t d); + void MOVLLG(uint32_t d); + void MOVBSG(uint32_t d); + void MOVWSG(uint32_t d); + void MOVLSG(uint32_t d); + void MOVBS4(uint32_t d, uint32_t n); + void MOVWS4(uint32_t d, uint32_t n); + void MOVLS4(uint32_t m, uint32_t d, uint32_t n); + void MOVBL4(uint32_t m, uint32_t d); + void MOVWL4(uint32_t m, uint32_t d); + void MOVLL4(uint32_t m, uint32_t d, uint32_t n); + void MOVA(uint32_t d); + void MOVT(uint32_t n); + void MULL(uint32_t m, uint32_t n); + void MULS(uint32_t m, uint32_t n); + void MULU(uint32_t m, uint32_t n); + void NEG(uint32_t m, uint32_t n); + void NEGC(uint32_t m, uint32_t n); + void NOP(void); + void NOT(uint32_t m, uint32_t n); + void OR(uint32_t m, uint32_t n); + void ORI(uint32_t i); + void ORM(uint32_t i); + void ROTCL(uint32_t n); + void ROTCR(uint32_t n); + void ROTL(uint32_t n); + void ROTR(uint32_t n); + void RTS(); + void SETT(); + void SHAL(uint32_t n); + void SHAR(uint32_t n); + void SHLL(uint32_t n); + void SHLL2(uint32_t n); + void SHLL8(uint32_t n); + void SHLL16(uint32_t n); + void SHLR(uint32_t n); + void SHLR2(uint32_t n); + void SHLR8(uint32_t n); + void SHLR16(uint32_t n); + void SLEEP(); + void STCSR(uint32_t n); + void STCGBR(uint32_t n); + void STCVBR(uint32_t n); + void STCMSR(uint32_t n); + void STCMGBR(uint32_t n); + void STCMVBR(uint32_t n); + void STSMACH(uint32_t n); + void STSMACL(uint32_t n); + void STSPR(uint32_t n); + void STSMMACH(uint32_t n); + void STSMMACL(uint32_t n); + void STSMPR(uint32_t n); + void SUB(uint32_t m, uint32_t n); + void SUBC(uint32_t m, uint32_t n); + void SUBV(uint32_t m, uint32_t n); + void SWAPB(uint32_t m, uint32_t n); + void SWAPW(uint32_t m, uint32_t n); + void TAS(uint32_t n); + void TST(uint32_t m, uint32_t n); + void TSTI(uint32_t i); + void TSTM(uint32_t i); + void XOR(uint32_t m, uint32_t n); + void XORI(uint32_t i); + void XORM(uint32_t i); + void XTRCT(uint32_t m, uint32_t n); + + void op0010(uint16_t opcode); + void op0011(uint16_t opcode); + void op0110(uint16_t opcode); + void op1000(uint16_t opcode); + void op1100(uint16_t opcode); + + void execute_one(const uint16_t opcode); + + virtual void execute_one_0000(uint16_t opcode); + virtual void execute_one_4000(uint16_t opcode); + virtual void execute_one_f000(uint16_t opcode) = 0; + + virtual void RTE() = 0; + virtual void LDCSR(const uint16_t opcode) = 0; + virtual void LDCMSR(const uint16_t opcode) = 0; + virtual void TRAPA(uint32_t i) = 0; + virtual void ILLEGAL() = 0; + + drc_cache m_cache; /* pointer to the DRC code cache */ + +public: + /* fast RAM */ + uint32_t m_fastram_select; + struct + { + offs_t start; /* start of the RAM block */ + offs_t end; /* end of the RAM block */ + bool readonly; /* true if read-only */ + void * base; /* base in memory where the RAM lives */ + } m_fastram[SH2_MAX_FASTRAM]; + + int m_pcfsel; // last pcflush entry set + uint32_t m_pcflushes[16]; // pcflush entries + + virtual void init_drc_frontend() = 0; + + void drc_start(); + + void sh2drc_add_fastram(offs_t start, offs_t end, uint8_t readonly, void *base); + + direct_read_data<0> *m_direct; + address_space *m_program; + + std::unique_ptr<drcuml_state> m_drcuml; /* DRC UML generator state */ + uint32_t m_drcoptions; /* configurable DRC options */ + + /* internal stuff */ + uint8_t m_cache_dirty; /* true if we need to flush the cache */ + + /* register mappings */ + uml::parameter m_regmap[16]; /* parameter to register mappings for all 16 integer registers */ + + uml::code_handle * m_entry; /* entry point */ + uml::code_handle * m_read8; /* read byte */ + uml::code_handle * m_write8; /* write byte */ + uml::code_handle * m_read16; /* read half */ + uml::code_handle * m_write16; /* write half */ + uml::code_handle * m_read32; /* read word */ + uml::code_handle * m_write32; /* write word */ + + uml::code_handle * m_interrupt; /* interrupt */ + uml::code_handle * m_nocode; /* nocode */ + uml::code_handle * m_out_of_cycles; /* out of cycles exception handler */ + + /* internal compiler state */ + struct compiler_state + { + uint32_t cycles; /* accumulated cycles */ + uint8_t checkints; /* need to check interrupts before next instruction */ + 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 generate_update_cycles(drcuml_block *block, compiler_state *compiler, uml::parameter param, bool allow_exception) = 0; + + virtual bool generate_group_0_RTE(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, uint16_t opcode, int in_delay_slot, uint32_t ovrpc); + virtual bool generate_group_4_LDCSR(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, uint16_t opcode, int in_delay_slot, uint32_t ovrpc); + virtual bool generate_group_4_LDCMSR(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, uint16_t opcode, int in_delay_slot, uint32_t ovrpc); + virtual bool generate_group_12_TRAPA(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, uint16_t opcode, int in_delay_slot, uint32_t ovrpc); + + + bool generate_opcode(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, uint32_t ovrpc); + virtual bool generate_group_0(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, uint16_t opcode, int in_delay_slot, uint32_t ovrpc); + bool generate_group_2(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, uint16_t opcode, int in_delay_slot, uint32_t ovrpc); + bool generate_group_3(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, uint16_t opcode, uint32_t ovrpc); + virtual bool generate_group_4(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, uint16_t opcode, int in_delay_slot, uint32_t ovrpc); + bool generate_group_6(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, uint16_t opcode, int in_delay_slot, uint32_t ovrpc); + bool generate_group_8(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, uint16_t opcode, int in_delay_slot, uint32_t ovrpc); + bool generate_group_12(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, uint16_t opcode, int in_delay_slot, uint32_t ovrpc); + virtual bool generate_group_15(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, uint16_t opcode, int in_delay_slot, uint32_t ovrpc); + + void func_printf_probe(); + void func_unimplemented(); + void func_MAC_W(); + void func_MAC_L(); + void func_DIV1(); + void func_ADDV(); + void func_SUBV(); + + int m_cpu_type; + uint32_t m_am; + bool m_isdrc; + int m_xor; + + void sh2drc_set_options(uint32_t options); + void sh2drc_add_pcflush(offs_t address); + + virtual void static_generate_entry_point() = 0; + virtual void static_generate_memory_accessor(int size, int iswrite, const char *name, uml::code_handle **handleptr) = 0; + virtual const opcode_desc* get_desclist(offs_t pc) = 0; + + uint32_t epc(const opcode_desc *desc); + void alloc_handle(drcuml_state *drcuml, uml::code_handle **handleptr, const char *name); + void load_fast_iregs(drcuml_block *block); + void save_fast_iregs(drcuml_block *block); + const char *log_desc_flags_to_string(uint32_t flags); + void log_register_list(drcuml_state *drcuml, const char *string, const uint32_t *reglist, const uint32_t *regnostarlist); + void log_opcode_desc(drcuml_state *drcuml, const opcode_desc *desclist, int indent); + void log_add_disasm_comment(drcuml_block *block, uint32_t pc, uint32_t op); + void generate_delay_slot(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, uint32_t ovrpc); + void generate_checksum_block(drcuml_block *block, compiler_state *compiler, const opcode_desc *seqhead, const opcode_desc *seqlast); + void generate_sequence_instruction(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, uint32_t ovrpc); + void static_generate_nocode_handler(); + void static_generate_out_of_cycles(); + void code_flush_cache(); + void execute_run_drc(); + void code_compile_block(uint8_t mode, offs_t pc); + + +protected: + // device-level overrides + virtual void device_start() override; +}; + +class sh_frontend : public drc_frontend +{ +public: + sh_frontend(sh_common_execution *device, uint32_t window_start, uint32_t window_end, uint32_t max_sequence); + +protected: + virtual uint16_t read_word(opcode_desc &desc); + virtual bool describe(opcode_desc &desc, const opcode_desc *prev) override; + +private: + bool describe_group_2(opcode_desc &desc, const opcode_desc *prev, uint16_t opcode); + bool describe_group_3(opcode_desc &desc, const opcode_desc *prev, uint16_t opcode); + bool describe_group_6(opcode_desc &desc, const opcode_desc *prev, uint16_t opcode); + bool describe_group_8(opcode_desc &desc, const opcode_desc *prev, uint16_t opcode); + bool describe_group_12(opcode_desc &desc, const opcode_desc *prev, uint16_t opcode); + +protected: + virtual bool describe_group_0(opcode_desc &desc, const opcode_desc *prev, uint16_t opcode); + virtual bool describe_group_4(opcode_desc &desc, const opcode_desc *prev, uint16_t opcode); + virtual bool describe_group_15(opcode_desc &desc, const opcode_desc *prev, uint16_t opcode) = 0; + + sh_common_execution *m_sh; +}; + +#endif // MAME_CPU_SH2_SH2_H diff --git a/src/devices/cpu/sh/sh2.cpp b/src/devices/cpu/sh/sh2.cpp index 9b1cf8dcbbf..3d565fb3519 100644 --- a/src/devices/cpu/sh/sh2.cpp +++ b/src/devices/cpu/sh/sh2.cpp @@ -95,33 +95,13 @@ #include "emu.h" #include "sh2.h" #include "sh2comn.h" - +#include "sh_dasm.h" #include "debugger.h" //#define VERBOSE 1 #include "logmacro.h" -/*************************************************************************** - DEBUGGING -***************************************************************************/ - -#define DISABLE_FAST_REGISTERS (0) // set to 1 to turn off usage of register caching -#define SINGLE_INSTRUCTION_MODE (0) - - -/*************************************************************************** - CONSTANTS -***************************************************************************/ - -/* size of the execution code cache */ -#define CACHE_SIZE (32 * 1024 * 1024) - -/* compilation boundaries -- how far back/forward does the analysis extend? */ -#define COMPILE_BACKWARDS_BYTES 64 -#define COMPILE_FORWARDS_BYTES 256 -#define COMPILE_MAX_INSTRUCTIONS ((COMPILE_BACKWARDS_BYTES/2) + (COMPILE_FORWARDS_BYTES/2)) -#define COMPILE_MAX_SEQUENCE 64 DEFINE_DEVICE_TYPE(SH1, sh1_device, "sh1", "SH-1") @@ -182,30 +162,18 @@ void sh2_device::device_stop() } + + 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) - : cpu_device(mconfig, type, tag, owner, clock) + : 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_cpu_type(cpu_type) - , m_cache(CACHE_SIZE + sizeof(internal_sh2_state)) - , m_drcuml(nullptr) -// , m_drcuml(*this, m_cache, 0, 1, 32, 1) , m_drcfe(nullptr) - , m_drcoptions(0) - , m_sh2_state(nullptr) - , m_entry(nullptr) - , m_read8(nullptr) - , m_write8(nullptr) - , m_read16(nullptr) - , m_write16(nullptr) - , m_read32(nullptr) - , m_write32(nullptr) - , m_interrupt(nullptr) - , m_nocode(nullptr) - , m_out_of_cycles(nullptr) , m_debugger_temp(0) { + m_cpu_type = cpu_type; + m_am = SH12_AM; m_isdrc = allow_drc(); } @@ -232,20 +200,15 @@ device_memory_interface::space_config_vector sh2_device::memory_space_config() c }; } -offs_t sh2_device::disasm_disassemble(std::ostream &stream, offs_t pc, const uint8_t *oprom, const uint8_t *opram, uint32_t options) +util::disasm_interface *sh2_device::create_disassembler() { - extern CPU_DISASSEMBLE( sh2 ); - return CPU_DISASSEMBLE_NAME( sh2 )(this, stream, pc, oprom, opram, options); + return new sh_disassembler(false); } - -/* speed up delay loops, bail out of tight loops */ -#define BUSY_LOOP_HACKS 1 - uint8_t sh2_device::RB(offs_t A) { if((A & 0xf0000000) == 0 || (A & 0xf0000000) == 0x20000000) - return m_program->read_byte(A & AM); + return m_program->read_byte(A & SH12_AM); return m_program->read_byte(A); } @@ -253,7 +216,7 @@ uint8_t sh2_device::RB(offs_t A) uint16_t sh2_device::RW(offs_t A) { if((A & 0xf0000000) == 0 || (A & 0xf0000000) == 0x20000000) - return m_program->read_word(A & AM); + return m_program->read_word(A & SH12_AM); return m_program->read_word(A); } @@ -263,7 +226,7 @@ uint32_t sh2_device::RL(offs_t A) /* 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 & AM); + return m_program->read_dword(A & SH12_AM); return m_program->read_dword(A); } @@ -272,7 +235,7 @@ void sh2_device::WB(offs_t A, uint8_t V) { if((A & 0xf0000000) == 0 || (A & 0xf0000000) == 0x20000000) { - m_program->write_byte(A & AM,V); + m_program->write_byte(A & SH12_AM,V); return; } @@ -283,7 +246,7 @@ void sh2_device::WW(offs_t A, uint16_t V) { if((A & 0xf0000000) == 0 || (A & 0xf0000000) == 0x20000000) { - m_program->write_word(A & AM,V); + m_program->write_word(A & SH12_AM,V); return; } @@ -294,7 +257,7 @@ void sh2_device::WL(offs_t A, uint32_t V) { if((A & 0xf0000000) == 0 || (A & 0xf0000000) == 0x20000000) { - m_program->write_dword(A & AM,V); + m_program->write_dword(A & SH12_AM,V); return; } @@ -303,1528 +266,42 @@ void sh2_device::WL(offs_t A, uint32_t V) m_program->write_dword(A,V); } -/* code cycles t-bit - * 0011 nnnn mmmm 1100 1 - - * ADD Rm,Rn - */ -void sh2_device::ADD(uint32_t m, uint32_t n) -{ - m_sh2_state->r[n] += m_sh2_state->r[m]; -} - -/* code cycles t-bit - * 0111 nnnn iiii iiii 1 - - * ADD #imm,Rn - */ -void sh2_device::ADDI(uint32_t i, uint32_t n) -{ - m_sh2_state->r[n] += (int32_t)(int16_t)(int8_t)i; -} - -/* code cycles t-bit - * 0011 nnnn mmmm 1110 1 carry - * ADDC Rm,Rn - */ -void sh2_device::ADDC(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]; - m_sh2_state->r[n] = tmp1 + (m_sh2_state->sr & T); - if (tmp0 > tmp1) - m_sh2_state->sr |= T; - else - m_sh2_state->sr &= ~T; - if (tmp1 > m_sh2_state->r[n]) - m_sh2_state->sr |= T; -} - -/* code cycles t-bit - * 0011 nnnn mmmm 1111 1 overflow - * ADDV Rm,Rn - */ -void sh2_device::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; - 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; - ans += dest; - if (src == 0 || src == 2) - { - if (ans == 1) - m_sh2_state->sr |= T; - else - m_sh2_state->sr &= ~T; - } - else - m_sh2_state->sr &= ~T; -} - -/* code cycles t-bit - * 0010 nnnn mmmm 1001 1 - - * AND Rm,Rn - */ -void sh2_device::AND(uint32_t m, uint32_t n) -{ - m_sh2_state->r[n] &= m_sh2_state->r[m]; -} - - -/* code cycles t-bit - * 1100 1001 iiii iiii 1 - - * AND #imm,R0 - */ -void sh2_device::ANDI(uint32_t i) -{ - m_sh2_state->r[0] &= i; -} - -/* code cycles t-bit - * 1100 1101 iiii iiii 1 - - * AND.B #imm,@(R0,GBR) - */ -void sh2_device::ANDM(uint32_t i) +/* LDC.L @Rm+,SR */ +inline void sh2_device::LDCMSR(const uint16_t opcode) // passes Rn { - uint32_t temp; + uint32_t x = Rn; - 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 ); + 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; m_sh2_state->icount -= 2; -} - -/* code cycles t-bit - * 1000 1011 dddd dddd 3/1 - - * BF disp8 - */ -void sh2_device::BF(uint32_t d) -{ - if ((m_sh2_state->sr & T) == 0) - { - int32_t disp = ((int32_t)d << 24) >> 24; - m_sh2_state->pc = m_sh2_state->ea = m_sh2_state->pc + disp * 2 + 2; - m_sh2_state->icount -= 2; - } -} - -/* code cycles t-bit - * 1000 1111 dddd dddd 3/1 - - * BFS disp8 - */ -void sh2_device::BFS(uint32_t d) -{ - if ((m_sh2_state->sr & T) == 0) - { - int32_t disp = ((int32_t)d << 24) >> 24; - m_delay = m_sh2_state->ea = m_sh2_state->pc + disp * 2 + 2; - m_sh2_state->icount--; - } -} - -/* code cycles t-bit - * 1010 dddd dddd dddd 2 - - * BRA disp12 - */ -void sh2_device::BRA(uint32_t d) -{ - int32_t disp = ((int32_t)d << 20) >> 20; - -#if BUSY_LOOP_HACKS - if (disp == -2) - { - uint32_t next_opcode = RW(m_sh2_state->pc & AM); - /* BRA $ - * NOP - */ - if (next_opcode == 0x0009) - m_sh2_state->icount %= 3; /* cycles for BRA $ and NOP taken (3) */ - } -#endif - m_delay = m_sh2_state->ea = m_sh2_state->pc + disp * 2 + 2; - m_sh2_state->icount--; -} - -/* code cycles t-bit - * 0000 mmmm 0010 0011 2 - - * BRAF Rm - */ -void sh2_device::BRAF(uint32_t m) -{ - m_delay = m_sh2_state->pc + m_sh2_state->r[m] + 2; - m_sh2_state->icount--; -} - -/* code cycles t-bit - * 1011 dddd dddd dddd 2 - - * BSR disp12 - */ -void sh2_device::BSR(uint32_t d) -{ - int32_t disp = ((int32_t)d << 20) >> 20; - - m_sh2_state->pr = m_sh2_state->pc + 2; - m_delay = m_sh2_state->ea = m_sh2_state->pc + disp * 2 + 2; - m_sh2_state->icount--; -} - -/* code cycles t-bit - * 0000 mmmm 0000 0011 2 - - * BSRF Rm - */ -void sh2_device::BSRF(uint32_t m) -{ - m_sh2_state->pr = m_sh2_state->pc + 2; - m_delay = m_sh2_state->pc + m_sh2_state->r[m] + 2; - m_sh2_state->icount--; -} - -/* code cycles t-bit - * 1000 1001 dddd dddd 3/1 - - * BT disp8 - */ -void sh2_device::BT(uint32_t d) -{ - if ((m_sh2_state->sr & T) != 0) - { - int32_t disp = ((int32_t)d << 24) >> 24; - m_sh2_state->pc = m_sh2_state->ea = m_sh2_state->pc + disp * 2 + 2; - m_sh2_state->icount -= 2; - } -} - -/* code cycles t-bit - * 1000 1101 dddd dddd 2/1 - - * BTS disp8 - */ -void sh2_device::BTS(uint32_t d) -{ - if ((m_sh2_state->sr & T) != 0) - { - int32_t disp = ((int32_t)d << 24) >> 24; - m_delay = m_sh2_state->ea = m_sh2_state->pc + disp * 2 + 2; - m_sh2_state->icount--; - } -} - -/* code cycles t-bit - * 0000 0000 0010 1000 1 - - * CLRMAC - */ -void sh2_device::CLRMAC() -{ - m_sh2_state->mach = 0; - m_sh2_state->macl = 0; -} - -/* code cycles t-bit - * 0000 0000 0000 1000 1 - - * CLRT - */ -void sh2_device::CLRT() -{ - m_sh2_state->sr &= ~T; -} - -/* code cycles t-bit - * 0011 nnnn mmmm 0000 1 comparison result - * CMP_EQ Rm,Rn - */ -void sh2_device::CMPEQ(uint32_t m, uint32_t n) -{ - if (m_sh2_state->r[n] == m_sh2_state->r[m]) - m_sh2_state->sr |= T; - else - m_sh2_state->sr &= ~T; -} - -/* code cycles t-bit - * 0011 nnnn mmmm 0011 1 comparison result - * CMP_GE Rm,Rn - */ -void sh2_device::CMPGE(uint32_t m, uint32_t n) -{ - if ((int32_t) m_sh2_state->r[n] >= (int32_t) m_sh2_state->r[m]) - m_sh2_state->sr |= T; - else - m_sh2_state->sr &= ~T; -} - -/* code cycles t-bit - * 0011 nnnn mmmm 0111 1 comparison result - * CMP_GT Rm,Rn - */ -void sh2_device::CMPGT(uint32_t m, uint32_t n) -{ - if ((int32_t) m_sh2_state->r[n] > (int32_t) m_sh2_state->r[m]) - m_sh2_state->sr |= T; - else - m_sh2_state->sr &= ~T; -} - -/* code cycles t-bit - * 0011 nnnn mmmm 0110 1 comparison result - * CMP_HI Rm,Rn - */ -void sh2_device::CMPHI(uint32_t m, uint32_t n) -{ - if ((uint32_t) m_sh2_state->r[n] > (uint32_t) m_sh2_state->r[m]) - m_sh2_state->sr |= T; - else - m_sh2_state->sr &= ~T; -} - -/* code cycles t-bit - * 0011 nnnn mmmm 0010 1 comparison result - * CMP_HS Rm,Rn - */ -void sh2_device::CMPHS(uint32_t m, uint32_t n) -{ - if ((uint32_t) m_sh2_state->r[n] >= (uint32_t) m_sh2_state->r[m]) - m_sh2_state->sr |= T; - else - m_sh2_state->sr &= ~T; -} - - -/* code cycles t-bit - * 0100 nnnn 0001 0101 1 comparison result - * CMP_PL Rn - */ -void sh2_device::CMPPL(uint32_t n) -{ - if ((int32_t) m_sh2_state->r[n] > 0) - m_sh2_state->sr |= T; - else - m_sh2_state->sr &= ~T; -} - -/* code cycles t-bit - * 0100 nnnn 0001 0001 1 comparison result - * CMP_PZ Rn - */ -void sh2_device::CMPPZ(uint32_t n) -{ - if ((int32_t) m_sh2_state->r[n] >= 0) - m_sh2_state->sr |= T; - else - m_sh2_state->sr &= ~T; -} - -/* code cycles t-bit - * 0010 nnnn mmmm 1100 1 comparison result - * CMP_STR Rm,Rn - */ -void sh2_device::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) - m_sh2_state->sr &= ~T; - else - m_sh2_state->sr |= T; - } - - -/* code cycles t-bit - * 1000 1000 iiii iiii 1 comparison result - * CMP/EQ #imm,R0 - */ -void sh2_device::CMPIM(uint32_t i) -{ - uint32_t imm = (uint32_t)(int32_t)(int16_t)(int8_t)i; - - if (m_sh2_state->r[0] == imm) - m_sh2_state->sr |= T; - else - m_sh2_state->sr &= ~T; -} - -/* code cycles t-bit - * 0010 nnnn mmmm 0111 1 calculation result - * DIV0S Rm,Rn - */ -void sh2_device::DIV0S(uint32_t m, uint32_t n) -{ - if ((m_sh2_state->r[n] & 0x80000000) == 0) - m_sh2_state->sr &= ~Q; - else - m_sh2_state->sr |= Q; - if ((m_sh2_state->r[m] & 0x80000000) == 0) - m_sh2_state->sr &= ~M; - else - m_sh2_state->sr |= M; - if ((m_sh2_state->r[m] ^ m_sh2_state->r[n]) & 0x80000000) - m_sh2_state->sr |= T; - else - m_sh2_state->sr &= ~T; -} - -/* code cycles t-bit - * 0000 0000 0001 1001 1 0 - * DIV0U - */ -void sh2_device::DIV0U() -{ - m_sh2_state->sr &= ~(M | Q | T); -} - -/* code cycles t-bit - * 0011 nnnn mmmm 0100 1 calculation result - * DIV1 Rm,Rn - */ -void sh2_device::DIV1(uint32_t m, uint32_t n) -{ - uint32_t tmp0; - uint32_t old_q; - - old_q = m_sh2_state->sr & Q; - if (0x80000000 & m_sh2_state->r[n]) - m_sh2_state->sr |= Q; - else - m_sh2_state->sr &= ~Q; - - m_sh2_state->r[n] = (m_sh2_state->r[n] << 1) | (m_sh2_state->sr & T); - - if (!old_q) - { - if (!(m_sh2_state->sr & M)) - { - tmp0 = m_sh2_state->r[n]; - m_sh2_state->r[n] -= m_sh2_state->r[m]; - if(!(m_sh2_state->sr & Q)) - if(m_sh2_state->r[n] > tmp0) - m_sh2_state->sr |= Q; - else - m_sh2_state->sr &= ~Q; - else - if(m_sh2_state->r[n] > tmp0) - m_sh2_state->sr &= ~Q; - else - m_sh2_state->sr |= Q; - } - else - { - tmp0 = m_sh2_state->r[n]; - m_sh2_state->r[n] += m_sh2_state->r[m]; - if(!(m_sh2_state->sr & Q)) - { - if(m_sh2_state->r[n] < tmp0) - m_sh2_state->sr &= ~Q; - else - m_sh2_state->sr |= Q; - } - else - { - if(m_sh2_state->r[n] < tmp0) - m_sh2_state->sr |= Q; - else - m_sh2_state->sr &= ~Q; - } - } - } - else - { - if (!(m_sh2_state->sr & M)) - { - tmp0 = m_sh2_state->r[n]; - m_sh2_state->r[n] += m_sh2_state->r[m]; - if(!(m_sh2_state->sr & Q)) - if(m_sh2_state->r[n] < tmp0) - m_sh2_state->sr |= Q; - else - m_sh2_state->sr &= ~Q; - else - if(m_sh2_state->r[n] < tmp0) - m_sh2_state->sr &= ~Q; - else - m_sh2_state->sr |= Q; - } - else - { - tmp0 = m_sh2_state->r[n]; - m_sh2_state->r[n] -= m_sh2_state->r[m]; - if(!(m_sh2_state->sr & Q)) - if(m_sh2_state->r[n] > tmp0) - m_sh2_state->sr &= ~Q; - else - m_sh2_state->sr |= Q; - else - if(m_sh2_state->r[n] > tmp0) - m_sh2_state->sr |= Q; - else - m_sh2_state->sr &= ~Q; - } - } - - tmp0 = (m_sh2_state->sr & (Q | M)); - if((!tmp0) || (tmp0 == 0x300)) /* if Q == M set T else clear T */ - m_sh2_state->sr |= T; - else - m_sh2_state->sr &= ~T; -} - -/* DMULS.L Rm,Rn */ -void sh2_device::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; - - 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) - { - Res2 = ~Res2; - if (Res0 == 0) - Res2++; - else - Res0 = (~Res0) + 1; - } - m_sh2_state->mach = Res2; - m_sh2_state->macl = Res0; - m_sh2_state->icount--; -} - -/* DMULU.L Rm,Rn */ -void sh2_device::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; - m_sh2_state->icount--; -} - -/* DT Rn */ -void sh2_device::DT(uint32_t n) -{ - m_sh2_state->r[n]--; - if (m_sh2_state->r[n] == 0) - m_sh2_state->sr |= T; - else - m_sh2_state->sr &= ~T; -#if BUSY_LOOP_HACKS - { - uint32_t next_opcode = RW(m_sh2_state->pc & AM); - /* DT Rn - * BF $-2 - */ - if (next_opcode == 0x8bfd) - { - while (m_sh2_state->r[n] > 1 && m_sh2_state->icount > 4) - { - m_sh2_state->r[n]--; - m_sh2_state->icount -= 4; /* cycles for DT (1) and BF taken (3) */ - } - } - } -#endif -} - -/* EXTS.B Rm,Rn */ -void sh2_device::EXTSB(uint32_t m, uint32_t n) -{ - m_sh2_state->r[n] = ((int32_t)m_sh2_state->r[m] << 24) >> 24; -} - -/* EXTS.W Rm,Rn */ -void sh2_device::EXTSW(uint32_t m, uint32_t n) -{ - m_sh2_state->r[n] = ((int32_t)m_sh2_state->r[m] << 16) >> 16; -} - -/* EXTU.B Rm,Rn */ -void sh2_device::EXTUB(uint32_t m, uint32_t n) -{ - m_sh2_state->r[n] = m_sh2_state->r[m] & 0x000000ff; -} - -/* EXTU.W Rm,Rn */ -void sh2_device::EXTUW(uint32_t m, uint32_t n) -{ - m_sh2_state->r[n] = m_sh2_state->r[m] & 0x0000ffff; -} - -/* ILLEGAL */ -void sh2_device::ILLEGAL() -{ - logerror("SH2.%s: Illegal opcode at %08x\n", tag(), m_sh2_state->pc - 2); - m_sh2_state->r[15] -= 4; - WL( 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 */ - - /* fetch PC */ - m_sh2_state->pc = RL( m_sh2_state->vbr + 4 * 4 ); - - /* TODO: timing is a guess */ - m_sh2_state->icount -= 5; -} - - -/* JMP @Rm */ -void sh2_device::JMP(uint32_t m) -{ - m_delay = m_sh2_state->ea = m_sh2_state->r[m]; - m_sh2_state->icount--; -} - -/* JSR @Rm */ -void sh2_device::JSR(uint32_t m) -{ - m_sh2_state->pr = m_sh2_state->pc + 2; - m_delay = m_sh2_state->ea = m_sh2_state->r[m]; - m_sh2_state->icount--; -} - - -/* LDC Rm,SR */ -void sh2_device::LDCSR(uint32_t m) -{ - m_sh2_state->sr = m_sh2_state->r[m] & FLAGS; m_test_irq = 1; } -/* LDC Rm,GBR */ -void sh2_device::LDCGBR(uint32_t m) -{ - m_sh2_state->gbr = m_sh2_state->r[m]; -} - -/* LDC Rm,VBR */ -void sh2_device::LDCVBR(uint32_t m) +/* LDC Rm,SR */ +inline void sh2_device::LDCSR(const uint16_t opcode) // passes Rn { - m_sh2_state->vbr = m_sh2_state->r[m]; -} + uint32_t x = Rn; -/* LDC.L @Rm+,SR */ -void sh2_device::LDCMSR(uint32_t m) -{ - m_sh2_state->ea = m_sh2_state->r[m]; - m_sh2_state->sr = RL( m_sh2_state->ea ) & FLAGS; - m_sh2_state->r[m] += 4; - m_sh2_state->icount -= 2; + m_sh2_state->sr = m_sh2_state->r[x] & SH_FLAGS; m_test_irq = 1; } -/* LDC.L @Rm+,GBR */ -void sh2_device::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->r[m] += 4; - m_sh2_state->icount -= 2; -} - -/* LDC.L @Rm+,VBR */ -void sh2_device::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->r[m] += 4; - m_sh2_state->icount -= 2; -} - -/* LDS Rm,MACH */ -void sh2_device::LDSMACH(uint32_t m) -{ - m_sh2_state->mach = m_sh2_state->r[m]; -} - -/* LDS Rm,MACL */ -void sh2_device::LDSMACL(uint32_t m) -{ - m_sh2_state->macl = m_sh2_state->r[m]; -} - -/* LDS Rm,PR */ -void sh2_device::LDSPR(uint32_t m) -{ - m_sh2_state->pr = m_sh2_state->r[m]; -} - -/* LDS.L @Rm+,MACH */ -void sh2_device::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->r[m] += 4; -} - -/* LDS.L @Rm+,MACL */ -void sh2_device::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->r[m] += 4; -} - -/* LDS.L @Rm+,PR */ -void sh2_device::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->r[m] += 4; -} - -/* MAC.L @Rm+,@Rn+ */ -void sh2_device::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] ); - m_sh2_state->r[n] += 4; - tempm = (int32_t) RL( m_sh2_state->r[m] ); - m_sh2_state->r[m] += 4; - if ((int32_t) (tempn ^ tempm) < 0) - fnLmL = -1; - else - fnLmL = 0; - 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) - { - Res2 = ~Res2; - if (Res0 == 0) - Res2++; - else - Res0 = (~Res0) + 1; - } - if (m_sh2_state->sr & 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)) - { - Res2 = 0x00008000; - Res0 = 0x00000000; - } - else if (((int32_t) Res2 > 0) && (Res2 > 0x00007fff)) - { - Res2 = 0x00007fff; - Res0 = 0xffffffff; - } - 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; - } - m_sh2_state->icount -= 2; -} - -/* MAC.W @Rm+,@Rn+ */ -void sh2_device::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] ); - m_sh2_state->r[n] += 2; - tempm = (int32_t) RW( 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; - m_sh2_state->macl += tempm; - if ((int32_t) m_sh2_state->macl >= 0) - ans = 0; - else - ans = 1; - ans += dest; - if (m_sh2_state->sr & S) - { - if (ans == 1) - { - if (src == 0) - m_sh2_state->macl = 0x7fffffff; - if (src == 2) - m_sh2_state->macl = 0x80000000; - } - } - else - { - m_sh2_state->mach += tempn; - if (templ > m_sh2_state->macl) - m_sh2_state->mach += 1; - } - m_sh2_state->icount -= 2; -} - -/* MOV Rm,Rn */ -void sh2_device::MOV(uint32_t m, uint32_t n) -{ - m_sh2_state->r[n] = m_sh2_state->r[m]; -} - -/* MOV.B Rm,@Rn */ -void sh2_device::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); -} - -/* MOV.W Rm,@Rn */ -void sh2_device::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); -} - -/* MOV.L Rm,@Rn */ -void sh2_device::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] ); -} - -/* MOV.B @Rm,Rn */ -void sh2_device::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 ); -} - -/* MOV.W @Rm,Rn */ -void sh2_device::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 ); -} - -/* MOV.L @Rm,Rn */ -void sh2_device::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 ); -} - -/* MOV.B Rm,@-Rn */ -void sh2_device::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; - - m_sh2_state->r[n] -= 1; - WB( m_sh2_state->r[n], data ); -} - -/* MOV.W Rm,@-Rn */ -void sh2_device::MOVWM(uint32_t m, uint32_t n) -{ - uint32_t data = m_sh2_state->r[m] & 0x0000ffff; - - m_sh2_state->r[n] -= 2; - WW( m_sh2_state->r[n], data ); -} - -/* MOV.L Rm,@-Rn */ -void sh2_device::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 ); -} - -/* MOV.B @Rm+,Rn */ -void sh2_device::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] ); - if (n != m) - m_sh2_state->r[m] += 1; -} - -/* MOV.W @Rm+,Rn */ -void sh2_device::MOVWP(uint32_t m, uint32_t n) -{ - m_sh2_state->r[n] = (uint32_t)(int32_t)(int16_t) RW( m_sh2_state->r[m] ); - if (n != m) - m_sh2_state->r[m] += 2; -} - -/* MOV.L @Rm+,Rn */ -void sh2_device::MOVLP(uint32_t m, uint32_t n) -{ - m_sh2_state->r[n] = RL( m_sh2_state->r[m] ); - if (n != m) - m_sh2_state->r[m] += 4; -} - -/* MOV.B Rm,@(R0,Rn) */ -void sh2_device::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 ); -} - -/* MOV.W Rm,@(R0,Rn) */ -void sh2_device::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 ); -} - -/* MOV.L Rm,@(R0,Rn) */ -void sh2_device::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] ); -} - -/* MOV.B @(R0,Rm),Rn */ -void sh2_device::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 ); -} - -/* MOV.W @(R0,Rm),Rn */ -void sh2_device::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 ); -} - -/* MOV.L @(R0,Rm),Rn */ -void sh2_device::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 ); -} - -/* MOV #imm,Rn */ -void sh2_device::MOVI(uint32_t i, uint32_t n) -{ - m_sh2_state->r[n] = (uint32_t)(int32_t)(int16_t)(int8_t) i; -} - -/* MOV.W @(disp8,PC),Rn */ -void sh2_device::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 ); -} - -/* MOV.L @(disp8,PC),Rn */ -void sh2_device::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 ); -} - -/* MOV.B @(disp8,GBR),R0 */ -void sh2_device::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 ); -} - -/* MOV.W @(disp8,GBR),R0 */ -void sh2_device::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 ); -} - -/* MOV.L @(disp8,GBR),R0 */ -void sh2_device::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 ); -} - -/* MOV.B R0,@(disp8,GBR) */ -void sh2_device::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 ); -} - -/* MOV.W R0,@(disp8,GBR) */ -void sh2_device::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 ); -} - -/* MOV.L R0,@(disp8,GBR) */ -void sh2_device::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] ); -} - -/* MOV.B R0,@(disp4,Rn) */ -void sh2_device::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 ); -} - -/* MOV.W R0,@(disp4,Rn) */ -void sh2_device::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 ); -} - -/* MOV.L Rm,@(disp4,Rn) */ -void sh2_device::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] ); -} - -/* MOV.B @(disp4,Rm),R0 */ -void sh2_device::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 ); -} - -/* MOV.W @(disp4,Rm),R0 */ -void sh2_device::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 ); -} - -/* MOV.L @(disp4,Rm),Rn */ -void sh2_device::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 ); -} - -/* MOVA @(disp8,PC),R0 */ -void sh2_device::MOVA(uint32_t d) -{ - uint32_t disp = d & 0xff; - m_sh2_state->ea = ((m_sh2_state->pc + 2) & ~3) + disp * 4; - m_sh2_state->r[0] = m_sh2_state->ea; -} - -/* MOVT Rn */ -void sh2_device::MOVT(uint32_t n) -{ - m_sh2_state->r[n] = m_sh2_state->sr & T; -} - -/* MUL.L Rm,Rn */ -void sh2_device::MULL(uint32_t m, uint32_t n) -{ - m_sh2_state->macl = m_sh2_state->r[n] * m_sh2_state->r[m]; - m_sh2_state->icount--; -} - -/* MULS Rm,Rn */ -void sh2_device::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]; -} - -/* MULU Rm,Rn */ -void sh2_device::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]; -} - -/* NEG Rm,Rn */ -void sh2_device::NEG(uint32_t m, uint32_t n) -{ - m_sh2_state->r[n] = 0 - m_sh2_state->r[m]; -} - -/* NEGC Rm,Rn */ -void sh2_device::NEGC(uint32_t m, uint32_t n) -{ - uint32_t temp; - - temp = m_sh2_state->r[m]; - m_sh2_state->r[n] = -temp - (m_sh2_state->sr & T); - if (temp || (m_sh2_state->sr & T)) - m_sh2_state->sr |= T; - else - m_sh2_state->sr &= ~T; -} - -/* NOP */ -void sh2_device::NOP(void) -{ -} - -/* NOT Rm,Rn */ -void sh2_device::NOT(uint32_t m, uint32_t n) -{ - m_sh2_state->r[n] = ~m_sh2_state->r[m]; -} - -/* OR Rm,Rn */ -void sh2_device::OR(uint32_t m, uint32_t n) -{ - m_sh2_state->r[n] |= m_sh2_state->r[m]; -} - -/* OR #imm,R0 */ -void sh2_device::ORI(uint32_t i) -{ - m_sh2_state->r[0] |= i; -} - -/* OR.B #imm,@(R0,GBR) */ -void sh2_device::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; -} - -/* ROTCL Rn */ -void sh2_device::ROTCL(uint32_t n) -{ - uint32_t temp; - - temp = (m_sh2_state->r[n] >> 31) & T; - m_sh2_state->r[n] = (m_sh2_state->r[n] << 1) | (m_sh2_state->sr & T); - m_sh2_state->sr = (m_sh2_state->sr & ~T) | temp; -} - -/* ROTCR Rn */ -void sh2_device::ROTCR(uint32_t n) -{ - uint32_t temp; - temp = (m_sh2_state->sr & T) << 31; - if (m_sh2_state->r[n] & T) - m_sh2_state->sr |= T; - else - m_sh2_state->sr &= ~T; - m_sh2_state->r[n] = (m_sh2_state->r[n] >> 1) | temp; -} - -/* ROTL Rn */ -void sh2_device::ROTL(uint32_t n) -{ - m_sh2_state->sr = (m_sh2_state->sr & ~T) | ((m_sh2_state->r[n] >> 31) & T); - m_sh2_state->r[n] = (m_sh2_state->r[n] << 1) | (m_sh2_state->r[n] >> 31); -} - -/* ROTR Rn */ -void sh2_device::ROTR(uint32_t n) -{ - m_sh2_state->sr = (m_sh2_state->sr & ~T) | (m_sh2_state->r[n] & T); - m_sh2_state->r[n] = (m_sh2_state->r[n] >> 1) | (m_sh2_state->r[n] << 31); -} - /* RTE */ -void sh2_device::RTE() +inline void sh2_device::RTE() { m_sh2_state->ea = m_sh2_state->r[15]; - m_delay = RL( m_sh2_state->ea ); + m_sh2_state->m_delay = RL( 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 ) & FLAGS; + m_sh2_state->sr = RL( m_sh2_state->ea ) & SH_FLAGS; m_sh2_state->r[15] += 4; m_sh2_state->icount -= 3; m_test_irq = 1; } -/* RTS */ -void sh2_device::RTS() -{ - m_delay = m_sh2_state->ea = m_sh2_state->pr; - m_sh2_state->icount--; -} - -/* SETT */ -void sh2_device::SETT() -{ - m_sh2_state->sr |= T; -} - -/* SHAL Rn (same as SHLL) */ -void sh2_device::SHAL(uint32_t n) -{ - m_sh2_state->sr = (m_sh2_state->sr & ~T) | ((m_sh2_state->r[n] >> 31) & T); - m_sh2_state->r[n] <<= 1; -} - -/* SHAR Rn */ -void sh2_device::SHAR(uint32_t n) -{ - m_sh2_state->sr = (m_sh2_state->sr & ~T) | (m_sh2_state->r[n] & T); - m_sh2_state->r[n] = (uint32_t)((int32_t)m_sh2_state->r[n] >> 1); -} - -/* SHLL Rn (same as SHAL) */ -void sh2_device::SHLL(uint32_t n) -{ - m_sh2_state->sr = (m_sh2_state->sr & ~T) | ((m_sh2_state->r[n] >> 31) & T); - m_sh2_state->r[n] <<= 1; -} - -/* SHLL2 Rn */ -void sh2_device::SHLL2(uint32_t n) -{ - m_sh2_state->r[n] <<= 2; -} - -/* SHLL8 Rn */ -void sh2_device::SHLL8(uint32_t n) -{ - m_sh2_state->r[n] <<= 8; -} - -/* SHLL16 Rn */ -void sh2_device::SHLL16(uint32_t n) -{ - m_sh2_state->r[n] <<= 16; -} - -/* SHLR Rn */ -void sh2_device::SHLR(uint32_t n) -{ - m_sh2_state->sr = (m_sh2_state->sr & ~T) | (m_sh2_state->r[n] & T); - m_sh2_state->r[n] >>= 1; -} - -/* SHLR2 Rn */ -void sh2_device::SHLR2(uint32_t n) -{ - m_sh2_state->r[n] >>= 2; -} - -/* SHLR8 Rn */ -void sh2_device::SHLR8(uint32_t n) -{ - m_sh2_state->r[n] >>= 8; -} - -/* SHLR16 Rn */ -void sh2_device::SHLR16(uint32_t n) -{ - m_sh2_state->r[n] >>= 16; -} - -/* SLEEP */ -void sh2_device::SLEEP() -{ - 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) - m_sh2_state->sleep_mode = 1; - else if(m_sh2_state->sleep_mode == 2) - m_sh2_state->sleep_mode = 0; -} - -/* STC SR,Rn */ -void sh2_device::STCSR(uint32_t n) -{ - m_sh2_state->r[n] = m_sh2_state->sr; -} - -/* STC GBR,Rn */ -void sh2_device::STCGBR(uint32_t n) -{ - m_sh2_state->r[n] = m_sh2_state->gbr; -} - -/* STC VBR,Rn */ -void sh2_device::STCVBR(uint32_t n) -{ - m_sh2_state->r[n] = m_sh2_state->vbr; -} - -/* STC.L SR,@-Rn */ -void sh2_device::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 ); - m_sh2_state->icount--; -} - -/* STC.L GBR,@-Rn */ -void sh2_device::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 ); - m_sh2_state->icount--; -} - -/* STC.L VBR,@-Rn */ -void sh2_device::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 ); - m_sh2_state->icount--; -} - -/* STS MACH,Rn */ -void sh2_device::STSMACH(uint32_t n) -{ - m_sh2_state->r[n] = m_sh2_state->mach; -} - -/* STS MACL,Rn */ -void sh2_device::STSMACL(uint32_t n) -{ - m_sh2_state->r[n] = m_sh2_state->macl; -} - -/* STS PR,Rn */ -void sh2_device::STSPR(uint32_t n) -{ - m_sh2_state->r[n] = m_sh2_state->pr; -} - -/* STS.L MACH,@-Rn */ -void sh2_device::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 ); -} - -/* STS.L MACL,@-Rn */ -void sh2_device::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 ); -} - -/* STS.L PR,@-Rn */ -void sh2_device::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 ); -} - -/* SUB Rm,Rn */ -void sh2_device::SUB(uint32_t m, uint32_t n) -{ - m_sh2_state->r[n] -= m_sh2_state->r[m]; -} - -/* SUBC Rm,Rn */ -void sh2_device::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]; - m_sh2_state->r[n] = tmp1 - (m_sh2_state->sr & T); - if (tmp0 < tmp1) - m_sh2_state->sr |= T; - else - m_sh2_state->sr &= ~T; - if (tmp1 < m_sh2_state->r[n]) - m_sh2_state->sr |= T; -} - -/* SUBV Rm,Rn */ -void sh2_device::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; - 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; - ans += dest; - if (src == 1) - { - if (ans == 1) - m_sh2_state->sr |= T; - else - m_sh2_state->sr &= ~T; - } - else - m_sh2_state->sr &= ~T; -} - -/* SWAP.B Rm,Rn */ -void sh2_device::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; -} - -/* SWAP.W Rm,Rn */ -void sh2_device::SWAPW(uint32_t m, uint32_t n) -{ - uint32_t temp; - - temp = (m_sh2_state->r[m] >> 16) & 0x0000ffff; - m_sh2_state->r[n] = (m_sh2_state->r[m] << 16) | temp; -} - -/* TAS.B @Rn */ -void sh2_device::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 ); - if (temp == 0) - m_sh2_state->sr |= T; - else - m_sh2_state->sr &= ~T; - temp |= 0x80; - /* Bus Lock disable */ - WB( m_sh2_state->ea, temp ); - m_sh2_state->icount -= 3; -} - /* TRAPA #imm */ -void sh2_device::TRAPA(uint32_t i) +inline void sh2_device::TRAPA(uint32_t i) { uint32_t imm = i & 0xff; @@ -1840,388 +317,28 @@ void sh2_device::TRAPA(uint32_t i) m_sh2_state->icount -= 7; } -/* TST Rm,Rn */ -void sh2_device::TST(uint32_t m, uint32_t n) -{ - if ((m_sh2_state->r[n] & m_sh2_state->r[m]) == 0) - m_sh2_state->sr |= T; - else - m_sh2_state->sr &= ~T; -} - -/* TST #imm,R0 */ -void sh2_device::TSTI(uint32_t i) -{ - uint32_t imm = i & 0xff; - - if ((imm & m_sh2_state->r[0]) == 0) - m_sh2_state->sr |= T; - else - m_sh2_state->sr &= ~T; -} - -/* TST.B #imm,@(R0,GBR) */ -void sh2_device::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) - m_sh2_state->sr |= T; - else - m_sh2_state->sr &= ~T; - m_sh2_state->icount -= 2; -} - -/* XOR Rm,Rn */ -void sh2_device::XOR(uint32_t m, uint32_t n) -{ - m_sh2_state->r[n] ^= m_sh2_state->r[m]; -} - -/* XOR #imm,R0 */ -void sh2_device::XORI(uint32_t i) -{ - uint32_t imm = i & 0xff; - m_sh2_state->r[0] ^= imm; -} - -/* XOR.B #imm,@(R0,GBR) */ -void sh2_device::XORM(uint32_t i) +/* ILLEGAL */ +inline void sh2_device::ILLEGAL() { - 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 ); - m_sh2_state->icount -= 2; -} + //logerror("Illegal opcode at %08x\n", m_sh2_state->pc - 2); + m_sh2_state->r[15] -= 4; + WL( 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 */ -/* XTRCT Rm,Rn */ -void sh2_device::XTRCT(uint32_t m, uint32_t n) -{ - uint32_t temp; + /* fetch PC */ + m_sh2_state->pc = RL( m_sh2_state->vbr + 4 * 4 ); - 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; + /* TODO: timing is a guess */ + m_sh2_state->icount -= 5; } /***************************************************************************** * OPCODE DISPATCHERS *****************************************************************************/ -void sh2_device::op0000(uint16_t opcode) -{ - 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 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 0x3a: ILLEGAL(); break; - case 0x3b: ILLEGAL(); break; - - - - } -} - -void sh2_device::op0001(uint16_t opcode) -{ - MOVLS4(Rm, opcode & 0x0f, Rn); -} -void sh2_device::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; - } -} - -void sh2_device::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; - } -} - -void sh2_device::op0100(uint16_t opcode) -{ - 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(Rn); 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(Rn); 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; - - } -} - -void sh2_device::op0101(uint16_t opcode) -{ - MOVLL4(Rm, opcode & 0x0f, Rn); -} - -void sh2_device::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; - } -} - -void sh2_device::op0111(uint16_t opcode) -{ - ADDI(opcode & 0xff, Rn); -} - -void sh2_device::op1000(uint16_t opcode) -{ - switch ( opcode & (15<<8) ) - { - 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; - } -} - - -void sh2_device::op1001(uint16_t opcode) -{ - MOVWI(opcode & 0xff, Rn); -} - -void sh2_device::op1010(uint16_t opcode) -{ - BRA(opcode & 0xfff); -} - -void sh2_device::op1011(uint16_t opcode) -{ - BSR(opcode & 0xfff); -} - -void sh2_device::op1100(uint16_t opcode) -{ - switch (opcode & (15<<8)) - { - 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; - 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; - } -} - -void sh2_device::op1101(uint16_t opcode) -{ - MOVLI(opcode & 0xff, Rn); -} - -void sh2_device::op1110(uint16_t opcode) -{ - MOVI(opcode & 0xff, Rn); -} - -void sh2_device::op1111(uint16_t opcode) +void sh2_device::execute_one_f000(uint16_t opcode) { ILLEGAL(); } @@ -2235,9 +352,10 @@ 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_delay = m_cpu_off = m_dvsr = m_dvdnth = m_dvdntl = m_dvcr = 0; + 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_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_icr = 0; m_frc_base = 0; @@ -2249,7 +367,7 @@ void sh2_device::device_reset() m_sh2_state->pc = RL(0); m_sh2_state->r[15] = RL(4); - m_sh2_state->sr = I; + m_sh2_state->sr = SH_I; m_sh2_state->sleep_mode = 0; m_sh2_state->internal_irq_level = -1; @@ -2273,55 +391,23 @@ void sh2_device::execute_run() return; } - // run any active DMAs now -#ifndef USE_TIMER_FOR_DMA - for ( int i = 0; i < m_sh2_state->icount ; i++) - { - for( int dma=0;dma<1;dma++) - { - if (m_dma_timer_active[dma]) - sh2_do_dma(dma); - } - } -#endif - do { - uint32_t opcode; - debugger_instruction_hook(this, m_sh2_state->pc); - opcode = m_program->read_word(m_sh2_state->pc & AM); + const uint16_t opcode = m_program->read_word(m_sh2_state->pc & SH12_AM); - if (m_delay) + if (m_sh2_state->m_delay) { - m_sh2_state->pc = m_delay; - m_delay = 0; + m_sh2_state->pc = m_sh2_state->m_delay; + m_sh2_state->m_delay = 0; } else m_sh2_state->pc += 2; - switch (opcode & ( 15 << 12)) - { - case 0<<12: op0000(opcode); break; - case 1<<12: op0001(opcode); break; - case 2<<12: op0010(opcode); break; - case 3<<12: op0011(opcode); break; - case 4<<12: op0100(opcode); break; - case 5<<12: op0101(opcode); break; - case 6<<12: op0110(opcode); break; - case 7<<12: op0111(opcode); break; - case 8<<12: op1000(opcode); break; - case 9<<12: op1001(opcode); break; - case 10<<12: op1010(opcode); break; - case 11<<12: op1011(opcode); break; - case 12<<12: op1100(opcode); break; - case 13<<12: op1101(opcode); break; - case 14<<12: op1110(opcode); break; - default: op1111(opcode); break; - } + execute_one(opcode); - if(m_test_irq && !m_delay) + if(m_test_irq && !m_sh2_state->m_delay) { CHECK_PENDING_IRQ("mame_sh2_execute"); m_test_irq = 0; @@ -2330,10 +416,15 @@ void sh2_device::execute_run() } 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() { - /* allocate the implementation-specific state from the full cache */ - m_sh2_state = (internal_sh2_state *)m_cache.alloc_near(sizeof(internal_sh2_state)); + 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); @@ -2349,41 +440,26 @@ void sh2_device::device_start() m_dma_fifo_data_available_cb.bind_relative_to(*owner()); m_ftcsr_read_cb.bind_relative_to(*owner()); - m_program = &space(AS_PROGRAM); m_decrypted_program = has_space(AS_OPCODES) ? &space(AS_OPCODES) : &space(AS_PROGRAM); - m_direct = &m_decrypted_program->direct(); + m_direct = m_decrypted_program->direct<0>(); m_internal = &space(AS_PROGRAM); - save_item(NAME(m_sh2_state->pc)); - save_item(NAME(m_sh2_state->sr)); - save_item(NAME(m_sh2_state->pr)); - save_item(NAME(m_sh2_state->gbr)); - save_item(NAME(m_sh2_state->vbr)); - save_item(NAME(m_sh2_state->mach)); - save_item(NAME(m_sh2_state->macl)); - save_item(NAME(m_sh2_state->r)); - save_item(NAME(m_sh2_state->ea)); - save_item(NAME(m_delay)); save_item(NAME(m_cpu_off)); - save_item(NAME(m_dvsr)); - save_item(NAME(m_dvdnth)); - save_item(NAME(m_dvdntl)); - save_item(NAME(m_dvcr)); - save_item(NAME(m_sh2_state->pending_irq)); + //save_item(NAME(m_dvsr)); + //save_item(NAME(m_dvdnth)); + //save_item(NAME(m_dvdntl)); + //save_item(NAME(m_dvcr)); save_item(NAME(m_test_irq)); - save_item(NAME(m_sh2_state->pending_nmi)); - save_item(NAME(m_sh2_state->irqline)); - save_item(NAME(m_sh2_state->evec)); - save_item(NAME(m_sh2_state->irqsr)); - save_item(NAME(m_sh2_state->target)); + + /* 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); + save_item(NAME(m_irq_queue[i].irq_vector), i); + save_item(NAME(m_irq_queue[i].irq_priority), i); } - save_item(NAME(m_pcfsel)); - save_item(NAME(m_maxpcfsel)); - save_item(NAME(m_pcflushes)); + */ + + save_item(NAME(m_irq_line_state)); save_item(NAME(m_m)); save_item(NAME(m_nmi_line_state)); @@ -2393,71 +469,24 @@ void sh2_device::device_start() save_item(NAME(m_icr)); save_item(NAME(m_frc_base)); save_item(NAME(m_frt_input)); - save_item(NAME(m_sh2_state->internal_irq_level)); save_item(NAME(m_internal_irq_vector)); save_item(NAME(m_dma_timer_active)); save_item(NAME(m_dma_irq)); save_item(NAME(m_wtcnt)); save_item(NAME(m_wtcsr)); - save_item(NAME(m_sh2_state->sleep_mode)); - - state_add( STATE_GENPC, "PC", m_sh2_state->pc).mask(AM).callimport(); - state_add( SH2_SR, "SR", m_sh2_state->sr).callimport().formatstr("%08X"); - state_add( SH2_PR, "PR", m_sh2_state->pr).formatstr("%08X"); - state_add( SH2_GBR, "GBR", m_sh2_state->gbr).formatstr("%08X"); - state_add( SH2_VBR, "VBR", m_sh2_state->vbr).formatstr("%08X"); - state_add( SH2_MACH, "MACH", m_sh2_state->mach).formatstr("%08X"); - state_add( SH2_MACL, "MACL", m_sh2_state->macl).formatstr("%08X"); - state_add( SH2_R0, "R0", m_sh2_state->r[ 0]).formatstr("%08X"); - state_add( SH2_R1, "R1", m_sh2_state->r[ 1]).formatstr("%08X"); - state_add( SH2_R2, "R2", m_sh2_state->r[ 2]).formatstr("%08X"); - state_add( SH2_R3, "R3", m_sh2_state->r[ 3]).formatstr("%08X"); - state_add( SH2_R4, "R4", m_sh2_state->r[ 4]).formatstr("%08X"); - state_add( SH2_R5, "R5", m_sh2_state->r[ 5]).formatstr("%08X"); - state_add( SH2_R6, "R6", m_sh2_state->r[ 6]).formatstr("%08X"); - state_add( SH2_R7, "R7", m_sh2_state->r[ 7]).formatstr("%08X"); - state_add( SH2_R8, "R8", m_sh2_state->r[ 8]).formatstr("%08X"); - state_add( SH2_R9, "R9", m_sh2_state->r[ 9]).formatstr("%08X"); - state_add( SH2_R10, "R10", m_sh2_state->r[10]).formatstr("%08X"); - state_add( SH2_R11, "R11", m_sh2_state->r[11]).formatstr("%08X"); - state_add( SH2_R12, "R12", m_sh2_state->r[12]).formatstr("%08X"); - state_add( SH2_R13, "R13", m_sh2_state->r[13]).formatstr("%08X"); - state_add( SH2_R14, "R14", m_sh2_state->r[14]).formatstr("%08X"); - state_add( SH2_R15, "R15", m_sh2_state->r[15]).formatstr("%08X"); - state_add( SH2_EA, "EA", m_sh2_state->ea).formatstr("%08X"); + state_add( STATE_GENPC, "PC", m_sh2_state->pc).mask(SH12_AM).callimport(); state_add( STATE_GENPCBASE, "CURPC", m_sh2_state->pc ).callimport().noshow(); - state_add( STATE_GENSP, "GENSP", m_sh2_state->r[15] ).noshow(); - state_add( STATE_GENFLAGS, "GENFLAGS", m_sh2_state->sr ).formatstr("%6s").noshow(); - - m_icountptr = &m_sh2_state->icount; // Clear state - m_sh2_state->pc = 0; - m_sh2_state->pr = 0; - m_sh2_state->sr = 0; - m_sh2_state->gbr = 0; - m_sh2_state->vbr = 0; - m_sh2_state->mach = 0; - m_sh2_state->macl = 0; - memset(m_sh2_state->r, 0, sizeof(m_sh2_state->r)); - m_sh2_state->ea = 0; - m_delay = 0; m_cpu_off = 0; - m_dvsr = 0; - m_dvdnth = 0; - m_dvdntl = 0; - m_dvcr = 0; - m_sh2_state->pending_irq = 0; + //m_dvsr = 0; + //m_dvdnth = 0; + //m_dvdntl = 0; + //m_dvcr = 0; m_test_irq = 0; - m_sh2_state->pending_nmi = 0; - m_sh2_state->irqline = 0; - m_sh2_state->evec = 0; - m_sh2_state->irqsr = 0; - m_sh2_state->target = 0; - memset(m_irq_queue, 0, sizeof(m_irq_queue)); - m_maxpcfsel = 0; - memset(m_pcflushes, 0, sizeof(m_pcflushes)); + + memset(m_irq_line_state, 0, sizeof(m_irq_line_state)); memset(m_m, 0, sizeof(m_m)); m_nmi_line_state = 0; @@ -2467,9 +496,8 @@ void sh2_device::device_start() m_icr = 0; m_frc_base = 0; m_frt_input = 0; - m_sh2_state->internal_irq_level = 0; m_internal_irq_vector = 0; - m_sh2_state->icount = 0; + for ( int i = 0; i < 2; i++ ) { m_dma_timer_active[i] = 0; @@ -2484,68 +512,8 @@ void sh2_device::device_start() } m_wtcnt = 0; m_wtcsr = 0; - m_sh2_state->sleep_mode = 0; - m_numcycles = 0; - m_sh2_state->arg0 = 0; - m_arg1 = 0; - m_irq = 0; - m_fastram_select = 0; - memset(m_fastram, 0, sizeof(m_fastram)); - - /* reset per-driver pcflushes */ - m_pcfsel = 0; - - /* initialize the UML generator */ - uint32_t flags = 0; - m_drcuml = std::make_unique<drcuml_state>(*this, m_cache, flags, 1, 32, 1); - - /* add symbols for our stuff */ - m_drcuml->symbol_add(&m_sh2_state->pc, sizeof(m_sh2_state->pc), "pc"); - m_drcuml->symbol_add(&m_sh2_state->icount, sizeof(m_sh2_state->icount), "icount"); - for (int regnum = 0; regnum < 16; regnum++) - { - char buf[10]; - sprintf(buf, "r%d", regnum); - m_drcuml->symbol_add(&m_sh2_state->r[regnum], sizeof(m_sh2_state->r[regnum]), buf); - } - m_drcuml->symbol_add(&m_sh2_state->pr, sizeof(m_sh2_state->pr), "pr"); - m_drcuml->symbol_add(&m_sh2_state->sr, sizeof(m_sh2_state->sr), "sr"); - m_drcuml->symbol_add(&m_sh2_state->gbr, sizeof(m_sh2_state->gbr), "gbr"); - m_drcuml->symbol_add(&m_sh2_state->vbr, sizeof(m_sh2_state->vbr), "vbr"); - m_drcuml->symbol_add(&m_sh2_state->macl, sizeof(m_sh2_state->macl), "macl"); - m_drcuml->symbol_add(&m_sh2_state->mach, sizeof(m_sh2_state->macl), "mach"); - - /* initialize the front-end helper */ - m_drcfe = std::make_unique<sh2_frontend>(this, COMPILE_BACKWARDS_BYTES, COMPILE_FORWARDS_BYTES, SINGLE_INSTRUCTION_MODE ? 1 : COMPILE_MAX_SEQUENCE); - /* compute the register parameters */ - for (int regnum = 0; regnum < 16; regnum++) - { - m_regmap[regnum] = uml::mem(&m_sh2_state->r[regnum]); - } - - /* if we have registers to spare, assign r0, r1, r2 to leftovers */ - /* WARNING: do not use synthetic registers that are mapped here! */ - if (!DISABLE_FAST_REGISTERS) - { - drcbe_info beinfo; - m_drcuml->get_backend_info(beinfo); - if (beinfo.direct_iregs > 4) - { - m_regmap[0] = uml::I4; - } - if (beinfo.direct_iregs > 5) - { - m_regmap[1] = uml::I5; - } - if (beinfo.direct_iregs > 6) - { - m_regmap[2] = uml::I6; - } - } - - /* mark the cache dirty so it is updated on next execute */ - m_cache_dirty = true; + drc_start(); } @@ -2555,11 +523,11 @@ void sh2_device::state_string_export(const device_state_entry &entry, std::strin { case STATE_GENFLAGS: str = string_format("%c%c%d%c%c", - m_sh2_state->sr & M ? 'M':'.', - m_sh2_state->sr & Q ? 'Q':'.', - (m_sh2_state->sr & I) >> 4, - m_sh2_state->sr & S ? 'S':'.', - m_sh2_state->sr & T ? 'T':'.'); + m_sh2_state->sr & SH_M ? 'M':'.', + m_sh2_state->sr & SH_Q ? 'Q':'.', + (m_sh2_state->sr & SH_I) >> 4, + m_sh2_state->sr & SH_S ? 'S':'.', + m_sh2_state->sr & SH_T ? 'T':'.'); break; } } @@ -2571,10 +539,10 @@ void sh2_device::state_import(const device_state_entry &entry) { case STATE_GENPC: case STATE_GENPCBASE: - m_delay = 0; + m_sh2_state->m_delay = 0; break; - case SH2_SR: + case SH_SR: CHECK_PENDING_IRQ("sh2_set_reg"); break; } @@ -2622,7 +590,7 @@ void sh2_device::execute_set_input(int irqline, int state) { m_test_irq = 1; } else { - if(m_delay) + if(m_sh2_state->m_delay) m_test_irq = 1; else CHECK_PENDING_IRQ("sh2_set_irq_line"); @@ -2672,14 +640,14 @@ void sh2_device::sh2_exception(const char *message, int irqline) if (m_isdrc) { m_sh2_state->evec = RL( m_sh2_state->vbr + vector * 4 ); - m_sh2_state->evec &= AM; + m_sh2_state->evec &= SH12_AM; m_sh2_state->irqsr = m_sh2_state->sr; /* set I flags in SR */ if (irqline > SH2_INT_15) - m_sh2_state->sr = m_sh2_state->sr | I; + m_sh2_state->sr = m_sh2_state->sr | SH_I; else - m_sh2_state->sr = (m_sh2_state->sr & ~I) | (irqline << 4); + 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 { @@ -2690,9 +658,9 @@ void sh2_device::sh2_exception(const char *message, int irqline) /* set I flags in SR */ if (irqline > SH2_INT_15) - m_sh2_state->sr = m_sh2_state->sr | I; + m_sh2_state->sr = m_sh2_state->sr | SH_I; else - m_sh2_state->sr = (m_sh2_state->sr & ~I) | (irqline << 4); + 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 ); @@ -2701,4 +669,324 @@ void sh2_device::sh2_exception(const char *message, int irqline) if(m_sh2_state->sleep_mode == 1) { m_sh2_state->sleep_mode = 2; } } -#include "sh2drc.cpp" +// license:BSD-3-Clause +// copyright-holders:R. Belmont +/*************************************************************************** + + sh2drc.c + Universal machine language-based SH-2 emulator. + +***************************************************************************/ + +#include "emu.h" +#include "debugger.h" +#include "sh2.h" +#include "sh2comn.h" + + +using namespace uml; + +const opcode_desc* sh2_device::get_desclist(offs_t pc) +{ + return m_drcfe->describe_code(pc); +} + + + +/*------------------------------------------------- + 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() +{ + drcuml_state *drcuml = m_drcuml.get(); + code_label skip = 1; + drcuml_block *block; + + /* begin generating */ + block = drcuml->begin_block(200); + + /* forward references */ + alloc_handle(drcuml, &m_nocode, "nocode"); + alloc_handle(drcuml, &m_write32, "write32"); // necessary? + alloc_handle(drcuml, &m_entry, "entry"); + UML_HANDLE(block, *m_entry); // handle entry + + /* load fast integer registers */ + load_fast_iregs(block); + + /* check for interrupts */ + UML_MOV(block, mem(&m_sh2_state->irqline), 0xffffffff); // mov irqline, #-1 + UML_CMP(block, mem(&m_sh2_state->pending_nmi), 0); // cmp pending_nmi, #0 + UML_JMPc(block, COND_Z, skip+2); // jz skip+2 + + UML_MOV(block, mem(&m_sh2_state->pending_nmi), 0); // zap pending_nmi + UML_JMP(block, skip+1); // and then go take it (evec is already set) + + UML_LABEL(block, skip+2); // skip+2: + UML_MOV(block, mem(&m_sh2_state->evec), 0xffffffff); // mov evec, -1 + UML_MOV(block, I0, 0xffffffff); // mov r0, -1 (r0 = irq) + UML_AND(block, I1, I0, 0xffff); // and r1, 0xffff + + UML_LZCNT(block, I1, mem(&m_sh2_state->pending_irq)); // lzcnt r1, r1 + UML_CMP(block, I1, 32); // cmp r1, #32 + UML_JMPc(block, COND_Z, skip+4); // jz skip+4 + + UML_SUB(block, mem(&m_sh2_state->irqline), 31, I1); // sub irqline, #31, r1 + + UML_LABEL(block, skip+4); // skip+4: + UML_CMP(block, mem(&m_sh2_state->internal_irq_level), 0xffffffff); // cmp internal_irq_level, #-1 + UML_JMPc(block, COND_Z, skip+3); // jz skip+3 + UML_CMP(block, mem(&m_sh2_state->internal_irq_level), mem(&m_sh2_state->irqline)); // cmp internal_irq_level, irqline + UML_JMPc(block, COND_LE, skip+3); // jle skip+3 + + UML_MOV(block, mem(&m_sh2_state->irqline), mem(&m_sh2_state->internal_irq_level)); // mov r0, internal_irq_level + + UML_LABEL(block, skip+3); // skip+3: + UML_CMP(block, mem(&m_sh2_state->irqline), 0xffffffff); // cmp irqline, #-1 + UML_JMPc(block, COND_Z, skip+1); // jz skip+1 + UML_CALLC(block, cfunc_fastirq, this); // callc fastirq + + UML_LABEL(block, skip+1); // skip+1: + + UML_CMP(block, mem(&m_sh2_state->evec), 0xffffffff); // cmp evec, 0xffffffff + UML_JMPc(block, COND_Z, skip); // jz skip + + UML_SUB(block, R32(15), R32(15), 4); // sub R15, R15, #4 + UML_MOV(block, I0, R32(15)); // mov r0, R15 + UML_MOV(block, I1, mem(&m_sh2_state->irqsr)); // mov r1, irqsr + UML_CALLH(block, *m_write32); // call write32 + + UML_SUB(block, R32(15), R32(15), 4); // sub R15, R15, #4 + UML_MOV(block, I0, R32(15)); // mov r0, R15 + UML_MOV(block, I1, mem(&m_sh2_state->pc)); // mov r1, pc + UML_CALLH(block, *m_write32); // call write32 + + UML_MOV(block, mem(&m_sh2_state->pc), mem(&m_sh2_state->evec)); // mov pc, evec + + UML_LABEL(block, skip); // skip: + + /* generate a hash jump via the current mode and PC */ + UML_HASHJMP(block, 0, mem(&m_sh2_state->pc), *m_nocode); // hashjmp <mode>,<pc>,nocode + + block->end(); +} + + +/*------------------------------------------------- + generate_update_cycles - generate code to + subtract cycles from the icount and generate + an exception if out +-------------------------------------------------*/ + +void sh2_device::generate_update_cycles(drcuml_block *block, compiler_state *compiler, uml::parameter param, bool allow_exception) +{ + /* check full interrupts if pending */ + if (compiler->checkints) + { + code_label skip = compiler->labelnum++; + + compiler->checkints = false; + compiler->labelnum += 4; + + /* check for interrupts */ + UML_MOV(block, mem(&m_sh2_state->irqline), 0xffffffff); // mov irqline, #-1 + UML_CMP(block, mem(&m_sh2_state->pending_nmi), 0); // cmp pending_nmi, #0 + UML_JMPc(block, COND_Z, skip+2); // jz skip+2 + + UML_MOV(block, mem(&m_sh2_state->pending_nmi), 0); // zap pending_nmi + UML_JMP(block, skip+1); // and then go take it (evec is already set) + + UML_LABEL(block, skip+2); // skip+2: + UML_MOV(block, mem(&m_sh2_state->evec), 0xffffffff); // mov evec, -1 + UML_MOV(block, I0, 0xffffffff); // mov r0, -1 (r0 = irq) + UML_AND(block, I1, I0, 0xffff); // and r1, r0, 0xffff + + UML_LZCNT(block, I1, mem(&m_sh2_state->pending_irq)); // lzcnt r1, pending_irq + UML_CMP(block, I1, 32); // cmp r1, #32 + UML_JMPc(block, COND_Z, skip+4); // jz skip+4 + + UML_SUB(block, mem(&m_sh2_state->irqline), 31, I1); // sub irqline, #31, r1 + + UML_LABEL(block, skip+4); // skip+4: + UML_CMP(block, mem(&m_sh2_state->internal_irq_level), 0xffffffff); // cmp internal_irq_level, #-1 + UML_JMPc(block, COND_Z, skip+3); // jz skip+3 + UML_CMP(block, mem(&m_sh2_state->internal_irq_level), mem(&m_sh2_state->irqline)); // cmp internal_irq_level, irqline + UML_JMPc(block, COND_LE, skip+3); // jle skip+3 + + UML_MOV(block, mem(&m_sh2_state->irqline), mem(&m_sh2_state->internal_irq_level)); // mov r0, internal_irq_level + + UML_LABEL(block, skip+3); // skip+3: + UML_CMP(block, mem(&m_sh2_state->irqline), 0xffffffff); // cmp irqline, #-1 + UML_JMPc(block, COND_Z, skip+1); // jz skip+1 + UML_CALLC(block, cfunc_fastirq, this); // callc fastirq + + UML_LABEL(block, skip+1); // skip+1: + UML_CMP(block, mem(&m_sh2_state->evec), 0xffffffff); // cmp evec, 0xffffffff + UML_JMPc(block, COND_Z, skip); // jz skip + + UML_SUB(block, R32(15), R32(15), 4); // sub R15, R15, #4 + UML_MOV(block, I0, R32(15)); // mov r0, R15 + UML_MOV(block, I1, mem(&m_sh2_state->irqsr)); // mov r1, irqsr + UML_CALLH(block, *m_write32); // call write32 + + UML_SUB(block, R32(15), R32(15), 4); // sub R15, R15, #4 + UML_MOV(block, I0, R32(15)); // mov r0, R15 + UML_MOV(block, I1, param); // mov r1, nextpc + UML_CALLH(block, *m_write32); // call write32 + + UML_HASHJMP(block, 0, mem(&m_sh2_state->evec), *m_nocode); // hashjmp m_sh2_state->evec + + UML_LABEL(block, skip); // skip: + } + + /* account for cycles */ + if (compiler->cycles > 0) + { + UML_SUB(block, mem(&m_sh2_state->icount), mem(&m_sh2_state->icount), MAPVAR_CYCLES); // sub icount,icount,cycles + UML_MAPVAR(block, MAPVAR_CYCLES, 0); // mapvar cycles,0 + if (allow_exception) + UML_EXHc(block, COND_S, *m_out_of_cycles, param); + // exh out_of_cycles,nextpc + } + compiler->cycles = 0; +} + +/*------------------------------------------------------------------ + static_generate_memory_accessor +------------------------------------------------------------------*/ + +void sh2_device::static_generate_memory_accessor(int size, int iswrite, const char *name, code_handle **handleptr) +{ + /* on entry, address is in I0; data for writes is in I1 */ + /* on exit, read result is in I0 */ + /* routine trashes I0 */ + drcuml_state *drcuml = m_drcuml.get(); + drcuml_block *block; + int label = 1; + + /* begin generating */ + block = drcuml->begin_block(1024); + + /* add a global entry for this */ + alloc_handle(drcuml, handleptr, name); + UML_HANDLE(block, **handleptr); // handle *handleptr + + // with internal handlers this becomes easier. + // if addr < 0x40000000 AND it with AM and do the read/write, else just do the read/write + UML_TEST(block, I0, 0x80000000); // test r0, #0x80000000 + UML_JMPc(block, COND_NZ, label); // if high bit is set, don't mask + + 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_LABEL(block, label++); // label: + + for (auto & elem : m_fastram) + { + if (elem.base != nullptr && (!iswrite || !elem.readonly)) + { + void *fastbase = (uint8_t *)elem.base - elem.start; + uint32_t skip = label++; + if (elem.end != 0xffffffff) + { + UML_CMP(block, I0, elem.end); // cmp i0,end + UML_JMPc(block, COND_A, skip); // ja skip + } + if (elem.start != 0x00000000) + { + UML_CMP(block, I0, elem.start);// cmp i0,fastram_start + UML_JMPc(block, COND_B, skip); // jb skip + } + + if (!iswrite) + { + if (size == 1) + { + UML_XOR(block, I0, I0, BYTE4_XOR_BE(0)); + UML_LOAD(block, I0, fastbase, I0, SIZE_BYTE, SCALE_x1); // load i0,fastbase,i0,byte + } + else if (size == 2) + { + UML_XOR(block, I0, I0, WORD_XOR_BE(0)); + UML_LOAD(block, I0, fastbase, I0, SIZE_WORD, SCALE_x1); // load i0,fastbase,i0,word_x1 + } + else if (size == 4) + { + UML_LOAD(block, I0, fastbase, I0, SIZE_DWORD, SCALE_x1); // load i0,fastbase,i0,dword_x1 + } + UML_RET(block); // ret + } + else + { + if (size == 1) + { + UML_XOR(block, I0, I0, BYTE4_XOR_BE(0)); + UML_STORE(block, fastbase, I0, I1, SIZE_BYTE, SCALE_x1);// store fastbase,i0,i1,byte + } + else if (size == 2) + { + UML_XOR(block, I0, I0, WORD_XOR_BE(0)); + UML_STORE(block, fastbase, I0, I1, SIZE_WORD, SCALE_x1);// store fastbase,i0,i1,word_x1 + } + else if (size == 4) + { + UML_STORE(block, fastbase, I0, I1, SIZE_DWORD, SCALE_x1); // store fastbase,i0,i1,dword_x1 + } + UML_RET(block); // ret + } + + UML_LABEL(block, skip); // skip: + } + } + + if (iswrite) + { + switch (size) + { + case 1: + UML_WRITE(block, I0, I1, SIZE_BYTE, SPACE_PROGRAM); // write r0, r1, program_byte + break; + + case 2: + UML_WRITE(block, I0, I1, SIZE_WORD, SPACE_PROGRAM); // write r0, r1, program_word + break; + + case 4: + UML_WRITE(block, I0, I1, SIZE_DWORD, SPACE_PROGRAM); // write r0, r1, program_dword + break; + } + } + else + { + switch (size) + { + case 1: + UML_READ(block, I0, I0, SIZE_BYTE, SPACE_PROGRAM); // read r0, program_byte + break; + + case 2: + UML_READ(block, I0, I0, SIZE_WORD, SPACE_PROGRAM); // read r0, program_word + break; + + case 4: + UML_READ(block, I0, I0, SIZE_DWORD, SPACE_PROGRAM); // read r0, program_dword + break; + } + } + + UML_RET(block); // ret + + block->end(); +} + + diff --git a/src/devices/cpu/sh/sh2.h b/src/devices/cpu/sh/sh2.h index 50ecf680c88..7c15b82d5e4 100644 --- a/src/devices/cpu/sh/sh2.h +++ b/src/devices/cpu/sh/sh2.h @@ -17,9 +17,8 @@ #pragma once -#include "cpu/drcfe.h" -#include "cpu/drcuml.h" +#include "sh.h" #define SH2_INT_NONE -1 #define SH2_INT_VBLIN 0 @@ -40,21 +39,12 @@ #define SH2_INT_15 15 #define SH2_INT_ABUS 16 -enum -{ - SH2_PC = STATE_GENPC, SH2_SR=1, SH2_PR, SH2_GBR, SH2_VBR, SH2_MACH, SH2_MACL, - SH2_R0, SH2_R1, SH2_R2, SH2_R3, SH2_R4, SH2_R5, SH2_R6, SH2_R7, - SH2_R8, SH2_R9, SH2_R10, SH2_R11, SH2_R12, SH2_R13, SH2_R14, SH2_R15, SH2_EA -}; - - #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) - #define MCFG_SH2_IS_SLAVE(_slave) \ sh2_device::set_is_slave(*device, _slave); @@ -68,22 +58,9 @@ enum sh2_device::set_ftcsr_read_callback(*device, sh2_device::ftcsr_read_delegate(&_class::_method, #_class "::" #_method, downcast<_class *>(owner))); -/*************************************************************************** - COMPILER-SPECIFIC OPTIONS -***************************************************************************/ - -#define SH2DRC_STRICT_VERIFY 0x0001 /* verify all instructions */ -#define SH2DRC_FLUSH_PC 0x0002 /* flush the PC value before each memory access */ -#define SH2DRC_STRICT_PCREL 0x0004 /* do actual loads on MOVLI/MOVWI instead of collapsing to immediates */ - -#define SH2DRC_COMPATIBLE_OPTIONS (SH2DRC_STRICT_VERIFY | SH2DRC_FLUSH_PC | SH2DRC_STRICT_PCREL) -#define SH2DRC_FASTEST_OPTIONS (0) - -#define SH2_MAX_FASTRAM 4 - class sh2_frontend; -class sh2_device : public cpu_device +class sh2_device : public sh_common_execution { friend class sh2_frontend; @@ -105,11 +82,8 @@ public: DECLARE_READ32_MEMBER(sh2_internal_a5); void sh2_set_frt_input(int state); - void sh2drc_set_options(uint32_t options); - void sh2drc_add_pcflush(offs_t address); - void sh2drc_add_fastram(offs_t start, offs_t end, uint8_t readonly, void *base); - void sh2_notify_dma_data_available(); + void func_fastirq(); 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); @@ -135,58 +109,18 @@ protected: virtual void state_string_export(const device_state_entry &entry, std::string &str) const override; // device_disasm_interface overrides - virtual uint32_t disasm_min_opcode_bytes() const override { return 2; } - virtual uint32_t disasm_max_opcode_bytes() const override { return 2; } - virtual offs_t disasm_disassemble(std::ostream &stream, offs_t pc, const uint8_t *oprom, const uint8_t *opram, uint32_t options) override; - address_space *m_program, *m_decrypted_program; + virtual util::disasm_interface *create_disassembler() override; + + address_space *m_decrypted_program; private: address_space_config m_program_config, m_decrypted_program_config; - // Data that needs to be stored close to the generated DRC code - struct internal_sh2_state - { - uint32_t pc; - uint32_t pr; - uint32_t sr; - uint32_t gbr; - uint32_t vbr; - uint32_t mach; - uint32_t macl; - uint32_t r[16]; - uint32_t ea; - uint32_t pending_irq; - uint32_t pending_nmi; - int32_t irqline; - uint32_t evec; // exception vector for DRC - uint32_t irqsr; // IRQ-time old SR for DRC - uint32_t target; // target for jmp/jsr/etc so the delay slot can't kill it - int internal_irq_level; - int icount; - uint8_t sleep_mode; - uint32_t arg0; /* print_debug argument 1 */ - }; - - uint32_t m_delay; uint32_t m_cpu_off; - uint32_t m_dvsr, m_dvdnth, m_dvdntl, m_dvcr; uint32_t m_test_irq; - struct - { - int irq_vector; - int irq_priority; - } m_irq_queue[16]; - - bool m_isdrc; - - int m_pcfsel; // last pcflush entry set - int m_maxpcfsel; // highest valid pcflush entry - uint32_t m_pcflushes[16]; // pcflush entries int8_t m_irq_line_state[17]; -protected: - direct_read_data *m_direct; -private: + address_space *m_internal; uint32_t m_m[0x200/4]; int8_t m_nmi_line_state; @@ -213,273 +147,46 @@ private: uint16_t m_wtcnt; uint8_t m_wtcsr; - int m_is_slave, m_cpu_type; + 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; - drc_cache m_cache; /* pointer to the DRC code cache */ - std::unique_ptr<drcuml_state> m_drcuml; /* DRC UML generator state */ std::unique_ptr<sh2_frontend> m_drcfe; /* pointer to the DRC front-end state */ - uint32_t m_drcoptions; /* configurable DRC options */ - - internal_sh2_state *m_sh2_state; - - /* internal stuff */ - uint8_t m_cache_dirty; /* true if we need to flush the cache */ - /* parameters for subroutines */ - uint64_t m_numcycles; /* return value from gettotalcycles */ - uint32_t m_arg1; /* print_debug argument 2 */ - uint32_t m_irq; /* irq we're taking */ - - /* register mappings */ - uml::parameter m_regmap[16]; /* parameter to register mappings for all 16 integer registers */ + uint32_t m_debugger_temp; - uml::code_handle * m_entry; /* entry point */ - uml::code_handle * m_read8; /* read byte */ - uml::code_handle * m_write8; /* write byte */ - uml::code_handle * m_read16; /* read half */ - uml::code_handle * m_write16; /* write half */ - uml::code_handle * m_read32; /* read word */ - uml::code_handle * m_write32; /* write word */ + inline uint8_t RB(offs_t A) override; + inline uint16_t RW(offs_t A) override; + inline uint32_t RL(offs_t A) override; + inline void WB(offs_t A, uint8_t V) override; + inline void WW(offs_t A, uint16_t V) override; + inline void WL(offs_t A, uint32_t V) override; - uml::code_handle * m_interrupt; /* interrupt */ - uml::code_handle * m_nocode; /* nocode */ - uml::code_handle * m_out_of_cycles; /* out of cycles exception handler */ + virtual void LDCMSR(const uint16_t opcode) override; + virtual void LDCSR(const uint16_t opcode) override; + virtual void TRAPA(uint32_t i) override; + virtual void RTE() override; + virtual void ILLEGAL() override; - /* fast RAM */ - uint32_t m_fastram_select; - struct - { - offs_t start; /* start of the RAM block */ - offs_t end; /* end of the RAM block */ - bool readonly; /* true if read-only */ - void * base; /* base in memory where the RAM lives */ - } m_fastram[SH2_MAX_FASTRAM]; + virtual void execute_one_f000(uint16_t opcode) override; - uint32_t m_debugger_temp; - - inline uint8_t RB(offs_t A); - inline uint16_t RW(offs_t A); - inline uint32_t RL(offs_t A); - inline void WB(offs_t A, uint8_t V); - inline void WW(offs_t A, uint16_t V); - inline void WL(offs_t A, uint32_t V); - inline void ADD(uint32_t m, uint32_t n); - inline void ADDI(uint32_t i, uint32_t n); - inline void ADDC(uint32_t m, uint32_t n); - inline void ADDV(uint32_t m, uint32_t n); - inline void AND(uint32_t m, uint32_t n); - inline void ANDI(uint32_t i); - inline void ANDM(uint32_t i); - inline void BF(uint32_t d); - inline void BFS(uint32_t d); - inline void BRA(uint32_t d); - inline void BRAF(uint32_t m); - inline void BSR(uint32_t d); - inline void BSRF(uint32_t m); - inline void BT(uint32_t d); - inline void BTS(uint32_t d); - inline void CLRMAC(); - inline void CLRT(); - inline void CMPEQ(uint32_t m, uint32_t n); - inline void CMPGE(uint32_t m, uint32_t n); - inline void CMPGT(uint32_t m, uint32_t n); - inline void CMPHI(uint32_t m, uint32_t n); - inline void CMPHS(uint32_t m, uint32_t n); - inline void CMPPL(uint32_t n); - inline void CMPPZ(uint32_t n); - inline void CMPSTR(uint32_t m, uint32_t n); - inline void CMPIM(uint32_t i); - inline void DIV0S(uint32_t m, uint32_t n); - inline void DIV0U(); - inline void DIV1(uint32_t m, uint32_t n); - inline void DMULS(uint32_t m, uint32_t n); - inline void DMULU(uint32_t m, uint32_t n); - inline void DT(uint32_t n); - inline void EXTSB(uint32_t m, uint32_t n); - inline void EXTSW(uint32_t m, uint32_t n); - inline void EXTUB(uint32_t m, uint32_t n); - inline void EXTUW(uint32_t m, uint32_t n); - inline void ILLEGAL(); - inline void JMP(uint32_t m); - inline void JSR(uint32_t m); - inline void LDCSR(uint32_t m); - inline void LDCGBR(uint32_t m); - inline void LDCVBR(uint32_t m); - inline void LDCMSR(uint32_t m); - inline void LDCMGBR(uint32_t m); - inline void LDCMVBR(uint32_t m); - inline void LDSMACH(uint32_t m); - inline void LDSMACL(uint32_t m); - inline void LDSPR(uint32_t m); - inline void LDSMMACH(uint32_t m); - inline void LDSMMACL(uint32_t m); - inline void LDSMPR(uint32_t m); - inline void MAC_L(uint32_t m, uint32_t n); - inline void MAC_W(uint32_t m, uint32_t n); - inline void MOV(uint32_t m, uint32_t n); - inline void MOVBS(uint32_t m, uint32_t n); - inline void MOVWS(uint32_t m, uint32_t n); - inline void MOVLS(uint32_t m, uint32_t n); - inline void MOVBL(uint32_t m, uint32_t n); - inline void MOVWL(uint32_t m, uint32_t n); - inline void MOVLL(uint32_t m, uint32_t n); - inline void MOVBM(uint32_t m, uint32_t n); - inline void MOVWM(uint32_t m, uint32_t n); - inline void MOVLM(uint32_t m, uint32_t n); - inline void MOVBP(uint32_t m, uint32_t n); - inline void MOVWP(uint32_t m, uint32_t n); - inline void MOVLP(uint32_t m, uint32_t n); - inline void MOVBS0(uint32_t m, uint32_t n); - inline void MOVWS0(uint32_t m, uint32_t n); - inline void MOVLS0(uint32_t m, uint32_t n); - inline void MOVBL0(uint32_t m, uint32_t n); - inline void MOVWL0(uint32_t m, uint32_t n); - inline void MOVLL0(uint32_t m, uint32_t n); - inline void MOVI(uint32_t i, uint32_t n); - inline void MOVWI(uint32_t d, uint32_t n); - inline void MOVLI(uint32_t d, uint32_t n); - inline void MOVBLG(uint32_t d); - inline void MOVWLG(uint32_t d); - inline void MOVLLG(uint32_t d); - inline void MOVBSG(uint32_t d); - inline void MOVWSG(uint32_t d); - inline void MOVLSG(uint32_t d); - inline void MOVBS4(uint32_t d, uint32_t n); - inline void MOVWS4(uint32_t d, uint32_t n); - inline void MOVLS4(uint32_t m, uint32_t d, uint32_t n); - inline void MOVBL4(uint32_t m, uint32_t d); - inline void MOVWL4(uint32_t m, uint32_t d); - inline void MOVLL4(uint32_t m, uint32_t d, uint32_t n); - inline void MOVA(uint32_t d); - inline void MOVT(uint32_t n); - inline void MULL(uint32_t m, uint32_t n); - inline void MULS(uint32_t m, uint32_t n); - inline void MULU(uint32_t m, uint32_t n); - inline void NEG(uint32_t m, uint32_t n); - inline void NEGC(uint32_t m, uint32_t n); - inline void NOP(void); - inline void NOT(uint32_t m, uint32_t n); - inline void OR(uint32_t m, uint32_t n); - inline void ORI(uint32_t i); - inline void ORM(uint32_t i); - inline void ROTCL(uint32_t n); - inline void ROTCR(uint32_t n); - inline void ROTL(uint32_t n); - inline void ROTR(uint32_t n); - inline void RTE(); - inline void RTS(); - inline void SETT(); - inline void SHAL(uint32_t n); - inline void SHAR(uint32_t n); - inline void SHLL(uint32_t n); - inline void SHLL2(uint32_t n); - inline void SHLL8(uint32_t n); - inline void SHLL16(uint32_t n); - inline void SHLR(uint32_t n); - inline void SHLR2(uint32_t n); - inline void SHLR8(uint32_t n); - inline void SHLR16(uint32_t n); - inline void SLEEP(); - inline void STCSR(uint32_t n); - inline void STCGBR(uint32_t n); - inline void STCVBR(uint32_t n); - inline void STCMSR(uint32_t n); - inline void STCMGBR(uint32_t n); - inline void STCMVBR(uint32_t n); - inline void STSMACH(uint32_t n); - inline void STSMACL(uint32_t n); - inline void STSPR(uint32_t n); - inline void STSMMACH(uint32_t n); - inline void STSMMACL(uint32_t n); - inline void STSMPR(uint32_t n); - inline void SUB(uint32_t m, uint32_t n); - inline void SUBC(uint32_t m, uint32_t n); - inline void SUBV(uint32_t m, uint32_t n); - inline void SWAPB(uint32_t m, uint32_t n); - inline void SWAPW(uint32_t m, uint32_t n); - inline void TAS(uint32_t n); - inline void TRAPA(uint32_t i); - inline void TST(uint32_t m, uint32_t n); - inline void TSTI(uint32_t i); - inline void TSTM(uint32_t i); - inline void XOR(uint32_t m, uint32_t n); - inline void XORI(uint32_t i); - inline void XORM(uint32_t i); - inline void XTRCT(uint32_t m, uint32_t n); - inline void op0000(uint16_t opcode); - inline void op0001(uint16_t opcode); - inline void op0010(uint16_t opcode); - inline void op0011(uint16_t opcode); - inline void op0100(uint16_t opcode); - inline void op0101(uint16_t opcode); - inline void op0110(uint16_t opcode); - inline void op0111(uint16_t opcode); - inline void op1000(uint16_t opcode); - inline void op1001(uint16_t opcode); - inline void op1010(uint16_t opcode); - inline void op1011(uint16_t opcode); - inline void op1100(uint16_t opcode); - inline void op1101(uint16_t opcode); - inline void op1110(uint16_t opcode); - inline void op1111(uint16_t opcode); 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 dma); - void sh2_exception(const char *message, int irqline); + virtual void sh2_exception(const char *message, int irqline) override; void sh2_dmac_check(int dma); void sh2_recalc_irq(); - /* internal compiler state */ - struct compiler_state - { - uint32_t cycles; /* accumulated cycles */ - uint8_t checkints; /* need to check interrupts before next instruction */ - uml::code_label labelnum; /* index for local labels */ - }; - - inline uint32_t epc(const opcode_desc *desc); - inline void alloc_handle(drcuml_state *drcuml, uml::code_handle **handleptr, const char *name); - inline void load_fast_iregs(drcuml_block *block); - inline void save_fast_iregs(drcuml_block *block); - - void code_flush_cache(); - void execute_run_drc(); - void code_compile_block(uint8_t mode, offs_t pc); - void static_generate_entry_point(); - void static_generate_nocode_handler(); - void static_generate_out_of_cycles(); - void static_generate_memory_accessor(int size, int iswrite, const char *name, uml::code_handle **handleptr); - const char *log_desc_flags_to_string(uint32_t flags); - void log_register_list(drcuml_state *drcuml, const char *string, const uint32_t *reglist, const uint32_t *regnostarlist); - void log_opcode_desc(drcuml_state *drcuml, const opcode_desc *desclist, int indent); - void log_add_disasm_comment(drcuml_block *block, uint32_t pc, uint32_t op); - void generate_update_cycles(drcuml_block *block, compiler_state *compiler, uml::parameter param, bool allow_exception); - void generate_checksum_block(drcuml_block *block, compiler_state *compiler, const opcode_desc *seqhead, const opcode_desc *seqlast); - void generate_sequence_instruction(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, uint32_t ovrpc); - void generate_delay_slot(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, uint32_t ovrpc); - bool generate_opcode(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, uint32_t ovrpc); - bool generate_group_0(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, uint16_t opcode, int in_delay_slot, uint32_t ovrpc); - bool generate_group_2(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, uint16_t opcode, int in_delay_slot, uint32_t ovrpc); - bool generate_group_3(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, uint16_t opcode, uint32_t ovrpc); - bool generate_group_4(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, uint16_t opcode, int in_delay_slot, uint32_t ovrpc); - bool generate_group_6(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, uint16_t opcode, int in_delay_slot, uint32_t ovrpc); - bool generate_group_8(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, uint16_t opcode, int in_delay_slot, uint32_t ovrpc); - bool generate_group_12(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, uint16_t opcode, int in_delay_slot, uint32_t ovrpc); + virtual void init_drc_frontend() override; + virtual const opcode_desc* get_desclist(offs_t pc) override; + + virtual void generate_update_cycles(drcuml_block *block, compiler_state *compiler, uml::parameter param, bool allow_exception) override; + 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; -public: - void func_printf_probe(); - void func_unimplemented(); - void func_fastirq(); - void func_MAC_W(); - void func_MAC_L(); - void func_DIV1(); - void func_ADDV(); - void func_SUBV(); }; class sh2a_device : public sh2_device @@ -528,30 +235,19 @@ private: }; -class sh2_frontend : public drc_frontend +class sh2_frontend : public sh_frontend { public: - sh2_frontend(sh2_device *device, uint32_t window_start, uint32_t window_end, uint32_t max_sequence); + sh2_frontend(sh_common_execution *device, uint32_t window_start, uint32_t window_end, uint32_t max_sequence); protected: - virtual bool describe(opcode_desc &desc, const opcode_desc *prev) override; private: - bool describe_group_0(opcode_desc &desc, const opcode_desc *prev, uint16_t opcode); - bool describe_group_2(opcode_desc &desc, const opcode_desc *prev, uint16_t opcode); - bool describe_group_3(opcode_desc &desc, const opcode_desc *prev, uint16_t opcode); - bool describe_group_4(opcode_desc &desc, const opcode_desc *prev, uint16_t opcode); - bool describe_group_6(opcode_desc &desc, const opcode_desc *prev, uint16_t opcode); - bool describe_group_8(opcode_desc &desc, const opcode_desc *prev, uint16_t opcode); - bool describe_group_12(opcode_desc &desc, const opcode_desc *prev, uint16_t opcode); - - sh2_device *m_sh2; + 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 diff --git a/src/devices/cpu/sh/sh2comn.cpp b/src/devices/cpu/sh/sh2comn.cpp index b6ac0e1cc65..fca8070c936 100644 --- a/src/devices/cpu/sh/sh2comn.cpp +++ b/src/devices/cpu/sh/sh2comn.cpp @@ -181,11 +181,8 @@ void sh2_device::sh2_do_dma(int dma) } } - #ifdef USE_TIMER_FOR_DMA - //schedule next DMA callback + //schedule next DMA callback m_dma_current_active_timer[dma]->adjust(cycles_to_attotime(2), dma); - #endif - dmadata = m_program->read_byte(tempsrc); if (!m_dma_kludge_cb.isnull()) dmadata = m_dma_kludge_cb(tempsrc, tempdst, dmadata, m_active_dma_size[dma]); @@ -229,10 +226,8 @@ void sh2_device::sh2_do_dma(int dma) } } - #ifdef USE_TIMER_FOR_DMA - //schedule next DMA callback + //schedule next DMA callback m_dma_current_active_timer[dma]->adjust(cycles_to_attotime(2), dma); - #endif // check: should this really be using read_word_32 / write_word_32? dmadata = m_program->read_word(tempsrc); @@ -276,10 +271,8 @@ void sh2_device::sh2_do_dma(int dma) } } - #ifdef USE_TIMER_FOR_DMA - //schedule next DMA callback + //schedule next DMA callback m_dma_current_active_timer[dma]->adjust(cycles_to_attotime(2), dma); - #endif dmadata = m_program->read_dword(tempsrc); if (!m_dma_kludge_cb.isnull()) dmadata = m_dma_kludge_cb(tempsrc, tempdst, dmadata, m_active_dma_size[dma]); @@ -321,10 +314,8 @@ void sh2_device::sh2_do_dma(int dma) } } - #ifdef USE_TIMER_FOR_DMA - //schedule next DMA callback + //schedule next DMA callback m_dma_current_active_timer[dma]->adjust(cycles_to_attotime(2), dma); - #endif dmadata = m_program->read_dword(tempsrc); if (!m_dma_kludge_cb.isnull()) dmadata = m_dma_kludge_cb(tempsrc, tempdst, dmadata, m_active_dma_size[dma]); @@ -409,8 +400,8 @@ void sh2_device::sh2_dmac_check(int dma) m_dma_timer_active[dma] = 1; - m_active_dma_src[dma] &= AM; - m_active_dma_dst[dma] &= AM; + m_active_dma_src[dma] &= SH12_AM; + m_active_dma_dst[dma] &= SH12_AM; switch(m_active_dma_size[dma]) { @@ -431,10 +422,6 @@ void sh2_device::sh2_dmac_check(int dma) break; } - - - -#ifdef USE_TIMER_FOR_DMA // start DMA timer // fever soccer uses cycle-stealing mode, requiring the CPU to be halted @@ -445,8 +432,6 @@ void sh2_device::sh2_dmac_check(int dma) } m_dma_current_active_timer[dma]->adjust(cycles_to_attotime(2), dma); -#endif - } } else diff --git a/src/devices/cpu/sh/sh2comn.h b/src/devices/cpu/sh/sh2comn.h index 1c859e227d6..fb1e63eac19 100644 --- a/src/devices/cpu/sh/sh2comn.h +++ b/src/devices/cpu/sh/sh2comn.h @@ -13,16 +13,6 @@ #pragma once - - -// do we use a timer for the DMA, or have it in CPU_EXECUTE -#define USE_TIMER_FOR_DMA - -#include "cpu/drcuml.h" -#include "cpu/drcumlsh.h" - -#define SH2_CODE_XOR(a) ((a) ^ NATIVE_ENDIAN_VALUE_LE_BE(2,0)) - enum { ICF = 0x00800000, @@ -31,31 +21,7 @@ enum OVF = 0x00020000 }; -#define T 0x00000001 -#define S 0x00000002 -#define I 0x000000f0 -#define Q 0x00000100 -#define M 0x00000200 - -#define AM 0xc7ffffff - -#define FLAGS (M|Q|I|S|T) - -#define Rn ((opcode>>8)&15) -#define Rm ((opcode>>4)&15) - -#define CPU_TYPE_SH1 (0) -#define CPU_TYPE_SH2 (1) - -#define REGFLAG_R(n) (1 << (n)) - -/* register flags 1 */ -#define REGFLAG_PR (1 << 0) -#define REGFLAG_MACL (1 << 1) -#define REGFLAG_MACH (1 << 2) -#define REGFLAG_GBR (1 << 3) -#define REGFLAG_VBR (1 << 4) -#define REGFLAG_SR (1 << 5) +#define SH12_AM 0xc7ffffff #define CHECK_PENDING_IRQ(message) \ do { \ diff --git a/src/devices/cpu/sh/sh2dasm.cpp b/src/devices/cpu/sh/sh2dasm.cpp deleted file mode 100644 index ef823ee28a5..00000000000 --- a/src/devices/cpu/sh/sh2dasm.cpp +++ /dev/null @@ -1,610 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:Juergen Buchmueller -#include "emu.h" -#include "debugger.h" -#include "sh2.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) - -static const char *const regname[16] = { - "R0", "R1", "R2", "R3", "R4", "R5", "R6", "R7", - "R8", "R9", "R10","R11","R12","R13","R14","SP" -}; - -static uint32_t op0000(std::ostream &stream, uint32_t pc, uint16_t opcode) -{ - uint32_t flags = 0; - switch(opcode & 0x3f) - { - case 0x02: - util::stream_format(stream, "STC SR,%s", regname[Rn]); - break; - case 0x03: - util::stream_format(stream, "BSRF %s", regname[Rn]); - break; - case 0x08: - stream << "CLRT"; - break; - case 0x09: - stream << "NOP"; - break; - case 0x0A: - util::stream_format(stream, "STS MACH,%s", regname[Rn]); - break; - case 0x0B: - stream << "RTS"; - flags = DASMFLAG_STEP_OUT; - break; - case 0x12: - util::stream_format(stream, "STS GBR,%s", regname[Rn]); - break; - case 0x18: - stream << "SETT"; - break; - case 0x19: - stream << "DIV0U"; - break; - case 0x1A: - util::stream_format(stream, "STS MACL,%s", regname[Rn]); - break; - case 0x1B: - stream << "SLEEP"; - break; - case 0x22: - util::stream_format(stream, "STC VBR,%s", regname[Rn]); - break; - case 0x23: - util::stream_format(stream, "BRAF %s", regname[Rn]); - break; - case 0x28: - stream << "CLRMAC"; - break; - case 0x29: - util::stream_format(stream, "MOVT %s", regname[Rn]); - break; - case 0x2A: - util::stream_format(stream, "STS PR,%s", regname[Rn]); - break; - case 0x2B: - stream << "RTE"; - flags = DASMFLAG_STEP_OUT; - break; - default: - switch(opcode & 15) - { - case 0: - util::stream_format(stream, "?????? $%04X", opcode); - break; - case 1: - util::stream_format(stream, "?????? $%04X", opcode); - break; - case 2: - util::stream_format(stream, "?????? $%04X", opcode); - break; - case 3: - util::stream_format(stream, "?????? $%04X", opcode); - break; - case 4: - util::stream_format(stream, "MOV.B %s,@(R0,%s)", regname[Rm], regname[Rn]); - break; - case 5: - util::stream_format(stream, "MOV.W %s,@(R0,%s)", regname[Rm], regname[Rn]); - break; - case 6: - util::stream_format(stream, "MOV.L %s,@(R0,%s)", regname[Rm], regname[Rn]); - break; - case 7: - util::stream_format(stream, "MUL.L %s,%s", regname[Rm], regname[Rn]); - break; - case 8: - util::stream_format(stream, "?????? $%04X", opcode); - break; - case 9: - util::stream_format(stream, "?????? $%04X", opcode); - break; - case 10: - util::stream_format(stream, "?????? $%04X", opcode); - break; - case 11: - util::stream_format(stream, "?????? $%04X", opcode); - break; - case 12: - util::stream_format(stream, "MOV.B @(R0,%s),%s", regname[Rm], regname[Rn]); - break; - case 13: - util::stream_format(stream, "MOV.W @(R0,%s),%s", regname[Rm], regname[Rn]); - break; - case 14: - 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]); - break; - } - } - return flags; -} - -static uint32_t op0001(std::ostream &stream, uint32_t pc, uint16_t opcode) -{ - util::stream_format(stream, "MOV.L %s,@($%02X,%s)", regname[Rm], (opcode & 15) * 4, regname[Rn]); - return 0; -} - -static uint32_t op0010(std::ostream &stream, uint32_t pc, uint16_t opcode) -{ - switch (opcode & 15) - { - case 0: - util::stream_format(stream, "MOV.B %s,@%s", regname[Rm], regname[Rn]); - break; - case 1: - util::stream_format(stream, "MOV.W %s,@%s", regname[Rm], regname[Rn]); - break; - case 2: - util::stream_format(stream, "MOV.L %s,@%s", regname[Rm], regname[Rn]); - break; - case 3: - util::stream_format(stream, "?????? $%04X", opcode); - break; - case 4: - util::stream_format(stream, "MOV.B %s,@-%s", regname[Rm], regname[Rn]); - break; - case 5: - util::stream_format(stream, "MOV.W %s,@-%s", regname[Rm], regname[Rn]); - break; - case 6: - util::stream_format(stream, "MOV.L %s,@-%s", regname[Rm], regname[Rn]); - break; - case 7: - util::stream_format(stream, "DIV0S %s,%s", regname[Rm], regname[Rn]); - break; - case 8: - util::stream_format(stream, "TST %s,%s", regname[Rm], regname[Rn]); - break; - case 9: - util::stream_format(stream, "AND %s,%s", regname[Rm], regname[Rn]); - break; - case 10: - util::stream_format(stream, "XOR %s,%s", regname[Rm], regname[Rn]); - break; - case 11: - util::stream_format(stream, "OR %s,%s", regname[Rm], regname[Rn]); - break; - case 12: - util::stream_format(stream, "CMP/STR %s,%s", regname[Rm], regname[Rn]); - break; - case 13: - util::stream_format(stream, "XTRCT %s,%s", regname[Rm], regname[Rn]); - break; - case 14: - util::stream_format(stream, "MULU.W %s,%s", regname[Rm], regname[Rn]); - break; - case 15: - util::stream_format(stream, "MULS.W %s,%s", regname[Rm], regname[Rn]); - break; - } - return 0; -} - -static uint32_t op0011(std::ostream &stream, uint32_t pc, uint16_t opcode) -{ - switch (opcode & 15) - { - case 0: - util::stream_format(stream, "CMP/EQ %s,%s", regname[Rm], regname[Rn]); - break; - case 1: - util::stream_format(stream, "?????? %s,%s", regname[Rm], regname[Rn]); - break; - case 2: - util::stream_format(stream, "CMP/HS %s,%s", regname[Rm], regname[Rn]); - break; - case 3: - util::stream_format(stream, "CMP/GE %s,%s", regname[Rm], regname[Rn]); - break; - case 4: - util::stream_format(stream, "DIV1 %s,%s", regname[Rm], regname[Rn]); - break; - case 5: - util::stream_format(stream, "DMULU.L %s,%s", regname[Rm], regname[Rn]); - break; - case 6: - util::stream_format(stream, "CMP/HI %s,%s", regname[Rm], regname[Rn]); - break; - case 7: - util::stream_format(stream, "CMP/GT %s,%s", regname[Rm], regname[Rn]); - break; - case 8: - util::stream_format(stream, "SUB %s,%s", regname[Rm], regname[Rn]); - break; - case 9: - util::stream_format(stream, "?????? %s,%s", regname[Rm], regname[Rn]); - break; - case 10: - util::stream_format(stream, "SUBC %s,%s", regname[Rm], regname[Rn]); - break; - case 11: - util::stream_format(stream, "SUBV %s,%s", regname[Rm], regname[Rn]); - break; - case 12: - util::stream_format(stream, "ADD %s,%s", regname[Rm], regname[Rn]); - break; - case 13: - util::stream_format(stream, "DMULS.L %s,%s", regname[Rm], regname[Rn]); - break; - case 14: - util::stream_format(stream, "ADDC %s,%s", regname[Rm], regname[Rn]); - break; - case 15: - util::stream_format(stream, "ADDV %s,%s", regname[Rm], regname[Rn]); - break; - } - return 0; -} - -static uint32_t op0100(std::ostream &stream, uint32_t pc, uint16_t opcode) -{ - uint32_t flags = 0; - switch(opcode & 0x3F) - { - case 0x00: - util::stream_format(stream, "SHLL %s", regname[Rn]); - break; - case 0x01: - util::stream_format(stream, "SHLR %s", regname[Rn]); - break; - case 0x02: - util::stream_format(stream, "STS.L MACH,@-%s", regname[Rn]); - break; - case 0x03: - util::stream_format(stream, "STC.L SR,@-%s", regname[Rn]); - break; - case 0x04: - util::stream_format(stream, "ROTL %s", regname[Rn]); - break; - case 0x05: - util::stream_format(stream, "ROTR %s", regname[Rn]); - break; - case 0x06: - util::stream_format(stream, "LDS.L @%s+,MACH", regname[Rn]); - break; - case 0x07: - util::stream_format(stream, "LDC.L @%s+,SR", regname[Rn]); - break; - case 0x08: - util::stream_format(stream, "SHLL2 %s", regname[Rn]); - break; - case 0x09: - util::stream_format(stream, "SHLR2 %s", regname[Rn]); - break; - case 0x0a: - util::stream_format(stream, "LDS %s,MACH", regname[Rn]); - break; - case 0x0b: - util::stream_format(stream, "JSR %s", regname[Rn]); - flags = DASMFLAG_STEP_OVER | DASMFLAG_STEP_OVER_EXTRA(1); - break; - case 0x0e: - util::stream_format(stream, "LDC %s,SR", regname[Rn]); - break; - case 0x10: - util::stream_format(stream, "DT %s", regname[Rn]); - break; - case 0x11: - util::stream_format(stream, "CMP/PZ %s", regname[Rn]); - break; - case 0x12: - util::stream_format(stream, "STS.L MACL,@-%s", regname[Rn]); - break; - case 0x13: - util::stream_format(stream, "STC.L GBR,@-%s", regname[Rn]); - break; - case 0x15: - util::stream_format(stream, "CMP/PL %s", regname[Rn]); - break; - case 0x16: - util::stream_format(stream, "LDS.L @%s+,MACL", regname[Rn]); - break; - case 0x17: - util::stream_format(stream, "LDC.L @%s+,GBR", regname[Rn]); - break; - case 0x18: - util::stream_format(stream, "SHLL8 %s", regname[Rn]); - break; - case 0x19: - util::stream_format(stream, "SHLR8 %s", regname[Rn]); - break; - case 0x1a: - util::stream_format(stream, "LDS %s,MACL", regname[Rn]); - break; - case 0x1b: - util::stream_format(stream, "TAS %s", regname[Rn]); - break; - case 0x1e: - util::stream_format(stream, "LDC %s,GBR", regname[Rn]); - break; - case 0x20: - util::stream_format(stream, "SHAL %s", regname[Rn]); - break; - case 0x21: - util::stream_format(stream, "SHAR %s", regname[Rn]); - break; - case 0x22: - util::stream_format(stream, "STS.L PR,@-%s", regname[Rn]); - break; - case 0x23: - util::stream_format(stream, "STC.L VBR,@-%s", regname[Rn]); - break; - case 0x24: - util::stream_format(stream, "ROTCL %s", regname[Rn]); - break; - case 0x25: - util::stream_format(stream, "ROTCR %s", regname[Rn]); - break; - case 0x26: - util::stream_format(stream, "LDS.L @%s+,PR", regname[Rn]); - break; - case 0x27: - util::stream_format(stream, "LDC.L @%s+,VBR", regname[Rn]); - break; - case 0x28: - util::stream_format(stream, "SHLL16 %s", regname[Rn]); - break; - case 0x29: - util::stream_format(stream, "SHLR16 %s", regname[Rn]); - break; - case 0x2a: - util::stream_format(stream, "LDS %s,PR", regname[Rn]); - break; - case 0x2b: - util::stream_format(stream, "JMP %s", regname[Rn]); - break; - case 0x2e: - util::stream_format(stream, "LDC %s,VBR", regname[Rn]); - break; - default: - if ((opcode & 15) == 15) - util::stream_format(stream, "MAC.W @%s+,@%s+", regname[Rm], regname[Rn]); - else - util::stream_format(stream, "?????? $%04X", opcode); - } - return flags; -} - -static uint32_t op0101(std::ostream &stream, uint32_t pc, uint16_t opcode) -{ - util::stream_format(stream, "MOV.L @($%02X,%s),%s", (opcode & 15) * 4, regname[Rm], regname[Rn]); - return 0; -} - -static uint32_t op0110(std::ostream &stream, uint32_t pc, uint16_t opcode) - -{ - switch(opcode & 0xF) - { - case 0x00: - util::stream_format(stream, "MOV.B @%s,%s", regname[Rm], regname[Rn]); - break; - case 0x01: - util::stream_format(stream, "MOV.W @%s,%s", regname[Rm], regname[Rn]); - break; - case 0x02: - util::stream_format(stream, "MOV.L @%s,%s", regname[Rm], regname[Rn]); - break; - case 0x03: - util::stream_format(stream, "MOV %s,%s", regname[Rm], regname[Rn]); - break; - case 0x04: - util::stream_format(stream, "MOV.B @%s+,%s", regname[Rm], regname[Rn]); - break; - case 0x05: - util::stream_format(stream, "MOV.W @%s+,%s", regname[Rm], regname[Rn]); - break; - case 0x06: - util::stream_format(stream, "MOV.L @%s+,%s", regname[Rm], regname[Rn]); - break; - case 0x07: - util::stream_format(stream, "NOT %s,%s", regname[Rm], regname[Rn]); - break; - case 0x08: - util::stream_format(stream, "SWAP.B %s,%s", regname[Rm], regname[Rn]); - break; - case 0x09: - util::stream_format(stream, "SWAP.W %s,%s", regname[Rm], regname[Rn]); - break; - case 0x0a: - util::stream_format(stream, "NEGC %s,%s", regname[Rm], regname[Rn]); - break; - case 0x0b: - util::stream_format(stream, "NEG %s,%s", regname[Rm], regname[Rn]); - break; - case 0x0c: - util::stream_format(stream, "EXTU.B %s,%s", regname[Rm], regname[Rn]); - break; - case 0x0d: - util::stream_format(stream, "EXTU.W %s,%s", regname[Rm], regname[Rn]); - break; - case 0x0e: - util::stream_format(stream, "EXTS.B %s,%s", regname[Rm], regname[Rn]); - break; - case 0x0f: - util::stream_format(stream, "EXTS.W %s,%s", regname[Rm], regname[Rn]); - break; - } - return 0; -} - -static uint32_t op0111(std::ostream &stream, uint32_t pc, uint16_t opcode) -{ - util::stream_format(stream, "ADD #$%02X,%s", opcode & 0xff, regname[Rn]); - return 0; -} - -static uint32_t op1000(std::ostream &stream, uint32_t pc, uint16_t opcode) -{ - switch((opcode >> 8) & 15) - { - case 0: - util::stream_format(stream, "MOV.B R0,@($%02X,%s)", (opcode & 15), regname[Rm]); - break; - case 1: - util::stream_format(stream, "MOV.W R0,@($%02X,%s)", (opcode & 15) * 2, regname[Rm]); - break; - case 4: - util::stream_format(stream, "MOV.B @($%02X,%s),R0", (opcode & 15), regname[Rm]); - break; - case 5: - util::stream_format(stream, "MOV.W @($%02X,%s),R0", (opcode & 15), regname[Rm]); - break; - case 8: - 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; - case 11: - util::stream_format(stream, "BF $%08X", pc + SIGNX8(opcode & 0xff) * 2 + 2); - break; - case 13: - util::stream_format(stream, "BTS $%08X", pc + SIGNX8(opcode & 0xff) * 2 + 2); - break; - case 15: - util::stream_format(stream, "BFS $%08X", pc + SIGNX8(opcode & 0xff) * 2 + 2); - break; - default : - util::stream_format(stream, "invalid $%04X", opcode); - } - return 0; -} - -static uint32_t op1001(std::ostream &stream, uint32_t pc, uint16_t opcode) -{ - util::stream_format(stream, "MOV.W @($%04X,PC),%s [%08X]", (opcode & 0xff) * 2, regname[Rn], pc+((opcode & 0xff) * 2)+2); - return 0; -} - -static uint32_t op1010(std::ostream &stream, uint32_t pc, uint16_t opcode) -{ - util::stream_format(stream, "BRA $%08X", SIGNX12(opcode & 0xfff) * 2 + pc + 2); - return 0; -} - -static uint32_t op1011(std::ostream &stream, uint32_t pc, uint16_t opcode) -{ - util::stream_format(stream, "BSR $%08X", SIGNX12(opcode & 0xfff) * 2 + pc + 2); - return DASMFLAG_STEP_OVER | DASMFLAG_STEP_OVER_EXTRA(1); -} - -static uint32_t op1100(std::ostream &stream, uint32_t pc, uint16_t opcode) -{ - uint32_t flags = 0; - switch((opcode >> 8) & 15) - { - case 0: - util::stream_format(stream, "MOV.B R0,@($%02X,GBR)", opcode & 0xff); - break; - case 1: - util::stream_format(stream, "MOV.W R0,@($%04X,GBR)", (opcode & 0xff) * 2); - break; - case 2: - util::stream_format(stream, "MOV.L R0,@($%04X,GBR)", (opcode & 0xff) * 4); - break; - case 3: - util::stream_format(stream, "TRAPA #$%02X", opcode & 0xff); - flags = DASMFLAG_STEP_OVER; - break; - case 4: - util::stream_format(stream, "MOV.B @($%02X,GBR),R0", opcode & 0xff); - break; - case 5: - util::stream_format(stream, "MOV.W @($%04X,GBR),R0", (opcode & 0xff) * 2); - break; - case 6: - util::stream_format(stream, "MOV.L @($%04X,GBR),R0", (opcode & 0xff) * 4); - break; - case 7: - util::stream_format(stream, "MOVA @($%04X,PC),R0 [%08X]", (opcode & 0xff) * 4, ((pc + 2) & ~3) + (opcode & 0xff) * 4); - break; - case 8: - util::stream_format(stream, "TST #$%02X,R0", opcode & 0xff); - break; - case 9: - util::stream_format(stream, "AND #$%02X,R0", opcode & 0xff); - break; - case 10: - util::stream_format(stream, "XOR #$%02X,R0", opcode & 0xff); - break; - case 11: - util::stream_format(stream, "OR #$%02X,R0", opcode & 0xff); - break; - case 12: - util::stream_format(stream, "TST.B #$%02X,@(R0,GBR)", opcode & 0xff); - break; - case 13: - util::stream_format(stream, "AND.B #$%02X,@(R0,GBR)", opcode & 0xff); - break; - case 14: - util::stream_format(stream, "XOR.B #$%02X,@(R0,GBR)", opcode & 0xff); - break; - case 15: - util::stream_format(stream, "OR.B #$%02X,@(R0,GBR)", opcode & 0xff); - break; - } - return flags; -} - -static uint32_t op1101(std::ostream &stream, uint32_t pc, uint16_t opcode) -{ - util::stream_format(stream, "MOV.L @($%02X,PC),%s [%08X]", (opcode * 4) & 0xff, regname[Rn], ((pc + 2) & ~3) + (opcode & 0xff) * 4); - return 0; -} - -static uint32_t op1110(std::ostream &stream, uint32_t pc, uint16_t opcode) -{ - util::stream_format(stream, "MOV #$%02X,%s", (opcode & 0xff), regname[Rn]); - return 0; -} - -static uint32_t op1111(std::ostream &stream, uint32_t pc, uint16_t opcode) -{ - util::stream_format(stream, "unknown $%04X", opcode); - return 0; -} - -unsigned DasmSH2(std::ostream &stream, unsigned pc, uint16_t opcode) -{ - uint32_t flags; - - pc += 2; - - switch ((opcode >> 12) & 15) - { - case 0: flags = op0000(stream, pc, opcode); break; - case 1: flags = op0001(stream, pc, opcode); break; - case 2: flags = op0010(stream, pc, opcode); break; - case 3: flags = op0011(stream, pc, opcode); break; - case 4: flags = op0100(stream, pc, opcode); break; - case 5: flags = op0101(stream, pc, opcode); break; - case 6: flags = op0110(stream, pc, opcode); break; - case 7: flags = op0111(stream, pc, opcode); break; - case 8: flags = op1000(stream, pc, opcode); break; - case 9: flags = op1001(stream, pc, opcode); break; - case 10: flags = op1010(stream, pc, opcode); break; - case 11: flags = op1011(stream, pc, opcode); break; - case 12: flags = op1100(stream, pc, opcode); break; - case 13: flags = op1101(stream, pc, opcode); break; - case 14: flags = op1110(stream, pc, opcode); break; - default: flags = op1111(stream, pc, opcode); break; - } - return 2 | flags | DASMFLAG_SUPPORTED; -} - -CPU_DISASSEMBLE(sh2) -{ - return DasmSH2(stream, pc, (oprom[0] << 8) | oprom[1]); -} diff --git a/src/devices/cpu/sh/sh2drc.cpp b/src/devices/cpu/sh/sh2drc.cpp index 1003463b97a..e69de29bb2d 100644 --- a/src/devices/cpu/sh/sh2drc.cpp +++ b/src/devices/cpu/sh/sh2drc.cpp @@ -1,2982 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:R. Belmont -/*************************************************************************** - - sh2drc.c - Universal machine language-based SH-2 emulator. - -***************************************************************************/ - -#include "emu.h" -#include "debugger.h" -#include "sh2.h" -#include "sh2comn.h" - -extern unsigned DasmSH2(std::ostream &stream, unsigned pc, uint16_t opcode); - -using namespace uml; - -/*************************************************************************** - DEBUGGING -***************************************************************************/ - -#define SET_EA (0) // makes slower but "shows work" in the EA fake register like the interpreter - -#define ADDSUBV_DIRECT (0) - -#if SET_EA -#define SETEA(x) UML_MOV(block, mem(&m_sh2_state->ea), ireg(x)) -#else -#define SETEA(x) -#endif - -/*************************************************************************** - CONSTANTS -***************************************************************************/ - -/* map variables */ -#define MAPVAR_PC M0 -#define MAPVAR_CYCLES M1 - -/* exit codes */ -#define EXECUTE_OUT_OF_CYCLES 0 -#define EXECUTE_MISSING_CODE 1 -#define EXECUTE_UNMAPPED_CODE 2 -#define EXECUTE_RESET_CACHE 3 - -#define PROBE_ADDRESS ~0 - - -/*************************************************************************** - MACROS -***************************************************************************/ - -#define R32(reg) m_regmap[reg] - -/*************************************************************************** - INLINE FUNCTIONS -***************************************************************************/ - -/*------------------------------------------------- - epc - compute the exception PC from a - descriptor --------------------------------------------------*/ - -uint32_t sh2_device::epc(const opcode_desc *desc) -{ - return (desc->flags & OPFLAG_IN_DELAY_SLOT) ? (desc->pc - 1) : desc->pc; -} - -/*------------------------------------------------- - alloc_handle - allocate a handle if not - already allocated --------------------------------------------------*/ - -void sh2_device::alloc_handle(drcuml_state *drcuml, code_handle **handleptr, const char *name) -{ - if (*handleptr == nullptr) - *handleptr = drcuml->handle_alloc(name); -} - -/*------------------------------------------------- - load_fast_iregs - load any fast integer - registers --------------------------------------------------*/ - -void sh2_device::load_fast_iregs(drcuml_block *block) -{ - int regnum; - - for (regnum = 0; regnum < ARRAY_LENGTH(m_regmap); regnum++) - { - if (m_regmap[regnum].is_int_register()) - { - UML_MOV(block, uml::parameter::make_ireg(m_regmap[regnum].ireg()), mem(&m_sh2_state->r[regnum])); - } - } -} - - -/*------------------------------------------------- - save_fast_iregs - save any fast integer - registers --------------------------------------------------*/ - -void sh2_device::save_fast_iregs(drcuml_block *block) -{ - int regnum; - - for (regnum = 0; regnum < ARRAY_LENGTH(m_regmap); regnum++) - { - if (m_regmap[regnum].is_int_register()) - { - UML_MOV(block, mem(&m_sh2_state->r[regnum]), uml::parameter::make_ireg(m_regmap[regnum].ireg())); - } - } -} - -/*------------------------------------------------- - cfunc_printf_probe - print the current CPU - state and return --------------------------------------------------*/ - -static void cfunc_printf_probe(void *param) -{ - ((sh2_device *)param)->func_printf_probe(); -} - -void sh2_device::func_printf_probe() -{ - uint32_t pc = m_sh2_state->pc; - - printf(" PC=%08X r0=%08X r1=%08X r2=%08X\n", - pc, - (uint32_t)m_sh2_state->r[0], - (uint32_t)m_sh2_state->r[1], - (uint32_t)m_sh2_state->r[2]); - printf(" r3=%08X r4=%08X r5=%08X r6=%08X\n", - (uint32_t)m_sh2_state->r[3], - (uint32_t)m_sh2_state->r[4], - (uint32_t)m_sh2_state->r[5], - (uint32_t)m_sh2_state->r[6]); - printf(" r7=%08X r8=%08X r9=%08X r10=%08X\n", - (uint32_t)m_sh2_state->r[7], - (uint32_t)m_sh2_state->r[8], - (uint32_t)m_sh2_state->r[9], - (uint32_t)m_sh2_state->r[10]); - printf(" r11=%08X r12=%08X r13=%08X r14=%08X\n", - (uint32_t)m_sh2_state->r[11], - (uint32_t)m_sh2_state->r[12], - (uint32_t)m_sh2_state->r[13], - (uint32_t)m_sh2_state->r[14]); - printf(" r15=%08X macl=%08X mach=%08X gbr=%08X\n", - (uint32_t)m_sh2_state->r[15], - (uint32_t)m_sh2_state->macl, - (uint32_t)m_sh2_state->mach, - (uint32_t)m_sh2_state->gbr); - printf(" evec %x irqsr %x pc=%08x\n", - (uint32_t)m_sh2_state->evec, - (uint32_t)m_sh2_state->irqsr, (uint32_t)m_sh2_state->pc); -} - -/*------------------------------------------------- - cfunc_unimplemented - handler for - unimplemented opcdes --------------------------------------------------*/ - -static void cfunc_unimplemented(void *param) -{ - ((sh2_device *)param)->func_unimplemented(); -} - -void sh2_device::func_unimplemented() -{ - // set up an invalid opcode exception - m_sh2_state->evec = RL( m_sh2_state->vbr + 4 * 4 ); - m_sh2_state->evec &= AM; - m_sh2_state->irqsr = m_sh2_state->sr; - // claim it's an NMI, because it pretty much is - m_sh2_state->pending_nmi = 1; -} - -/*------------------------------------------------- - cfunc_fastirq - checks for pending IRQs --------------------------------------------------*/ -static void cfunc_fastirq(void *param) -{ - ((sh2_device *)param)->func_fastirq(); -} - -void sh2_device::func_fastirq() -{ - sh2_exception("fastirq",m_sh2_state->irqline); -} - -/*------------------------------------------------- - cfunc_MAC_W - implementation of MAC_W Rm,Rn --------------------------------------------------*/ -static void cfunc_MAC_W(void *param) -{ - ((sh2_device *)param)->func_MAC_W(); -} - -void sh2_device::func_MAC_W() -{ - int32_t tempm, tempn, dest, src, ans; - uint32_t templ; - uint16_t opcode; - int n, m; - - // recover the opcode - opcode = m_sh2_state->arg0; - - // extract the operands - n = Rn; - m = Rm; - - tempn = (int32_t) RW( m_sh2_state->r[n] ); - m_sh2_state->r[n] += 2; - tempm = (int32_t) RW( 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; - m_sh2_state->macl += tempm; - if ((int32_t) m_sh2_state->macl >= 0) - ans = 0; - else - ans = 1; - ans += dest; - if (m_sh2_state->sr & S) - { - if (ans == 1) - { - if ((m_cpu_type == CPU_TYPE_SH1) && ((src == 0) || (src == 2))) - { - m_sh2_state->mach |= 0x00000001; - } - - if (src == 0) - m_sh2_state->macl = 0x7fffffff; - if (src == 2) - m_sh2_state->macl = 0x80000000; - } - } - else - { - m_sh2_state->mach += tempn; - if (templ > m_sh2_state->macl) - m_sh2_state->mach += 1; - - // SH-1 has limited precision - if (m_cpu_type == CPU_TYPE_SH1) - { - if ((m_sh2_state->mach & 0x200) == 0) - { - m_sh2_state->mach &= 0x3ff; - } - else - { - m_sh2_state->mach |= 0xfffffc00; - } - } - - - } -} - -/*------------------------------------------------- - cfunc_MAC_L - implementation of MAC_L Rm,Rn --------------------------------------------------*/ -static void cfunc_MAC_L(void *param) -{ - ((sh2_device *)param)->func_MAC_L(); -} - -void sh2_device::func_MAC_L() -{ - uint32_t RnL, RnH, RmL, RmH, Res0, Res1, Res2; - uint32_t temp0, temp1, temp2, temp3; - int32_t tempm, tempn, fnLmL; - uint16_t opcode; - int n, m; - - // recover the opcode - opcode = m_sh2_state->arg0; - - // extract the operands - n = Rn; - m = Rm; - - tempn = (int32_t) RL( m_sh2_state->r[n] ); - m_sh2_state->r[n] += 4; - tempm = (int32_t) RL( m_sh2_state->r[m] ); - m_sh2_state->r[m] += 4; - if ((int32_t) (tempn ^ tempm) < 0) - fnLmL = -1; - else - fnLmL = 0; - 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) - { - Res2 = ~Res2; - if (Res0 == 0) - Res2++; - else - Res0 = (~Res0) + 1; - } - if (m_sh2_state->sr & 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)) - { - Res2 = 0x00008000; - Res0 = 0x00000000; - } - else if (((int32_t) Res2 > 0) && (Res2 > 0x00007fff)) - { - Res2 = 0x00007fff; - Res0 = 0xffffffff; - } - 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; - } -} - -/*------------------------------------------------- - cfunc_DIV1 - implementation of DIV1 Rm,Rn --------------------------------------------------*/ -static void cfunc_DIV1(void *param) -{ - ((sh2_device *)param)->func_DIV1(); -} - -void sh2_device::func_DIV1() -{ - uint32_t tmp0; - uint32_t old_q; - uint16_t opcode; - int n, m; - - // recover the opcode - opcode = m_sh2_state->arg0; - - // extract the operands - n = Rn; - m = Rm; - - old_q = m_sh2_state->sr & Q; - if (0x80000000 & m_sh2_state->r[n]) - m_sh2_state->sr |= Q; - else - m_sh2_state->sr &= ~Q; - - m_sh2_state->r[n] = (m_sh2_state->r[n] << 1) | (m_sh2_state->sr & T); - - if (!old_q) - { - if (!(m_sh2_state->sr & M)) - { - tmp0 = m_sh2_state->r[n]; - m_sh2_state->r[n] -= m_sh2_state->r[m]; - if(!(m_sh2_state->sr & Q)) - if(m_sh2_state->r[n] > tmp0) - m_sh2_state->sr |= Q; - else - m_sh2_state->sr &= ~Q; - else - if(m_sh2_state->r[n] > tmp0) - m_sh2_state->sr &= ~Q; - else - m_sh2_state->sr |= Q; - } - else - { - tmp0 = m_sh2_state->r[n]; - m_sh2_state->r[n] += m_sh2_state->r[m]; - if(!(m_sh2_state->sr & Q)) - { - if(m_sh2_state->r[n] < tmp0) - m_sh2_state->sr &= ~Q; - else - m_sh2_state->sr |= Q; - } - else - { - if(m_sh2_state->r[n] < tmp0) - m_sh2_state->sr |= Q; - else - m_sh2_state->sr &= ~Q; - } - } - } - else - { - if (!(m_sh2_state->sr & M)) - { - tmp0 = m_sh2_state->r[n]; - m_sh2_state->r[n] += m_sh2_state->r[m]; - if(!(m_sh2_state->sr & Q)) - if(m_sh2_state->r[n] < tmp0) - m_sh2_state->sr |= Q; - else - m_sh2_state->sr &= ~Q; - else - if(m_sh2_state->r[n] < tmp0) - m_sh2_state->sr &= ~Q; - else - m_sh2_state->sr |= Q; - } - else - { - tmp0 = m_sh2_state->r[n]; - m_sh2_state->r[n] -= m_sh2_state->r[m]; - if(!(m_sh2_state->sr & Q)) - if(m_sh2_state->r[n] > tmp0) - m_sh2_state->sr &= ~Q; - else - m_sh2_state->sr |= Q; - else - if(m_sh2_state->r[n] > tmp0) - m_sh2_state->sr |= Q; - else - m_sh2_state->sr &= ~Q; - } - } - - tmp0 = (m_sh2_state->sr & (Q | M)); - if((!tmp0) || (tmp0 == 0x300)) /* if Q == M set T else clear T */ - m_sh2_state->sr |= T; - else - m_sh2_state->sr &= ~T; -} - -#if (!ADDSUBV_DIRECT) -/*------------------------------------------------- - cfunc_ADDV - implementation of ADDV Rm,Rn --------------------------------------------------*/ -static void cfunc_ADDV(void *param) -{ - ((sh2_device *)param)->func_ADDV(); -} - -void sh2_device::func_ADDV() -{ - int32_t dest, src, ans; - uint16_t opcode; - int n, m; - - // recover the opcode - opcode = m_sh2_state->arg0; - - // extract the operands - n = Rn; - m = Rm; - - 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; - 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; - ans += dest; - if (src == 0 || src == 2) - { - if (ans == 1) - m_sh2_state->sr |= T; - else - m_sh2_state->sr &= ~T; - } - else - m_sh2_state->sr &= ~T; -} - -/*------------------------------------------------- - cfunc_SUBV - implementation of SUBV Rm,Rn --------------------------------------------------*/ -static void cfunc_SUBV(void *param) -{ - ((sh2_device *)param)->func_SUBV(); -} - -void sh2_device::func_SUBV() -{ - int32_t dest, src, ans; - uint16_t opcode; - int n, m; - - // recover the opcode - opcode = m_sh2_state->arg0; - - // extract the operands - n = Rn; - m = Rm; - - 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; - 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; - ans += dest; - if (src == 1) - { - if (ans == 1) - m_sh2_state->sr |= T; - else - m_sh2_state->sr &= ~T; - } - else - m_sh2_state->sr &= ~T; -} -#else -void sh2_device::func_ADDV() {} -void sh2_device::func_SUBV() {} -#endif - -/*------------------------------------------------- - code_flush_cache - flush the cache and - regenerate static code --------------------------------------------------*/ - -void sh2_device::code_flush_cache() -{ - drcuml_state *drcuml = m_drcuml.get(); - - /* empty the transient cache contents */ - drcuml->reset(); - - try - { - /* generate the entry point and out-of-cycles handlers */ - static_generate_nocode_handler(); - static_generate_out_of_cycles(); - static_generate_entry_point(); - - /* add subroutines for memory accesses */ - static_generate_memory_accessor(1, false, "read8", &m_read8); - static_generate_memory_accessor(1, true, "write8", &m_write8); - static_generate_memory_accessor(2, false, "read16", &m_read16); - static_generate_memory_accessor(2, true, "write16", &m_write16); - static_generate_memory_accessor(4, false, "read32", &m_read32); - static_generate_memory_accessor(4, true, "write32", &m_write32); - } - catch (drcuml_block::abort_compilation &) - { - fatalerror("Unable to generate SH2 static code\n"); - } - - m_cache_dirty = false; -} - -/* Execute cycles - returns number of cycles actually run */ -void sh2_device::execute_run_drc() -{ - drcuml_state *drcuml = m_drcuml.get(); - int execute_result; - - // run any active DMAs now -#ifndef USE_TIMER_FOR_DMA - for ( int i = 0; i < m_sh2_state->icount ; i++) - { - for( int dma=0;dma<1;dma++) - { - if (m_dma_timer_active[dma]) - sh2_do_dma(dma); - } - } -#endif - - /* reset the cache if dirty */ - if (m_cache_dirty) - code_flush_cache(); - - /* execute */ - do - { - /* run as much as we can */ - execute_result = drcuml->execute(*m_entry); - - /* if we need to recompile, do it */ - if (execute_result == EXECUTE_MISSING_CODE) - { - code_compile_block(0, m_sh2_state->pc); - } - else if (execute_result == EXECUTE_UNMAPPED_CODE) - { - fatalerror("Attempted to execute unmapped code at PC=%08X\n", m_sh2_state->pc); - } - else if (execute_result == EXECUTE_RESET_CACHE) - { - code_flush_cache(); - } - } while (execute_result != EXECUTE_OUT_OF_CYCLES); -} - -/*------------------------------------------------- - code_compile_block - compile a block of the - given mode at the specified pc --------------------------------------------------*/ - -void sh2_device::code_compile_block(uint8_t mode, offs_t pc) -{ - drcuml_state *drcuml = m_drcuml.get(); - compiler_state compiler = { 0 }; - const opcode_desc *seqhead, *seqlast; - const opcode_desc *desclist; - bool override = false; - drcuml_block *block; - - g_profiler.start(PROFILER_DRC_COMPILE); - - /* get a description of this sequence */ - desclist = m_drcfe->describe_code(pc); - if (drcuml->logging() || drcuml->logging_native()) - log_opcode_desc(drcuml, desclist, 0); - - bool succeeded = false; - while (!succeeded) - { - try - { - /* start the block */ - block = drcuml->begin_block(4096); - - /* loop until we get through all instruction sequences */ - for (seqhead = desclist; seqhead != nullptr; seqhead = seqlast->next()) - { - const opcode_desc *curdesc; - uint32_t nextpc; - - /* add a code log entry */ - if (drcuml->logging()) - block->append_comment("-------------------------"); // comment - - /* determine the last instruction in this sequence */ - for (seqlast = seqhead; seqlast != nullptr; seqlast = seqlast->next()) - if (seqlast->flags & OPFLAG_END_SEQUENCE) - break; - assert(seqlast != nullptr); - - /* if we don't have a hash for this mode/pc, or if we are overriding all, add one */ - if (override || !drcuml->hash_exists(mode, seqhead->pc)) - UML_HASH(block, mode, seqhead->pc); // hash mode,pc - - /* if we already have a hash, and this is the first sequence, assume that we */ - /* are recompiling due to being out of sync and allow future overrides */ - else if (seqhead == desclist) - { - override = true; - UML_HASH(block, mode, seqhead->pc); // hash mode,pc - } - - /* otherwise, redispatch to that fixed PC and skip the rest of the processing */ - else - { - UML_LABEL(block, seqhead->pc | 0x80000000); // label seqhead->pc | 0x80000000 - UML_HASHJMP(block, 0, seqhead->pc, *m_nocode); - // hashjmp <mode>,seqhead->pc,nocode - continue; - } - - /* validate this code block if we're not pointing into ROM */ - if (m_program->get_write_ptr(seqhead->physpc) != nullptr) - generate_checksum_block(block, &compiler, seqhead, seqlast); - - /* label this instruction, if it may be jumped to locally */ - if (seqhead->flags & OPFLAG_IS_BRANCH_TARGET) - { - UML_LABEL(block, seqhead->pc | 0x80000000); // label seqhead->pc | 0x80000000 - } - - /* iterate over instructions in the sequence and compile them */ - for (curdesc = seqhead; curdesc != seqlast->next(); curdesc = curdesc->next()) - { - generate_sequence_instruction(block, &compiler, curdesc, 0xffffffff); - } - - /* if we need to return to the start, do it */ - if (seqlast->flags & OPFLAG_RETURN_TO_START) - { - nextpc = pc; - } - /* otherwise we just go to the next instruction */ - else - { - nextpc = seqlast->pc + (seqlast->skipslots + 1) * 2; - } - - /* count off cycles and go there */ - generate_update_cycles(block, &compiler, nextpc, true); // <subtract cycles> - - /* SH2 has no modes */ - if (seqlast->next() == nullptr || seqlast->next()->pc != nextpc) - { - UML_HASHJMP(block, 0, nextpc, *m_nocode); - } - // hashjmp <mode>,nextpc,nocode - } - - /* end the sequence */ - block->end(); - g_profiler.stop(); - succeeded = true; - } - catch (drcuml_block::abort_compilation &) - { - code_flush_cache(); - } - } -} - -/*------------------------------------------------- - static_generate_entry_point - generate a - static entry point --------------------------------------------------*/ - -void sh2_device::static_generate_entry_point() -{ - drcuml_state *drcuml = m_drcuml.get(); - code_label skip = 1; - drcuml_block *block; - - /* begin generating */ - block = drcuml->begin_block(200); - - /* forward references */ - alloc_handle(drcuml, &m_nocode, "nocode"); - alloc_handle(drcuml, &m_write32, "write32"); // necessary? - alloc_handle(drcuml, &m_entry, "entry"); - UML_HANDLE(block, *m_entry); // handle entry - - /* load fast integer registers */ - load_fast_iregs(block); - - /* check for interrupts */ - UML_MOV(block, mem(&m_sh2_state->irqline), 0xffffffff); // mov irqline, #-1 - UML_CMP(block, mem(&m_sh2_state->pending_nmi), 0); // cmp pending_nmi, #0 - UML_JMPc(block, COND_Z, skip+2); // jz skip+2 - - UML_MOV(block, mem(&m_sh2_state->pending_nmi), 0); // zap pending_nmi - UML_JMP(block, skip+1); // and then go take it (evec is already set) - - UML_LABEL(block, skip+2); // skip+2: - UML_MOV(block, mem(&m_sh2_state->evec), 0xffffffff); // mov evec, -1 - UML_MOV(block, I0, 0xffffffff); // mov r0, -1 (r0 = irq) - UML_AND(block, I1, I0, 0xffff); // and r1, 0xffff - - UML_LZCNT(block, I1, mem(&m_sh2_state->pending_irq)); // lzcnt r1, r1 - UML_CMP(block, I1, 32); // cmp r1, #32 - UML_JMPc(block, COND_Z, skip+4); // jz skip+4 - - UML_SUB(block, mem(&m_sh2_state->irqline), 31, I1); // sub irqline, #31, r1 - - UML_LABEL(block, skip+4); // skip+4: - UML_CMP(block, mem(&m_sh2_state->internal_irq_level), 0xffffffff); // cmp internal_irq_level, #-1 - UML_JMPc(block, COND_Z, skip+3); // jz skip+3 - UML_CMP(block, mem(&m_sh2_state->internal_irq_level), mem(&m_sh2_state->irqline)); // cmp internal_irq_level, irqline - UML_JMPc(block, COND_LE, skip+3); // jle skip+3 - - UML_MOV(block, mem(&m_sh2_state->irqline), mem(&m_sh2_state->internal_irq_level)); // mov r0, internal_irq_level - - UML_LABEL(block, skip+3); // skip+3: - UML_CMP(block, mem(&m_sh2_state->irqline), 0xffffffff); // cmp irqline, #-1 - UML_JMPc(block, COND_Z, skip+1); // jz skip+1 - UML_CALLC(block, cfunc_fastirq, this); // callc fastirq - - UML_LABEL(block, skip+1); // skip+1: - - UML_CMP(block, mem(&m_sh2_state->evec), 0xffffffff); // cmp evec, 0xffffffff - UML_JMPc(block, COND_Z, skip); // jz skip - - UML_SUB(block, R32(15), R32(15), 4); // sub R15, R15, #4 - UML_MOV(block, I0, R32(15)); // mov r0, R15 - UML_MOV(block, I1, mem(&m_sh2_state->irqsr)); // mov r1, irqsr - UML_CALLH(block, *m_write32); // call write32 - - UML_SUB(block, R32(15), R32(15), 4); // sub R15, R15, #4 - UML_MOV(block, I0, R32(15)); // mov r0, R15 - UML_MOV(block, I1, mem(&m_sh2_state->pc)); // mov r1, pc - UML_CALLH(block, *m_write32); // call write32 - - UML_MOV(block, mem(&m_sh2_state->pc), mem(&m_sh2_state->evec)); // mov pc, evec - - UML_LABEL(block, skip); // skip: - - /* generate a hash jump via the current mode and PC */ - UML_HASHJMP(block, 0, mem(&m_sh2_state->pc), *m_nocode); // hashjmp <mode>,<pc>,nocode - - block->end(); -} - -/*------------------------------------------------- - static_generate_nocode_handler - generate an - exception handler for "out of code" --------------------------------------------------*/ - -void sh2_device::static_generate_nocode_handler() -{ - drcuml_state *drcuml = m_drcuml.get(); - drcuml_block *block; - - /* begin generating */ - block = drcuml->begin_block(10); - - /* generate a hash jump via the current mode and PC */ - alloc_handle(drcuml, &m_nocode, "nocode"); - UML_HANDLE(block, *m_nocode); // handle nocode - UML_GETEXP(block, I0); // getexp i0 - UML_MOV(block, mem(&m_sh2_state->pc), I0); // mov [pc],i0 - save_fast_iregs(block); - UML_EXIT(block, EXECUTE_MISSING_CODE); // exit EXECUTE_MISSING_CODE - - block->end(); -} - - -/*------------------------------------------------- - static_generate_out_of_cycles - generate an - out of cycles exception handler --------------------------------------------------*/ - -void sh2_device::static_generate_out_of_cycles() -{ - drcuml_state *drcuml = m_drcuml.get(); - drcuml_block *block; - - /* begin generating */ - block = drcuml->begin_block(10); - - /* generate a hash jump via the current mode and PC */ - alloc_handle(drcuml, &m_out_of_cycles, "out_of_cycles"); - UML_HANDLE(block, *m_out_of_cycles); // handle out_of_cycles - UML_GETEXP(block, I0); // getexp i0 - UML_MOV(block, mem(&m_sh2_state->pc), I0); // mov <pc>,i0 - save_fast_iregs(block); - UML_EXIT(block, EXECUTE_OUT_OF_CYCLES); // exit EXECUTE_OUT_OF_CYCLES - - block->end(); -} - -/*------------------------------------------------------------------ - static_generate_memory_accessor -------------------------------------------------------------------*/ - -void sh2_device::static_generate_memory_accessor(int size, int iswrite, const char *name, code_handle **handleptr) -{ - /* on entry, address is in I0; data for writes is in I1 */ - /* on exit, read result is in I0 */ - /* routine trashes I0 */ - drcuml_state *drcuml = m_drcuml.get(); - drcuml_block *block; - int label = 1; - - /* begin generating */ - block = drcuml->begin_block(1024); - - /* add a global entry for this */ - alloc_handle(drcuml, handleptr, name); - UML_HANDLE(block, **handleptr); // handle *handleptr - - // with internal handlers this becomes easier. - // if addr < 0x40000000 AND it with AM and do the read/write, else just do the read/write - UML_TEST(block, I0, 0x80000000); // test r0, #0x80000000 - UML_JMPc(block, COND_NZ, label); // if high bit is set, don't mask - - UML_CMP(block, I0, 0x40000000); // cmp #0x40000000, r0 - UML_JMPc(block, COND_AE, label); // bae label - - UML_AND(block, I0, I0, AM); // and r0, r0, #AM (0xc7ffffff) - - UML_LABEL(block, label++); // label: - - for (auto & elem : m_fastram) - { - if (elem.base != nullptr && (!iswrite || !elem.readonly)) - { - void *fastbase = (uint8_t *)elem.base - elem.start; - uint32_t skip = label++; - if (elem.end != 0xffffffff) - { - UML_CMP(block, I0, elem.end); // cmp i0,end - UML_JMPc(block, COND_A, skip); // ja skip - } - if (elem.start != 0x00000000) - { - UML_CMP(block, I0, elem.start);// cmp i0,fastram_start - UML_JMPc(block, COND_B, skip); // jb skip - } - - if (!iswrite) - { - if (size == 1) - { - UML_XOR(block, I0, I0, BYTE4_XOR_BE(0)); - UML_LOAD(block, I0, fastbase, I0, SIZE_BYTE, SCALE_x1); // load i0,fastbase,i0,byte - } - else if (size == 2) - { - UML_XOR(block, I0, I0, WORD_XOR_BE(0)); - UML_LOAD(block, I0, fastbase, I0, SIZE_WORD, SCALE_x1); // load i0,fastbase,i0,word_x1 - } - else if (size == 4) - { - UML_LOAD(block, I0, fastbase, I0, SIZE_DWORD, SCALE_x1); // load i0,fastbase,i0,dword_x1 - } - UML_RET(block); // ret - } - else - { - if (size == 1) - { - UML_XOR(block, I0, I0, BYTE4_XOR_BE(0)); - UML_STORE(block, fastbase, I0, I1, SIZE_BYTE, SCALE_x1);// store fastbase,i0,i1,byte - } - else if (size == 2) - { - UML_XOR(block, I0, I0, WORD_XOR_BE(0)); - UML_STORE(block, fastbase, I0, I1, SIZE_WORD, SCALE_x1);// store fastbase,i0,i1,word_x1 - } - else if (size == 4) - { - UML_STORE(block, fastbase, I0, I1, SIZE_DWORD, SCALE_x1); // store fastbase,i0,i1,dword_x1 - } - UML_RET(block); // ret - } - - UML_LABEL(block, skip); // skip: - } - } - - if (iswrite) - { - switch (size) - { - case 1: - UML_WRITE(block, I0, I1, SIZE_BYTE, SPACE_PROGRAM); // write r0, r1, program_byte - break; - - case 2: - UML_WRITE(block, I0, I1, SIZE_WORD, SPACE_PROGRAM); // write r0, r1, program_word - break; - - case 4: - UML_WRITE(block, I0, I1, SIZE_DWORD, SPACE_PROGRAM); // write r0, r1, program_dword - break; - } - } - else - { - switch (size) - { - case 1: - UML_READ(block, I0, I0, SIZE_BYTE, SPACE_PROGRAM); // read r0, program_byte - break; - - case 2: - UML_READ(block, I0, I0, SIZE_WORD, SPACE_PROGRAM); // read r0, program_word - break; - - case 4: - UML_READ(block, I0, I0, SIZE_DWORD, SPACE_PROGRAM); // read r0, program_dword - break; - } - } - - UML_RET(block); // ret - - block->end(); -} - -/*------------------------------------------------- - log_desc_flags_to_string - generate a string - representing the instruction description - flags --------------------------------------------------*/ - -const char *sh2_device::log_desc_flags_to_string(uint32_t flags) -{ - static char tempbuf[30]; - char *dest = tempbuf; - - /* branches */ - if (flags & OPFLAG_IS_UNCONDITIONAL_BRANCH) - *dest++ = 'U'; - else if (flags & OPFLAG_IS_CONDITIONAL_BRANCH) - *dest++ = 'C'; - else - *dest++ = '.'; - - /* intrablock branches */ - *dest++ = (flags & OPFLAG_INTRABLOCK_BRANCH) ? 'i' : '.'; - - /* branch targets */ - *dest++ = (flags & OPFLAG_IS_BRANCH_TARGET) ? 'B' : '.'; - - /* delay slots */ - *dest++ = (flags & OPFLAG_IN_DELAY_SLOT) ? 'D' : '.'; - - /* exceptions */ - if (flags & OPFLAG_WILL_CAUSE_EXCEPTION) - *dest++ = 'E'; - else if (flags & OPFLAG_CAN_CAUSE_EXCEPTION) - *dest++ = 'e'; - else - *dest++ = '.'; - - /* read/write */ - if (flags & OPFLAG_READS_MEMORY) - *dest++ = 'R'; - else if (flags & OPFLAG_WRITES_MEMORY) - *dest++ = 'W'; - else - *dest++ = '.'; - - /* TLB validation */ - *dest++ = (flags & OPFLAG_VALIDATE_TLB) ? 'V' : '.'; - - /* TLB modification */ - *dest++ = (flags & OPFLAG_MODIFIES_TRANSLATION) ? 'T' : '.'; - - /* redispatch */ - *dest++ = (flags & OPFLAG_REDISPATCH) ? 'R' : '.'; - return tempbuf; -} - - -/*------------------------------------------------- - log_register_list - log a list of GPR registers --------------------------------------------------*/ - -void sh2_device::log_register_list(drcuml_state *drcuml, const char *string, const uint32_t *reglist, const uint32_t *regnostarlist) -{ - int count = 0; - int regnum; - - /* skip if nothing */ - if (reglist[0] == 0 && reglist[1] == 0 && reglist[2] == 0) - return; - - drcuml->log_printf("[%s:", string); - - for (regnum = 0; regnum < 16; regnum++) - { - if (reglist[0] & REGFLAG_R(regnum)) - { - drcuml->log_printf("%sr%d", (count++ == 0) ? "" : ",", regnum); - if (regnostarlist != nullptr && !(regnostarlist[0] & REGFLAG_R(regnum))) - drcuml->log_printf("*"); - } - } - - if (reglist[1] & REGFLAG_PR) - { - drcuml->log_printf("%spr", (count++ == 0) ? "" : ","); - if (regnostarlist != nullptr && !(regnostarlist[1] & REGFLAG_PR)) - drcuml->log_printf("*"); - } - - if (reglist[1] & REGFLAG_SR) - { - drcuml->log_printf("%ssr", (count++ == 0) ? "" : ","); - if (regnostarlist != nullptr && !(regnostarlist[1] & REGFLAG_SR)) - drcuml->log_printf("*"); - } - - if (reglist[1] & REGFLAG_MACL) - { - drcuml->log_printf("%smacl", (count++ == 0) ? "" : ","); - if (regnostarlist != nullptr && !(regnostarlist[1] & REGFLAG_MACL)) - drcuml->log_printf("*"); - } - - if (reglist[1] & REGFLAG_MACH) - { - drcuml->log_printf("%smach", (count++ == 0) ? "" : ","); - if (regnostarlist != nullptr && !(regnostarlist[1] & REGFLAG_MACH)) - drcuml->log_printf("*"); - } - - if (reglist[1] & REGFLAG_GBR) - { - drcuml->log_printf("%sgbr", (count++ == 0) ? "" : ","); - if (regnostarlist != nullptr && !(regnostarlist[1] & REGFLAG_GBR)) - drcuml->log_printf("*"); - } - - if (reglist[1] & REGFLAG_VBR) - { - drcuml->log_printf("%svbr", (count++ == 0) ? "" : ","); - if (regnostarlist != nullptr && !(regnostarlist[1] & REGFLAG_VBR)) - drcuml->log_printf("*"); - } - - drcuml->log_printf("] "); -} - -/*------------------------------------------------- - log_opcode_desc - log a list of descriptions --------------------------------------------------*/ - -void sh2_device::log_opcode_desc(drcuml_state *drcuml, const opcode_desc *desclist, int indent) -{ - /* open the file, creating it if necessary */ - if (indent == 0) - drcuml->log_printf("\nDescriptor list @ %08X\n", desclist->pc); - - /* output each descriptor */ - for ( ; desclist != nullptr; desclist = desclist->next()) - { - std::ostringstream stream; - - /* disassemle the current instruction and output it to the log */ - if (drcuml->logging() || drcuml->logging_native()) - { - if (desclist->flags & OPFLAG_VIRTUAL_NOOP) - stream << "<virtual nop>"; - else - DasmSH2(stream, desclist->pc, desclist->opptr.w[0]); - } - else - stream << "???"; - drcuml->log_printf("%08X [%08X] t:%08X f:%s: %-30s", desclist->pc, desclist->physpc, desclist->targetpc, log_desc_flags_to_string(desclist->flags), stream.str().c_str()); - - /* output register states */ - log_register_list(drcuml, "use", desclist->regin, nullptr); - log_register_list(drcuml, "mod", desclist->regout, desclist->regreq); - drcuml->log_printf("\n"); - - /* if we have a delay slot, output it recursively */ - if (desclist->delay.first() != nullptr) - log_opcode_desc(drcuml, desclist->delay.first(), indent + 1); - - /* at the end of a sequence add a dividing line */ - if (desclist->flags & OPFLAG_END_SEQUENCE) - drcuml->log_printf("-----\n"); - } -} - -/*------------------------------------------------- - log_add_disasm_comment - add a comment - including disassembly of an SH2 instruction --------------------------------------------------*/ - -void sh2_device::log_add_disasm_comment(drcuml_block *block, uint32_t pc, uint32_t op) -{ - if (m_drcuml->logging()) - { - std::ostringstream stream; - DasmSH2(stream, pc, op); - block->append_comment("%08X: %s", pc, stream.str().c_str()); - } -} - -/*------------------------------------------------- - generate_update_cycles - generate code to - subtract cycles from the icount and generate - an exception if out --------------------------------------------------*/ -void sh2_device::generate_update_cycles(drcuml_block *block, compiler_state *compiler, uml::parameter param, bool allow_exception) -{ - /* check full interrupts if pending */ - if (compiler->checkints) - { - code_label skip = compiler->labelnum++; - - compiler->checkints = false; - compiler->labelnum += 4; - - /* check for interrupts */ - UML_MOV(block, mem(&m_sh2_state->irqline), 0xffffffff); // mov irqline, #-1 - UML_CMP(block, mem(&m_sh2_state->pending_nmi), 0); // cmp pending_nmi, #0 - UML_JMPc(block, COND_Z, skip+2); // jz skip+2 - - UML_MOV(block, mem(&m_sh2_state->pending_nmi), 0); // zap pending_nmi - UML_JMP(block, skip+1); // and then go take it (evec is already set) - - UML_LABEL(block, skip+2); // skip+2: - UML_MOV(block, mem(&m_sh2_state->evec), 0xffffffff); // mov evec, -1 - UML_MOV(block, I0, 0xffffffff); // mov r0, -1 (r0 = irq) - UML_AND(block, I1, I0, 0xffff); // and r1, r0, 0xffff - - UML_LZCNT(block, I1, mem(&m_sh2_state->pending_irq)); // lzcnt r1, pending_irq - UML_CMP(block, I1, 32); // cmp r1, #32 - UML_JMPc(block, COND_Z, skip+4); // jz skip+4 - - UML_SUB(block, mem(&m_sh2_state->irqline), 31, I1); // sub irqline, #31, r1 - - UML_LABEL(block, skip+4); // skip+4: - UML_CMP(block, mem(&m_sh2_state->internal_irq_level), 0xffffffff); // cmp internal_irq_level, #-1 - UML_JMPc(block, COND_Z, skip+3); // jz skip+3 - UML_CMP(block, mem(&m_sh2_state->internal_irq_level), mem(&m_sh2_state->irqline)); // cmp internal_irq_level, irqline - UML_JMPc(block, COND_LE, skip+3); // jle skip+3 - - UML_MOV(block, mem(&m_sh2_state->irqline), mem(&m_sh2_state->internal_irq_level)); // mov r0, internal_irq_level - - UML_LABEL(block, skip+3); // skip+3: - UML_CMP(block, mem(&m_sh2_state->irqline), 0xffffffff); // cmp irqline, #-1 - UML_JMPc(block, COND_Z, skip+1); // jz skip+1 - UML_CALLC(block, cfunc_fastirq, this); // callc fastirq - - UML_LABEL(block, skip+1); // skip+1: - UML_CMP(block, mem(&m_sh2_state->evec), 0xffffffff); // cmp evec, 0xffffffff - UML_JMPc(block, COND_Z, skip); // jz skip - - UML_SUB(block, R32(15), R32(15), 4); // sub R15, R15, #4 - UML_MOV(block, I0, R32(15)); // mov r0, R15 - UML_MOV(block, I1, mem(&m_sh2_state->irqsr)); // mov r1, irqsr - UML_CALLH(block, *m_write32); // call write32 - - UML_SUB(block, R32(15), R32(15), 4); // sub R15, R15, #4 - UML_MOV(block, I0, R32(15)); // mov r0, R15 - UML_MOV(block, I1, param); // mov r1, nextpc - UML_CALLH(block, *m_write32); // call write32 - - UML_HASHJMP(block, 0, mem(&m_sh2_state->evec), *m_nocode); // hashjmp m_sh2_state->evec - - UML_LABEL(block, skip); // skip: - } - - /* account for cycles */ - if (compiler->cycles > 0) - { - UML_SUB(block, mem(&m_sh2_state->icount), mem(&m_sh2_state->icount), MAPVAR_CYCLES); // sub icount,icount,cycles - UML_MAPVAR(block, MAPVAR_CYCLES, 0); // mapvar cycles,0 - if (allow_exception) - UML_EXHc(block, COND_S, *m_out_of_cycles, param); - // exh out_of_cycles,nextpc - } - compiler->cycles = 0; -} - -/*------------------------------------------------- - generate_checksum_block - generate code to - validate a sequence of opcodes --------------------------------------------------*/ - -void sh2_device::generate_checksum_block(drcuml_block *block, compiler_state *compiler, const opcode_desc *seqhead, const opcode_desc *seqlast) -{ - const opcode_desc *curdesc; - if (m_drcuml->logging()) - block->append_comment("[Validation for %08X]", seqhead->pc); // comment - - /* loose verify or single instruction: just compare and fail */ - if (!(m_drcoptions & SH2DRC_STRICT_VERIFY) || seqhead->next() == nullptr) - { - if (!(seqhead->flags & OPFLAG_VIRTUAL_NOOP)) - { - void *base = m_direct->read_ptr(seqhead->physpc, SH2_CODE_XOR(0)); - UML_LOAD(block, I0, base, 0, SIZE_WORD, SCALE_x2); // load i0,base,word - UML_CMP(block, I0, seqhead->opptr.w[0]); // cmp i0,*opptr - UML_EXHc(block, COND_NE, *m_nocode, epc(seqhead)); // exne nocode,seqhead->pc - } - } - - /* full verification; sum up everything */ - else - { -#if 0 - for (curdesc = seqhead->next(); curdesc != seqlast->next(); curdesc = curdesc->next()) - if (!(curdesc->flags & OPFLAG_VIRTUAL_NOOP)) - { - base = m_direct->read_ptr(curdesc->physpc, SH2_CODE_XOR(0)); - UML_LOAD(block, I0, curdesc->opptr.w, 0, SIZE_WORD, SCALE_x2); // load i0,*opptr,0,word - UML_CMP(block, I0, curdesc->opptr.w[0]); // cmp i0,*opptr - UML_EXHc(block, COND_NE, *m_nocode, epc(seqhead)); // exne nocode,seqhead->pc - } -#else - uint32_t sum = 0; - void *base = m_direct->read_ptr(seqhead->physpc, SH2_CODE_XOR(0)); - UML_LOAD(block, I0, base, 0, SIZE_WORD, SCALE_x4); // load i0,base,word - sum += seqhead->opptr.w[0]; - for (curdesc = seqhead->next(); curdesc != seqlast->next(); curdesc = curdesc->next()) - if (!(curdesc->flags & OPFLAG_VIRTUAL_NOOP)) - { - base = m_direct->read_ptr(curdesc->physpc, SH2_CODE_XOR(0)); - UML_LOAD(block, I1, base, 0, SIZE_WORD, SCALE_x2); // load i1,*opptr,word - UML_ADD(block, I0, I0, I1); // add i0,i0,i1 - sum += curdesc->opptr.w[0]; - } - UML_CMP(block, I0, sum); // cmp i0,sum - UML_EXHc(block, COND_NE, *m_nocode, epc(seqhead)); // exne nocode,seqhead->pc -#endif - } -} - - -/*------------------------------------------------- - generate_sequence_instruction - generate code - for a single instruction in a sequence --------------------------------------------------*/ - -void sh2_device::generate_sequence_instruction(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, uint32_t ovrpc) -{ - offs_t expc; - - /* add an entry for the log */ - if (m_drcuml->logging() && !(desc->flags & OPFLAG_VIRTUAL_NOOP)) - log_add_disasm_comment(block, desc->pc, desc->opptr.w[0]); - - /* set the PC map variable */ - expc = (desc->flags & OPFLAG_IN_DELAY_SLOT) ? desc->pc - 1 : desc->pc; - UML_MAPVAR(block, MAPVAR_PC, expc); // mapvar PC,expc - - /* accumulate total cycles */ - compiler->cycles += desc->cycles; - - /* update the icount map variable */ - UML_MAPVAR(block, MAPVAR_CYCLES, compiler->cycles); // mapvar CYCLES,compiler->cycles - - /* if we want a probe, add it here */ - if (desc->pc == PROBE_ADDRESS) - { - UML_MOV(block, mem(&m_sh2_state->pc), desc->pc); // mov [pc],desc->pc - UML_CALLC(block, cfunc_printf_probe, this); // callc cfunc_printf_probe,sh2 - } - - /* if we are debugging, call the debugger */ - if ((machine().debug_flags & DEBUG_FLAG_ENABLED) != 0) - { - UML_MOV(block, mem(&m_sh2_state->pc), desc->pc); // mov [pc],desc->pc - save_fast_iregs(block); - UML_DEBUG(block, desc->pc); // debug desc->pc - } - else // not debug, see what other reasons there are for flushing the PC - { - if (m_drcoptions & SH2DRC_FLUSH_PC) // always flush? - { - UML_MOV(block, mem(&m_sh2_state->pc), desc->pc); // mov m_sh2_state->pc, desc->pc - } - else // check for driver-selected flushes - { - int pcflush; - - for (pcflush = 0; pcflush < m_pcfsel; pcflush++) - { - if (desc->pc == m_pcflushes[pcflush]) - { - UML_MOV(block, mem(&m_sh2_state->pc), desc->pc); // mov m_sh2_state->pc, desc->pc - } - } - } - } - - - /* if we hit an unmapped address, fatal error */ - if (desc->flags & OPFLAG_COMPILER_UNMAPPED) - { - UML_MOV(block, mem(&m_sh2_state->pc), desc->pc); // mov [pc],desc->pc - save_fast_iregs(block); - UML_EXIT(block, EXECUTE_UNMAPPED_CODE); // exit EXECUTE_UNMAPPED_CODE - } - - /* if this is an invalid opcode, die */ - if (desc->flags & OPFLAG_INVALID_OPCODE) - { - fatalerror("SH2DRC: invalid opcode!\n"); - } - - /* otherwise, unless this is a virtual no-op, it's a regular instruction */ - else if (!(desc->flags & OPFLAG_VIRTUAL_NOOP)) - { - /* compile the instruction */ - if (!generate_opcode(block, compiler, desc, ovrpc)) - { - // handle an illegal op - UML_MOV(block, mem(&m_sh2_state->pc), desc->pc); // mov [pc],desc->pc - UML_MOV(block, mem(&m_sh2_state->arg0), desc->opptr.w[0]); // mov [arg0],opcode - UML_CALLC(block, cfunc_unimplemented, this); // callc cfunc_unimplemented - } - } -} - -/*------------------------------------------------------------------ - generate_delay_slot -------------------------------------------------------------------*/ - -void sh2_device::generate_delay_slot(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, uint32_t ovrpc) -{ - compiler_state compiler_temp = *compiler; - - /* compile the delay slot using temporary compiler state */ - assert(desc->delay.first() != nullptr); - generate_sequence_instruction(block, &compiler_temp, desc->delay.first(), ovrpc); // <next instruction> - - /* update the label */ - compiler->labelnum = compiler_temp.labelnum; -} - -/*------------------------------------------------- - generate_opcode - generate code for a specific - opcode --------------------------------------------------*/ - -bool sh2_device::generate_opcode(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, uint32_t ovrpc) -{ - uint32_t scratch, scratch2; - int32_t disp; - uint16_t opcode = desc->opptr.w[0]; - uint8_t opswitch = opcode >> 12; - int in_delay_slot = ((desc->flags & OPFLAG_IN_DELAY_SLOT) != 0); - - switch (opswitch) - { - case 0: - return generate_group_0(block, compiler, desc, opcode, in_delay_slot, ovrpc); - - 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 - SETEA(0); // set ea for debug - UML_CALLH(block, *m_write32); - - if (!in_delay_slot) - generate_update_cycles(block, compiler, desc->pc + 2, true); - return true; - - case 2: - return generate_group_2(block, compiler, desc, opcode, in_delay_slot, ovrpc); - case 3: - return generate_group_3(block, compiler, desc, opcode, ovrpc); - case 4: - return generate_group_4(block, compiler, desc, opcode, in_delay_slot, ovrpc); - - case 5: // MOVLL4 - scratch = (opcode & 0x0f) * 4; - UML_ADD(block, I0, R32(Rm), 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 - - if (!in_delay_slot) - generate_update_cycles(block, compiler, desc->pc + 2, true); - return true; - - case 6: - return generate_group_6(block, compiler, desc, opcode, in_delay_slot, ovrpc); - - 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 - return true; - - case 8: - return generate_group_8(block, compiler, desc, opcode, in_delay_slot, ovrpc); - - 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 - } - else - { - scratch2 = (uint32_t)(int32_t)(int16_t) RW(scratch); - UML_MOV(block, R32(Rn), scratch2); // mov Rn, scratch2 - } - - if (!in_delay_slot) - generate_update_cycles(block, compiler, desc->pc + 2, true); - return true; - - case 10: // BRA - disp = ((int32_t)opcode << 20) >> 20; - 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); - - generate_update_cycles(block, compiler, m_sh2_state->ea, true); // <subtract cycles> - UML_HASHJMP(block, 0, m_sh2_state->ea, *m_nocode); // hashjmp m_sh2_state->ea - return true; - - case 11: // BSR - // panicstr @ 403da22 relies on the delay slot clobbering the PR set by a BSR, so - // 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; - 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); - - generate_update_cycles(block, compiler, m_sh2_state->ea, true); // <subtract cycles> - UML_HASHJMP(block, 0, m_sh2_state->ea, *m_nocode); // hashjmp m_sh2_state->ea - return true; - - case 12: - return generate_group_12(block, compiler, desc, opcode, in_delay_slot, ovrpc); - - case 13: // MOVLI - if (ovrpc == 0xffffffff) - { - scratch = ((desc->pc + 4) & ~3) + ((opcode & 0xff) * 4); - } - else - { - scratch = ((ovrpc + 4) & ~3) + ((opcode & 0xff) * 4); - } - - if (m_drcoptions & SH2DRC_STRICT_PCREL) - { - 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 - } - else - { - scratch2 = RL(scratch); - UML_MOV(block, R32(Rn), scratch2); // mov Rn, scratch2 - } - - if (!in_delay_slot) - generate_update_cycles(block, compiler, desc->pc + 2, true); - return true; - - case 14: // MOVI - scratch = opcode & 0xff; - scratch2 = (uint32_t)(int32_t)(int16_t)(int8_t)scratch; - UML_MOV(block, R32(Rn), scratch2); - return true; - - case 15: - return false; - } - - return false; -} - -bool sh2_device::generate_group_0(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, uint16_t opcode, int in_delay_slot, uint32_t ovrpc) -{ - switch (opcode & 0x3F) - { - case 0x00: // these are all illegal - case 0x01: - case 0x10: - case 0x11: - case 0x13: - case 0x20: - case 0x21: - case 0x30: - case 0x31: - case 0x32: - case 0x33: - case 0x38: - case 0x39: - case 0x3a: - case 0x3b: - return false; - - case 0x09: // NOP(); - return true; - - case 0x02: // STCSR(Rn); - UML_MOV(block, R32(Rn), 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), mem(&m_sh2_state->target), desc->pc); // add target, target, pc - - // 32x Cosmic Carnage @ 6002cb0 relies on the delay slot - // clobbering the calculated PR, so do it first - UML_ADD(block, mem(&m_sh2_state->pr), desc->pc, 4); // add m_pr, desc->pc, #4 (skip the current insn & delay slot) - - generate_delay_slot(block, compiler, desc, m_sh2_state->target); - - generate_update_cycles(block, compiler, mem(&m_sh2_state->target), true); // <subtract cycles> - UML_HASHJMP(block, 0, mem(&m_sh2_state->target), *m_nocode); // jmp target - return true; - } - break; - - case 0x04: // MOVBS0(Rm, Rn); - 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_CALLH(block, *m_write8); // call write8 - - if (!in_delay_slot) - generate_update_cycles(block, compiler, desc->pc + 2, true); - return true; - - case 0x05: // MOVWS0(Rm, Rn); - 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_CALLH(block, *m_write16); // call write16 - - if (!in_delay_slot) - generate_update_cycles(block, compiler, desc->pc + 2, true); - return true; - - case 0x06: // MOVLS0(Rm, Rn); - 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_CALLH(block, *m_write32); // call write32 - - if (!in_delay_slot) - generate_update_cycles(block, compiler, desc->pc + 2, true); - return true; - - case 0x07: // MULL(Rm, Rn); - case 0x17: // MULL(Rm, Rn); - case 0x27: // MULL(Rm, Rn); - 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 - return true; - } - break; - - case 0x08: // CLRT(); - UML_AND(block, mem(&m_sh2_state->sr), mem(&m_sh2_state->sr), ~T); // and r0, sr, ~T (clear the T bit) - return true; - - case 0x0a: // STSMACH(Rn); - UML_MOV(block, R32(Rn), mem(&m_sh2_state->mach)); // mov Rn, mach - return true; - - case 0x0b: // RTS(); - UML_MOV(block, mem(&m_sh2_state->target), mem(&m_sh2_state->pr)); // mov target, pr (in case of d-slot shenanigans) - - generate_delay_slot(block, compiler, desc, m_sh2_state->target); - - generate_update_cycles(block, compiler, mem(&m_sh2_state->target), true); // <subtract cycles> - UML_HASHJMP(block, 0, mem(&m_sh2_state->target), *m_nocode); - return true; - - case 0x0c: // MOVBL0(Rm, Rn); - 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_CALLH(block, *m_read8); // call read8 - UML_SEXT(block, R32(Rn), I0, SIZE_BYTE); // sext Rn, r0, BYTE - - if (!in_delay_slot) - generate_update_cycles(block, compiler, desc->pc + 2, true); - return true; - - case 0x0d: // MOVWL0(Rm, Rn); - 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_CALLH(block, *m_read16); // call read16 - UML_SEXT(block, R32(Rn), I0, SIZE_WORD); // sext Rn, r0, WORD - - if (!in_delay_slot) - generate_update_cycles(block, compiler, desc->pc + 2, true); - return true; - - case 0x0e: // MOVLL0(Rm, Rn); - 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_CALLH(block, *m_read32); // call read32 - UML_MOV(block, R32(Rn), I0); // mov Rn, r0 - - if (!in_delay_slot) - generate_update_cycles(block, compiler, desc->pc + 2, true); - return true; - - case 0x0f: // MAC_L(Rm, Rn); - case 0x1f: // MAC_L(Rm, Rn); - case 0x2f: // MAC_L(Rm, Rn); - case 0x3f: // MAC_L(Rm, Rn); - if (m_cpu_type > CPU_TYPE_SH1) - { - save_fast_iregs(block); - UML_MOV(block, mem(&m_sh2_state->arg0), desc->opptr.w[0]); - UML_CALLC(block, cfunc_MAC_L, this); - load_fast_iregs(block); - return true; - } - break; - - case 0x12: // STCGBR(Rn); - UML_MOV(block, R32(Rn), mem(&m_sh2_state->gbr)); // mov Rn, gbr - return true; - - case 0x18: // SETT(); - UML_OR(block, mem(&m_sh2_state->sr), mem(&m_sh2_state->sr), T); // or sr, sr, T - return true; - - case 0x19: // DIV0U(); - UML_AND(block, mem(&m_sh2_state->sr), mem(&m_sh2_state->sr), ~(M|Q|T)); // and sr, sr, ~(M|Q|T) - return true; - - case 0x1a: // STSMACL(Rn); - UML_MOV(block, R32(Rn), mem(&m_sh2_state->macl)); // mov Rn, macl - return true; - - case 0x1b: // SLEEP(); - UML_MOV(block, I0, mem(&m_sh2_state->sleep_mode)); // mov i0, sleep_mode - UML_CMP(block, I0, 0x2); // cmp i0, #2 - UML_JMPc(block, COND_E, compiler->labelnum); // beq labelnum - // sleep mode != 2 - UML_MOV(block, mem(&m_sh2_state->sleep_mode), 0x1); // mov sleep_mode, #1 - generate_update_cycles(block, compiler, desc->pc, true); // repeat this insn - UML_JMP(block, compiler->labelnum+1); // jmp labelnum+1 - - UML_LABEL(block, compiler->labelnum++); // labelnum: - // sleep_mode == 2 - UML_MOV(block, mem(&m_sh2_state->sleep_mode), 0x0); // sleep_mode = 0 - generate_update_cycles(block, compiler, desc->pc+2, true); // go to next insn - - UML_LABEL(block, compiler->labelnum++); // labelnum+1: - return true; - - case 0x22: // STCVBR(Rn); - UML_MOV(block, R32(Rn), 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 - - generate_delay_slot(block, compiler, desc, m_sh2_state->target); - - generate_update_cycles(block, compiler, mem(&m_sh2_state->target), true); // <subtract cycles> - UML_HASHJMP(block, 0, mem(&m_sh2_state->target), *m_nocode); // jmp target - return true; - } - break; - - case 0x28: // CLRMAC(); - UML_MOV(block, mem(&m_sh2_state->macl), 0); // mov macl, #0 - UML_MOV(block, mem(&m_sh2_state->mach), 0); // mov mach, #0 - return true; - - case 0x29: // MOVT(Rn); - UML_AND(block, R32(Rn), mem(&m_sh2_state->sr), T); // and Rn, sr, T - return true; - - case 0x2a: // STSPR(Rn); - UML_MOV(block, R32(Rn), mem(&m_sh2_state->pr)); // mov Rn, pr - return true; - - case 0x2b: // RTE(); - generate_delay_slot(block, compiler, desc, 0xffffffff); - - UML_MOV(block, I0, R32(15)); // mov r0, R15 - UML_CALLH(block, *m_read32); // call read32 - UML_MOV(block, mem(&m_sh2_state->pc), I0); // mov pc, r0 - UML_ADD(block, R32(15), R32(15), 4); // add R15, R15, #4 - - UML_MOV(block, I0, R32(15)); // mov r0, R15 - UML_CALLH(block, *m_read32); // call read32 - UML_MOV(block, mem(&m_sh2_state->sr), I0); // mov sr, r0 - UML_ADD(block, R32(15), R32(15), 4); // add R15, R15, #4 - - compiler->checkints = true; - UML_MOV(block, mem(&m_sh2_state->ea), mem(&m_sh2_state->pc)); // mov ea, pc - generate_update_cycles(block, compiler, mem(&m_sh2_state->ea), true); // <subtract cycles> - UML_HASHJMP(block, 0, mem(&m_sh2_state->pc), *m_nocode); // and jump to the "resume PC" - - return true; - } - - return false; -} - -bool sh2_device::generate_group_2(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, uint16_t opcode, int in_delay_slot, uint32_t ovrpc) -{ - 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_CALLH(block, *m_write8); - - if (!in_delay_slot) - generate_update_cycles(block, compiler, desc->pc + 2, true); - 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_CALLH(block, *m_write16); - - if (!in_delay_slot) - generate_update_cycles(block, compiler, desc->pc + 2, true); - 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_CALLH(block, *m_write32); - - if (!in_delay_slot) - generate_update_cycles(block, compiler, desc->pc + 2, true); - return true; - - case 3: - 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_CALLH(block, *m_write8); // call write8 - - if (!in_delay_slot) - generate_update_cycles(block, compiler, desc->pc + 2, true); - 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_CALLH(block, *m_write16); // call write16 - - if (!in_delay_slot) - generate_update_cycles(block, compiler, desc->pc + 2, true); - 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_CALLH(block, *m_write32); // call write32 - - if (!in_delay_slot) - generate_update_cycles(block, compiler, desc->pc + 2, true); - return true; - - case 13: // XTRCT(Rm, Rn); - UML_SHL(block, I0, R32(Rm), 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_AND(block, I1, I1, 0xffff); // and r1, r1, #0x0000ffff - - UML_OR(block, R32(Rn), 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, ~(Q|M|T)); // and r0, r0, ~(Q|M|T) (clear the Q,M, and T bits) - - UML_TEST(block, R32(Rn), 0x80000000); // test Rn, #0x80000000 - UML_JMPc(block, COND_Z, compiler->labelnum); // jz labelnum - - UML_OR(block, I0, I0, Q); // or r0, r0, Q - UML_LABEL(block, compiler->labelnum++); // labelnum: - - UML_TEST(block, R32(Rm), 0x80000000); // test Rm, #0x80000000 - UML_JMPc(block, COND_Z, compiler->labelnum); // jz labelnum - - UML_OR(block, I0, I0, M); // or r0, r0, M - UML_LABEL(block, compiler->labelnum++); // labelnum: - - UML_XOR(block, I1, R32(Rn), R32(Rm)); // xor r1, Rn, Rm - UML_TEST(block, I1, 0x80000000); // test r1, #0x80000000 - UML_JMPc(block, COND_Z, compiler->labelnum); // jz labelnum - - UML_OR(block, I0, I0, T); // or r0, r0, T - UML_LABEL(block, compiler->labelnum++); // labelnum: - UML_MOV(block, mem(&m_sh2_state->sr), I0); // mov sr, r0 - return true; - - case 8: // TST(Rm, Rn); - UML_AND(block, I0, mem(&m_sh2_state->sr), ~T); // and r0, sr, ~T (clear the T bit) - UML_TEST(block, R32(Rm), R32(Rn)); // test Rm, Rn - UML_JMPc(block, COND_NZ, compiler->labelnum); // jnz compiler->labelnum - - UML_OR(block, I0, I0, T); // or r0, r0, T - UML_LABEL(block, compiler->labelnum++); // desc->pc: - - UML_MOV(block, mem(&m_sh2_state->sr), I0); // mov m_sh2_state->sr, r0 - return true; - - case 12: // CMPSTR(Rm, Rn); - UML_XOR(block, I0, R32(Rn), R32(Rm)); // 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 - - UML_SHR(block, I2, I0, 16); // shr r2, r0, #16 (HL) - UML_AND(block, I2, I2, 0xff); // and r2, r2, #0xff - - UML_SHR(block, I3, I0, 8); // shr r3, r0, #8 (LH) - UML_AND(block, I3, I3, 0xff); // and r3, r3, #0xff - - UML_AND(block, I7, I0, 0xff); // and r7, r0, #0xff (LL) - - UML_AND(block, mem(&m_sh2_state->sr), mem(&m_sh2_state->sr), ~T); // and sr, sr, ~T (clear the T bit) - - UML_CMP(block, I1, 0); // cmp r1, #0 - UML_JMPc(block, COND_Z, compiler->labelnum); // jnz labelnum - UML_CMP(block, I2, 0); // cmp r2, #0 - UML_JMPc(block, COND_Z, compiler->labelnum); // jnz labelnum - UML_CMP(block, I3, 0); // cmp r3, #0 - UML_JMPc(block, COND_Z, compiler->labelnum); // jnz labelnum - UML_CMP(block, I7, 0); // cmp r7, #0 - UML_JMPc(block, COND_NZ, compiler->labelnum+1); // jnz labelnum - - UML_LABEL(block, compiler->labelnum++); // labelnum: - UML_OR(block, mem(&m_sh2_state->sr), mem(&m_sh2_state->sr), T); // or sr, sr, T - - UML_LABEL(block, compiler->labelnum++); // labelnum+1: - return true; - - case 9: // AND(Rm, Rn); - UML_AND(block, R32(Rn), R32(Rn), R32(Rm)); // and Rn, Rn, Rm - return true; - - case 10: // XOR(Rm, Rn); - UML_XOR(block, R32(Rn), R32(Rn), R32(Rm)); // xor Rn, Rn, Rm - return true; - - case 11: // OR(Rm, Rn); - UML_OR(block, R32(Rn), R32(Rn), R32(Rm)); // 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_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_MULS(block, mem(&m_sh2_state->macl), mem(&m_sh2_state->ea), I0, I1); // muls macl, ea, r0, r1 - return true; - } - - return false; -} - -bool sh2_device::generate_group_3(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, uint16_t opcode, uint32_t ovrpc) -{ - switch (opcode & 15) - { - case 0: // CMPEQ(Rm, Rn); (equality) - UML_CMP(block, R32(Rn), R32(Rm)); // 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_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_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_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_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; - - case 1: - case 9: - return false; - - case 4: // DIV1(Rm, Rn); - save_fast_iregs(block); - UML_MOV(block, mem(&m_sh2_state->arg0), desc->opptr.w[0]); - UML_CALLC(block, cfunc_DIV1, this); - load_fast_iregs(block); - return true; - - 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)); - return true; - } - break; - - 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)); - return true; - } - break; - - case 8: // SUB(Rm, Rn); - UML_SUB(block, R32(Rn), R32(Rn), R32(Rm)); // sub Rn, Rn, Rm - return true; - - case 12: // ADD(Rm, Rn); - UML_ADD(block, R32(Rn), R32(Rn), R32(Rm)); // 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_SETc(block, COND_C, I0); // setc i0, C - UML_ROLINS(block, mem(&m_sh2_state->sr), I0, 0, T); // rolins sr,i0,0,T - return true; - - case 11: // SUBV(Rm, Rn); -#if ADDSUBV_DIRECT - UML_SUB(block, R32(Rn), R32(Rn), R32(Rm)); // sub Rn, Rn, Rm - UML_SETc(block, COND_V, I0); // setc i0, V - UML_ROLINS(block, mem(&m_sh2_state->sr), I0, 0, T); // rolins [sr],i0,0,T -#else - save_fast_iregs(block); - UML_MOV(block, mem(&m_sh2_state->arg0), desc->opptr.w[0]); - UML_CALLC(block, cfunc_SUBV, this); - load_fast_iregs(block); -#endif - return true; - - 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_SETc(block, COND_C, I0); // setc i0, C - UML_ROLINS(block, mem(&m_sh2_state->sr), I0, 0, T); // rolins sr,i0,0,T - return true; - - case 15: // ADDV(Rm, Rn); -#if ADDSUBV_DIRECT - UML_ADD(block, R32(Rn), R32(Rn), R32(Rm)); // add Rn, Rn, Rm - UML_SETc(block, COND_V, I0); // setc i0, V - UML_ROLINS(block, mem(&m_sh2_state->sr), I0, 0, T); // rolins [sr],i0,0,T -#else - save_fast_iregs(block); - UML_MOV(block, mem(&m_sh2_state->arg0), desc->opptr.w[0]); - UML_CALLC(block, cfunc_ADDV, this); - load_fast_iregs(block); -#endif - return true; - } - return false; -} - -bool sh2_device::generate_group_4(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, uint16_t opcode, int in_delay_slot, uint32_t ovrpc) -{ - switch (opcode & 0x3F) - { - case 0x00: // SHLL(Rn); - UML_SHL(block, R32(Rn), R32(Rn), 1); // shl Rn, Rn, 1 - UML_SETc(block, COND_C, I0); // set i0,C - UML_ROLINS(block, mem(&m_sh2_state->sr), I0, 0, 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_SETc(block, COND_C, I0); // set i0,C - UML_ROLINS(block, mem(&m_sh2_state->sr), I0, 0, 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_SETc(block, COND_C, I0); // set i0,C - UML_ROLINS(block, mem(&m_sh2_state->sr), I0, 0, 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_SETc(block, COND_C, I0); // set i0,C - UML_ROLINS(block, mem(&m_sh2_state->sr), I0, 0, 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_MOV(block, I1, mem(&m_sh2_state->mach)); // mov r1, mach - SETEA(0); // set ea for debug - UML_CALLH(block, *m_write32); // call write32 - - if (!in_delay_slot) - generate_update_cycles(block, compiler, desc->pc + 2, true); - 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_MOV(block, I1, mem(&m_sh2_state->sr)); // mov r1, sr - SETEA(0); // set ea for debug - UML_CALLH(block, *m_write32); // call write32 - - if (!in_delay_slot) - generate_update_cycles(block, compiler, desc->pc + 2, true); - return true; - - case 0x06: // LDSMMACH(Rn); - UML_MOV(block, I0, R32(Rn)); // mov r0, Rn - SETEA(0); - UML_CALLH(block, *m_read32); // call read32 - UML_ADD(block, R32(Rn), R32(Rn), 4); // add Rn, #4 - UML_MOV(block, mem(&m_sh2_state->mach), I0); // mov mach, r0 - - if (!in_delay_slot) - generate_update_cycles(block, compiler, desc->pc + 2, true); - return true; - - case 0x07: // LDCMSR(Rn); - UML_MOV(block, I0, R32(Rn)); // mov r0, Rn - SETEA(0); - UML_CALLH(block, *m_read32); // call read32 - UML_ADD(block, R32(Rn), R32(Rn), 4); // add Rn, #4 - UML_MOV(block, mem(&m_sh2_state->sr), I0); // mov sr, r0 - - compiler->checkints = true; - if (!in_delay_slot) - generate_update_cycles(block, compiler, desc->pc + 2, true); - return true; - - - case 0x08: // SHLL2(Rn); - UML_SHL(block, R32(Rn), R32(Rn), 2); - return true; - - case 0x09: // SHLR2(Rn); - UML_SHR(block, R32(Rn), R32(Rn), 2); - return true; - - case 0x18: // SHLL8(Rn); - UML_SHL(block, R32(Rn), R32(Rn), 8); - return true; - - case 0x19: // SHLR8(Rn); - UML_SHR(block, R32(Rn), R32(Rn), 8); - return true; - - case 0x28: // SHLL16(Rn); - UML_SHL(block, R32(Rn), R32(Rn), 16); - return true; - - case 0x29: // SHLR16(Rn); - UML_SHR(block, R32(Rn), R32(Rn), 16); - return true; - - case 0x0a: // LDSMACH(Rn); - UML_MOV(block, mem(&m_sh2_state->mach), R32(Rn)); // mov mach, Rn - return true; - - case 0x0b: // JSR(Rn); - UML_MOV(block, mem(&m_sh2_state->target), R32(Rn)); // 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) - - generate_delay_slot(block, compiler, desc, m_sh2_state->target-4); - - generate_update_cycles(block, compiler, mem(&m_sh2_state->target), true); // <subtract cycles> - UML_HASHJMP(block, 0, mem(&m_sh2_state->target), *m_nocode); // and do the jump - return true; - - case 0x0e: // LDCSR(Rn); - UML_MOV(block, I0, R32(Rn)); // mov r0, Rn - UML_AND(block, I0, I0, FLAGS); // and r0, r0, FLAGS - UML_MOV(block, mem(&m_sh2_state->sr), I0); - - compiler->checkints = true; - return true; - - case 0x0f: // MAC_W(Rm, Rn); - case 0x1f: // MAC_W(Rm, Rn); - case 0x2f: // MAC_W(Rm, Rn); - case 0x3f: // MAC_W(Rm, Rn); - save_fast_iregs(block); - UML_MOV(block, mem(&m_sh2_state->arg0), desc->opptr.w[0]); - UML_CALLC(block, cfunc_MAC_W, this); - load_fast_iregs(block); - return true; - - case 0x10: // DT(Rn); - if (m_cpu_type > CPU_TYPE_SH1) - { - UML_AND(block, I0, mem(&m_sh2_state->sr), ~T); // and r0, sr, ~T (clear the T bit) - UML_SUB(block, R32(Rn), R32(Rn), 1); // sub Rn, Rn, 1 - UML_JMPc(block, COND_NZ, compiler->labelnum); // jz compiler->labelnum - - UML_OR(block, I0, I0, T); // or r0, r0, T - UML_LABEL(block, compiler->labelnum++); // desc->pc: - - UML_MOV(block, mem(&m_sh2_state->sr), I0); // mov m_sh2_state->sr, r0 - return true; - } - break; - - case 0x11: // CMPPZ(Rn); - UML_AND(block, I0, mem(&m_sh2_state->sr), ~T); // and r0, sr, ~T (clear the T bit) - - UML_CMP(block, R32(Rn), 0); // cmp Rn, 0 - UML_JMPc(block, COND_S, compiler->labelnum); // js compiler->labelnum (if negative) - - UML_OR(block, I0, I0, T); // or r0, r0, T - UML_LABEL(block, compiler->labelnum++); // desc->pc: - - UML_MOV(block, mem(&m_sh2_state->sr), I0); // mov m_sh2_state->sr, r0 - return true; - - case 0x15: // CMPPL(Rn); - UML_AND(block, I0, mem(&m_sh2_state->sr), ~T); // and r0, sr, ~T (clear the T bit) - - UML_CMP(block, R32(Rn), 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) - - UML_OR(block, I0, I0, T); // or r0, r0, T - - UML_LABEL(block, compiler->labelnum++); // desc->pc: - UML_MOV(block, mem(&m_sh2_state->sr), I0); // mov m_sh2_state->sr, r0 - 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_MOV(block, I1, mem(&m_sh2_state->macl)); // mov r1, macl - SETEA(0); // set ea for debug - UML_CALLH(block, *m_write32); // call write32 - - if (!in_delay_slot) - generate_update_cycles(block, compiler, desc->pc + 2, true); - 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_MOV(block, I1, mem(&m_sh2_state->gbr)); // mov r1, gbr - SETEA(0); // set ea for debug - UML_CALLH(block, *m_write32); // call write32 - - if (!in_delay_slot) - generate_update_cycles(block, compiler, desc->pc + 2, true); - return true; - - case 0x16: // LDSMMACL(Rn); - UML_MOV(block, I0, R32(Rn)); // mov r0, Rn - SETEA(0); - UML_CALLH(block, *m_read32); // call read32 - UML_ADD(block, R32(Rn), R32(Rn), 4); // add Rn, #4 - UML_MOV(block, mem(&m_sh2_state->macl), I0); // mov macl, r0 - - if (!in_delay_slot) - generate_update_cycles(block, compiler, desc->pc + 2, true); - return true; - - case 0x17: // LDCMGBR(Rn); - UML_MOV(block, I0, R32(Rn)); // mov r0, Rn - SETEA(0); - UML_CALLH(block, *m_read32); // call read32 - UML_ADD(block, R32(Rn), R32(Rn), 4); // add Rn, #4 - UML_MOV(block, mem(&m_sh2_state->gbr), I0); // mov gbr, r0 - - if (!in_delay_slot) - generate_update_cycles(block, compiler, desc->pc + 2, true); - return true; - - case 0x1a: // LDSMACL(Rn); - UML_MOV(block, mem(&m_sh2_state->macl), R32(Rn)); // mov macl, Rn - return true; - - case 0x1b: // TAS(Rn); - UML_MOV(block, I0, R32(Rn)); // mov r0, Rn - SETEA(0); - UML_CALLH(block, *m_read8); // call read8 - - UML_AND(block, mem(&m_sh2_state->sr), mem(&m_sh2_state->sr), ~T); // and sr, sr, ~T - - UML_CMP(block, I0, 0); // cmp r0, #0 - UML_JMPc(block, COND_NZ, compiler->labelnum); // jnz labelnum - - UML_OR(block, mem(&m_sh2_state->sr), mem(&m_sh2_state->sr), T); // or sr, sr, T - - UML_LABEL(block, compiler->labelnum++); // labelnum: - - UML_OR(block, I1, I0, 0x80); // or r1, r0, #0x80 - - UML_MOV(block, I0, R32(Rn)); // mov r0, Rn - UML_CALLH(block, *m_write8); // write the value back - - if (!in_delay_slot) - generate_update_cycles(block, compiler, desc->pc + 2, true); - return true; - - case 0x1e: // LDCGBR(Rn); - UML_MOV(block, mem(&m_sh2_state->gbr), R32(Rn)); // mov gbr, Rn - return true; - - case 0x20: // SHAL(Rn); - UML_AND(block, mem(&m_sh2_state->sr), mem(&m_sh2_state->sr), ~T); // and sr, sr, ~T - UML_SHR(block, I0, R32(Rn), 31); // shr r0, Rn, 31 - UML_AND(block, I0, I0, 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 - return true; - - case 0x21: // SHAR(Rn); - UML_AND(block, mem(&m_sh2_state->sr), mem(&m_sh2_state->sr), ~T); // and sr, sr, ~T - UML_AND(block, I0, R32(Rn), 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 - 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 - SETEA(0); - UML_MOV(block, I1, mem(&m_sh2_state->pr)); // mov r1, pr - UML_CALLH(block, *m_write32); // call write32 - - if (!in_delay_slot) - generate_update_cycles(block, compiler, desc->pc + 2, true); - 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 - SETEA(0); - UML_MOV(block, I1, mem(&m_sh2_state->vbr)); // mov r1, vbr - UML_CALLH(block, *m_write32); // call write32 - - if (!in_delay_slot) - generate_update_cycles(block, compiler, desc->pc + 2, true); - return true; - - 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_SETc(block, COND_C, I0); // set i0,C - UML_ROLINS(block, mem(&m_sh2_state->sr), I0, 0, 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_SETc(block, COND_C, I0); // set i0,C - UML_ROLINS(block, mem(&m_sh2_state->sr), I0, 0, T); // rolins sr,i0,0,T - return true; - - case 0x26: // LDSMPR(Rn); - UML_MOV(block, I0, R32(Rn)); // 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 - - 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 - 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 - - 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 - return true; - - case 0x2b: // JMP(Rn); - UML_MOV(block, mem(&m_sh2_state->target), R32(Rn)); // mov target, Rn - - generate_delay_slot(block, compiler, desc, m_sh2_state->target); - - generate_update_cycles(block, compiler, mem(&m_sh2_state->target), true); // <subtract cycles> - UML_HASHJMP(block, 0, mem(&m_sh2_state->target), *m_nocode); // jmp (target) - return true; - - case 0x2e: // LDCVBR(Rn); - UML_MOV(block, mem(&m_sh2_state->vbr), R32(Rn)); // mov vbr, Rn - return true; - - case 0x0c: - case 0x0d: - case 0x14: - case 0x1c: - case 0x1d: - case 0x2c: - case 0x2d: - case 0x30: - case 0x31: - case 0x32: - case 0x33: - case 0x34: - case 0x35: - case 0x36: - case 0x37: - case 0x38: - case 0x39: - case 0x3a: - case 0x3b: - case 0x3c: - case 0x3d: - case 0x3e: - return false; - } - - return false; -} - -bool sh2_device::generate_group_6(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, uint16_t opcode, int in_delay_slot, uint32_t ovrpc) -{ - switch (opcode & 15) - { - case 0: // MOVBL(Rm, Rn); - UML_MOV(block, I0, R32(Rm)); // 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 - - 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 - SETEA(0); // debug: ea = r0 - UML_CALLH(block, *m_read16); // call read16 - UML_SEXT(block, R32(Rn), 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 - SETEA(0); // debug: ea = r0 - UML_CALLH(block, *m_read32); // call read32 - UML_MOV(block, R32(Rn), 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 - return true; - - case 7: // NOT(Rm, Rn); - UML_XOR(block, R32(Rn), R32(Rm), 0xffffffff); // xor Rn, Rm, 0xffffffff - return true; - - case 9: // SWAPW(Rm, Rn); - UML_ROL(block, R32(Rn), R32(Rm), 16); // rol Rn, Rm, 16 - return true; - - case 11: // NEG(Rm, Rn); - UML_SUB(block, R32(Rn), 0, R32(Rm)); // sub Rn, 0, Rm - return true; - - case 12: // EXTUB(Rm, Rn); - UML_AND(block, R32(Rn), R32(Rm), 0x000000ff); // and Rn, Rm, 0xff - return true; - - case 13: // EXTUW(Rm, Rn); - UML_AND(block, R32(Rn), R32(Rm), 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 - return true; - - case 15: // EXTSW(Rm, Rn); - UML_SEXT(block, R32(Rn), R32(Rm), SIZE_WORD); // sext Rn, Rm, WORD - return true; - - case 4: // MOVBP(Rm, Rn); - UML_MOV(block, I0, R32(Rm)); // mov r0, Rm - UML_CALLH(block, *m_read8); // call read8 - UML_SEXT(block, R32(Rn), I0, SIZE_BYTE); // sext Rn, r0, BYTE - - if (Rm != Rn) - UML_ADD(block, R32(Rm), R32(Rm), 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_CALLH(block, *m_read16); // call read16 - UML_SEXT(block, R32(Rn), I0, SIZE_WORD); // sext Rn, r0, WORD - - if (Rm != Rn) - UML_ADD(block, R32(Rm), R32(Rm), 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_CALLH(block, *m_read32); // call read32 - UML_MOV(block, R32(Rn), I0); // mov Rn, r0 - - if (Rm != Rn) - UML_ADD(block, R32(Rm), R32(Rm), 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_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 - 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), ~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_JMPc(block, COND_NC, compiler->labelnum); // jnc labelnum - - UML_OR(block, mem(&m_sh2_state->sr), mem(&m_sh2_state->sr), T); // or sr, sr, T - - UML_LABEL(block, compiler->labelnum++); // labelnum: - - return true; - } - - return false; -} - -bool sh2_device::generate_group_8(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, uint16_t opcode, int in_delay_slot, uint32_t ovrpc) -{ - int32_t disp; - uint32_t udisp; - code_label templabel; - - switch ( opcode & (15<<8) ) - { - case 0 << 8: // MOVBS4(opcode & 0x0f, Rm); - udisp = (opcode & 0x0f); - UML_ADD(block, I0, R32(Rm), udisp); // add r0, Rm, udisp - UML_MOV(block, I1, R32(0)); // mov r1, R0 - UML_CALLH(block, *m_write8); // call write8 - - if (!in_delay_slot) - generate_update_cycles(block, compiler, desc->pc + 2, true); - return true; - - case 1 << 8: // MOVWS4(opcode & 0x0f, Rm); - udisp = (opcode & 0x0f) * 2; - UML_ADD(block, I0, R32(Rm), udisp); // add r0, Rm, udisp - UML_MOV(block, I1, R32(0)); // mov r1, R0 - UML_CALLH(block, *m_write16); // call write16 - - if (!in_delay_slot) - 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: - return false; - - case 4<< 8: // MOVBL4(Rm, opcode & 0x0f); - udisp = opcode & 0x0f; - UML_ADD(block, I0, R32(Rm), 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 - - if (!in_delay_slot) - generate_update_cycles(block, compiler, desc->pc + 2, true); - return true; - - case 5<< 8: // MOVWL4(Rm, opcode & 0x0f); - udisp = (opcode & 0x0f)*2; - UML_ADD(block, I0, R32(Rm), 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 - - if (!in_delay_slot) - generate_update_cycles(block, compiler, desc->pc + 2, true); - return true; - - case 8<< 8: // CMPIM(opcode & 0xff); - UML_AND(block, I0, mem(&m_sh2_state->sr), ~T); // and r0, sr, ~T (clear the T bit) - - UML_SEXT(block, I1, opcode&0xff, SIZE_BYTE); // sext r1, opcode&0xff, BYTE - UML_CMP(block, I1, R32(0)); // cmp r1, R0 - UML_JMPc(block, COND_NZ, compiler->labelnum); // jnz compiler->labelnum (if negative) - - UML_OR(block, I0, I0, T); // or r0, r0, T - - UML_LABEL(block, compiler->labelnum++); // labelnum: - UML_MOV(block, mem(&m_sh2_state->sr), I0); // mov m_sh2_state->sr, r0 - return true; - - case 9<< 8: // BT(opcode & 0xff); - UML_TEST(block, mem(&m_sh2_state->sr), T); // test m_sh2_state->sr, T - UML_JMPc(block, COND_Z, compiler->labelnum); // jz compiler->labelnum - - disp = ((int32_t)opcode << 24) >> 24; - 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> - UML_HASHJMP(block, 0, m_sh2_state->ea, *m_nocode); // jmp m_sh2_state->ea - - UML_LABEL(block, compiler->labelnum++); // labelnum: - return true; - - case 11<< 8: // BF(opcode & 0xff); - UML_TEST(block, mem(&m_sh2_state->sr), T); // test m_sh2_state->sr, T - UML_JMPc(block, COND_NZ, compiler->labelnum); // jnz compiler->labelnum - - disp = ((int32_t)opcode << 24) >> 24; - 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> - UML_HASHJMP(block, 0, m_sh2_state->ea, *m_nocode); // jmp m_sh2_state->ea - - UML_LABEL(block, compiler->labelnum++); // labelnum: - return true; - - case 13<< 8: // BTS(opcode & 0xff); - if (m_cpu_type > CPU_TYPE_SH1) - { - UML_TEST(block, mem(&m_sh2_state->sr), T); // test m_sh2_state->sr, T - UML_JMPc(block, COND_Z, compiler->labelnum); // jz compiler->labelnum - - disp = ((int32_t)opcode << 24) >> 24; - m_sh2_state->ea = (desc->pc + 2) + disp * 2 + 2; // m_sh2_state->ea = destination - - templabel = compiler->labelnum; // save our label - compiler->labelnum++; // make sure the delay slot doesn't use it - generate_delay_slot(block, compiler, desc, m_sh2_state->ea-2); - - generate_update_cycles(block, compiler, m_sh2_state->ea, true); // <subtract cycles> - UML_HASHJMP(block, 0, m_sh2_state->ea, *m_nocode); // jmp m_sh2_state->ea - - UML_LABEL(block, templabel); // labelnum: - return true; - } - break; - - case 15<< 8: // BFS(opcode & 0xff); - if (m_cpu_type > CPU_TYPE_SH1) - { - UML_TEST(block, mem(&m_sh2_state->sr), T); // test m_sh2_state->sr, T - UML_JMPc(block, COND_NZ, compiler->labelnum); // jnz compiler->labelnum - - disp = ((int32_t)opcode << 24) >> 24; - m_sh2_state->ea = (desc->pc + 2) + disp * 2 + 2; // m_sh2_state->ea = destination - - templabel = compiler->labelnum; // save our label - compiler->labelnum++; // make sure the delay slot doesn't use it - generate_delay_slot(block, compiler, desc, m_sh2_state->ea-2); // delay slot only if the branch is taken - - generate_update_cycles(block, compiler, m_sh2_state->ea, true); // <subtract cycles> - UML_HASHJMP(block, 0, m_sh2_state->ea, *m_nocode); // jmp m_sh2_state->ea - - UML_LABEL(block, templabel); // labelnum: - return true; - } - break; - } - - return false; -} - -bool sh2_device::generate_group_12(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, uint16_t opcode, int in_delay_slot, uint32_t ovrpc) -{ - uint32_t scratch; - - switch (opcode & (15<<8)) - { - case 0<<8: // 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 - UML_CALLH(block, *m_write8); // call write8 - - if (!in_delay_slot) - generate_update_cycles(block, compiler, desc->pc + 2, true); - return true; - - case 1<<8: // 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 - UML_CALLH(block, *m_write16); // call write16 - - if (!in_delay_slot) - generate_update_cycles(block, compiler, desc->pc + 2, true); - return true; - - case 2<<8: // 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 - UML_CALLH(block, *m_write32); // call write32 - - if (!in_delay_slot) - generate_update_cycles(block, compiler, desc->pc + 2, true); - return true; - - case 3<<8: // TRAPA(opcode & 0xff); - scratch = (opcode & 0xff) * 4; - UML_ADD(block, mem(&m_sh2_state->ea), mem(&m_sh2_state->vbr), scratch); // add ea, vbr, scratch - - UML_SUB(block, R32(15), R32(15), 4); // sub R15, R15, #4 - UML_MOV(block, I0, R32(15)); // mov r0, R15 - UML_MOV(block, I1, mem(&m_sh2_state->sr)); // mov r1, sr - UML_CALLH(block, *m_write32); // write32 - - UML_SUB(block, R32(15), R32(15), 4); // sub R15, R15, #4 - UML_MOV(block, I0, R32(15)); // mov r0, R15 - UML_MOV(block, I1, desc->pc+2); // mov r1, pc+2 - UML_CALLH(block, *m_write32); // write32 - - UML_MOV(block, I0, mem(&m_sh2_state->ea)); // mov r0, ea - UML_CALLH(block, *m_read32); // read32 - UML_HASHJMP(block, 0, I0, *m_nocode); // jmp (r0) - - return true; - - case 4<<8: // 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 - UML_SEXT(block, R32(0), I0, SIZE_BYTE); // sext R0, r0, BYTE - - if (!in_delay_slot) - generate_update_cycles(block, compiler, desc->pc + 2, true); - return true; - - case 5<<8: // 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 - UML_SEXT(block, R32(0), I0, SIZE_WORD); // sext R0, r0, WORD - - if (!in_delay_slot) - generate_update_cycles(block, compiler, desc->pc + 2, true); - return true; - - case 6<<8: // 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 - UML_MOV(block, R32(0), I0); // mov R0, r0 - - if (!in_delay_slot) - generate_update_cycles(block, compiler, desc->pc + 2, true); - return true; - - case 7<<8: // 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); - scratch = opcode & 0xff; - - UML_AND(block, mem(&m_sh2_state->sr), mem(&m_sh2_state->sr), ~T); // and sr, sr, ~T (clear the T bit) - UML_AND(block, I0, R32(0), scratch); // and r0, R0, scratch - UML_CMP(block, I0, 0); // cmp r0, #0 - UML_JMPc(block, COND_NZ, compiler->labelnum); // jnz labelnum - - UML_OR(block, mem(&m_sh2_state->sr), mem(&m_sh2_state->sr), T); // or sr, sr, T - - UML_LABEL(block, compiler->labelnum++); // labelnum: - return true; - - case 9<<8: // 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); - UML_XOR(block, R32(0), R32(0), opcode & 0xff); // xor r0, r0, opcode & 0xff - return true; - - case 11<<8: // 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); - UML_AND(block, mem(&m_sh2_state->sr), mem(&m_sh2_state->sr), ~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 - - UML_AND(block, I0, I0, opcode & 0xff); - UML_CMP(block, I0, 0); // cmp r0, #0 - UML_JMPc(block, COND_NZ, compiler->labelnum); // jnz labelnum - - UML_OR(block, mem(&m_sh2_state->sr), mem(&m_sh2_state->sr), T); // or sr, sr, T - - UML_LABEL(block, compiler->labelnum++); // labelnum: - return true; - - case 13<<8: // ANDM(opcode & 0xff); - UML_ADD(block, I0, R32(0), mem(&m_sh2_state->gbr)); // add r0, R0, gbr - UML_CALLH(block, *m_read8); // read8 - - UML_AND(block, I1, I0, opcode&0xff); // and r1, r0, #opcode&0xff - UML_ADD(block, I0, R32(0), mem(&m_sh2_state->gbr)); // add r0, R0, gbr - SETEA(0); - UML_CALLH(block, *m_write8); // write8 - return true; - - case 14<<8: // XORM(opcode & 0xff); - UML_ADD(block, I0, R32(0), mem(&m_sh2_state->gbr)); // add r0, R0, gbr - UML_CALLH(block, *m_read8); // read8 - - UML_XOR(block, I1, I0, opcode&0xff); // xor r1, r0, #opcode&0xff - UML_ADD(block, I0, R32(0), mem(&m_sh2_state->gbr)); // add r0, R0, gbr - SETEA(0); - UML_CALLH(block, *m_write8); // write8 - return true; - - case 15<<8: // ORM(opcode & 0xff); - UML_ADD(block, I0, R32(0), mem(&m_sh2_state->gbr)); // add r0, R0, gbr - UML_CALLH(block, *m_read8); // read8 - - UML_OR(block, I1, I0, opcode&0xff); // or r1, r0, #opcode&0xff - UML_ADD(block, I0, R32(0), mem(&m_sh2_state->gbr)); // add r0, R0, gbr - SETEA(0); - UML_CALLH(block, *m_write8); // write8 - return true; - } - - return false; -} - -/*************************************************************************** - CORE CALLBACKS -***************************************************************************/ - -/*------------------------------------------------- - sh2drc_set_options - configure DRC options --------------------------------------------------*/ - -void sh2_device::sh2drc_set_options(uint32_t options) -{ - if (!allow_drc()) return; - m_drcoptions = options; -} - - -/*------------------------------------------------- - sh2drc_add_pcflush - add a new address where - the PC must be flushed for speedups to work --------------------------------------------------*/ - -void sh2_device::sh2drc_add_pcflush(offs_t address) -{ - if (!allow_drc()) return; - - if (m_pcfsel < ARRAY_LENGTH(m_pcflushes)) - m_pcflushes[m_pcfsel++] = address; -} - - -/*------------------------------------------------- - sh2drc_add_fastram - add a new fastram - region --------------------------------------------------*/ - -void sh2_device::sh2drc_add_fastram(offs_t start, offs_t end, uint8_t readonly, void *base) -{ - if (m_fastram_select < ARRAY_LENGTH(m_fastram)) - { - m_fastram[m_fastram_select].start = start; - m_fastram[m_fastram_select].end = end; - m_fastram[m_fastram_select].readonly = readonly; - m_fastram[m_fastram_select].base = base; - m_fastram_select++; - } -} diff --git a/src/devices/cpu/sh/sh2fe.cpp b/src/devices/cpu/sh/sh2fe.cpp index f6b409a0cd5..3019dc02ab7 100644 --- a/src/devices/cpu/sh/sh2fe.cpp +++ b/src/devices/cpu/sh/sh2fe.cpp @@ -18,745 +18,14 @@ INSTRUCTION PARSERS ***************************************************************************/ -sh2_frontend::sh2_frontend(sh2_device *device, uint32_t window_start, uint32_t window_end, uint32_t max_sequence) - : drc_frontend(*device, window_start, window_end, max_sequence) - , m_sh2(device) +sh2_frontend::sh2_frontend(sh_common_execution *device, uint32_t window_start, uint32_t window_end, uint32_t max_sequence) + : sh_frontend(device, window_start, window_end, max_sequence) { } -/*------------------------------------------------- - describe_instruction - build a description - of a single instruction --------------------------------------------------*/ -bool sh2_frontend::describe(opcode_desc &desc, const opcode_desc *prev) -{ - uint16_t opcode; - - /* fetch the opcode */ - opcode = desc.opptr.w[0] = m_sh2->m_direct->read_word(desc.physpc, SH2_CODE_XOR(0)); - - /* all instructions are 2 bytes and most are a single cycle */ - desc.length = 2; - desc.cycles = 1; - - switch (opcode>>12) - { - case 0: - return describe_group_0(desc, prev, opcode); - - case 1: // MOVLS4 - desc.regin[0] |= REGFLAG_R(Rn) | REGFLAG_R(Rm); - desc.flags |= OPFLAG_WRITES_MEMORY; - return true; - - case 2: - return describe_group_2(desc, prev, opcode); - - case 3: - return describe_group_3(desc, prev, opcode); - - case 4: - return describe_group_4(desc, prev, opcode); - - case 5: // MOVLL4 - desc.regin[0] |= REGFLAG_R(Rm); - desc.regout[0] |= REGFLAG_R(Rn); - desc.flags |= OPFLAG_READS_MEMORY; - return true; - - case 6: - return describe_group_6(desc, prev, opcode); - - case 7: // ADDI - desc.regin[0] |= REGFLAG_R(Rn); - desc.regout[0] |= REGFLAG_R(Rn); - return true; - - case 8: - return describe_group_8(desc, prev, opcode); - - case 9: // MOVWI - desc.regout[0] |= REGFLAG_R(Rn); - 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) - case 10: // BRA - { - int32_t disp = ((int32_t)opcode << 20) >> 20; - - desc.flags |= OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE; - desc.targetpc = (desc.pc + 2) + disp * 2 + 2; - desc.delayslots = 1; - desc.cycles = 2; - return true; - } - - case 12: - return describe_group_12(desc, prev, opcode); - - case 13: // MOVLI - desc.regout[0] |= REGFLAG_R(Rn); - desc.flags |= OPFLAG_READS_MEMORY; - return true; - - case 14: // MOVI - desc.regout[0] |= REGFLAG_R(Rn); - return true; - - case 15: // NOP - return true; - } - - return false; -} - -bool sh2_frontend::describe_group_0(opcode_desc &desc, const opcode_desc *prev, uint16_t opcode) -{ - switch (opcode & 0x3F) - { - case 0x00: // NOP(); - case 0x01: // NOP(); - case 0x09: // NOP(); - case 0x10: // NOP(); - case 0x11: // NOP(); - case 0x13: // NOP(); - case 0x20: // NOP(); - case 0x21: // NOP(); - case 0x30: // NOP(); - case 0x31: // NOP(); - case 0x32: // NOP(); - case 0x33: // NOP(); - case 0x38: // NOP(); - case 0x39: // NOP(); - case 0x3a: // NOP(); - case 0x3b: // NOP(); - return true; - - case 0x02: // STCSR(Rn); - desc.regout[0] |= REGFLAG_R(Rn); - return true; - - case 0x03: // BSRF(Rn); - desc.regout[1] |= REGFLAG_PR; - - desc.flags |= OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE; - desc.targetpc = BRANCH_TARGET_DYNAMIC; - desc.delayslots = 1; - - return true; - - case 0x04: // MOVBS0(Rm, Rn); - case 0x05: // MOVWS0(Rm, Rn); - case 0x06: // MOVLS0(Rm, Rn); - case 0x14: // MOVBS0(Rm, Rn); - case 0x15: // MOVWS0(Rm, Rn); - case 0x16: // MOVLS0(Rm, Rn); - case 0x24: // MOVBS0(Rm, Rn); - case 0x25: // MOVWS0(Rm, Rn); - case 0x26: // MOVLS0(Rm, Rn); - 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.flags |= OPFLAG_READS_MEMORY; - return true; - - case 0x07: // MULL(Rm, Rn); - 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.regout[1] |= REGFLAG_MACL; - desc.cycles = 2; - return true; - - case 0x08: // CLRT(); - desc.regout[1] |= REGFLAG_SR; - return true; - - case 0x0a: // STSMACH(Rn); - desc.regout[0] |= REGFLAG_R(Rn); - desc.regout[1] |= REGFLAG_MACH; - return true; - - case 0x0b: // RTS(); - desc.regin[1] |= REGFLAG_PR; - - desc.flags |= OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE; - desc.targetpc = BRANCH_TARGET_DYNAMIC; - desc.delayslots = 1; - desc.cycles = 2; - - return true; - - case 0x0c: // MOVBL0(Rm, Rn); - case 0x0d: // MOVWL0(Rm, Rn); - case 0x0e: // MOVLL0(Rm, Rn); - case 0x1c: // MOVBL0(Rm, Rn); - case 0x1d: // MOVWL0(Rm, Rn); - case 0x1e: // MOVLL0(Rm, Rn); - case 0x2c: // MOVBL0(Rm, Rn); - case 0x2d: // MOVWL0(Rm, Rn); - case 0x2e: // MOVLL0(Rm, Rn); - 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.flags |= OPFLAG_READS_MEMORY; - return true; - - case 0x0f: // MAC_L(Rm, Rn); - 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.regout[1] |= REGFLAG_MACL | REGFLAG_MACH; - desc.cycles = 3; - return true; - - case 0x12: // STCGBR(Rn); - desc.regout[0] |= REGFLAG_R(Rn); - desc.regin[1] |= REGFLAG_GBR; - return true; - - case 0x18: // SETT(); - desc.regout[1] |= REGFLAG_SR; - return true; - - case 0x19: // DIV0U(); - desc.regout[1] |= REGFLAG_SR; - return true; - - case 0x1a: // STSMACL(Rn); - desc.regin[1] |= REGFLAG_MACL; - desc.regout[0] |= REGFLAG_R(Rn); - return true; - - case 0x1b: // SLEEP(); - desc.cycles = 3; - return true; - - case 0x22: // STCVBR(Rn); - desc.regin[0] |= REGFLAG_R(Rn); - desc.regout[1] |= REGFLAG_VBR; - return true; - - case 0x23: // BRAF(Rn); - desc.regin[0] |= REGFLAG_R(Rm); - desc.flags |= OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE; - desc.targetpc = BRANCH_TARGET_DYNAMIC; - desc.delayslots = 1; - desc.cycles = 2; - return true; - - case 0x28: // CLRMAC(); - desc.regout[1] |= REGFLAG_MACL | REGFLAG_MACH; - return true; - - case 0x29: // MOVT(Rn); - desc.regin[1] |= REGFLAG_SR; - desc.regout[0] |= REGFLAG_R(Rn); - return true; - - case 0x2a: // STSPR(Rn); - desc.regin[1] |= REGFLAG_PR; - desc.regout[0] |= REGFLAG_R(Rn); - return true; - - case 0x2b: // RTE(); - desc.regin[0] |= REGFLAG_R(15); - desc.regout[0] |= REGFLAG_R(15); - - desc.flags |= OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE | OPFLAG_CAN_EXPOSE_EXTERNAL_INT; - desc.targetpc = BRANCH_TARGET_DYNAMIC; - desc.delayslots = 1; - desc.cycles = 4; - - return true; - } - - return false; -} - -bool sh2_frontend::describe_group_2(opcode_desc &desc, const opcode_desc *prev, uint16_t opcode) -{ - switch (opcode & 15) - { - 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.flags |= OPFLAG_WRITES_MEMORY; - return true; - - case 3: // NOP(); - return true; - - case 4: // MOVBM(Rm, Rn); - 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.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.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); - return true; - - case 14: // MULU(Rm, Rn); - case 15: // MULS(Rm, Rn); - desc.regin[0] |= REGFLAG_R(Rm) | REGFLAG_R(Rn); - desc.regout[1] |= REGFLAG_MACL | REGFLAG_MACH; - desc.cycles = 2; - return true; - } - - return false; -} - -bool sh2_frontend::describe_group_3(opcode_desc &desc, const opcode_desc *prev, uint16_t opcode) -{ - switch (opcode & 15) - { - case 0: // CMPEQ(Rm, Rn); - case 2: // CMPHS(Rm, Rn); - 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.regout[1] |= REGFLAG_SR; - return true; - - case 1: // NOP(); - case 9: // NOP(); - return true; - - case 4: // DIV1(Rm, Rn); - desc.regin[0] |= REGFLAG_R(Rm) | REGFLAG_R(Rn); - desc.regout[0] |= REGFLAG_R(Rn); - 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.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); - 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[1] |= REGFLAG_SR; - desc.regout[0] |= REGFLAG_R(Rn); - desc.regout[1] |= REGFLAG_SR; - return true; - } - return false; -} - -bool sh2_frontend::describe_group_4(opcode_desc &desc, const opcode_desc *prev, uint16_t opcode) +bool sh2_frontend::describe_group_15(opcode_desc &desc, const opcode_desc *prev, uint16_t opcode) { - switch (opcode & 0x3F) - { - case 0x00: // SHLL(Rn); - 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.regout[1] |= REGFLAG_SR; - return true; - - case 0x02: // STSMMACH(Rn); - desc.regin[0] |= REGFLAG_R(Rn); - desc.regin[1] |= REGFLAG_MACH; - desc.regout[0] |= REGFLAG_R(Rn); - desc.flags |= OPFLAG_WRITES_MEMORY; - return true; - - case 0x03: // STCMSR(Rn); - desc.regin[0] |= REGFLAG_R(Rn); - desc.regout[0] |= REGFLAG_R(Rn); - 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.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.regout[1] |= REGFLAG_SR; - desc.cycles = 3; - desc.flags |= OPFLAG_READS_MEMORY | OPFLAG_CAN_EXPOSE_EXTERNAL_INT | OPFLAG_END_SEQUENCE; - return true; - - case 0x08: // SHLL2(Rn); - case 0x09: // SHLR2(Rn); - case 0x18: // SHLL8(Rn); - case 0x19: // SHLR8(Rn); - case 0x28: // SHLL16(Rn); - case 0x29: // SHLR16(Rn); - desc.regin[0] |= REGFLAG_R(Rn); - desc.regout[0] |= REGFLAG_R(Rn); - return true; - - case 0x0a: // LDSMACH(Rn); - desc.regin[0] |= REGFLAG_R(Rn); - desc.regout[1] |= REGFLAG_MACH; - return true; - - case 0x0b: // JSR(Rn); - desc.regin[0] |= REGFLAG_R(Rn); - desc.regout[1] |= REGFLAG_PR; - desc.flags |= OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE; - desc.targetpc = BRANCH_TARGET_DYNAMIC; - desc.delayslots = 1; - return true; - - case 0x0e: // LDCSR(Rn); - desc.regin[0] |= REGFLAG_R(Rn); - desc.regout[1] |= REGFLAG_SR; - desc.flags |= OPFLAG_CAN_EXPOSE_EXTERNAL_INT | OPFLAG_END_SEQUENCE; - return true; - - case 0x0f: // MAC_W(Rm, Rn); - 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[1] |= REGFLAG_MACL | REGFLAG_MACH; - desc.regout[0] |= REGFLAG_R(Rm) | REGFLAG_R(Rn); - desc.regout[1] |= REGFLAG_MACL | REGFLAG_MACH; - desc.cycles = 3; - return true; - - case 0x10: // DT(Rn); - desc.regin[0] |= REGFLAG_R(Rn); - desc.regin[1] |= REGFLAG_SR; - desc.regout[0] |= REGFLAG_R(Rn); - desc.regout[1] |= REGFLAG_SR; - return true; - - case 0x11: // CMPPZ(Rn); - case 0x15: // CMPPL(Rn); - desc.regin[0] |= REGFLAG_R(Rn); - desc.regin[1] |= REGFLAG_SR; - desc.regout[1] |= REGFLAG_SR; - return true; - - case 0x12: // STSMMACL(Rn); - desc.regin[0] |= REGFLAG_R(Rn); - desc.regin[1] |= REGFLAG_MACL; - desc.regout[0] |= REGFLAG_R(Rn); - desc.flags |= OPFLAG_WRITES_MEMORY; - return true; - - case 0x13: // STCMGBR(Rn); - desc.regin[0] |= REGFLAG_R(Rn); - desc.regin[1] |= REGFLAG_GBR; - desc.regout[0] |= REGFLAG_R(Rn); - 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.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.regout[1] |= REGFLAG_GBR; - desc.flags |= OPFLAG_READS_MEMORY; - return true; - - case 0x1a: // LDSMACL(Rn); - desc.regin[0] |= REGFLAG_R(Rn); - desc.regout[1] |= REGFLAG_MACL; - return true; - - case 0x1b: // TAS(Rn); - desc.regin[0] |= REGFLAG_R(Rn); - desc.regin[1] |= REGFLAG_SR; - desc.regout[1] |= REGFLAG_SR; - desc.cycles = 4; - desc.flags |= OPFLAG_READS_MEMORY | OPFLAG_WRITES_MEMORY; - return true; - - case 0x1e: // LDCGBR(Rn); - desc.regin[0] |= REGFLAG_R(Rn); - 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.regout[1] |= REGFLAG_SR; - return true; - - case 0x22: // STSMPR(Rn); - desc.regin[0] |= REGFLAG_R(Rn); - desc.regin[1] |= REGFLAG_PR; - desc.regout[0] |= REGFLAG_R(Rn); - desc.flags |= OPFLAG_WRITES_MEMORY; - return true; - - case 0x23: // STCMVBR(Rn); - desc.regin[0] |= REGFLAG_R(Rn); - desc.regin[1] |= REGFLAG_VBR; - desc.regout[0] |= REGFLAG_R(Rn); - desc.flags |= OPFLAG_WRITES_MEMORY; - return true; - - case 0x24: // ROTCL(Rn); - case 0x25: // ROTCR(Rn); - desc.regin[0] |= REGFLAG_R(Rn); - desc.regin[1] |= REGFLAG_SR; - desc.regout[0] |= REGFLAG_R(Rn); - desc.regout[1] |= REGFLAG_SR; - return true; - - case 0x26: // LDSMPR(Rn); - desc.regin[0] |= REGFLAG_R(Rn); - desc.regout[0] |= REGFLAG_R(Rn); - 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.regout[1] |= REGFLAG_VBR; - desc.flags |= OPFLAG_READS_MEMORY; - return true; - - case 0x2a: // LDSPR(Rn); - desc.regin[0] |= REGFLAG_R(Rn); - desc.regout[1] |= REGFLAG_PR; - return true; - - case 0x2b: // JMP(Rm); - desc.regin[0] |= REGFLAG_R(Rm); - 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.regout[1] |= REGFLAG_VBR; - return true; - - case 0x0c: // NOP(); - case 0x0d: // NOP(); - case 0x14: // NOP(); - case 0x1c: // NOP(); - case 0x1d: // NOP(); - case 0x2c: // NOP(); - case 0x2d: // NOP(); - case 0x30: // NOP(); - case 0x31: // NOP(); - case 0x32: // NOP(); - case 0x33: // NOP(); - case 0x34: // NOP(); - case 0x35: // NOP(); - case 0x36: // NOP(); - case 0x37: // NOP(); - case 0x38: // NOP(); - case 0x39: // NOP(); - case 0x3a: // NOP(); - case 0x3b: // NOP(); - case 0x3c: // NOP(); - case 0x3d: // NOP(); - case 0x3e: // NOP(); - return true; - } - - return false; -} - -bool sh2_frontend::describe_group_6(opcode_desc &desc, const opcode_desc *prev, uint16_t opcode) -{ - switch (opcode & 15) - { - case 0: // MOVBL(Rm, Rn); - case 1: // MOVWL(Rm, Rn); - case 2: // MOVLL(Rm, Rn); - case 3: // MOV(Rm, Rn); - case 7: // NOT(Rm, Rn); - case 9: // SWAPW(Rm, Rn); - case 11: // NEG(Rm, Rn); - case 12: // EXTUB(Rm, Rn); - 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); - 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.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); - return true; - - case 10: // NEGC(Rm, Rn); - desc.regin[0] |= REGFLAG_R(Rm); - desc.regout[0] |= REGFLAG_R(Rn); - desc.regout[1] |= REGFLAG_SR; - return true; - } - return false; -} - -bool sh2_frontend::describe_group_8(opcode_desc &desc, const opcode_desc *prev, uint16_t opcode) -{ - int32_t disp; - - 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.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(); - return true; - - case 4<< 8: // MOVBL4(Rm, opcode & 0x0f); - case 5<< 8: // MOVWL4(Rm, opcode & 0x0f); - desc.regin[0] |= REGFLAG_R(Rm); - 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); - desc.regin[1] |= REGFLAG_SR; - desc.regout[1] |= REGFLAG_SR; - return true; - - 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; - desc.targetpc = (desc.pc + 2) + disp * 2 + 2; - return true; - - 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; - desc.targetpc = (desc.pc + 2) + disp * 2 + 2; - desc.delayslots = 1; - return true; - } - - return false; -} - -bool sh2_frontend::describe_group_12(opcode_desc &desc, const opcode_desc *prev, uint16_t opcode) -{ - switch (opcode & (15<<8)) - { - 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); - desc.regin[0] |= REGFLAG_R(15); - desc.regin[1] |= REGFLAG_VBR; - desc.regout[0] |= REGFLAG_R(15); - desc.cycles = 8; - desc.targetpc = BRANCH_TARGET_DYNAMIC; - 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); - desc.regout[0] |= REGFLAG_R(0); - desc.flags |= OPFLAG_READS_MEMORY; - return true; - - 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); - 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); - desc.regin[0] |= REGFLAG_R(0); - desc.regin[1] |= REGFLAG_SR | REGFLAG_GBR; - desc.regout[1] |= REGFLAG_SR; - desc.flags |= OPFLAG_READS_MEMORY; - return true; - } - - return false; + return true; } diff --git a/src/devices/cpu/sh/sh3comn.cpp b/src/devices/cpu/sh/sh3comn.cpp index 4a50e748eb9..6871a1aef01 100644 --- a/src/devices/cpu/sh/sh3comn.cpp +++ b/src/devices/cpu/sh/sh3comn.cpp @@ -21,23 +21,23 @@ WRITE32_MEMBER( sh3_base_device::sh3_internal_high_w ) 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_pc & AM,(offset *4)+SH3_UPPER_REGBASE,data,mem_mask); + 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_pc & AM,(offset *4)+SH3_UPPER_REGBASE,data,mem_mask); + 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_pc & AM,(offset *4)+SH3_UPPER_REGBASE,data,mem_mask); + 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_pc & AM,(offset *4)+SH3_UPPER_REGBASE,data,mem_mask); + 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); @@ -63,7 +63,7 @@ WRITE32_MEMBER( sh3_base_device::sh3_internal_high_w ) 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_pc & AM,(offset *4)+SH3_UPPER_REGBASE,data,mem_mask); + 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; } @@ -80,11 +80,11 @@ READ32_MEMBER( sh3_base_device::sh3_internal_high_r ) 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_pc & AM,(offset *4)+SH3_UPPER_REGBASE,mem_mask, m_sh3internal_upper[offset]); + 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_pc & AM,(offset *4)+SH3_UPPER_REGBASE,mem_mask, m_sh3internal_upper[offset]); + 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: @@ -115,22 +115,22 @@ READ32_MEMBER( sh3_base_device::sh3_internal_high_r ) case SH3_TRA_ADDR: - logerror("'%s' (%08x): unmapped internal read from %08x mask %08x (SH3 TRA - %08x)\n",tag(), m_pc & AM,(offset *4)+SH3_UPPER_REGBASE,mem_mask, m_sh3internal_upper[offset]); + 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_pc & AM,(offset *4)+SH3_UPPER_REGBASE,mem_mask, m_sh3internal_upper[offset]); + 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_pc & AM,(offset *4)+SH3_UPPER_REGBASE,mem_mask, m_sh3internal_upper[offset]); + 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_pc & AM,(offset *4)+SH3_UPPER_REGBASE,mem_mask); + 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]; } } @@ -163,7 +163,7 @@ READ32_MEMBER( sh3_base_device::sh3_internal_r ) case INTEVT2: { - // logerror("'%s' (%08x): unmapped internal read from %08x mask %08x (INTEVT2)\n",tag(), m_pc & AM,(offset *4)+0x4000000,mem_mask); + // 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]; } @@ -173,17 +173,17 @@ READ32_MEMBER( sh3_base_device::sh3_internal_r ) { if (mem_mask & 0xff000000) { - logerror("'%s' (%08x): unmapped internal read from %08x mask %08x (IRR0)\n",tag(), m_pc & AM,(offset *4)+0x4000000,mem_mask); + 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_pc & AM,(offset *4)+0x4000000,mem_mask); + 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_pc & AM,(offset *4)+0x4000000,mem_mask); + 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); } } @@ -191,13 +191,13 @@ READ32_MEMBER( sh3_base_device::sh3_internal_r ) { if (mem_mask & 0xffff0000) { - //logerror("'%s' (%08x): unmapped internal read from %08x mask %08x (PADR)\n",tag(), m_pc & AM,(offset *4)+0x4000000,mem_mask); + //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_pc & AM,(offset *4)+0x4000000,mem_mask); + //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; } } @@ -207,13 +207,13 @@ READ32_MEMBER( sh3_base_device::sh3_internal_r ) { if (mem_mask & 0xffff0000) { - //logerror("'%s' (%08x): unmapped internal read from %08x mask %08x (PCDR)\n",tag(), m_pc & AM,(offset *4)+0x4000000,mem_mask); + //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_pc & AM,(offset *4)+0x4000000,mem_mask); + //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; } } @@ -223,13 +223,13 @@ READ32_MEMBER( sh3_base_device::sh3_internal_r ) { if (mem_mask & 0xffff0000) { - //logerror("'%s' (%08x): unmapped internal read from %08x mask %08x (PEDR)\n",tag(), m_pc & AM,(offset *4)+0x4000000,mem_mask); + //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_pc & AM,(offset *4)+0x4000000,mem_mask); + //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; } } @@ -239,13 +239,13 @@ READ32_MEMBER( sh3_base_device::sh3_internal_r ) { if (mem_mask & 0xffff0000) { - //logerror("'%s' (%08x): unmapped internal read from %08x mask %08x (PGDR)\n",tag(), m_pc & AM,(offset *4)+0x4000000,mem_mask); + //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_pc & AM,(offset *4)+0x4000000,mem_mask); + //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; } } @@ -255,13 +255,13 @@ READ32_MEMBER( sh3_base_device::sh3_internal_r ) { if (mem_mask & 0xffff0000) { - //logerror("'%s' (%08x): unmapped internal read from %08x mask %08x (PJDR)\n",tag(), m_pc & AM,(offset *4)+0x4000000,mem_mask); + //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_pc & AM,(offset *4)+0x4000000,mem_mask); + //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; } } @@ -271,13 +271,13 @@ READ32_MEMBER( sh3_base_device::sh3_internal_r ) { if (mem_mask & 0xffff0000) { - //logerror("'%s' (%08x): unmapped internal read from %08x mask %08x (PLDR)\n",tag(), m_pc & AM,(offset *4)+0x4000000,mem_mask); + //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_pc & AM,(offset *4)+0x4000000,mem_mask); + 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; } } @@ -288,13 +288,13 @@ READ32_MEMBER( sh3_base_device::sh3_internal_r ) { if (mem_mask & 0xff000000) { - logerror("'%s' (%08x): SCIF internal read from %08x mask %08x (SCSMR2 - Serial Mode Register 2)\n",tag(), m_pc & AM,(offset *4)+0x4000000,mem_mask); + 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_pc & AM,(offset *4)+0x4000000,mem_mask); + 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]; } } @@ -304,13 +304,13 @@ READ32_MEMBER( sh3_base_device::sh3_internal_r ) { if (mem_mask & 0xff000000) { - logerror("'%s' (%08x): SCIF internal read from %08x mask %08x (SCSCR2 - Serial Control Register 2)\n",tag(), m_pc & AM,(offset *4)+0x4000000,mem_mask); + 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_pc & AM,(offset *4)+0x4000000,mem_mask); + 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]; } } @@ -320,13 +320,13 @@ READ32_MEMBER( sh3_base_device::sh3_internal_r ) { if (mem_mask & 0xffff0000) { - logerror("'%s' (%08x): SCIF internal read from %08x mask %08x (SCSSR2 - Serial Status Register 2)\n",tag(), m_pc & AM,(offset *4)+0x4000000,mem_mask); + 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_pc & AM,(offset *4)+0x4000000,mem_mask); + 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]; } } @@ -336,13 +336,13 @@ READ32_MEMBER( sh3_base_device::sh3_internal_r ) { if (mem_mask & 0xff000000) { - logerror("'%s' (%08x): SCIF internal read from %08x mask %08x (SCFCR2 - Fifo Control Register 2)\n",tag(), m_pc & AM,(offset *4)+0x4000000,mem_mask); + 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_pc & AM,(offset *4)+0x4000000,mem_mask); + 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]; } } @@ -352,7 +352,7 @@ READ32_MEMBER( sh3_base_device::sh3_internal_r ) default: { logerror("'%s' (%08x): unmapped internal read from %08x mask %08x\n", - tag(), m_pc & AM, + tag(), m_sh2_state->pc & SH34_AM, (offset *4)+0x4000000, mem_mask); } @@ -364,7 +364,7 @@ READ32_MEMBER( sh3_base_device::sh3_internal_r ) else { logerror("'%s' (%08x): unmapped internal read from %08x mask %08x\n", - tag(), m_pc & AM, + tag(), m_sh2_state->pc & SH34_AM, (offset *4)+0x4000000, mem_mask); } @@ -407,7 +407,7 @@ WRITE32_MEMBER( sh3_base_device::sh3_internal_w ) { if (mem_mask & 0xff000000) { - logerror("'%s' (%08x): unmapped internal write to %08x = %08x & %08x (IRR0)\n",tag(), m_pc & AM,(offset *4)+0x4000000,data,mem_mask); + 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); @@ -417,11 +417,11 @@ WRITE32_MEMBER( sh3_base_device::sh3_internal_w ) } if (mem_mask & 0x0000ff00) { - logerror("'%s' (%08x): unmapped internal write to %08x = %08x & %08x (IRR1)\n",tag(), m_pc & AM,(offset *4)+0x4000000,data,mem_mask); + 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_pc & AM,(offset *4)+0x4000000,data,mem_mask); + 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); } } } @@ -431,14 +431,14 @@ WRITE32_MEMBER( sh3_base_device::sh3_internal_w ) { if (mem_mask & 0xffff0000) { - logerror("'%s' (%08x): unmapped internal write to %08x = %08x & %08x (PINTER)\n",tag(), m_pc & AM,(offset *4)+0x4000000,data,mem_mask); + 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_pc & AM,(offset *4)+0x4000000,data,mem_mask); + 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); @@ -452,12 +452,12 @@ WRITE32_MEMBER( sh3_base_device::sh3_internal_w ) { if (mem_mask & 0xffff0000) { - logerror("'%s' (%08x): unmapped internal write to %08x = %08x & %08x (PCCR)\n",tag(), m_pc & AM,(offset *4)+0x4000000,data,mem_mask); + 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_pc & AM,(offset *4)+0x4000000,data,mem_mask); + 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; @@ -466,12 +466,12 @@ WRITE32_MEMBER( sh3_base_device::sh3_internal_w ) { if (mem_mask & 0xffff0000) { - logerror("'%s' (%08x): unmapped internal write to %08x = %08x & %08x (PECR)\n",tag(), m_pc & AM,(offset *4)+0x4000000,data,mem_mask); + 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_pc & AM,(offset *4)+0x4000000,data,mem_mask); + 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; @@ -481,12 +481,12 @@ WRITE32_MEMBER( sh3_base_device::sh3_internal_w ) { if (mem_mask & 0xffff0000) { - logerror("'%s' (%08x): unmapped internal write to %08x = %08x & %08x (PGCR)\n",tag(), m_pc & AM,(offset *4)+0x4000000,data,mem_mask); + 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_pc & AM,(offset *4)+0x4000000,data,mem_mask); + 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; @@ -496,12 +496,12 @@ WRITE32_MEMBER( sh3_base_device::sh3_internal_w ) { if (mem_mask & 0xffff0000) { - logerror("'%s' (%08x): unmapped internal write to %08x = %08x & %08x (PJCR)\n",tag(), m_pc & AM,(offset *4)+0x4000000,data,mem_mask); + 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_pc & AM,(offset *4)+0x4000000,data,mem_mask); + 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; @@ -511,12 +511,12 @@ WRITE32_MEMBER( sh3_base_device::sh3_internal_w ) { if (mem_mask & 0xffff0000) { - logerror("'%s' (%08x): unmapped internal write to %08x = %08x & %08x (PLCR)\n",tag(), m_pc & AM,(offset *4)+0x4000000,data,mem_mask); + 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_pc & AM,(offset *4)+0x4000000,data,mem_mask); + 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; @@ -526,13 +526,13 @@ WRITE32_MEMBER( sh3_base_device::sh3_internal_w ) 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_pc & AM,(offset *4)+0x4000000,data,mem_mask); + // 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_pc & AM,(offset *4)+0x4000000,data,mem_mask); + // 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; @@ -542,13 +542,13 @@ WRITE32_MEMBER( sh3_base_device::sh3_internal_w ) 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_pc & AM,(offset *4)+0x4000000,data,mem_mask); + // 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_pc & AM,(offset *4)+0x4000000,data,mem_mask); + // 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; @@ -557,13 +557,13 @@ WRITE32_MEMBER( sh3_base_device::sh3_internal_w ) 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_pc & AM,(offset *4)+0x4000000,data,mem_mask); + // 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_pc & AM,(offset *4)+0x4000000,data,mem_mask); + // 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; @@ -573,13 +573,13 @@ WRITE32_MEMBER( sh3_base_device::sh3_internal_w ) 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_pc & AM,(offset *4)+0x4000000,data,mem_mask); + // 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_pc & AM,(offset *4)+0x4000000,data,mem_mask); + // 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; @@ -590,13 +590,13 @@ WRITE32_MEMBER( sh3_base_device::sh3_internal_w ) 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_pc & AM,(offset *4)+0x4000000,data,mem_mask); + // 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_pc & AM,(offset *4)+0x4000000,data,mem_mask); + //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; @@ -605,12 +605,12 @@ WRITE32_MEMBER( sh3_base_device::sh3_internal_w ) { if (mem_mask & 0xff000000) { - logerror("'%s' (%08x): SCIF internal write to %08x = %08x & %08x (SCSMR2 - Serial Mode Register 2)\n",tag(), m_pc & AM,(offset *4)+0x4000000,data,mem_mask); + 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_pc & AM,(offset *4)+0x4000000,data,mem_mask); + 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; @@ -619,12 +619,12 @@ WRITE32_MEMBER( sh3_base_device::sh3_internal_w ) { if (mem_mask & 0xff000000) { - logerror("'%s' (%08x): SCIF internal write to %08x = %08x & %08x (SCSCR2 - Serial Control Register 2)\n",tag(), m_pc & AM,(offset *4)+0x4000000,data,mem_mask); + 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_pc & AM,(offset *4)+0x4000000,data,mem_mask); + 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; @@ -633,12 +633,12 @@ WRITE32_MEMBER( sh3_base_device::sh3_internal_w ) { if (mem_mask & 0xffff0000) { - logerror("'%s' (%08x): SCIF internal write to %08x = %08x & %08x (SCSSR2 - Serial Status Register 2)\n",tag(), m_pc & AM,(offset *4)+0x4000000,data,mem_mask); + 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_pc & AM,(offset *4)+0x4000000,data,mem_mask); + 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; @@ -647,12 +647,12 @@ WRITE32_MEMBER( sh3_base_device::sh3_internal_w ) { if (mem_mask & 0xff000000) { - logerror("'%s' (%08x): SCIF internal write to %08x = %08x & %08x (SCFCR2 - Fifo Control Register 2)\n",tag(), m_pc & AM,(offset *4)+0x4000000,data,mem_mask); + 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_pc & AM,(offset *4)+0x4000000,data,mem_mask); + 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; @@ -660,7 +660,7 @@ WRITE32_MEMBER( sh3_base_device::sh3_internal_w ) default: { logerror("'%s' (%08x): unmapped internal write to %08x = %08x & %08x\n", - tag(), m_pc & AM, + tag(), m_sh2_state->pc & SH34_AM, (offset *4)+0x4000000, data, mem_mask); @@ -672,7 +672,7 @@ WRITE32_MEMBER( sh3_base_device::sh3_internal_w ) else { logerror("'%s' (%08x): unmapped internal write to %08x = %08x & %08x\n", - tag(), m_pc & AM, + tag(), m_sh2_state->pc & SH34_AM, (offset *4)+0x4000000, data, mem_mask); diff --git a/src/devices/cpu/sh/sh4.cpp b/src/devices/cpu/sh/sh4.cpp index cc7c333d9cc..e4e4429c132 100644 --- a/src/devices/cpu/sh/sh4.cpp +++ b/src/devices/cpu/sh/sh4.cpp @@ -30,33 +30,10 @@ #include "sh4comn.h" #include "sh3comn.h" #include "sh4tmu.h" - +#include "sh_dasm.h" #include "debugger.h" -#if SH4_USE_FASTRAM_OPTIMIZATION -void sh34_base_device::add_fastram(offs_t start, offs_t end, uint8_t readonly, void *base) -{ - if (m_fastram_select < ARRAY_LENGTH(m_fastram)) - { - m_fastram[m_fastram_select].start = start; - m_fastram[m_fastram_select].end = end; - m_fastram[m_fastram_select].readonly = readonly; - m_fastram[m_fastram_select].base = base; - m_fastram_select++; - } -} -#else -void sh34_base_device::add_fastram(offs_t start, offs_t end, uint8_t readonly, void *base) -{ -} -#endif - - -CPU_DISASSEMBLE( sh4 ); -CPU_DISASSEMBLE( sh4be ); - - DEFINE_DEVICE_TYPE(SH3LE, sh3_device, "sh3le", "SH-3 (little)") DEFINE_DEVICE_TYPE(SH3BE, sh3be_device, "sh3be", "SH-3 (big)") DEFINE_DEVICE_TYPE(SH4LE, sh4_device, "sh4le", "SH-4 (little)") @@ -92,7 +69,7 @@ ADDRESS_MAP_END 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) - : cpu_device(mconfig, type, tag, owner, clock) + : sh_common_execution(mconfig, type, tag, owner, clock, endianness, internal) , m_program_config("program", endianness, 64, 32, 0, internal) , m_io_config("io", endianness, 64, 8) , c_md2(0) @@ -106,17 +83,8 @@ sh34_base_device::sh34_base_device(const machine_config &mconfig, device_type ty , c_md8(0) , c_clock(0) , m_mmuhack(1) -#if SH4_USE_FASTRAM_OPTIMIZATION , m_bigendian(endianness == ENDIANNESS_BIG) - , m_byte_xor(m_bigendian ? BYTE8_XOR_BE(0) : BYTE8_XOR_LE(0)) - , m_word_xor(m_bigendian ? WORD2_XOR_BE(0) : WORD2_XOR_LE(0)) - , m_dword_xor(m_bigendian ? DWORD_XOR_BE(0) : DWORD_XOR_LE(0)) - , m_fastram_select(0) -#endif { -#if SH4_USE_FASTRAM_OPTIMIZATION - memset(m_fastram, 0, sizeof(m_fastram)); -#endif } device_memory_interface::space_config_vector sh34_base_device::memory_space_config() const @@ -132,6 +100,7 @@ sh3_base_device::sh3_base_device(const machine_config &mconfig, device_type type : sh34_base_device(mconfig, type, tag, owner, clock, endianness, ADDRESS_MAP_NAME(sh3_internal_map)) { m_cpu_type = CPU_TYPE_SH3; + m_am = SH34_AM; } @@ -139,54 +108,41 @@ sh4_base_device::sh4_base_device(const machine_config &mconfig, device_type type : sh34_base_device(mconfig, type, tag, owner, clock, endianness, ADDRESS_MAP_NAME(sh4_internal_map)) { m_cpu_type = CPU_TYPE_SH4; + m_am = SH34_AM; } 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) { + m_xor = 1; } 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) { + m_xor = 2; } 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) { + m_xor = 1; } 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) { + m_xor = 2; } -offs_t sh34_base_device::disasm_disassemble(std::ostream &stream, offs_t pc, const uint8_t *oprom, const uint8_t *opram, uint32_t options) -{ - extern CPU_DISASSEMBLE( sh4 ); - - return CPU_DISASSEMBLE_NAME(sh4)(this, stream, pc, oprom, opram, options); -} - - -offs_t sh3be_device::disasm_disassemble(std::ostream &stream, offs_t pc, const uint8_t *oprom, const uint8_t *opram, uint32_t options) -{ - extern CPU_DISASSEMBLE( sh4be ); - - return CPU_DISASSEMBLE_NAME(sh4be)(this, stream, pc, oprom, opram, options); -} - - -offs_t sh4be_device::disasm_disassemble(std::ostream &stream, offs_t pc, const uint8_t *oprom, const uint8_t *opram, uint32_t options) +util::disasm_interface *sh34_base_device::create_disassembler() { - extern CPU_DISASSEMBLE( sh4be ); - - return CPU_DISASSEMBLE_NAME(sh4be)(this, stream, pc, oprom, opram, options); + return new sh_disassembler(true); } @@ -207,20 +163,20 @@ void sh4_base_device::LDTLB(const uint16_t opcode) 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].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; // 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].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].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; // these come from PTEA m_utlb[replace].TC = (m_m[PTEA] & 0x00000008) >> 3; m_utlb[replace].SA = (m_m[PTEA] & 0x00000007) >> 0; @@ -229,22 +185,22 @@ void sh4_base_device::LDTLB(const uint16_t opcode) #if 0 int sign_of(int n) { - return(m_fr[n]>>31); + return(m_fr[n] >> 31); } -void zero(int n,int sign) +void zero(int n, int sign) { -if (sign == 0) - m_fr[n] = 0x00000000; -else - m_fr[n] = 0x80000000; -if ((m_fpscr & PR) == 1) - m_fr[n+1] = 0x00000000; + if (sign == 0) + m_fr[n] = 0x00000000; + else + m_fr[n] = 0x80000000; + if ((m_fpscr & PR) == 1) + m_fr[n + 1] = 0x00000000; } int data_type_of(int n) { -uint32_t abs; + uint32_t abs; abs = m_fr[n] & 0x7fffffff; if ((m_fpscr & PR) == 0) { /* Single-precision */ @@ -253,13 +209,16 @@ uint32_t abs; if (sign_of(n) == 0) { zero(n, 0); return(SH4_FPU_PZERO); - } else { + } + else { zero(n, 1); return(SH4_FPU_NZERO); } - } else + } + else return(SH4_FPU_DENORM); - } else + } + else if (abs < 0x7f800000) return(SH4_FPU_NORM); else @@ -268,33 +227,39 @@ uint32_t abs; return(SH4_FPU_PINF); else return(SH4_FPU_NINF); - } else + } + else if (abs < 0x7fc00000) return(SH4_FPU_qNaN); else return(SH4_FPU_sNaN); - } else { /* Double-precision */ + } + else { /* Double-precision */ if (abs < 0x00100000) { - if (((m_fpscr & DN) == 1) || ((abs == 0x00000000) && (m_fr[n+1] == 0x00000000))) { - if(sign_of(n) == 0) { + if (((m_fpscr & DN) == 1) || ((abs == 0x00000000) && (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); } - } else + } + else return(SH4_FPU_DENORM); - } else + } + else if (abs < 0x7ff00000) return(SH4_FPU_NORM); else - if ((abs == 0x7ff00000) && (m_fr[n+1] == 0x00000000)) { + if ((abs == 0x7ff00000) && (m_fr[n + 1] == 0x00000000)) { if (sign_of(n) == 0) return(SH4_FPU_PINF); else return(SH4_FPU_NINF); - } else + } + else if (abs < 0x7ff80000) return(SH4_FPU_qNaN); else @@ -311,35 +276,20 @@ inline uint8_t sh34_base_device::RB(offs_t A) if (A >= 0x80000000) // P1/P2/P3 region { -#if SH4_USE_FASTRAM_OPTIMIZATION - const offs_t _A = A & AM; - for (int ramnum = 0; ramnum < m_fastram_select; ramnum++) - { - if (_A < m_fastram[ramnum].start || _A > m_fastram[ramnum].end) - { - continue; - } - uint8_t *fastbase = (uint8_t*)m_fastram[ramnum].base - m_fastram[ramnum].start; - return fastbase[_A ^ m_byte_xor]; - } - return m_program->read_byte(_A); -#else - return m_program->read_byte(A & AM); -#endif + return m_program->read_byte(A & SH34_AM); } else // P0 region { if (!m_sh4_mmu_enabled) { - return m_program->read_byte(A & AM); + return m_program->read_byte(A & SH34_AM); } else { - A = get_remap(A & AM); + A = get_remap(A & SH34_AM); return m_program->read_byte(A); } } - } inline uint16_t sh34_base_device::RW(offs_t A) @@ -349,35 +299,20 @@ inline uint16_t sh34_base_device::RW(offs_t A) if (A >= 0x80000000) // P1/P2/P3 region { -#if SH4_USE_FASTRAM_OPTIMIZATION - const offs_t _A = A & AM; - for (int ramnum = 0; ramnum < m_fastram_select; ramnum++) - { - if (_A < m_fastram[ramnum].start || _A > m_fastram[ramnum].end) - { - continue; - } - uint8_t *fastbase = (uint8_t*)m_fastram[ramnum].base - m_fastram[ramnum].start; - return ((uint16_t*)fastbase)[(_A ^ m_word_xor) >> 1]; - } - return m_program->read_word(_A); -#else - return m_program->read_word(A & AM); -#endif + return m_program->read_word(A & SH34_AM); } else { if (!m_sh4_mmu_enabled) { - return m_program->read_word(A & AM); + return m_program->read_word(A & SH34_AM); } else { - A = get_remap(A & AM); + A = get_remap(A & SH34_AM); return m_program->read_word(A); } } - } inline uint32_t sh34_base_device::RL(offs_t A) @@ -387,820 +322,136 @@ inline uint32_t sh34_base_device::RL(offs_t A) if (A >= 0x80000000) // P1/P2/P3 region { -#if SH4_USE_FASTRAM_OPTIMIZATION - const offs_t _A = A & AM; - for (int ramnum = 0; ramnum < m_fastram_select; ramnum++) - { - if (_A < m_fastram[ramnum].start || _A > m_fastram[ramnum].end) - { - continue; - } - uint8_t *fastbase = (uint8_t*)m_fastram[ramnum].base - m_fastram[ramnum].start; - return ((uint32_t*)fastbase)[(_A^m_dword_xor) >> 2]; - } - return m_program->read_dword(_A); -#else - return m_program->read_dword(A & AM); -#endif + return m_program->read_dword(A & SH34_AM); } else { if (!m_sh4_mmu_enabled) { - return m_program->read_dword(A & AM); + return m_program->read_dword(A & SH34_AM); } else { - A = get_remap(A & AM); + A = get_remap(A & SH34_AM); return m_program->read_dword(A); } } - } inline void sh34_base_device::WB(offs_t A, uint8_t V) { if (A >= 0xe0000000) { - m_program->write_byte(A,V); + m_program->write_byte(A, V); return; } if (A >= 0x80000000) // P1/P2/P3 region { -#if SH4_USE_FASTRAM_OPTIMIZATION - const offs_t _A = A & AM; - for (int ramnum = 0; ramnum < m_fastram_select; ramnum++) - { - if (m_fastram[ramnum].readonly == true || _A < m_fastram[ramnum].start || _A > m_fastram[ramnum].end) - { - continue; - } - uint8_t *fastbase = (uint8_t*)m_fastram[ramnum].base - m_fastram[ramnum].start; - fastbase[_A ^ m_byte_xor] = V; - return; - } - m_program->write_byte(_A, V); -#else - m_program->write_byte(A & AM, V); -#endif + m_program->write_byte(A & SH34_AM, V); } else { if (!m_sh4_mmu_enabled) { - m_program->write_byte(A & AM, V); + m_program->write_byte(A & SH34_AM, V); } else { - A = get_remap(A & AM); + A = get_remap(A & SH34_AM); m_program->write_byte(A, V); } } - } inline void sh34_base_device::WW(offs_t A, uint16_t V) { if (A >= 0xe0000000) { - m_program->write_word(A,V); + m_program->write_word(A, V); return; } if (A >= 0x80000000) // P1/P2/P3 region { -#if SH4_USE_FASTRAM_OPTIMIZATION - const offs_t _A = A & AM; - for (int ramnum = 0; ramnum < m_fastram_select; ramnum++) - { - if (m_fastram[ramnum].readonly == true || _A < m_fastram[ramnum].start || _A > m_fastram[ramnum].end) - { - continue; - } - void *fastbase = (uint8_t*)m_fastram[ramnum].base - m_fastram[ramnum].start; - ((uint16_t*)fastbase)[(_A ^ m_word_xor) >> 1] = V; - return; - } - m_program->write_word(_A, V); -#else - m_program->write_word(A & AM, V); -#endif + m_program->write_word(A & SH34_AM, V); } else { if (!m_sh4_mmu_enabled) { - m_program->write_word(A & AM, V); + m_program->write_word(A & SH34_AM, V); } else { - A = get_remap(A & AM); + A = get_remap(A & SH34_AM); m_program->write_word(A, V); } } - } inline void sh34_base_device::WL(offs_t A, uint32_t V) { if (A >= 0xe0000000) { - m_program->write_dword(A,V); + m_program->write_dword(A, V); return; } if (A >= 0x80000000) // P1/P2/P3 region { -#if SH4_USE_FASTRAM_OPTIMIZATION - const offs_t _A = A & AM; - for (int ramnum = 0; ramnum < m_fastram_select; ramnum++) - { - if (m_fastram[ramnum].readonly == true || _A < m_fastram[ramnum].start || _A > m_fastram[ramnum].end) - { - continue; - } - void *fastbase = (uint8_t*)m_fastram[ramnum].base - m_fastram[ramnum].start; - ((uint32_t*)fastbase)[(_A ^ m_dword_xor) >> 2] = V; - return; - } - m_program->write_dword(_A, V); -#else - m_program->write_dword(A & AM, V); -#endif + m_program->write_dword(A & SH34_AM, V); } else { if (!m_sh4_mmu_enabled) { - m_program->write_dword(A & AM, V); + m_program->write_dword(A & SH34_AM, V); } else { - A = get_remap(A & AM); + A = get_remap(A & SH34_AM); m_program->write_dword(A, V); } } - -} - -/* code cycles t-bit - * 0011 nnnn mmmm 1100 1 - - * ADD Rm,Rn - */ -inline void sh34_base_device::ADD(const uint16_t opcode) -{ - m_r[Rn] += m_r[Rm]; -} - -/* code cycles t-bit - * 0111 nnnn iiii iiii 1 - - * ADD #imm,Rn - */ -inline void sh34_base_device::ADDI(const uint16_t opcode) -{ - m_r[Rn] += (int32_t)(int16_t)(int8_t)(opcode&0xff); -} - -/* code cycles t-bit - * 0011 nnnn mmmm 1110 1 carry - * ADDC Rm,Rn - */ -inline void sh34_base_device::ADDC(const uint16_t opcode) -{ - uint32_t m = Rm; uint32_t n = Rn; - uint32_t tmp0, tmp1; - - tmp1 = m_r[n] + m_r[m]; - tmp0 = m_r[n]; - m_r[n] = tmp1 + (m_sr & T); - if (tmp0 > tmp1) - m_sr |= T; - else - m_sr &= ~T; - if (tmp1 > m_r[n]) - m_sr |= T; -} - -/* code cycles t-bit - * 0011 nnnn mmmm 1111 1 overflow - * ADDV Rm,Rn - */ -inline void sh34_base_device::ADDV(const uint16_t opcode) -{ - uint32_t m = Rm; uint32_t n = Rn; - int32_t dest, src, ans; - - if ((int32_t) m_r[n] >= 0) - dest = 0; - else - dest = 1; - if ((int32_t) m_r[m] >= 0) - src = 0; - else - src = 1; - src += dest; - m_r[n] += m_r[m]; - if ((int32_t) m_r[n] >= 0) - ans = 0; - else - ans = 1; - ans += dest; - if (src == 0 || src == 2) - { - if (ans == 1) - m_sr |= T; - else - m_sr &= ~T; - } - else - m_sr &= ~T; -} - -/* code cycles t-bit - * 0010 nnnn mmmm 1001 1 - - * AND Rm,Rn - */ -inline void sh34_base_device::AND(const uint16_t opcode) -{ - m_r[Rn] &= m_r[Rm]; -} - - -/* code cycles t-bit - * 1100 1001 iiii iiii 1 - - * AND #imm,R0 - */ -inline void sh34_base_device::ANDI(const uint16_t opcode) -{ - m_r[0] &= (opcode&0xff); -} - -/* code cycles t-bit - * 1100 1101 iiii iiii 1 - - * AND.B #imm,@(R0,GBR) - */ -inline void sh34_base_device::ANDM(const uint16_t opcode) -{ - uint32_t temp; - - m_ea = m_gbr + m_r[0]; - temp = (opcode&0xff) & RB( m_ea ); - WB(m_ea, temp ); - m_sh4_icount -= 2; -} - -/* code cycles t-bit - * 1000 1011 dddd dddd 3/1 - - * BF disp8 - */ -inline void sh34_base_device::BF(const uint16_t opcode) -{ - if ((m_sr & T) == 0) - { - int32_t disp = ((int32_t)(opcode&0xff) << 24) >> 24; - m_pc = m_ea = m_pc + disp * 2 + 2; - m_sh4_icount -= 2; - } -} - -/* code cycles t-bit - * 1000 1111 dddd dddd 3/1 - - * BFS disp8 - */ -inline void sh34_base_device::BFS(const uint16_t opcode) -{ - if ((m_sr & T) == 0) - { - int32_t disp = ((int32_t)(opcode&0xff) << 24) >> 24; - m_delay = m_ea = m_pc + disp * 2 + 2; - m_sh4_icount--; - } -} - -/* code cycles t-bit - * 1010 dddd dddd dddd 2 - - * BRA disp12 - */ -inline void sh34_base_device::BRA(const uint16_t opcode) -{ - int32_t disp = ((int32_t)(opcode&0xfff) << 20) >> 20; - -#if BUSY_LOOP_HACKS - if (disp == -2) - { - uint32_t next_opcode = RW(m_pc & AM); - /* BRA $ - * NOP - */ - if (next_opcode == 0x0009) - m_sh4_icount %= 3; /* cycles for BRA $ and NOP taken (3) */ - } -#endif - m_delay = m_ea = m_pc + disp * 2 + 2; - m_sh4_icount--; -} - -/* code cycles t-bit - * 0000 mmmm 0010 0011 2 - - * BRAF Rm - */ -inline void sh34_base_device::BRAF(const uint16_t opcode) -{ - m_delay = m_pc + m_r[Rn] + 2; - m_sh4_icount--; -} - -/* code cycles t-bit - * 1011 dddd dddd dddd 2 - - * BSR disp12 - */ -inline void sh34_base_device::BSR(const uint16_t opcode) -{ - int32_t disp = ((int32_t)(opcode&0xfff) << 20) >> 20; - - m_pr = m_pc + 2; - m_delay = m_ea = m_pc + disp * 2 + 2; - m_sh4_icount--; -} - -/* code cycles t-bit - * 0000 mmmm 0000 0011 2 - - * BSRF Rm - */ -inline void sh34_base_device::BSRF(const uint16_t opcode) -{ - m_pr = m_pc + 2; - m_delay = m_pc + m_r[Rn] + 2; - m_sh4_icount--; -} - -/* code cycles t-bit - * 1000 1001 dddd dddd 3/1 - - * BT disp8 - */ -inline void sh34_base_device::BT(const uint16_t opcode) -{ - if ((m_sr & T) != 0) - { - int32_t disp = ((int32_t)(opcode&0xff) << 24) >> 24; - m_pc = m_ea = m_pc + disp * 2 + 2; - m_sh4_icount -= 2; - } -} - -/* code cycles t-bit - * 1000 1101 dddd dddd 2/1 - - * BTS disp8 - */ -inline void sh34_base_device::BTS(const uint16_t opcode) -{ - if ((m_sr & T) != 0) - { - int32_t disp = ((int32_t)(opcode&0xff) << 24) >> 24; - m_delay = m_ea = m_pc + disp * 2 + 2; - m_sh4_icount--; - } -} - -/* code cycles t-bit - * 0000 0000 0010 1000 1 - - * CLRMAC - */ -inline void sh34_base_device::CLRMAC(const uint16_t opcode) -{ - m_mach = 0; - m_macl = 0; -} - -/* code cycles t-bit - * 0000 0000 0000 1000 1 - - * CLRT - */ -inline void sh34_base_device::CLRT(const uint16_t opcode) -{ - m_sr &= ~T; -} - -/* code cycles t-bit - * 0011 nnnn mmmm 0000 1 comparison result - * CMP_EQ Rm,Rn - */ -inline void sh34_base_device::CMPEQ(const uint16_t opcode) -{ - if (m_r[Rn] == m_r[Rm]) - m_sr |= T; - else - m_sr &= ~T; -} - -/* code cycles t-bit - * 0011 nnnn mmmm 0011 1 comparison result - * CMP_GE Rm,Rn - */ -inline void sh34_base_device::CMPGE(const uint16_t opcode) -{ - if ((int32_t) m_r[Rn] >= (int32_t) m_r[Rm]) - m_sr |= T; - else - m_sr &= ~T; -} - -/* code cycles t-bit - * 0011 nnnn mmmm 0111 1 comparison result - * CMP_GT Rm,Rn - */ -inline void sh34_base_device::CMPGT(const uint16_t opcode) -{ - if ((int32_t) m_r[Rn] > (int32_t) m_r[Rm]) - m_sr |= T; - else - m_sr &= ~T; -} - -/* code cycles t-bit - * 0011 nnnn mmmm 0110 1 comparison result - * CMP_HI Rm,Rn - */ -inline void sh34_base_device::CMPHI(const uint16_t opcode) -{ - if ((uint32_t) m_r[Rn] > (uint32_t) m_r[Rm]) - m_sr |= T; - else - m_sr &= ~T; -} - -/* code cycles t-bit - * 0011 nnnn mmmm 0010 1 comparison result - * CMP_HS Rm,Rn - */ -inline void sh34_base_device::CMPHS(const uint16_t opcode) -{ - if ((uint32_t) m_r[Rn] >= (uint32_t) m_r[Rm]) - m_sr |= T; - else - m_sr &= ~T; -} - - -/* code cycles t-bit - * 0100 nnnn 0001 0101 1 comparison result - * CMP_PL Rn - */ -inline void sh34_base_device::CMPPL(const uint16_t opcode) -{ - if ((int32_t) m_r[Rn] > 0) - m_sr |= T; - else - m_sr &= ~T; -} - -/* code cycles t-bit - * 0100 nnnn 0001 0001 1 comparison result - * CMP_PZ Rn - */ -inline void sh34_base_device::CMPPZ(const uint16_t opcode) -{ - if ((int32_t) m_r[Rn] >= 0) - m_sr |= T; - else - m_sr &= ~T; -} - -/* code cycles t-bit - * 0010 nnnn mmmm 1100 1 comparison result - * CMP_STR Rm,Rn - */ -inline void sh34_base_device::CMPSTR(const uint16_t opcode) -{ - uint32_t temp; - int32_t HH, HL, LH, LL; - temp = m_r[Rn] ^ m_r[Rm]; - HH = (temp >> 24) & 0xff; - HL = (temp >> 16) & 0xff; - LH = (temp >> 8) & 0xff; - LL = temp & 0xff; - if (HH && HL && LH && LL) - m_sr &= ~T; - else - m_sr |= T; - } - - -/* code cycles t-bit - * 1000 1000 iiii iiii 1 comparison result - * CMP/EQ #imm,R0 - */ -inline void sh34_base_device::CMPIM(const uint16_t opcode) -{ - uint32_t imm = (uint32_t)(int32_t)(int16_t)(int8_t)(opcode&0xff); - - if (m_r[0] == imm) - m_sr |= T; - else - m_sr &= ~T; -} - -/* code cycles t-bit - * 0010 nnnn mmmm 0111 1 calculation result - * DIV0S Rm,Rn - */ -inline void sh34_base_device::DIV0S(const uint16_t opcode) -{ - uint32_t m = Rm; uint32_t n = Rn; - - if ((m_r[n] & 0x80000000) == 0) - m_sr &= ~Q; - else - m_sr |= Q; - if ((m_r[m] & 0x80000000) == 0) - m_sr &= ~M; - else - m_sr |= M; - if ((m_r[m] ^ m_r[n]) & 0x80000000) - m_sr |= T; - else - m_sr &= ~T; -} - -/* code cycles t-bit - * 0000 0000 0001 1001 1 0 - * DIV0U - */ -inline void sh34_base_device::DIV0U(const uint16_t opcode) -{ - m_sr &= ~(M | Q | T); -} - -/* code cycles t-bit - * 0011 nnnn mmmm 0100 1 calculation result - * DIV1 Rm,Rn - */ -inline void sh34_base_device::DIV1(const uint16_t opcode) -{ - uint32_t m = Rm; uint32_t n = Rn; - - uint32_t tmp0; - uint32_t old_q; - - old_q = m_sr & Q; - if (0x80000000 & m_r[n]) - m_sr |= Q; - else - m_sr &= ~Q; - - m_r[n] = (m_r[n] << 1) | (m_sr & T); - - if (!old_q) - { - if (!(m_sr & M)) - { - tmp0 = m_r[n]; - m_r[n] -= m_r[m]; - if(!(m_sr & Q)) - if(m_r[n] > tmp0) - m_sr |= Q; - else - m_sr &= ~Q; - else - if(m_r[n] > tmp0) - m_sr &= ~Q; - else - m_sr |= Q; - } - else - { - tmp0 = m_r[n]; - m_r[n] += m_r[m]; - if(!(m_sr & Q)) - { - if(m_r[n] < tmp0) - m_sr &= ~Q; - else - m_sr |= Q; - } - else - { - if(m_r[n] < tmp0) - m_sr |= Q; - else - m_sr &= ~Q; - } - } - } - else - { - if (!(m_sr & M)) - { - tmp0 = m_r[n]; - m_r[n] += m_r[m]; - if(!(m_sr & Q)) - if(m_r[n] < tmp0) - m_sr |= Q; - else - m_sr &= ~Q; - else - if(m_r[n] < tmp0) - m_sr &= ~Q; - else - m_sr |= Q; - } - else - { - tmp0 = m_r[n]; - m_r[n] -= m_r[m]; - if(!(m_sr & Q)) - if(m_r[n] > tmp0) - m_sr &= ~Q; - else - m_sr |= Q; - else - if(m_r[n] > tmp0) - m_sr |= Q; - else - m_sr &= ~Q; - } - } - - tmp0 = (m_sr & (Q | M)); - if((!tmp0) || (tmp0 == 0x300)) /* if Q == M set T else clear T */ - m_sr |= T; - else - m_sr &= ~T; } -/* DMULS.L Rm,Rn */ -inline void sh34_base_device::DMULS(const uint16_t opcode) +inline void sh34_base_device::ILLEGAL() { - uint32_t m = Rm; uint32_t n = Rn; - - uint32_t RnL, RnH, RmL, RmH, Res0, Res1, Res2; - uint32_t temp0, temp1, temp2, temp3; - int32_t tempm, tempn, fnLmL; - - tempn = (int32_t) m_r[n]; - tempm = (int32_t) m_r[m]; - if (tempn < 0) - tempn = 0 - tempn; - if (tempm < 0) - tempm = 0 - tempm; - if ((int32_t) (m_r[n] ^ m_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) - { - Res2 = ~Res2; - if (Res0 == 0) - Res2++; - else - Res0 = (~Res0) + 1; - } - m_mach = Res2; - m_macl = Res0; - m_sh4_icount--; + NOP(); } -/* DMULU.L Rm,Rn */ -inline void sh34_base_device::DMULU(const uint16_t opcode) -{ - uint32_t m = Rm; uint32_t n = Rn; - - uint32_t RnL, RnH, RmL, RmH, Res0, Res1, Res2; - uint32_t temp0, temp1, temp2, temp3; - - RnL = m_r[n] & 0x0000ffff; - RnH = (m_r[n] >> 16) & 0x0000ffff; - RmL = m_r[m] & 0x0000ffff; - RmH = (m_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_mach = Res2; - m_macl = Res0; - m_sh4_icount--; -} - -/* DT Rn */ -inline void sh34_base_device::DT(const uint16_t opcode) -{ - uint32_t n = Rn; - - m_r[n]--; - if (m_r[n] == 0) - m_sr |= T; - else - m_sr &= ~T; -#if BUSY_LOOP_HACKS - { - uint32_t next_opcode = RW(m_pc & AM); - /* DT Rn - * BF $-2 - */ - if (next_opcode == 0x8bfd) - { - while (m_r[n] > 1 && m_sh4_icount > 4) - { - m_r[n]--; - m_sh4_icount -= 4; /* cycles for DT (1) and BF taken (3) */ - } - } - } -#endif -} - -/* EXTS.B Rm,Rn */ -inline void sh34_base_device::EXTSB(const uint16_t opcode) -{ - m_r[Rn] = ((int32_t)m_r[Rm] << 24) >> 24; -} - -/* EXTS.W Rm,Rn */ -inline void sh34_base_device::EXTSW(const uint16_t opcode) -{ - m_r[Rn] = ((int32_t)m_r[Rm] << 16) >> 16; -} - -/* EXTU.B Rm,Rn */ -inline void sh34_base_device::EXTUB(const uint16_t opcode) -{ - m_r[Rn] = m_r[Rm] & 0x000000ff; -} - -/* EXTU.W Rm,Rn */ -inline void sh34_base_device::EXTUW(const uint16_t opcode) +/* MOVCA.L R0,@Rn */ +inline void sh34_base_device::MOVCAL(const uint16_t opcode) { - m_r[Rn] = m_r[Rm] & 0x0000ffff; + m_sh2_state->ea = m_sh2_state->r[Rn]; + WL(m_sh2_state->ea, m_sh2_state->r[0]); } -/* JMP @Rm */ -inline void sh34_base_device::JMP(const uint16_t opcode) +inline void sh34_base_device::CLRS(const uint16_t opcode) { - m_delay = m_ea = m_r[Rn]; + m_sh2_state->sr &= ~SH_S; } -/* JSR @Rm */ -inline void sh34_base_device::JSR(const uint16_t opcode) +inline void sh34_base_device::SETS(const uint16_t opcode) { - m_pr = m_pc + 2; - m_delay = m_ea = m_r[Rn]; - m_sh4_icount--; + m_sh2_state->sr |= SH_S; } - /* LDC Rm,SR */ inline void sh34_base_device::LDCSR(const uint16_t opcode) { - uint32_t reg; + // 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]; - reg = m_r[Rn]; if ((machine().debug_flags & DEBUG_FLAG_ENABLED) != 0) - sh4_syncronize_register_bank((m_sr & sRB) >> 29); - if ((m_r[Rn] & sRB) != (m_sr & sRB)) - sh4_change_register_bank(m_r[Rn] & sRB ? 1 : 0); - m_sr = reg & FLAGS; - sh4_exception_recompute(); -} + sh4_syncronize_register_bank((m_sh2_state->sr & sRB) >> 29); -/* LDC Rm,GBR */ -inline void sh34_base_device::LDCGBR(const uint16_t opcode) -{ - m_gbr = m_r[Rn]; -} + if ((m_sh2_state->r[Rn] & sRB) != (m_sh2_state->sr & sRB)) + sh4_change_register_bank(m_sh2_state->r[Rn] & sRB ? 1 : 0); -/* LDC Rm,VBR */ -inline void sh34_base_device::LDCVBR(const uint16_t opcode) -{ - m_vbr = m_r[Rn]; + m_sh2_state->sr = reg & SH34_FLAGS; + sh4_exception_recompute(); } /* LDC.L @Rm+,SR */ @@ -1208,924 +459,37 @@ inline void sh34_base_device::LDCMSR(const uint16_t opcode) { uint32_t old; - old = m_sr; - m_ea = m_r[Rn]; - m_sr = RL(m_ea ) & FLAGS; + 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) sh4_syncronize_register_bank((old & sRB) >> 29); - if ((old & sRB) != (m_sr & sRB)) - sh4_change_register_bank(m_sr & sRB ? 1 : 0); - m_r[Rn] += 4; - m_sh4_icount -= 2; + 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->icount -= 2; sh4_exception_recompute(); } -/* LDC.L @Rm+,GBR */ -inline void sh34_base_device::LDCMGBR(const uint16_t opcode) -{ - m_ea = m_r[Rn]; - m_gbr = RL(m_ea ); - m_r[Rn] += 4; - m_sh4_icount -= 2; -} - -/* LDC.L @Rm+,VBR */ -inline void sh34_base_device::LDCMVBR(const uint16_t opcode) -{ - m_ea = m_r[Rn]; - m_vbr = RL(m_ea ); - m_r[Rn] += 4; - m_sh4_icount -= 2; -} - -/* LDS Rm,MACH */ -inline void sh34_base_device::LDSMACH(const uint16_t opcode) -{ - m_mach = m_r[Rn]; -} - -/* LDS Rm,MACL */ -inline void sh34_base_device::LDSMACL(const uint16_t opcode) -{ - m_macl = m_r[Rn]; -} - -/* LDS Rm,PR */ -inline void sh34_base_device::LDSPR(const uint16_t opcode) -{ - m_pr = m_r[Rn]; -} - -/* LDS.L @Rm+,MACH */ -inline void sh34_base_device::LDSMMACH(const uint16_t opcode) -{ - m_ea = m_r[Rn]; - m_mach = RL(m_ea ); - m_r[Rn] += 4; -} - -/* LDS.L @Rm+,MACL */ -inline void sh34_base_device::LDSMMACL(const uint16_t opcode) -{ - m_ea = m_r[Rn]; - m_macl = RL(m_ea ); - m_r[Rn] += 4; -} - -/* LDS.L @Rm+,PR */ -inline void sh34_base_device::LDSMPR(const uint16_t opcode) -{ - m_ea = m_r[Rn]; - m_pr = RL(m_ea ); - m_r[Rn] += 4; -} - -/* MAC.L @Rm+,@Rn+ */ -inline void sh34_base_device::MAC_L(const uint16_t opcode) -{ - uint32_t m = Rm; uint32_t n = Rn; - - 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_r[n] ); - m_r[n] += 4; - tempm = (int32_t) RL(m_r[m] ); - m_r[m] += 4; - if ((int32_t) (tempn ^ tempm) < 0) - fnLmL = -1; - else - fnLmL = 0; - 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) - { - Res2 = ~Res2; - if (Res0 == 0) - Res2++; - else - Res0 = (~Res0) + 1; - } - if (m_sr & S) - { - Res0 = m_macl + Res0; - if (m_macl > Res0) - Res2++; - Res2 += (m_mach & 0x0000ffff); - if (((int32_t) Res2 < 0) && (Res2 < 0xffff8000)) - { - Res2 = 0x00008000; - Res0 = 0x00000000; - } - else if (((int32_t) Res2 > 0) && (Res2 > 0x00007fff)) - { - Res2 = 0x00007fff; - Res0 = 0xffffffff; - } - m_mach = Res2; - m_macl = Res0; - } - else - { - Res0 = m_macl + Res0; - if (m_macl > Res0) - Res2++; - Res2 += m_mach; - m_mach = Res2; - m_macl = Res0; - } - m_sh4_icount -= 2; -} - -/* MAC.W @Rm+,@Rn+ */ -inline void sh34_base_device::MAC_W(const uint16_t opcode) -{ - uint32_t m = Rm; uint32_t n = Rn; - - int32_t tempm, tempn, dest, src, ans; - uint32_t templ; - - tempn = (int32_t) RW(m_r[n] ); - m_r[n] += 2; - tempm = (int32_t) RW(m_r[m] ); - m_r[m] += 2; - templ = m_macl; - tempm = ((int32_t) (short) tempn * (int32_t) (short) tempm); - if ((int32_t) m_macl >= 0) - dest = 0; - else - dest = 1; - if ((int32_t) tempm >= 0) - { - src = 0; - tempn = 0; - } - else - { - src = 1; - tempn = 0xffffffff; - } - src += dest; - m_macl += tempm; - if ((int32_t) m_macl >= 0) - ans = 0; - else - ans = 1; - ans += dest; - if (m_sr & S) - { - if (ans == 1) - { - if (src == 0) - m_macl = 0x7fffffff; - if (src == 2) - m_macl = 0x80000000; - } - } - else - { - m_mach += tempn; - if (templ > m_macl) - m_mach += 1; - } - m_sh4_icount -= 2; -} - -/* MOV Rm,Rn */ -inline void sh34_base_device::MOV(const uint16_t opcode) -{ - m_r[Rn] = m_r[Rm]; -} - -/* MOV.B Rm,@Rn */ -inline void sh34_base_device::MOVBS(const uint16_t opcode) -{ - m_ea = m_r[Rn]; - WB(m_ea, m_r[Rm] & 0x000000ff); -} - -/* MOV.W Rm,@Rn */ -inline void sh34_base_device::MOVWS(const uint16_t opcode) -{ - m_ea = m_r[Rn]; - WW(m_ea, m_r[Rm] & 0x0000ffff); -} - -/* MOV.L Rm,@Rn */ -inline void sh34_base_device::MOVLS(const uint16_t opcode) -{ - m_ea = m_r[Rn]; - WL(m_ea, m_r[Rm] ); -} - -/* MOV.B @Rm,Rn */ -inline void sh34_base_device::MOVBL(const uint16_t opcode) -{ - m_ea = m_r[Rm]; - m_r[Rn] = (uint32_t)(int32_t)(int16_t)(int8_t) RB( m_ea ); -} - -/* MOV.W @Rm,Rn */ -inline void sh34_base_device::MOVWL(const uint16_t opcode) -{ - m_ea = m_r[Rm]; - m_r[Rn] = (uint32_t)(int32_t)(int16_t) RW(m_ea ); -} - -/* MOV.L @Rm,Rn */ -inline void sh34_base_device::MOVLL(const uint16_t opcode) -{ - m_ea = m_r[Rm]; - m_r[Rn] = RL(m_ea ); -} - -/* MOV.B Rm,@-Rn */ -inline void sh34_base_device::MOVBM(const uint16_t opcode) -{ - uint32_t data = m_r[Rm] & 0x000000ff; - - m_r[Rn] -= 1; - WB(m_r[Rn], data ); -} - -/* MOV.W Rm,@-Rn */ -inline void sh34_base_device::MOVWM(const uint16_t opcode) -{ - uint32_t data = m_r[Rm] & 0x0000ffff; - - m_r[Rn] -= 2; - WW(m_r[Rn], data ); -} - -/* MOV.L Rm,@-Rn */ -inline void sh34_base_device::MOVLM(const uint16_t opcode) -{ - uint32_t data = m_r[Rm]; - - m_r[Rn] -= 4; - WL(m_r[Rn], data ); -} - -/* MOV.B @Rm+,Rn */ -inline void sh34_base_device::MOVBP(const uint16_t opcode) -{ - uint32_t m = Rm; uint32_t n = Rn; - - m_r[n] = (uint32_t)(int32_t)(int16_t)(int8_t) RB( m_r[m] ); - if (n != m) - m_r[m] += 1; -} - -/* MOV.W @Rm+,Rn */ -inline void sh34_base_device::MOVWP(const uint16_t opcode) -{ - uint32_t m = Rm; uint32_t n = Rn; - - m_r[n] = (uint32_t)(int32_t)(int16_t) RW(m_r[m] ); - if (n != m) - m_r[m] += 2; -} - -/* MOV.L @Rm+,Rn */ -inline void sh34_base_device::MOVLP(const uint16_t opcode) -{ - uint32_t m = Rm; uint32_t n = Rn; - - m_r[n] = RL(m_r[m] ); - if (n != m) - m_r[m] += 4; -} - -/* MOV.B Rm,@(R0,Rn) */ -inline void sh34_base_device::MOVBS0(const uint16_t opcode) -{ - m_ea = m_r[Rn] + m_r[0]; - WB(m_ea, m_r[Rm] & 0x000000ff ); -} - -/* MOV.W Rm,@(R0,Rn) */ -inline void sh34_base_device::MOVWS0(const uint16_t opcode) -{ - m_ea = m_r[Rn] + m_r[0]; - WW(m_ea, m_r[Rm] & 0x0000ffff ); -} - -/* MOV.L Rm,@(R0,Rn) */ -inline void sh34_base_device::MOVLS0(const uint16_t opcode) -{ - m_ea = m_r[Rn] + m_r[0]; - WL(m_ea, m_r[Rm] ); -} - -/* MOV.B @(R0,Rm),Rn */ -inline void sh34_base_device::MOVBL0(const uint16_t opcode) -{ - m_ea = m_r[Rm] + m_r[0]; - m_r[Rn] = (uint32_t)(int32_t)(int16_t)(int8_t) RB( m_ea ); -} - -/* MOV.W @(R0,Rm),Rn */ -inline void sh34_base_device::MOVWL0(const uint16_t opcode) -{ - m_ea = m_r[Rm] + m_r[0]; - m_r[Rn] = (uint32_t)(int32_t)(int16_t) RW(m_ea ); -} - -/* MOV.L @(R0,Rm),Rn */ -inline void sh34_base_device::MOVLL0(const uint16_t opcode) -{ - m_ea = m_r[Rm] + m_r[0]; - m_r[Rn] = RL(m_ea ); -} - -/* MOV #imm,Rn */ -inline void sh34_base_device::MOVI(const uint16_t opcode) -{ - m_r[Rn] = (uint32_t)(int32_t)(int16_t)(int8_t)(opcode&0xff); -} - -/* MOV.W @(disp8,PC),Rn */ -inline void sh34_base_device::MOVWI(const uint16_t opcode) -{ - uint32_t disp = opcode & 0xff; - m_ea = m_pc + disp * 2 + 2; - m_r[Rn] = (uint32_t)(int32_t)(int16_t) RW(m_ea ); -} - -/* MOV.L @(disp8,PC),Rn */ -inline void sh34_base_device::MOVLI(const uint16_t opcode) -{ - uint32_t disp = opcode & 0xff; - m_ea = ((m_pc + 2) & ~3) + disp * 4; - m_r[Rn] = RL(m_ea ); -} - -/* MOV.B @(disp8,GBR),R0 */ -inline void sh34_base_device::MOVBLG(const uint16_t opcode) -{ - uint32_t disp = opcode & 0xff; - m_ea = m_gbr + disp; - m_r[0] = (uint32_t)(int32_t)(int16_t)(int8_t) RB( m_ea ); -} - -/* MOV.W @(disp8,GBR),R0 */ -inline void sh34_base_device::MOVWLG(const uint16_t opcode) -{ - uint32_t disp = opcode & 0xff; - m_ea = m_gbr + disp * 2; - m_r[0] = (int32_t)(int16_t) RW(m_ea ); -} - -/* MOV.L @(disp8,GBR),R0 */ -inline void sh34_base_device::MOVLLG(const uint16_t opcode) -{ - uint32_t disp = opcode & 0xff; - m_ea = m_gbr + disp * 4; - m_r[0] = RL(m_ea ); -} - -/* MOV.B R0,@(disp8,GBR) */ -inline void sh34_base_device::MOVBSG(const uint16_t opcode) -{ - uint32_t disp = opcode & 0xff; - m_ea = m_gbr + disp; - WB(m_ea, m_r[0] & 0x000000ff ); -} - -/* MOV.W R0,@(disp8,GBR) */ -inline void sh34_base_device::MOVWSG(const uint16_t opcode) -{ - uint32_t disp = opcode & 0xff; - m_ea = m_gbr + disp * 2; - WW(m_ea, m_r[0] & 0x0000ffff ); -} - -/* MOV.L R0,@(disp8,GBR) */ -inline void sh34_base_device::MOVLSG(const uint16_t opcode) -{ - uint32_t disp = opcode & 0xff; - m_ea = m_gbr + disp * 4; - WL(m_ea, m_r[0] ); -} - -/* MOV.B R0,@(disp4,Rm) */ -inline void sh34_base_device::MOVBS4(const uint16_t opcode) -{ - uint32_t disp = opcode & 0x0f; - m_ea = m_r[Rm] + disp; - WB(m_ea, m_r[0] & 0x000000ff ); -} - -/* MOV.W R0,@(disp4,Rm) */ -inline void sh34_base_device::MOVWS4(const uint16_t opcode) -{ - uint32_t disp = opcode & 0x0f; - m_ea = m_r[Rm] + disp * 2; - WW(m_ea, m_r[0] & 0x0000ffff ); -} - -/* MOV.L Rm,@(disp4,Rn) */ -inline void sh34_base_device::MOVLS4(const uint16_t opcode) -{ - uint32_t disp = opcode & 0x0f; - m_ea = m_r[Rn] + disp * 4; - WL(m_ea, m_r[Rm] ); -} - -/* MOV.B @(disp4,Rm),R0 */ -inline void sh34_base_device::MOVBL4(const uint16_t opcode) -{ - uint32_t disp = opcode & 0x0f; - m_ea = m_r[Rm] + disp; - m_r[0] = (uint32_t)(int32_t)(int16_t)(int8_t) RB( m_ea ); -} - -/* MOV.W @(disp4,Rm),R0 */ -inline void sh34_base_device::MOVWL4(const uint16_t opcode) -{ - uint32_t disp = opcode & 0x0f; - m_ea = m_r[Rm] + disp * 2; - m_r[0] = (uint32_t)(int32_t)(int16_t) RW(m_ea ); -} - -/* MOV.L @(disp4,Rm),Rn */ -inline void sh34_base_device::MOVLL4(const uint16_t opcode) -{ - uint32_t disp = opcode & 0x0f; - m_ea = m_r[Rm] + disp * 4; - m_r[Rn] = RL(m_ea ); -} - -/* MOVA @(disp8,PC),R0 */ -inline void sh34_base_device::MOVA(const uint16_t opcode) -{ - uint32_t disp = opcode & 0xff; - m_ea = ((m_pc + 2) & ~3) + disp * 4; - m_r[0] = m_ea; -} - -/* MOVT Rn */ -void sh34_base_device::MOVT(const uint16_t opcode) -{ - m_r[Rn] = m_sr & T; -} - -/* MUL.L Rm,Rn */ -inline void sh34_base_device::MULL(const uint16_t opcode) -{ - m_macl = m_r[Rn] * m_r[Rm]; - m_sh4_icount--; -} - -/* MULS Rm,Rn */ -inline void sh34_base_device::MULS(const uint16_t opcode) -{ - m_macl = (int16_t) m_r[Rn] * (int16_t) m_r[Rm]; -} - -/* MULU Rm,Rn */ -inline void sh34_base_device::MULU(const uint16_t opcode) -{ - m_macl = (uint16_t) m_r[Rn] * (uint16_t) m_r[Rm]; -} - -/* NEG Rm,Rn */ -inline void sh34_base_device::NEG(const uint16_t opcode) -{ - m_r[Rn] = 0 - m_r[Rm]; -} - -/* NEGC Rm,Rn */ -inline void sh34_base_device::NEGC(const uint16_t opcode) -{ - uint32_t temp; - - temp = m_r[Rm]; - m_r[Rn] = -temp - (m_sr & T); - if (temp || (m_sr & T)) - m_sr |= T; - else - m_sr &= ~T; -} - -/* NOP */ -inline void sh34_base_device::NOP(const uint16_t opcode) -{ -} - -/* NOT Rm,Rn */ -inline void sh34_base_device::NOT(const uint16_t opcode) -{ - m_r[Rn] = ~m_r[Rm]; -} - -/* OR Rm,Rn */ -inline void sh34_base_device::OR(const uint16_t opcode) -{ - m_r[Rn] |= m_r[Rm]; -} - -/* OR #imm,R0 */ -inline void sh34_base_device::ORI(const uint16_t opcode) -{ - m_r[0] |= (opcode&0xff); - m_sh4_icount -= 2; -} - -/* OR.B #imm,@(R0,GBR) */ -inline void sh34_base_device::ORM(const uint16_t opcode) -{ - uint32_t temp; - - m_ea = m_gbr + m_r[0]; - temp = RB( m_ea ); - temp |= (opcode&0xff); - WB(m_ea, temp ); -} - -/* ROTCL Rn */ -inline void sh34_base_device::ROTCL(const uint16_t opcode) -{ - uint32_t n = Rn; - - uint32_t temp; - - temp = (m_r[n] >> 31) & T; - m_r[n] = (m_r[n] << 1) | (m_sr & T); - m_sr = (m_sr & ~T) | temp; -} - -/* ROTCR Rn */ -inline void sh34_base_device::ROTCR(const uint16_t opcode) -{ - uint32_t n = Rn; - - uint32_t temp; - temp = (m_sr & T) << 31; - if (m_r[n] & T) - m_sr |= T; - else - m_sr &= ~T; - m_r[n] = (m_r[n] >> 1) | temp; -} - -/* ROTL Rn */ -inline void sh34_base_device::ROTL(const uint16_t opcode) -{ - uint32_t n = Rn; - - m_sr = (m_sr & ~T) | ((m_r[n] >> 31) & T); - m_r[n] = (m_r[n] << 1) | (m_r[n] >> 31); -} - -/* ROTR Rn */ -inline void sh34_base_device::ROTR(const uint16_t opcode) -{ - uint32_t n = Rn; - - m_sr = (m_sr & ~T) | (m_r[n] & T); - m_r[n] = (m_r[n] >> 1) | (m_r[n] << 31); -} - /* RTE */ -inline void sh34_base_device::RTE(const uint16_t opcode) +inline void sh34_base_device::RTE() { - m_delay = m_ea = m_spc; + m_sh2_state->m_delay = m_sh2_state->ea = m_spc; + if ((machine().debug_flags & DEBUG_FLAG_ENABLED) != 0) - sh4_syncronize_register_bank((m_sr & sRB) >> 29); - if ((m_ssr & sRB) != (m_sr & sRB)) + sh4_syncronize_register_bank((m_sh2_state->sr & sRB) >> 29); + if ((m_ssr & sRB) != (m_sh2_state->sr & sRB)) sh4_change_register_bank(m_ssr & sRB ? 1 : 0); - m_sr = m_ssr; - m_sh4_icount--; - sh4_exception_recompute(); -} - -/* RTS */ -inline void sh34_base_device::RTS(const uint16_t opcode) -{ - m_delay = m_ea = m_pr; - m_sh4_icount--; -} - -/* SETT */ -inline void sh34_base_device::SETT(const uint16_t opcode) -{ - m_sr |= T; -} - -/* SHAL Rn (same as SHLL) */ -inline void sh34_base_device::SHAL(const uint16_t opcode) -{ - uint32_t n = Rn; - - m_sr = (m_sr & ~T) | ((m_r[n] >> 31) & T); - m_r[n] <<= 1; -} - -/* SHAR Rn */ -inline void sh34_base_device::SHAR(const uint16_t opcode) -{ - uint32_t n = Rn; - - m_sr = (m_sr & ~T) | (m_r[n] & T); - m_r[n] = (uint32_t)((int32_t)m_r[n] >> 1); -} - -/* SHLL Rn (same as SHAL) */ -inline void sh34_base_device::SHLL(const uint16_t opcode) -{ - uint32_t n = Rn; - - m_sr = (m_sr & ~T) | ((m_r[n] >> 31) & T); - m_r[n] <<= 1; -} - -/* SHLL2 Rn */ -inline void sh34_base_device::SHLL2(const uint16_t opcode) -{ - m_r[Rn] <<= 2; -} - -/* SHLL8 Rn */ -inline void sh34_base_device::SHLL8(const uint16_t opcode) -{ - m_r[Rn] <<= 8; -} - -/* SHLL16 Rn */ -inline void sh34_base_device::SHLL16(const uint16_t opcode) -{ - m_r[Rn] <<= 16; -} - -/* SHLR Rn */ -inline void sh34_base_device::SHLR(const uint16_t opcode) -{ - uint32_t n = Rn; - - m_sr = (m_sr & ~T) | (m_r[n] & T); - m_r[n] >>= 1; -} - -/* SHLR2 Rn */ -inline void sh34_base_device::SHLR2(const uint16_t opcode) -{ - m_r[Rn] >>= 2; -} - -/* SHLR8 Rn */ -inline void sh34_base_device::SHLR8(const uint16_t opcode) -{ - m_r[Rn] >>= 8; -} - -/* SHLR16 Rn */ -inline void sh34_base_device::SHLR16(const uint16_t opcode) -{ - m_r[Rn] >>= 16; -} - -/* SLEEP */ -inline void sh34_base_device::SLEEP(const uint16_t opcode) -{ - /* 0 = normal mode */ - /* 1 = enters into power-down mode */ - /* 2 = go out the power-down mode after an exception */ - if(m_sleep_mode != 2) - m_pc -= 2; - m_sh4_icount -= 2; - /* Wait_for_exception; */ - if(m_sleep_mode == 0) - m_sleep_mode = 1; - else if(m_sleep_mode == 2) - m_sleep_mode = 0; -} - -/* STC SR,Rn */ -inline void sh34_base_device::STCSR(const uint16_t opcode) -{ - m_r[Rn] = m_sr; -} - -/* STC GBR,Rn */ -inline void sh34_base_device::STCGBR(const uint16_t opcode) -{ - m_r[Rn] = m_gbr; -} - -/* STC VBR,Rn */ -inline void sh34_base_device::STCVBR(const uint16_t opcode) -{ - m_r[Rn] = m_vbr; -} - -/* STC.L SR,@-Rn */ -inline void sh34_base_device::STCMSR(const uint16_t opcode) -{ - uint32_t n = Rn; - - m_r[n] -= 4; - m_ea = m_r[n]; - WL(m_ea, m_sr ); - m_sh4_icount--; -} - -/* STC.L GBR,@-Rn */ -inline void sh34_base_device::STCMGBR(const uint16_t opcode) -{ - uint32_t n = Rn; - - m_r[n] -= 4; - m_ea = m_r[n]; - WL(m_ea, m_gbr ); - m_sh4_icount--; -} - -/* STC.L VBR,@-Rn */ -inline void sh34_base_device::STCMVBR(const uint16_t opcode) -{ - uint32_t n = Rn; - - m_r[n] -= 4; - m_ea = m_r[n]; - WL(m_ea, m_vbr ); - m_sh4_icount--; -} - -/* STS MACH,Rn */ -inline void sh34_base_device::STSMACH(const uint16_t opcode) -{ - m_r[Rn] = m_mach; -} - -/* STS MACL,Rn */ -inline void sh34_base_device::STSMACL(const uint16_t opcode) -{ - m_r[Rn] = m_macl; -} - -/* STS PR,Rn */ -inline void sh34_base_device::STSPR(const uint16_t opcode) -{ - m_r[Rn] = m_pr; -} - -/* STS.L MACH,@-Rn */ -inline void sh34_base_device::STSMMACH(const uint16_t opcode) -{ - uint32_t n = Rn; - - m_r[n] -= 4; - m_ea = m_r[n]; - WL(m_ea, m_mach ); -} - -/* STS.L MACL,@-Rn */ -inline void sh34_base_device::STSMMACL(const uint16_t opcode) -{ - uint32_t n = Rn; - - m_r[n] -= 4; - m_ea = m_r[n]; - WL(m_ea, m_macl ); -} - -/* STS.L PR,@-Rn */ -inline void sh34_base_device::STSMPR(const uint16_t opcode) -{ - uint32_t n = Rn; - - m_r[n] -= 4; - m_ea = m_r[n]; - WL(m_ea, m_pr ); -} - -/* SUB Rm,Rn */ -inline void sh34_base_device::SUB(const uint16_t opcode) -{ - m_r[Rn] -= m_r[Rm]; -} - -/* SUBC Rm,Rn */ -inline void sh34_base_device::SUBC(const uint16_t opcode) -{ - uint32_t m = Rm; uint32_t n = Rn; - - uint32_t tmp0, tmp1; - - tmp1 = m_r[n] - m_r[m]; - tmp0 = m_r[n]; - m_r[n] = tmp1 - (m_sr & T); - if (tmp0 < tmp1) - m_sr |= T; - else - m_sr &= ~T; - if (tmp1 < m_r[n]) - m_sr |= T; -} - -/* SUBV Rm,Rn */ -inline void sh34_base_device::SUBV(const uint16_t opcode) -{ - uint32_t m = Rm; uint32_t n = Rn; - - int32_t dest, src, ans; - - if ((int32_t) m_r[n] >= 0) - dest = 0; - else - dest = 1; - if ((int32_t) m_r[m] >= 0) - src = 0; - else - src = 1; - src += dest; - m_r[n] -= m_r[m]; - if ((int32_t) m_r[n] >= 0) - ans = 0; - else - ans = 1; - ans += dest; - if (src == 1) - { - if (ans == 1) - m_sr |= T; - else - m_sr &= ~T; - } - else - m_sr &= ~T; -} - -/* SWAP.B Rm,Rn */ -inline void sh34_base_device::SWAPB(const uint16_t opcode) -{ - uint32_t m = Rm; uint32_t n = Rn; - - uint32_t temp0, temp1; - - temp0 = m_r[m] & 0xffff0000; - temp1 = (m_r[m] & 0x000000ff) << 8; - m_r[n] = (m_r[m] >> 8) & 0x000000ff; - m_r[n] = m_r[n] | temp1 | temp0; -} - -/* SWAP.W Rm,Rn */ -inline void sh34_base_device::SWAPW(const uint16_t opcode) -{ - uint32_t m = Rm; uint32_t n = Rn; - - uint32_t temp; - temp = (m_r[m] >> 16) & 0x0000ffff; - m_r[n] = (m_r[m] << 16) | temp; -} - -/* TAS.B @Rn */ -inline void sh34_base_device::TAS(const uint16_t opcode) -{ - uint32_t n = Rn; - - uint32_t temp; - m_ea = m_r[n]; - /* Bus Lock enable */ - temp = RB( m_ea ); - if (temp == 0) - m_sr |= T; - else - m_sr &= ~T; - temp |= 0x80; - /* Bus Lock disable */ - WB(m_ea, temp ); - m_sh4_icount -= 3; + m_sh2_state->sr = m_ssr; + m_sh2_state->icount--; + sh4_exception_recompute(); } /* TRAPA #imm */ -inline void sh34_base_device::TRAPA(const uint16_t opcode) +inline void sh34_base_device::TRAPA(uint32_t i) { - uint32_t imm = opcode & 0xff; + uint32_t imm = i & 0xff; if (m_cpu_type == CPU_TYPE_SH4) { @@ -2136,18 +500,18 @@ inline void sh34_base_device::TRAPA(const uint16_t opcode) m_sh3internal_upper[SH3_TRA_ADDR] = imm << 2; } + m_ssr = m_sh2_state->sr; + m_spc = m_sh2_state->pc; - m_ssr = m_sr; - m_spc = m_pc; - m_sgr = m_r[15]; + m_sgr = m_sh2_state->r[15]; - m_sr |= MD; + m_sh2_state->sr |= MD; if ((machine().debug_flags & DEBUG_FLAG_ENABLED) != 0) - sh4_syncronize_register_bank((m_sr & sRB) >> 29); - if (!(m_sr & sRB)) + sh4_syncronize_register_bank((m_sh2_state->sr & sRB) >> 29); + if (!(m_sh2_state->sr & sRB)) sh4_change_register_bank(1); - m_sr |= sRB; - m_sr |= BL; + m_sh2_state->sr |= sRB; + m_sh2_state->sr |= BL; sh4_exception_recompute(); if (m_cpu_type == CPU_TYPE_SH4) @@ -2159,116 +523,9 @@ inline void sh34_base_device::TRAPA(const uint16_t opcode) m_sh3internal_upper[SH3_EXPEVT_ADDR] = 0x00000160; } - m_pc = m_vbr + 0x00000100; - - m_sh4_icount -= 7; -} - -/* TST Rm,Rn */ -inline void sh34_base_device::TST(const uint16_t opcode) -{ - if ((m_r[Rn] & m_r[Rm]) == 0) - m_sr |= T; - else - m_sr &= ~T; -} - -/* TST #imm,R0 */ -inline void sh34_base_device::TSTI(const uint16_t opcode) -{ - uint32_t imm = opcode & 0xff; - - if ((imm & m_r[0]) == 0) - m_sr |= T; - else - m_sr &= ~T; -} - -/* TST.B #imm,@(R0,GBR) */ -inline void sh34_base_device::TSTM(const uint16_t opcode) -{ - uint32_t imm = opcode & 0xff; - - m_ea = m_gbr + m_r[0]; - if ((imm & RB( m_ea )) == 0) - m_sr |= T; - else - m_sr &= ~T; - m_sh4_icount -= 2; -} + m_sh2_state->pc = m_sh2_state->vbr + 0x00000100; -/* XOR Rm,Rn */ -inline void sh34_base_device::XOR(const uint16_t opcode) -{ - m_r[Rn] ^= m_r[Rm]; -} - -/* XOR #imm,R0 */ -inline void sh34_base_device::XORI(const uint16_t opcode) -{ - uint32_t imm = opcode & 0xff; - m_r[0] ^= imm; -} - -/* XOR.B #imm,@(R0,GBR) */ -inline void sh34_base_device::XORM(const uint16_t opcode) -{ - uint32_t imm = opcode & 0xff; - uint32_t temp; - - m_ea = m_gbr + m_r[0]; - temp = RB( m_ea ); - temp ^= imm; - WB(m_ea, temp ); - m_sh4_icount -= 2; -} - -/* XTRCT Rm,Rn */ -inline void sh34_base_device::XTRCT(const uint16_t opcode) -{ - uint32_t m = Rm; uint32_t n = Rn; - - uint32_t temp; - - temp = (m_r[m] << 16) & 0xffff0000; - m_r[n] = (m_r[n] >> 16) & 0x0000ffff; - m_r[n] |= temp; -} - -/* STC SSR,Rn */ -inline void sh34_base_device::STCSSR(const uint16_t opcode) -{ - m_r[Rn] = m_ssr; -} - -/* STC SPC,Rn */ -inline void sh34_base_device::STCSPC(const uint16_t opcode) -{ - m_r[Rn] = m_spc; -} - -/* STC SGR,Rn */ -inline void sh34_base_device::STCSGR(const uint16_t opcode) -{ - m_r[Rn] = m_sgr; -} - -/* STS FPUL,Rn */ -inline void sh34_base_device::STSFPUL(const uint16_t opcode) -{ - m_r[Rn] = m_fpul; -} - -/* STS FPSCR,Rn */ -inline void sh34_base_device::STSFPSCR(const uint16_t opcode) -{ - m_r[Rn] = m_fpscr & 0x003FFFFF; -} - -/* STC DBR,Rn */ -inline void sh34_base_device::STCDBR(const uint16_t opcode) -{ - m_r[Rn] = m_dbr; + m_sh2_state->icount -= 7; } /* STCRBANK Rm_BANK,Rn */ @@ -2276,7 +533,7 @@ inline void sh34_base_device::STCRBANK(const uint16_t opcode) { uint32_t m = Rm; - m_r[Rn] = m_rbnk[m_sr&sRB ? 0 : 1][m & 7]; + m_sh2_state->r[Rn] = m_rbnk[m_sh2_state->sr&sRB ? 0 : 1][m & 7]; } /* STCMRBANK Rm_BANK,@-Rn */ @@ -2284,27 +541,10 @@ inline void sh34_base_device::STCMRBANK(const uint16_t opcode) { uint32_t m = Rm; uint32_t n = Rn; - m_r[n] -= 4; - m_ea = m_r[n]; - WL(m_ea, m_rbnk[m_sr&sRB ? 0 : 1][m & 7]); - m_sh4_icount--; -} - -/* MOVCA.L R0,@Rn */ -inline void sh34_base_device::MOVCAL(const uint16_t opcode) -{ - m_ea = m_r[Rn]; - WL(m_ea, m_r[0] ); -} - -inline void sh34_base_device::CLRS(const uint16_t opcode) -{ - m_sr &= ~S; -} - -inline void sh34_base_device::SETS(const uint16_t opcode) -{ - m_sr |= S; + m_sh2_state->r[n] -= 4; + m_sh2_state->ea = m_sh2_state->r[n]; + WL(m_sh2_state->ea, m_rbnk[m_sh2_state->sr&sRB ? 0 : 1][m & 7]); + m_sh2_state->icount--; } /* STS.L SGR,@-Rn */ @@ -2312,9 +552,9 @@ inline void sh34_base_device::STCMSGR(const uint16_t opcode) { uint32_t n = Rn; - m_r[n] -= 4; - m_ea = m_r[n]; - WL(m_ea, m_sgr ); + m_sh2_state->r[n] -= 4; + m_sh2_state->ea = m_sh2_state->r[n]; + WL(m_sh2_state->ea, m_sgr); } /* STS.L FPUL,@-Rn */ @@ -2322,9 +562,9 @@ inline void sh34_base_device::STSMFPUL(const uint16_t opcode) { uint32_t n = Rn; - m_r[n] -= 4; - m_ea = m_r[n]; - WL(m_ea, m_fpul ); + m_sh2_state->r[n] -= 4; + m_sh2_state->ea = m_sh2_state->r[n]; + WL(m_sh2_state->ea, m_fpul); } /* STS.L FPSCR,@-Rn */ @@ -2332,9 +572,9 @@ inline void sh34_base_device::STSMFPSCR(const uint16_t opcode) { uint32_t n = Rn; - m_r[n] -= 4; - m_ea = m_r[n]; - WL(m_ea, m_fpscr & 0x003FFFFF); + m_sh2_state->r[n] -= 4; + m_sh2_state->ea = m_sh2_state->r[n]; + WL(m_sh2_state->ea, m_fpscr & 0x003FFFFF); } /* STC.L DBR,@-Rn */ @@ -2342,9 +582,9 @@ inline void sh34_base_device::STCMDBR(const uint16_t opcode) { uint32_t n = Rn; - m_r[n] -= 4; - m_ea = m_r[n]; - WL(m_ea, m_dbr ); + m_sh2_state->r[n] -= 4; + m_sh2_state->ea = m_sh2_state->r[n]; + WL(m_sh2_state->ea, m_dbr); } /* STC.L SSR,@-Rn */ @@ -2352,9 +592,9 @@ inline void sh34_base_device::STCMSSR(const uint16_t opcode) { uint32_t n = Rn; - m_r[n] -= 4; - m_ea = m_r[n]; - WL(m_ea, m_ssr ); + m_sh2_state->r[n] -= 4; + m_sh2_state->ea = m_sh2_state->r[n]; + WL(m_sh2_state->ea, m_ssr); } /* STC.L SPC,@-Rn */ @@ -2362,17 +602,17 @@ inline void sh34_base_device::STCMSPC(const uint16_t opcode) { uint32_t n = Rn; - m_r[n] -= 4; - m_ea = m_r[n]; - WL(m_ea, m_spc ); + m_sh2_state->r[n] -= 4; + m_sh2_state->ea = m_sh2_state->r[n]; + WL(m_sh2_state->ea, m_spc); } /* LDS.L @Rm+,FPUL */ inline void sh34_base_device::LDSMFPUL(const uint16_t opcode) { - m_ea = m_r[Rn]; - m_fpul = RL(m_ea ); - m_r[Rn] += 4; + m_sh2_state->ea = m_sh2_state->r[Rn]; + m_fpul = RL(m_sh2_state->ea); + m_sh2_state->r[Rn] += 4; } /* LDS.L @Rm+,FPSCR */ @@ -2381,10 +621,10 @@ inline void sh34_base_device::LDSMFPSCR(const uint16_t opcode) uint32_t s; s = m_fpscr; - m_ea = m_r[Rn]; - m_fpscr = RL(m_ea ); + m_sh2_state->ea = m_sh2_state->r[Rn]; + m_fpscr = RL(m_sh2_state->ea); m_fpscr &= 0x003FFFFF; - m_r[Rn] += 4; + m_sh2_state->r[Rn] += 4; if ((s & FR) != (m_fpscr & FR)) sh4_swap_fp_registers(); #ifdef LSB_FIRST @@ -2398,9 +638,9 @@ 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_ea = m_r[Rn]; - m_dbr = RL(m_ea ); - m_r[Rn] += 4; + m_sh2_state->ea = m_sh2_state->r[Rn]; + m_dbr = RL(m_sh2_state->ea); + m_sh2_state->r[Rn] += 4; } /* LDC.L @Rn+,Rm_BANK */ @@ -2408,31 +648,31 @@ inline void sh34_base_device::LDCMRBANK(const uint16_t opcode) { uint32_t m = Rm; uint32_t n = Rn; - m_ea = m_r[n]; - m_rbnk[m_sr&sRB ? 0 : 1][m & 7] = RL(m_ea ); - m_r[n] += 4; + m_sh2_state->ea = m_sh2_state->r[n]; + m_rbnk[m_sh2_state->sr&sRB ? 0 : 1][m & 7] = RL(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_ea = m_r[Rn]; - m_ssr = RL(m_ea ); - m_r[Rn] += 4; + m_sh2_state->ea = m_sh2_state->r[Rn]; + m_ssr = RL(m_sh2_state->ea); + m_sh2_state->r[Rn] += 4; } /* LDC.L @Rm+,SPC */ inline void sh34_base_device::LDCMSPC(const uint16_t opcode) { - m_ea = m_r[Rn]; - m_spc = RL(m_ea ); - m_r[Rn] += 4; + m_sh2_state->ea = m_sh2_state->r[Rn]; + m_spc = RL(m_sh2_state->ea); + m_sh2_state->r[Rn] += 4; } /* LDS Rm,FPUL */ inline void sh34_base_device::LDSFPUL(const uint16_t opcode) { - m_fpul = m_r[Rn]; + m_fpul = m_sh2_state->r[Rn]; } /* LDS Rm,FPSCR */ @@ -2441,7 +681,7 @@ inline void sh34_base_device::LDSFPSCR(const uint16_t opcode) uint32_t s; s = m_fpscr; - m_fpscr = m_r[Rn] & 0x003FFFFF; + m_fpscr = m_sh2_state->r[Rn] & 0x003FFFFF; if ((s & FR) != (m_fpscr & FR)) sh4_swap_fp_registers(); #ifdef LSB_FIRST @@ -2455,7 +695,44 @@ inline void sh34_base_device::LDSFPSCR(const uint16_t opcode) /* LDC Rm,DBR */ inline void sh34_base_device::LDCDBR(const uint16_t opcode) { - m_dbr = m_r[Rn]; + m_dbr = m_sh2_state->r[Rn]; +} + + +/* STC SSR,Rn */ +inline void sh34_base_device::STCSSR(const uint16_t opcode) +{ + m_sh2_state->r[Rn] = m_ssr; +} + +/* STC SPC,Rn */ +inline void sh34_base_device::STCSPC(const uint16_t opcode) +{ + m_sh2_state->r[Rn] = m_spc; +} + +/* STC SGR,Rn */ +inline void sh34_base_device::STCSGR(const uint16_t opcode) +{ + m_sh2_state->r[Rn] = m_sgr; +} + +/* STS FPUL,Rn */ +inline void sh34_base_device::STSFPUL(const uint16_t opcode) +{ + m_sh2_state->r[Rn] = m_fpul; +} + +/* STS FPSCR,Rn */ +inline void sh34_base_device::STSFPSCR(const uint16_t opcode) +{ + m_sh2_state->r[Rn] = m_fpscr & 0x003FFFFF; +} + +/* STC DBR,Rn */ +inline void sh34_base_device::STCDBR(const uint16_t opcode) +{ + m_sh2_state->r[Rn] = m_dbr; } /* SHAD Rm,Rn */ @@ -2463,15 +740,16 @@ inline void sh34_base_device::SHAD(const uint16_t opcode) { uint32_t m = Rm; uint32_t n = Rn; - if ((m_r[m] & 0x80000000) == 0) - m_r[n] = m_r[n] << (m_r[m] & 0x1F); - else if ((m_r[m] & 0x1F) == 0) { - if ((m_r[n] & 0x80000000) == 0) - m_r[n] = 0; + 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) { + if ((m_sh2_state->r[n] & 0x80000000) == 0) + m_sh2_state->r[n] = 0; else - m_r[n] = 0xFFFFFFFF; - } else - m_r[n]=(int32_t)m_r[n] >> ((~m_r[m] & 0x1F)+1); + m_sh2_state->r[n] = 0xFFFFFFFF; + } + else + m_sh2_state->r[n] = (int32_t)m_sh2_state->r[n] >> ((~m_sh2_state->r[m] & 0x1F) + 1); } /* SHLD Rm,Rn */ @@ -2479,12 +757,12 @@ inline void sh34_base_device::SHLD(const uint16_t opcode) { uint32_t m = Rm; uint32_t n = Rn; - if ((m_r[m] & 0x80000000) == 0) - m_r[n] = m_r[n] << (m_r[m] & 0x1F); - else if ((m_r[m] & 0x1F) == 0) - m_r[n] = 0; + 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) + m_sh2_state->r[n] = 0; else - m_r[n] = m_r[n] >> ((~m_r[m] & 0x1F)+1); + m_sh2_state->r[n] = m_sh2_state->r[n] >> ((~m_sh2_state->r[m] & 0x1F) + 1); } /* LDCRBANK Rn,Rm_BANK */ @@ -2492,28 +770,28 @@ inline void sh34_base_device::LDCRBANK(const uint16_t opcode) { uint32_t m = Rm; - m_rbnk[m_sr&sRB ? 0 : 1][m & 7] = m_r[Rn]; + m_rbnk[m_sh2_state->sr&sRB ? 0 : 1][m & 7] = m_sh2_state->r[Rn]; } /* LDC Rm,SSR */ inline void sh34_base_device::LDCSSR(const uint16_t opcode) { - m_ssr = m_r[Rn]; + m_ssr = m_sh2_state->r[Rn]; } /* LDC Rm,SPC */ inline void sh34_base_device::LDCSPC(const uint16_t opcode) { - m_spc = m_r[Rn]; + m_spc = m_sh2_state->r[Rn]; } /* PREF @Rn */ inline void sh34_base_device::PREFM(const uint16_t opcode) { int a; - uint32_t addr,dest,sq; + uint32_t addr, dest, sq; - addr = m_r[Rn]; // address + addr = m_sh2_state->r[Rn]; // address if ((addr >= 0xE0000000) && (addr <= 0xE3FFFFFF)) { if (m_sh4_mmu_enabled) @@ -2582,28 +860,30 @@ inline void sh34_base_device::FMOVMRIFR(const uint16_t opcode) #ifdef LSB_FIRST n ^= m_fpu_pr; #endif - m_ea = m_r[m]; - m_xf[n] = RL(m_ea ); - m_r[m] += 4; - m_xf[n^1] = RL(m_ea+4 ); - m_r[m] += 4; - } else { + m_sh2_state->ea = m_sh2_state->r[m]; + m_xf[n] = RL(m_sh2_state->ea); + m_sh2_state->r[m] += 4; + m_xf[n ^ 1] = RL(m_sh2_state->ea + 4); + m_sh2_state->r[m] += 4; + } + else { #ifdef LSB_FIRST n ^= m_fpu_pr; #endif - m_ea = m_r[m]; - m_fr[n] = RL(m_ea ); - m_r[m] += 4; - m_fr[n^1] = RL(m_ea+4 ); - m_r[m] += 4; + m_sh2_state->ea = m_sh2_state->r[m]; + m_fr[n] = RL(m_sh2_state->ea); + m_sh2_state->r[m] += 4; + m_fr[n ^ 1] = RL(m_sh2_state->ea + 4); + m_sh2_state->r[m] += 4; } - } else { /* SZ = 0 */ - m_ea = m_r[m]; + } + else { /* SZ = 0 */ + m_sh2_state->ea = m_sh2_state->r[m]; #ifdef LSB_FIRST n ^= m_fpu_pr; #endif - m_fr[n] = RL(m_ea ); - m_r[m] += 4; + m_fr[n] = RL(m_sh2_state->ea); + m_sh2_state->r[m] += 4; } } @@ -2621,23 +901,25 @@ inline void sh34_base_device::FMOVFRMR(const uint16_t opcode) #ifdef LSB_FIRST m ^= m_fpu_pr; #endif - m_ea = m_r[n]; - WL(m_ea,m_xf[m] ); - WL(m_ea+4,m_xf[m^1] ); - } else { + m_sh2_state->ea = m_sh2_state->r[n]; + WL(m_sh2_state->ea, m_xf[m]); + WL(m_sh2_state->ea + 4, m_xf[m ^ 1]); + } + else { #ifdef LSB_FIRST m ^= m_fpu_pr; #endif - m_ea = m_r[n]; - WL(m_ea,m_fr[m] ); - WL(m_ea+4,m_fr[m^1] ); + m_sh2_state->ea = m_sh2_state->r[n]; + WL(m_sh2_state->ea, m_fr[m]); + WL(m_sh2_state->ea + 4, m_fr[m ^ 1]); } - } else { /* SZ = 0 */ - m_ea = m_r[n]; + } + else { /* SZ = 0 */ + m_sh2_state->ea = m_sh2_state->r[n]; #ifdef LSB_FIRST m ^= m_fpu_pr; #endif - WL(m_ea,m_fr[m] ); + WL(m_sh2_state->ea, m_fr[m]); } } @@ -2655,26 +937,28 @@ inline void sh34_base_device::FMOVFRMDR(const uint16_t opcode) #ifdef LSB_FIRST m ^= m_fpu_pr; #endif - m_r[n] -= 8; - m_ea = m_r[n]; - WL(m_ea,m_xf[m] ); - WL(m_ea+4,m_xf[m^1] ); - } else { + m_sh2_state->r[n] -= 8; + m_sh2_state->ea = m_sh2_state->r[n]; + WL(m_sh2_state->ea, m_xf[m]); + WL(m_sh2_state->ea + 4, m_xf[m ^ 1]); + } + else { #ifdef LSB_FIRST m ^= m_fpu_pr; #endif - m_r[n] -= 8; - m_ea = m_r[n]; - WL(m_ea,m_fr[m] ); - WL(m_ea+4,m_fr[m^1] ); + m_sh2_state->r[n] -= 8; + m_sh2_state->ea = m_sh2_state->r[n]; + WL(m_sh2_state->ea, m_fr[m]); + WL(m_sh2_state->ea + 4, m_fr[m ^ 1]); } - } else { /* SZ = 0 */ - m_r[n] -= 4; - m_ea = m_r[n]; + } + else { /* SZ = 0 */ + m_sh2_state->r[n] -= 4; + m_sh2_state->ea = m_sh2_state->r[n]; #ifdef LSB_FIRST m ^= m_fpu_pr; #endif - WL(m_ea,m_fr[m] ); + WL(m_sh2_state->ea, m_fr[m]); } } @@ -2692,23 +976,25 @@ inline void sh34_base_device::FMOVFRS0(const uint16_t opcode) #ifdef LSB_FIRST m ^= m_fpu_pr; #endif - m_ea = m_r[0] + m_r[n]; - WL(m_ea,m_xf[m] ); - WL(m_ea+4,m_xf[m^1] ); - } else { + m_sh2_state->ea = m_sh2_state->r[0] + m_sh2_state->r[n]; + WL(m_sh2_state->ea, m_xf[m]); + WL(m_sh2_state->ea + 4, m_xf[m ^ 1]); + } + else { #ifdef LSB_FIRST m ^= m_fpu_pr; #endif - m_ea = m_r[0] + m_r[n]; - WL(m_ea,m_fr[m] ); - WL(m_ea+4,m_fr[m^1] ); + m_sh2_state->ea = m_sh2_state->r[0] + m_sh2_state->r[n]; + WL(m_sh2_state->ea, m_fr[m]); + WL(m_sh2_state->ea + 4, m_fr[m ^ 1]); } - } else { /* SZ = 0 */ - m_ea = m_r[0] + m_r[n]; + } + else { /* SZ = 0 */ + m_sh2_state->ea = m_sh2_state->r[0] + m_sh2_state->r[n]; #ifdef LSB_FIRST m ^= m_fpu_pr; #endif - WL(m_ea,m_fr[m] ); + WL(m_sh2_state->ea, m_fr[m]); } } @@ -2726,23 +1012,25 @@ inline void sh34_base_device::FMOVS0FR(const uint16_t opcode) #ifdef LSB_FIRST n ^= m_fpu_pr; #endif - m_ea = m_r[0] + m_r[m]; - m_xf[n] = RL(m_ea ); - m_xf[n^1] = RL(m_ea+4 ); - } else { + m_sh2_state->ea = m_sh2_state->r[0] + m_sh2_state->r[m]; + m_xf[n] = RL(m_sh2_state->ea); + m_xf[n ^ 1] = RL(m_sh2_state->ea + 4); + } + else { #ifdef LSB_FIRST n ^= m_fpu_pr; #endif - m_ea = m_r[0] + m_r[m]; - m_fr[n] = RL(m_ea ); - m_fr[n^1] = RL(m_ea+4 ); + m_sh2_state->ea = m_sh2_state->r[0] + m_sh2_state->r[m]; + m_fr[n] = RL(m_sh2_state->ea); + m_fr[n ^ 1] = RL(m_sh2_state->ea + 4); } - } else { /* SZ = 0 */ - m_ea = m_r[0] + m_r[m]; + } + else { /* SZ = 0 */ + m_sh2_state->ea = m_sh2_state->r[0] + m_sh2_state->r[m]; #ifdef LSB_FIRST n ^= m_fpu_pr; #endif - m_fr[n] = RL(m_ea ); + m_fr[n] = RL(m_sh2_state->ea); } } @@ -2761,23 +1049,25 @@ inline void sh34_base_device::FMOVMRFR(const uint16_t opcode) #ifdef LSB_FIRST n ^= m_fpu_pr; #endif - m_ea = m_r[m]; - m_xf[n] = RL(m_ea ); - m_xf[n^1] = RL(m_ea+4 ); - } else { + m_sh2_state->ea = m_sh2_state->r[m]; + m_xf[n] = RL(m_sh2_state->ea); + m_xf[n ^ 1] = RL(m_sh2_state->ea + 4); + } + else { #ifdef LSB_FIRST n ^= m_fpu_pr; #endif - m_ea = m_r[m]; - m_fr[n] = RL(m_ea ); - m_fr[n^1] = RL(m_ea+4 ); + m_sh2_state->ea = m_sh2_state->r[m]; + m_fr[n] = RL(m_sh2_state->ea); + m_fr[n ^ 1] = RL(m_sh2_state->ea + 4); } - } else { /* SZ = 0 */ - m_ea = m_r[m]; + } + else { /* SZ = 0 */ + m_sh2_state->ea = m_sh2_state->r[m]; #ifdef LSB_FIRST n ^= m_fpu_pr; #endif - m_fr[n] = RL(m_ea ); + m_fr[n] = RL(m_sh2_state->ea); } } @@ -2790,7 +1080,7 @@ inline void sh34_base_device::FMOVFR(const uint16_t opcode) { uint32_t m = Rm; uint32_t n = Rn; - if (m_fpu_sz == 0) { /* SZ = 0 */ + if (m_fpu_sz == 0) { /* SZ = 0 */ #ifdef LSB_FIRST n ^= m_fpu_pr; m ^= m_fpu_pr; @@ -2802,15 +1092,18 @@ inline void sh34_base_device::FMOVFR(const uint16_t opcode) if (n & 1) { m_xf[n & 14] = m_xf[m & 14]; m_xf[n | 1] = m_xf[m | 1]; - } else { + } + else { m_fr[n] = m_xf[m & 14]; m_fr[n | 1] = m_xf[m | 1]; } - } else { + } + else { if (n & 1) { m_xf[n & 14] = m_fr[m]; m_xf[n | 1] = m_fr[m | 1]; // (a&14)+1 -> a|1 - } else { + } + else { m_fr[n] = m_fr[m]; m_fr[n | 1] = m_fr[m | 1]; } @@ -2839,7 +1132,7 @@ inline void sh34_base_device::FLDI0(const uint16_t opcode) } /* FLDS FRm,FPUL 1111mmmm00011101 */ -inline void sh34_base_device:: FLDS(const uint16_t opcode) +inline void sh34_base_device::FLDS(const uint16_t opcode) { #ifdef LSB_FIRST m_fpul = m_fr[Rn ^ m_fpu_pr]; @@ -2849,7 +1142,7 @@ inline void sh34_base_device:: FLDS(const uint16_t opcode) } /* FSTS FPUL,FRn 1111nnnn00001101 */ -inline void sh34_base_device:: FSTS(const uint16_t opcode) +inline void sh34_base_device::FSTS(const uint16_t opcode) { #ifdef LSB_FIRST m_fr[Rn ^ m_fpu_pr] = m_fpul; @@ -2879,13 +1172,14 @@ inline void sh34_base_device::FTRC(const uint16_t opcode) uint32_t n = Rn; if (m_fpu_pr) { /* PR = 1 */ - if(n & 1) - fatalerror("SH-4: FTRC opcode used with n %d",n); + if (n & 1) + fatalerror("SH-4: FTRC opcode used with n %d", n); n = n & 14; *((int32_t *)&m_fpul) = (int32_t)FP_RFD(n); - } else { /* PR = 0 */ - /* read m_fr[n] as float -> truncate -> fpul(32) */ + } + else { /* PR = 0 */ + /* read m_fr[n] as float -> truncate -> fpul(32) */ *((int32_t *)&m_fpul) = (int32_t)FP_RFS(n); } } @@ -2897,12 +1191,13 @@ inline void sh34_base_device::FLOAT(const uint16_t opcode) uint32_t n = Rn; if (m_fpu_pr) { /* PR = 1 */ - if(n & 1) - fatalerror("SH-4: FLOAT opcode used with n %d",n); + if (n & 1) + fatalerror("SH-4: FLOAT opcode used with n %d", n); n = n & 14; FP_RFD(n) = (double)*((int32_t *)&m_fpul); - } else { /* PR = 0 */ + } + else { /* PR = 0 */ FP_RFS(n) = (float)*((int32_t *)&m_fpul); } } @@ -2915,7 +1210,8 @@ inline void sh34_base_device::FNEG(const uint16_t opcode) if (m_fpu_pr) { /* PR = 1 */ FP_RFD(n) = -FP_RFD(n); - } else { /* PR = 0 */ + } + else { /* PR = 0 */ FP_RFS(n) = -FP_RFS(n); } } @@ -2934,7 +1230,8 @@ inline void sh34_base_device::FABS(const uint16_t opcode) n = n & 14; m_fr[n] = m_fr[n] & 0x7fffffff; #endif - } else { /* PR = 0 */ + } + else { /* PR = 0 */ m_fr[n] = m_fr[n] & 0x7fffffff; } } @@ -2949,14 +1246,15 @@ inline void sh34_base_device::FCMP_EQ(const uint16_t opcode) n = n & 14; m = m & 14; if (FP_RFD(n) == FP_RFD(m)) - m_sr |= T; + m_sh2_state->sr |= SH_T; else - m_sr &= ~T; - } else { /* PR = 0 */ + m_sh2_state->sr &= ~SH_T; + } + else { /* PR = 0 */ if (FP_RFS(n) == FP_RFS(m)) - m_sr |= T; + m_sh2_state->sr |= SH_T; else - m_sr &= ~T; + m_sh2_state->sr &= ~SH_T; } } @@ -2970,14 +1268,15 @@ inline void sh34_base_device::FCMP_GT(const uint16_t opcode) n = n & 14; m = m & 14; if (FP_RFD(n) > FP_RFD(m)) - m_sr |= T; + m_sh2_state->sr |= SH_T; else - m_sr &= ~T; - } else { /* PR = 0 */ + m_sh2_state->sr &= ~SH_T; + } + else { /* PR = 0 */ if (FP_RFS(n) > FP_RFS(m)) - m_sr |= T; + m_sh2_state->sr |= SH_T; else - m_sr &= ~T; + m_sh2_state->sr &= ~SH_T; } } @@ -2989,7 +1288,7 @@ inline void sh34_base_device::FCNVDS(const uint16_t opcode) if (m_fpu_pr) { /* PR = 1 */ n = n & 14; if (m_fpscr & RM) - m_fr[n | NATIVE_ENDIAN_VALUE_LE_BE(0,1)] &= 0xe0000000; /* round toward zero*/ + m_fr[n | NATIVE_ENDIAN_VALUE_LE_BE(0, 1)] &= 0xe0000000; /* round toward zero*/ *((float *)&m_fpul) = (float)FP_RFD(n); } } @@ -3015,7 +1314,8 @@ inline void sh34_base_device::FADD(const uint16_t opcode) 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); } } @@ -3030,7 +1330,8 @@ inline void sh34_base_device::FSUB(const uint16_t opcode) 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); } } @@ -3046,7 +1347,8 @@ inline void sh34_base_device::FMUL(const uint16_t opcode) 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); } } @@ -3063,7 +1365,8 @@ inline void sh34_base_device::FDIV(const uint16_t opcode) 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); @@ -3091,7 +1394,8 @@ inline void sh34_base_device::FSQRT(const uint16_t opcode) 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)); @@ -3115,9 +1419,9 @@ void sh34_base_device::FSSCA(const uint16_t opcode) float angle; - angle = (((float)(m_fpul & 0xFFFF)) / 65536.0f) * 2.0f * (float) M_PI; + angle = (((float)(m_fpul & 0xFFFF)) / 65536.0f) * 2.0f * (float)M_PI; FP_RFS(n) = sinf(angle); - FP_RFS(n+1) = cosf(angle); + FP_RFS(n + 1) = cosf(angle); } /* FIPR FVm,FVn PR=0 1111nnmm11101101 */ @@ -3125,15 +1429,15 @@ inline void sh34_base_device::FIPR(const uint16_t opcode) { uint32_t n = Rn; -uint32_t m; -float ml[4]; -int a; + uint32_t m; + float ml[4]; + int a; m = (n & 3) << 2; n = n & 12; for (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]; + ml[a] = FP_RFS(n + a) * FP_RFS(m + a); + FP_RFS(n + 3) = ml[0] + ml[1] + ml[2] + ml[3]; } /* FTRV XMTRX,FVn PR=0 1111nn0111111101 */ @@ -3141,13 +1445,13 @@ void sh34_base_device::FTRV(const uint16_t opcode) { uint32_t n = Rn; -int i,j; -float sum[4]; + int i, j; + float sum[4]; n = n & 12; for (i = 0;i < 4;i++) { sum[i] = 0; - for (j=0;j < 4;j++) + for (j = 0;j < 4;j++) sum[i] += FP_XFS((j << 2) + i)*FP_RFS(n + j); } for (i = 0;i < 4;i++) @@ -3157,25 +1461,27 @@ float sum[4]; inline void sh34_base_device::op1111_0xf13(const uint16_t opcode) { if (opcode & 0x100) { - if (opcode & 0x200) { - switch (opcode & 0xC00) - { - case 0x000: - FSCHG(); - break; - case 0x800: - FRCHG(); - break; - default: - machine().debug_break(); - break; - } - } else { - FTRV(opcode); + if (opcode & 0x200) { + switch (opcode & 0xC00) + { + case 0x000: + FSCHG(); + break; + case 0x800: + FRCHG(); + break; + default: + machine().debug_break(); + break; } - } else { - FSSCA(opcode); } + else { + FTRV(opcode); + } + } + else { + FSSCA(opcode); + } } void sh34_base_device::dbreak(const uint16_t opcode) @@ -3186,24 +1492,24 @@ void sh34_base_device::dbreak(const uint16_t opcode) inline void sh34_base_device::op1111_0x13(uint16_t opcode) { - switch((opcode >> 4) & 0x0f) + switch ((opcode >> 4) & 0x0f) { - case 0x00: FSTS(opcode); break; - case 0x01: FLDS(opcode); break; - case 0x02: FLOAT(opcode); break; - case 0x03: FTRC(opcode); break; - case 0x04: FNEG(opcode); break; - case 0x05: FABS(opcode); break; - case 0x06: FSQRT(opcode); break; - case 0x07: FSRRA(opcode); break; - case 0x08: FLDI0(opcode); break; - case 0x09: FLDI1(opcode); break; - case 0x0a: FCNVSD(opcode); break; - case 0x0b: FCNVDS(opcode); break; - case 0x0c: dbreak(opcode); break; - case 0x0d: dbreak(opcode); break; - case 0x0e: FIPR(opcode); break; - case 0x0f: op1111_0xf13(opcode); break; + case 0x00: FSTS(opcode); break; + case 0x01: FLDS(opcode); break; + case 0x02: FLOAT(opcode); break; + case 0x03: FTRC(opcode); break; + case 0x04: FNEG(opcode); break; + case 0x05: FABS(opcode); break; + case 0x06: FSQRT(opcode); break; + case 0x07: FSRRA(opcode); break; + case 0x08: FLDI0(opcode); break; + case 0x09: FLDI1(opcode); break; + case 0x0a: FCNVSD(opcode); break; + case 0x0b: FCNVDS(opcode); break; + case 0x0c: dbreak(opcode); break; + case 0x0d: dbreak(opcode); break; + case 0x0e: FIPR(opcode); break; + case 0x0f: op1111_0xf13(opcode); break; } } @@ -3215,20 +1521,20 @@ inline void sh34_base_device::op1111_0x13(uint16_t opcode) void sh34_base_device::device_reset() { m_spc = 0; - m_pr = 0; - m_sr = 0; + m_sh2_state->pr = 0; + m_sh2_state->sr = 0; m_ssr = 0; - m_gbr = 0; - m_vbr = 0; - m_mach = 0; - m_macl = 0; - memset(m_r, 0, sizeof(m_r)); + m_sh2_state->gbr = 0; + m_sh2_state->vbr = 0; + m_sh2_state->mach = 0; + m_sh2_state->macl = 0; + memset(m_sh2_state->r, 0, sizeof(m_sh2_state->r)); memset(m_rbnk, 0, sizeof(m_rbnk)); m_sgr = 0; memset(m_fr, 0, sizeof(m_fr)); memset(m_xf, 0, sizeof(m_xf)); - m_ea = 0; - m_delay = 0; + m_sh2_state->ea = 0; + m_sh2_state->m_delay = 0; m_cpu_off = 0; m_pending_irq = 0; m_test_irq = 0; @@ -3290,10 +1596,10 @@ void sh34_base_device::device_reset() m_rtc_timer->adjust(attotime::from_hz(128)); - m_pc = 0xa0000000; - m_ppc = m_pc & AM; - m_r[15] = RL(4); - m_sr = 0x700000f0; + m_sh2_state->pc = 0xa0000000; + m_ppc = m_sh2_state->pc & SH34_AM; + m_sh2_state->r[15] = RL(4); + m_sh2_state->sr = 0x700000f0; m_fpscr = 0x00040001; m_fpu_sz = (m_fpscr & SZ) ? 1 : 0; m_fpu_pr = (m_fpscr & PR) ? 1 : 0; @@ -3302,9 +1608,10 @@ void sh34_base_device::device_reset() m_internal_irq_level = -1; m_irln = 15; - m_sleep_mode = 0; + m_sh2_state->sleep_mode = 0; m_sh4_mmu_enabled = 0; + m_cache_dirty = true; } /*------------------------------------------------- @@ -3338,846 +1645,344 @@ void sh4_base_device::device_reset() inline void sh34_base_device::execute_one_0000(const uint16_t opcode) { - switch(opcode & 0xff) + switch (opcode & 0xff) { - // 0x00 - case 0x00: NOP(opcode); break; - case 0x10: NOP(opcode); break; - case 0x20: NOP(opcode); break; - case 0x30: NOP(opcode); break; - case 0x40: NOP(opcode); break; - case 0x50: NOP(opcode); break; - case 0x60: NOP(opcode); break; - case 0x70: NOP(opcode); break; - case 0x80: NOP(opcode); break; - case 0x90: NOP(opcode); break; - case 0xa0: NOP(opcode); break; - case 0xb0: NOP(opcode); break; - case 0xc0: NOP(opcode); break; - case 0xd0: NOP(opcode); break; - case 0xe0: NOP(opcode); break; - case 0xf0: NOP(opcode); break; - // 0x10 - case 0x01: NOP(opcode); break; - case 0x11: NOP(opcode); break; - case 0x21: NOP(opcode); break; - case 0x31: NOP(opcode); break; - case 0x41: NOP(opcode); break; - case 0x51: NOP(opcode); break; - case 0x61: NOP(opcode); break; - case 0x71: NOP(opcode); break; - case 0x81: NOP(opcode); break; - case 0x91: NOP(opcode); break; - case 0xa1: NOP(opcode); break; - case 0xb1: NOP(opcode); break; - case 0xc1: NOP(opcode); break; - case 0xd1: NOP(opcode); break; - case 0xe1: NOP(opcode); break; - case 0xf1: NOP(opcode); break; - // 0x20 - case 0x02: STCSR(opcode); break; - case 0x12: STCGBR(opcode); break; - case 0x22: STCVBR(opcode); break; - case 0x32: STCSSR(opcode); break; - case 0x42: STCSPC(opcode); break; - case 0x52: NOP(opcode); break; - case 0x62: NOP(opcode); break; - case 0x72: NOP(opcode); break; - case 0x82: STCRBANK(opcode); break; - case 0x92: STCRBANK(opcode); break; - case 0xa2: STCRBANK(opcode); break; - case 0xb2: STCRBANK(opcode); break; - case 0xc2: STCRBANK(opcode); break; - case 0xd2: STCRBANK(opcode); break; - case 0xe2: STCRBANK(opcode); break; - case 0xf2: STCRBANK(opcode); break; - // 0x30 - case 0x03: BSRF(opcode); break; - case 0x13: NOP(opcode); break; - case 0x23: BRAF(opcode); break; - case 0x33: NOP(opcode); break; - case 0x43: NOP(opcode); break; - case 0x53: NOP(opcode); break; - case 0x63: NOP(opcode); break; - case 0x73: NOP(opcode); break; - case 0x83: PREFM(opcode); break; - case 0x93: TODO(opcode); break; - case 0xa3: TODO(opcode); break; - case 0xb3: TODO(opcode); break; - case 0xc3: MOVCAL(opcode); break; - case 0xd3: NOP(opcode); break; - case 0xe3: NOP(opcode); break; - case 0xf3: NOP(opcode); break; - // 0x40 - case 0x04: MOVBS0(opcode); break; - case 0x14: MOVBS0(opcode); break; - case 0x24: MOVBS0(opcode); break; - case 0x34: MOVBS0(opcode); break; - case 0x44: MOVBS0(opcode); break; - case 0x54: MOVBS0(opcode); break; - case 0x64: MOVBS0(opcode); break; - case 0x74: MOVBS0(opcode); break; - case 0x84: MOVBS0(opcode); break; - case 0x94: MOVBS0(opcode); break; - case 0xa4: MOVBS0(opcode); break; - case 0xb4: MOVBS0(opcode); break; - case 0xc4: MOVBS0(opcode); break; - case 0xd4: MOVBS0(opcode); break; - case 0xe4: MOVBS0(opcode); break; - case 0xf4: MOVBS0(opcode); break; - // 0x50 - case 0x05: MOVWS0(opcode); break; - case 0x15: MOVWS0(opcode); break; - case 0x25: MOVWS0(opcode); break; - case 0x35: MOVWS0(opcode); break; - case 0x45: MOVWS0(opcode); break; - case 0x55: MOVWS0(opcode); break; - case 0x65: MOVWS0(opcode); break; - case 0x75: MOVWS0(opcode); break; - case 0x85: MOVWS0(opcode); break; - case 0x95: MOVWS0(opcode); break; - case 0xa5: MOVWS0(opcode); break; - case 0xb5: MOVWS0(opcode); break; - case 0xc5: MOVWS0(opcode); break; - case 0xd5: MOVWS0(opcode); break; - case 0xe5: MOVWS0(opcode); break; - case 0xf5: MOVWS0(opcode); break; - // 0x60 - case 0x06: MOVLS0(opcode); break; - case 0x16: MOVLS0(opcode); break; - case 0x26: MOVLS0(opcode); break; - case 0x36: MOVLS0(opcode); break; - case 0x46: MOVLS0(opcode); break; - case 0x56: MOVLS0(opcode); break; - case 0x66: MOVLS0(opcode); break; - case 0x76: MOVLS0(opcode); break; - case 0x86: MOVLS0(opcode); break; - case 0x96: MOVLS0(opcode); break; - case 0xa6: MOVLS0(opcode); break; - case 0xb6: MOVLS0(opcode); break; - case 0xc6: MOVLS0(opcode); break; - case 0xd6: MOVLS0(opcode); break; - case 0xe6: MOVLS0(opcode); break; - case 0xf6: MOVLS0(opcode); break; - // 0x70 - case 0x07: MULL(opcode); break; - case 0x17: MULL(opcode); break; - case 0x27: MULL(opcode); break; - case 0x37: MULL(opcode); break; - case 0x47: MULL(opcode); break; - case 0x57: MULL(opcode); break; - case 0x67: MULL(opcode); break; - case 0x77: MULL(opcode); break; - case 0x87: MULL(opcode); break; - case 0x97: MULL(opcode); break; - case 0xa7: MULL(opcode); break; - case 0xb7: MULL(opcode); break; - case 0xc7: MULL(opcode); break; - case 0xd7: MULL(opcode); break; - case 0xe7: MULL(opcode); break; - case 0xf7: MULL(opcode); break; - // 0x80 - case 0x08: CLRT(opcode); break; - case 0x18: SETT(opcode); break; - case 0x28: CLRMAC(opcode); break; - case 0x38: LDTLB(opcode); break; - case 0x48: CLRS(opcode); break; - case 0x58: SETS(opcode); break; - case 0x68: NOP(opcode); break; - case 0x78: NOP(opcode); break; - case 0x88: CLRT(opcode); break; - case 0x98: SETT(opcode); break; - case 0xa8: CLRMAC(opcode); break; - case 0xb8: LDTLB(opcode); break; - case 0xc8: CLRS(opcode); break; - case 0xd8: SETS(opcode); break; - case 0xe8: NOP(opcode); break; - case 0xf8: NOP(opcode); break; - // 0x90 - case 0x09: NOP(opcode); break; - case 0x19: DIV0U(opcode); break; - case 0x29: MOVT(opcode); break; - case 0x39: NOP(opcode); break; - case 0x49: NOP(opcode); break; - case 0x59: DIV0U(opcode); break; - case 0x69: MOVT(opcode); break; - case 0x79: NOP(opcode); break; - case 0x89: NOP(opcode); break; - case 0x99: DIV0U(opcode); break; - case 0xa9: MOVT(opcode); break; - case 0xb9: NOP(opcode); break; - case 0xc9: NOP(opcode); break; - case 0xd9: DIV0U(opcode); break; - case 0xe9: MOVT(opcode); break; - case 0xf9: NOP(opcode); break; - // 0xa0 - case 0x0a: STSMACH(opcode); break; - case 0x1a: STSMACL(opcode); break; - case 0x2a: STSPR(opcode); break; - case 0x3a: STCSGR(opcode); break; - case 0x4a: NOP(opcode); break; - case 0x5a: STSFPUL(opcode); break; - case 0x6a: STSFPSCR(opcode); break; - case 0x7a: STCDBR(opcode); break; - case 0x8a: STSMACH(opcode); break; - case 0x9a: STSMACL(opcode); break; - case 0xaa: STSPR(opcode); break; - case 0xba: STCSGR(opcode); break; - case 0xca: NOP(opcode); break; - case 0xda: STSFPUL(opcode); break; - case 0xea: STSFPSCR(opcode); break; - case 0xfa: STCDBR(opcode); break; - // 0xb0 - case 0x0b: RTS(opcode); break; - case 0x1b: SLEEP(opcode); break; - case 0x2b: RTE(opcode); break; - case 0x3b: NOP(opcode); break; - case 0x4b: RTS(opcode); break; - case 0x5b: SLEEP(opcode); break; - case 0x6b: RTE(opcode); break; - case 0x7b: NOP(opcode); break; - case 0x8b: RTS(opcode); break; - case 0x9b: SLEEP(opcode); break; - case 0xab: RTE(opcode); break; - case 0xbb: NOP(opcode); break; - case 0xcb: RTS(opcode); break; - case 0xdb: SLEEP(opcode); break; - case 0xeb: RTE(opcode); break; - case 0xfb: NOP(opcode); break; - // 0xc0 - case 0x0c: MOVBL0(opcode); break; - case 0x1c: MOVBL0(opcode); break; - case 0x2c: MOVBL0(opcode); break; - case 0x3c: MOVBL0(opcode); break; - case 0x4c: MOVBL0(opcode); break; - case 0x5c: MOVBL0(opcode); break; - case 0x6c: MOVBL0(opcode); break; - case 0x7c: MOVBL0(opcode); break; - case 0x8c: MOVBL0(opcode); break; - case 0x9c: MOVBL0(opcode); break; - case 0xac: MOVBL0(opcode); break; - case 0xbc: MOVBL0(opcode); break; - case 0xcc: MOVBL0(opcode); break; - case 0xdc: MOVBL0(opcode); break; - case 0xec: MOVBL0(opcode); break; - case 0xfc: MOVBL0(opcode); break; - // 0xd0 - case 0x0d: MOVWL0(opcode); break; - case 0x1d: MOVWL0(opcode); break; - case 0x2d: MOVWL0(opcode); break; - case 0x3d: MOVWL0(opcode); break; - case 0x4d: MOVWL0(opcode); break; - case 0x5d: MOVWL0(opcode); break; - case 0x6d: MOVWL0(opcode); break; - case 0x7d: MOVWL0(opcode); break; - case 0x8d: MOVWL0(opcode); break; - case 0x9d: MOVWL0(opcode); break; - case 0xad: MOVWL0(opcode); break; - case 0xbd: MOVWL0(opcode); break; - case 0xcd: MOVWL0(opcode); break; - case 0xdd: MOVWL0(opcode); break; - case 0xed: MOVWL0(opcode); break; - case 0xfd: MOVWL0(opcode); break; - // 0xe0 - case 0x0e: MOVLL0(opcode); break; - case 0x1e: MOVLL0(opcode); break; - case 0x2e: MOVLL0(opcode); break; - case 0x3e: MOVLL0(opcode); break; - case 0x4e: MOVLL0(opcode); break; - case 0x5e: MOVLL0(opcode); break; - case 0x6e: MOVLL0(opcode); break; - case 0x7e: MOVLL0(opcode); break; - case 0x8e: MOVLL0(opcode); break; - case 0x9e: MOVLL0(opcode); break; - case 0xae: MOVLL0(opcode); break; - case 0xbe: MOVLL0(opcode); break; - case 0xce: MOVLL0(opcode); break; - case 0xde: MOVLL0(opcode); break; - case 0xee: MOVLL0(opcode); break; - case 0xfe: MOVLL0(opcode); break; - // 0xf0 - case 0x0f: MAC_L(opcode); break; - case 0x1f: MAC_L(opcode); break; - case 0x2f: MAC_L(opcode); break; - case 0x3f: MAC_L(opcode); break; - case 0x4f: MAC_L(opcode); break; - case 0x5f: MAC_L(opcode); break; - case 0x6f: MAC_L(opcode); break; - case 0x7f: MAC_L(opcode); break; - case 0x8f: MAC_L(opcode); break; - case 0x9f: MAC_L(opcode); break; - case 0xaf: MAC_L(opcode); break; - case 0xbf: MAC_L(opcode); break; - case 0xcf: MAC_L(opcode); break; - case 0xdf: MAC_L(opcode); break; - case 0xef: MAC_L(opcode); break; - case 0xff: MAC_L(opcode); break; + default: + // fall through to SH2 handlers + sh_common_execution::execute_one_0000(opcode); break; + + case 0x52: + case 0x62: + case 0x43: + case 0x63: + case 0xe3: + case 0x68: + case 0xe8: + case 0x4a: + case 0xca: + ILLEGAL(); break; // illegal on sh4 + + case 0x93: + case 0xa3: + case 0xb3: + TODO(opcode); break; + + case 0x82: + case 0x92: + case 0xa2: + case 0xb2: + case 0xc2: + case 0xd2: + case 0xe2: + case 0xf2: + STCRBANK(opcode); break; // sh4 only + + case 0x32: STCSSR(opcode); break; // sh4 only + case 0x42: STCSPC(opcode); break; // sh4 only + case 0x83: PREFM(opcode); break; // sh4 only + case 0xc3: MOVCAL(opcode); break; // sh4 only + + case 0x38: + case 0xb8: + LDTLB(opcode); break; // sh4 only + + case 0x48: + case 0xc8: + CLRS(opcode); break; // sh4 only + + case 0x58: + case 0xd8: + SETS(opcode); break; // sh4 only + + case 0x3a: + case 0xba: + STCSGR(opcode); break; // sh4 only + + case 0x5a: + case 0xda: + STSFPUL(opcode); break; // sh4 only + + case 0x6a: + case 0xea: + STSFPSCR(opcode); break; // sh4 only + + case 0x7a: + case 0xfa: + STCDBR(opcode); break; // sh4 only } } inline void sh34_base_device::execute_one_4000(const uint16_t opcode) { - switch(opcode & 0xff) + switch (opcode & 0xff) { - // 0x00 - case 0x00: SHLL(opcode); break; - case 0x10: DT(opcode); break; - case 0x20: SHAL(opcode); break; - case 0x30: NOP(opcode); break; - case 0x40: SHLL(opcode); break; - case 0x50: DT(opcode); break; - case 0x60: SHAL(opcode); break; - case 0x70: NOP(opcode); break; - case 0x80: SHLL(opcode); break; - case 0x90: DT(opcode); break; - case 0xa0: SHAL(opcode); break; - case 0xb0: NOP(opcode); break; - case 0xc0: SHLL(opcode); break; - case 0xd0: DT(opcode); break; - case 0xe0: SHAL(opcode); break; - case 0xf0: NOP(opcode); break; - // 0x10 - case 0x01: SHLR(opcode); break; - case 0x11: CMPPZ(opcode); break; - case 0x21: SHAR(opcode); break; - case 0x31: NOP(opcode); break; - case 0x41: SHLR(opcode); break; - case 0x51: CMPPZ(opcode); break; - case 0x61: SHAR(opcode); break; - case 0x71: NOP(opcode); break; - case 0x81: SHLR(opcode); break; - case 0x91: CMPPZ(opcode); break; - case 0xa1: SHAR(opcode); break; - case 0xb1: NOP(opcode); break; - case 0xc1: SHLR(opcode); break; - case 0xd1: CMPPZ(opcode); break; - case 0xe1: SHAR(opcode); break; - case 0xf1: NOP(opcode); break; - // 0x20 - case 0x02: STSMMACH(opcode); break; - case 0x12: STSMMACL(opcode); break; - case 0x22: STSMPR(opcode); break; - case 0x32: STCMSGR(opcode); break; - case 0x42: NOP(opcode); break; - case 0x52: STSMFPUL(opcode); break; - case 0x62: STSMFPSCR(opcode); break; - case 0x72: NOP(opcode); break; - case 0x82: NOP(opcode); break; - case 0x92: NOP(opcode); break; - case 0xa2: NOP(opcode); break; - case 0xb2: NOP(opcode); break; - case 0xc2: NOP(opcode); break; - case 0xd2: NOP(opcode); break; - case 0xe2: NOP(opcode); break; - case 0xf2: STCMDBR(opcode); break; - // 0x30 - case 0x03: STCMSR(opcode); break; - case 0x13: STCMGBR(opcode); break; - case 0x23: STCMVBR(opcode); break; - case 0x33: STCMSSR(opcode); break; - case 0x43: STCMSPC(opcode); break; - case 0x53: NOP(opcode); break; - case 0x63: NOP(opcode); break; - case 0x73: NOP(opcode); break; - case 0x83: STCMRBANK(opcode); break; - case 0x93: STCMRBANK(opcode); break; - case 0xa3: STCMRBANK(opcode); break; - case 0xb3: STCMRBANK(opcode); break; - case 0xc3: STCMRBANK(opcode); break; - case 0xd3: STCMRBANK(opcode); break; - case 0xe3: STCMRBANK(opcode); break; - case 0xf3: STCMRBANK(opcode); break; - // 0x40 - case 0x04: ROTL(opcode); break; - case 0x14: NOP(opcode); break; - case 0x24: ROTCL(opcode); break; - case 0x34: NOP(opcode); break; - case 0x44: ROTL(opcode); break; - case 0x54: NOP(opcode); break; - case 0x64: ROTCL(opcode); break; - case 0x74: NOP(opcode); break; - case 0x84: ROTL(opcode); break; - case 0x94: NOP(opcode); break; - case 0xa4: ROTCL(opcode); break; - case 0xb4: NOP(opcode); break; - case 0xc4: ROTL(opcode); break; - case 0xd4: NOP(opcode); break; - case 0xe4: ROTCL(opcode); break; - case 0xf4: NOP(opcode); break; - // 0x50 - case 0x05: ROTR(opcode); break; - case 0x15: CMPPL(opcode); break; - case 0x25: ROTCR(opcode); break; - case 0x35: NOP(opcode); break; - case 0x45: ROTR(opcode); break; - case 0x55: CMPPL(opcode); break; - case 0x65: ROTCR(opcode); break; - case 0x75: NOP(opcode); break; - case 0x85: ROTR(opcode); break; - case 0x95: CMPPL(opcode); break; - case 0xa5: ROTCR(opcode); break; - case 0xb5: NOP(opcode); break; - case 0xc5: ROTR(opcode); break; - case 0xd5: CMPPL(opcode); break; - case 0xe5: ROTCR(opcode); break; - case 0xf5: NOP(opcode); break; - // 0x60 - case 0x06: LDSMMACH(opcode); break; - case 0x16: LDSMMACL(opcode); break; - case 0x26: LDSMPR(opcode); break; - case 0x36: NOP(opcode); break; - case 0x46: NOP(opcode); break; - case 0x56: LDSMFPUL(opcode); break; - case 0x66: LDSMFPSCR(opcode); break; - case 0x76: NOP(opcode); break; - case 0x86: NOP(opcode); break; - case 0x96: NOP(opcode); break; - case 0xa6: NOP(opcode); break; - case 0xb6: NOP(opcode); break; - case 0xc6: NOP(opcode); break; - case 0xd6: NOP(opcode); break; - case 0xe6: NOP(opcode); break; - case 0xf6: LDCMDBR(opcode); break; - // 0x70 - case 0x07: LDCMSR(opcode); break; - case 0x17: LDCMGBR(opcode); break; - case 0x27: LDCMVBR(opcode); break; - case 0x37: LDCMSSR(opcode); break; - case 0x47: LDCMSPC(opcode); break; - case 0x57: NOP(opcode); break; - case 0x67: NOP(opcode); break; - case 0x77: NOP(opcode); break; - case 0x87: LDCMRBANK(opcode); break; - case 0x97: LDCMRBANK(opcode); break; - case 0xa7: LDCMRBANK(opcode); break; - case 0xb7: LDCMRBANK(opcode); break; - case 0xc7: LDCMRBANK(opcode); break; - case 0xd7: LDCMRBANK(opcode); break; - case 0xe7: LDCMRBANK(opcode); break; - case 0xf7: LDCMRBANK(opcode); break; - // 0x80 - case 0x08: SHLL2(opcode); break; - case 0x18: SHLL8(opcode); break; - case 0x28: SHLL16(opcode); break; - case 0x38: NOP(opcode); break; - case 0x48: SHLL2(opcode); break; - case 0x58: SHLL8(opcode); break; - case 0x68: SHLL16(opcode); break; - case 0x78: NOP(opcode); break; - case 0x88: SHLL2(opcode); break; - case 0x98: SHLL8(opcode); break; - case 0xa8: SHLL16(opcode); break; - case 0xb8: NOP(opcode); break; - case 0xc8: SHLL2(opcode); break; - case 0xd8: SHLL8(opcode); break; - case 0xe8: SHLL16(opcode); break; - case 0xf8: NOP(opcode); break; - // 0x90 - case 0x09: SHLR2(opcode); break; - case 0x19: SHLR8(opcode); break; - case 0x29: SHLR16(opcode); break; - case 0x39: NOP(opcode); break; - case 0x49: SHLR2(opcode); break; - case 0x59: SHLR8(opcode); break; - case 0x69: SHLR16(opcode); break; - case 0x79: NOP(opcode); break; - case 0x89: SHLR2(opcode); break; - case 0x99: SHLR8(opcode); break; - case 0xa9: SHLR16(opcode); break; - case 0xb9: NOP(opcode); break; - case 0xc9: SHLR2(opcode); break; - case 0xd9: SHLR8(opcode); break; - case 0xe9: SHLR16(opcode); break; - case 0xf9: NOP(opcode); break; - // 0xa0 - case 0x0a: LDSMACH(opcode); break; - case 0x1a: LDSMACL(opcode); break; - case 0x2a: LDSPR(opcode); break; - case 0x3a: NOP(opcode); break; - case 0x4a: NOP(opcode); break; - case 0x5a: LDSFPUL(opcode); break; - case 0x6a: LDSFPSCR(opcode); break; - case 0x7a: NOP(opcode); break; - case 0x8a: NOP(opcode); break; - case 0x9a: NOP(opcode); break; - case 0xaa: NOP(opcode); break; - case 0xba: NOP(opcode); break; - case 0xca: NOP(opcode); break; - case 0xda: NOP(opcode); break; - case 0xea: NOP(opcode); break; - case 0xfa: LDCDBR(opcode); break; - // 0xb0 - case 0x0b: JSR(opcode); break; - case 0x1b: TAS(opcode); break; - case 0x2b: JMP(opcode); break; - case 0x3b: NOP(opcode); break; - case 0x4b: JSR(opcode); break; - case 0x5b: TAS(opcode); break; - case 0x6b: JMP(opcode); break; - case 0x7b: NOP(opcode); break; - case 0x8b: JSR(opcode); break; - case 0x9b: TAS(opcode); break; - case 0xab: JMP(opcode); break; - case 0xbb: NOP(opcode); break; - case 0xcb: JSR(opcode); break; - case 0xdb: TAS(opcode); break; - case 0xeb: JMP(opcode); break; - case 0xfb: NOP(opcode); break; - // 0xc0 - case 0x0c: SHAD(opcode); break; - case 0x1c: SHAD(opcode); break; - case 0x2c: SHAD(opcode); break; - case 0x3c: SHAD(opcode); break; - case 0x4c: SHAD(opcode); break; - case 0x5c: SHAD(opcode); break; - case 0x6c: SHAD(opcode); break; - case 0x7c: SHAD(opcode); break; - case 0x8c: SHAD(opcode); break; - case 0x9c: SHAD(opcode); break; - case 0xac: SHAD(opcode); break; - case 0xbc: SHAD(opcode); break; - case 0xcc: SHAD(opcode); break; - case 0xdc: SHAD(opcode); break; - case 0xec: SHAD(opcode); break; - case 0xfc: SHAD(opcode); break; - // 0xd0 - case 0x0d: SHLD(opcode); break; - case 0x1d: SHLD(opcode); break; - case 0x2d: SHLD(opcode); break; - case 0x3d: SHLD(opcode); break; - case 0x4d: SHLD(opcode); break; - case 0x5d: SHLD(opcode); break; - case 0x6d: SHLD(opcode); break; - case 0x7d: SHLD(opcode); break; - case 0x8d: SHLD(opcode); break; - case 0x9d: SHLD(opcode); break; - case 0xad: SHLD(opcode); break; - case 0xbd: SHLD(opcode); break; - case 0xcd: SHLD(opcode); break; - case 0xdd: SHLD(opcode); break; - case 0xed: SHLD(opcode); break; - case 0xfd: SHLD(opcode); break; - // 0xe0 - case 0x0e: LDCSR(opcode); break; - case 0x1e: LDCGBR(opcode); break; - case 0x2e: LDCVBR(opcode); break; - case 0x3e: LDCSSR(opcode); break; - case 0x4e: LDCSPC(opcode); break; - case 0x5e: NOP(opcode); break; - case 0x6e: NOP(opcode); break; - case 0x7e: NOP(opcode); break; - case 0x8e: LDCRBANK(opcode); break; - case 0x9e: LDCRBANK(opcode); break; - case 0xae: LDCRBANK(opcode); break; - case 0xbe: LDCRBANK(opcode); break; - case 0xce: LDCRBANK(opcode); break; - case 0xde: LDCRBANK(opcode); break; - case 0xee: LDCRBANK(opcode); break; - case 0xfe: LDCRBANK(opcode); break; - // 0xf0 - case 0x0f: MAC_W(opcode); break; - case 0x1f: MAC_W(opcode); break; - case 0x2f: MAC_W(opcode); break; - case 0x3f: MAC_W(opcode); break; - case 0x4f: MAC_W(opcode); break; - case 0x5f: MAC_W(opcode); break; - case 0x6f: MAC_W(opcode); break; - case 0x7f: MAC_W(opcode); break; - case 0x8f: MAC_W(opcode); break; - case 0x9f: MAC_W(opcode); break; - case 0xaf: MAC_W(opcode); break; - case 0xbf: MAC_W(opcode); break; - case 0xcf: MAC_W(opcode); break; - case 0xdf: MAC_W(opcode); break; - case 0xef: MAC_W(opcode); break; - case 0xff: MAC_W(opcode); break; - } -} - -inline void sh34_base_device::execute_one(const uint16_t opcode) -{ - switch(opcode & 0xf000) + default: // LDCMSR (0x0e) has sh2/4 flag difference + // fall through to SH2 handlers + sh_common_execution::execute_one_4000(opcode); break; + + case 0x42: + case 0x46: + case 0x4a: + case 0x53: + case 0x57: + case 0x5e: + case 0x63: + case 0x67: + case 0x6e: + case 0x82: + case 0x86: + case 0x8a: + case 0x92: + case 0x96: + case 0x9a: + case 0xa2: + case 0xa6: + case 0xaa: + case 0xc2: + case 0xc6: + case 0xca: + case 0xd2: + case 0xd6: + case 0xda: + case 0xe2: + case 0xe6: + case 0xea: + ILLEGAL(); break; // defined as illegal on SH4 + + case 0x0c: + case 0x1c: + case 0x2c: + case 0x3c: + case 0x4c: + case 0x5c: + case 0x6c: + case 0x7c: + case 0x8c: + case 0x9c: + case 0xac: + case 0xbc: + case 0xcc: + case 0xdc: + case 0xec: + case 0xfc: + SHAD(opcode); break; // sh3/4 only + + case 0x0d: + case 0x1d: + case 0x2d: + case 0x3d: + case 0x4d: + case 0x5d: + case 0x6d: + case 0x7d: + case 0x8d: + case 0x9d: + case 0xad: + case 0xbd: + case 0xcd: + case 0xdd: + case 0xed: + case 0xfd: + SHLD(opcode); break; // sh3/4 only + + case 0x8e: + case 0x9e: + case 0xae: + case 0xbe: + case 0xce: + case 0xde: + case 0xee: + case 0xfe: + LDCRBANK(opcode); break; // sh3/4 only + + case 0x83: + case 0x93: + case 0xa3: + case 0xb3: + case 0xc3: + case 0xd3: + case 0xe3: + case 0xf3: + STCMRBANK(opcode); break; // sh3/4 only + + case 0x87: + case 0x97: + case 0xa7: + case 0xb7: + case 0xc7: + case 0xd7: + case 0xe7: + case 0xf7: + LDCMRBANK(opcode); break; // sh3/4 only + + case 0x32: STCMSGR(opcode); break; // sh4 only + case 0x33: STCMSSR(opcode); break; // sh4 only + case 0x37: LDCMSSR(opcode); break; // sh4 only + case 0x3e: LDCSSR(opcode); break; // sh4 only + case 0x43: STCMSPC(opcode); break; // sh4 only + case 0x47: LDCMSPC(opcode); break; // sh4 only + case 0x4e: LDCSPC(opcode); break; // sh4 only + case 0x52: STSMFPUL(opcode); break; // sh4 only + case 0x56: LDSMFPUL(opcode); break; // sh4 only + case 0x5a: LDSFPUL(opcode); break; // sh4 only + case 0x62: STSMFPSCR(opcode); break; // sh4 only + case 0x66: LDSMFPSCR(opcode); break; // sh4 only + case 0x6a: LDSFPSCR(opcode); break; // sh4 only + case 0xf2: STCMDBR(opcode); break; // sh4 only + case 0xf6: LDCMDBR(opcode); break; // sh4 only + case 0xfa: LDCDBR(opcode); break; // sh4 only + + } +} + +inline void sh34_base_device::execute_one_f000(const uint16_t opcode) +{ + // the SH3 doesn't have these? + + switch (opcode & 0x0f) { - case 0x0000: - execute_one_0000(opcode); - break; - - case 0x1000: - MOVLS4(opcode); - break; - - case 0x2000: - switch(opcode & 0x0f) - { - case 0x00: MOVBS(opcode); break; - case 0x01: MOVWS(opcode); break; - case 0x02: MOVLS(opcode); break; - case 0x03: NOP(opcode); break; - case 0x04: MOVBM(opcode); break; - case 0x05: MOVWM(opcode); break; - case 0x06: MOVLM(opcode); break; - case 0x07: DIV0S(opcode); break; - case 0x08: TST(opcode); break; - case 0x09: AND(opcode); break; - case 0x0a: XOR(opcode); break; - case 0x0b: OR(opcode); break; - case 0x0c: CMPSTR(opcode); break; - case 0x0d: XTRCT(opcode); break; - case 0x0e: MULU(opcode); break; - case 0x0f: MULS(opcode); break; - } - break; - - case 0x3000: - switch(opcode & 0x0f) - { - case 0x00: CMPEQ(opcode); break; - case 0x01: NOP(opcode); break; - case 0x02: CMPHS(opcode); break; - case 0x03: CMPGE(opcode); break; - case 0x04: DIV1(opcode); break; - case 0x05: DMULU(opcode); break; - case 0x06: CMPHI(opcode); break; - case 0x07: CMPGT(opcode); break; - case 0x08: SUB(opcode); break; - case 0x09: NOP(opcode); break; - case 0x0a: SUBC(opcode); break; - case 0x0b: SUBV(opcode); break; - case 0x0c: ADD(opcode); break; - case 0x0d: DMULS(opcode); break; - case 0x0e: ADDC(opcode); break; - case 0x0f: ADDV(opcode); break; - } - break; - - case 0x4000: - execute_one_4000(opcode); - break; - - case 0x5000: - MOVLL4(opcode); - break; - - case 0x6000: - switch(opcode & 0x0f) - { - case 0x00: MOVBL(opcode); break; - case 0x01: MOVWL(opcode); break; - case 0x02: MOVLL(opcode); break; - case 0x03: MOV(opcode); break; - case 0x04: MOVBP(opcode); break; - case 0x05: MOVWP(opcode); break; - case 0x06: MOVLP(opcode); break; - case 0x07: NOT(opcode); break; - case 0x08: SWAPB(opcode); break; - case 0x09: SWAPW(opcode); break; - case 0x0a: NEGC(opcode); break; - case 0x0b: NEG(opcode); break; - case 0x0c: EXTUB(opcode); break; - case 0x0d: EXTUW(opcode); break; - case 0x0e: EXTSB(opcode); break; - case 0x0f: EXTSW(opcode); break; - } - break; - - case 0x7000: - ADDI(opcode); - break; - - case 0x8000: - switch((opcode >> 8) & 0x0f) - { - case 0x00: MOVBS4(opcode); break; - case 0x01: MOVWS4(opcode); break; - case 0x02: NOP(opcode); break; - case 0x03: NOP(opcode); break; - case 0x04: MOVBL4(opcode); break; - case 0x05: MOVWL4(opcode); break; - case 0x06: NOP(opcode); break; - case 0x07: NOP(opcode); break; - case 0x08: CMPIM(opcode); break; - case 0x09: BT(opcode); break; - case 0x0a: NOP(opcode); break; - case 0x0b: BF(opcode); break; - case 0x0c: NOP(opcode); break; - case 0x0d: BTS(opcode); break; - case 0x0e: NOP(opcode); break; - case 0x0f: BFS(opcode); break; - } - break; - - case 0x9000: - MOVWI(opcode); - break; - - case 0xa000: - BRA(opcode); - break; - - case 0xb000: - BSR(opcode); - break; - - case 0xc000: - switch((opcode >> 8) & 0x0f) - { - case 0x00: MOVBSG(opcode); break; - case 0x01: MOVWSG(opcode); break; - case 0x02: MOVLSG(opcode); break; - case 0x03: TRAPA(opcode); break; - case 0x04: MOVBLG(opcode); break; - case 0x05: MOVWLG(opcode); break; - case 0x06: MOVLLG(opcode); break; - case 0x07: MOVA(opcode); break; - case 0x08: TSTI(opcode); break; - case 0x09: ANDI(opcode); break; - case 0x0a: XORI(opcode); break; - case 0x0b: ORI(opcode); break; - case 0x0c: TSTM(opcode); break; - case 0x0d: ANDM(opcode); break; - case 0x0e: XORM(opcode); break; - case 0x0f: ORM(opcode); break; - } - break; - - case 0xd000: - MOVLI(opcode); - break; - - case 0xe000: - MOVI(opcode); - break; - - case 0xf000: - switch(opcode & 0x0f) - { - case 0x00: FADD(opcode); break; - case 0x01: FSUB(opcode); break; - case 0x02: FMUL(opcode); break; - case 0x03: FDIV(opcode); break; - case 0x04: FCMP_EQ(opcode); break; - case 0x05: FCMP_GT(opcode); break; - case 0x06: FMOVS0FR(opcode); break; - case 0x07: FMOVFRS0(opcode); break; - case 0x08: FMOVMRFR(opcode); break; - case 0x09: FMOVMRIFR(opcode); break; - case 0x0a: FMOVFRMR(opcode); break; - case 0x0b: FMOVFRMDR(opcode); break; - case 0x0c: FMOVFR(opcode); break; - case 0x0d: op1111_0x13(opcode); break; - case 0x0e: FMAC(opcode); break; - case 0x0f: dbreak(opcode); break; - } - break; + case 0x00: FADD(opcode); break; + case 0x01: FSUB(opcode); break; + case 0x02: FMUL(opcode); break; + case 0x03: FDIV(opcode); break; + case 0x04: FCMP_EQ(opcode); break; + case 0x05: FCMP_GT(opcode); break; + case 0x06: FMOVS0FR(opcode); break; + case 0x07: FMOVFRS0(opcode); break; + case 0x08: FMOVMRFR(opcode); break; + case 0x09: FMOVMRIFR(opcode); break; + case 0x0a: FMOVFRMR(opcode); break; + case 0x0b: FMOVFRMDR(opcode); break; + case 0x0c: FMOVFR(opcode); break; + case 0x0d: op1111_0x13(opcode); break; + case 0x0e: FMAC(opcode); break; + case 0x0f: dbreak(opcode); break; } } - /* Execute cycles - returns number of cycles actually run */ void sh34_base_device::execute_run() { + if ( m_isdrc ) + { + execute_run_drc(); + return; + } + if (m_cpu_off) { - m_sh4_icount = 0; + m_sh2_state->icount = 0; return; } do { - m_ppc = m_pc & AM; - debugger_instruction_hook(this, m_pc & AM); + m_ppc = m_sh2_state->pc & SH34_AM; + debugger_instruction_hook(this, m_sh2_state->pc & SH34_AM); uint16_t opcode; - if (!m_sh4_mmu_enabled) opcode = m_direct->read_word(m_pc & AM, WORD2_XOR_LE(0)); - else opcode = RW(m_pc); // should probably use a different function as this needs to go through the ITLB + if (!m_sh4_mmu_enabled) opcode = m_direct->read_word(m_sh2_state->pc & SH34_AM, WORD2_XOR_LE(0)); + else opcode = RW(m_sh2_state->pc); // should probably use a different function as this needs to go through the ITLB - if (m_delay) + if (m_sh2_state->m_delay) { - m_pc = m_delay; - m_delay = 0; + m_sh2_state->pc = m_sh2_state->m_delay; + m_sh2_state->m_delay = 0; } else - m_pc += 2; + m_sh2_state->pc += 2; execute_one(opcode); - if (m_test_irq && !m_delay) + if (m_test_irq && !m_sh2_state->m_delay) { sh4_check_pending_irq("mame_sh4_execute"); } - m_sh4_icount--; - } while( m_sh4_icount > 0 ); + m_sh2_state->icount--; + } while (m_sh2_state->icount > 0); } void sh3be_device::execute_run() { + if ( m_isdrc ) + { + execute_run_drc(); + return; + } + if (m_cpu_off) { - m_sh4_icount = 0; + m_sh2_state->icount = 0; return; } do { - m_ppc = m_pc & AM; - debugger_instruction_hook(this, m_pc & AM); + m_ppc = m_sh2_state->pc & SH34_AM; + debugger_instruction_hook(this, m_sh2_state->pc & SH34_AM); - const uint16_t opcode = m_direct->read_word(m_pc & AM, WORD_XOR_LE(6)); + const uint16_t opcode = m_direct->read_word(m_sh2_state->pc & SH34_AM, WORD_XOR_LE(6)); - if (m_delay) + if (m_sh2_state->m_delay) { - m_pc = m_delay; - m_delay = 0; + m_sh2_state->pc = m_sh2_state->m_delay; + m_sh2_state->m_delay = 0; } else - m_pc += 2; + m_sh2_state->pc += 2; execute_one(opcode); - if (m_test_irq && !m_delay) + if (m_test_irq && !m_sh2_state->m_delay) { sh4_check_pending_irq("mame_sh4_execute"); } - m_sh4_icount--; - } while( m_sh4_icount > 0 ); + m_sh2_state->icount--; + } while (m_sh2_state->icount > 0); } void sh4be_device::execute_run() { + if ( m_isdrc ) + { + execute_run_drc(); + return; + } + if (m_cpu_off) { - m_sh4_icount = 0; + m_sh2_state->icount = 0; return; } do { - m_ppc = m_pc & AM; - debugger_instruction_hook(this, m_pc & AM); + m_ppc = m_sh2_state->pc & SH34_AM; + debugger_instruction_hook(this, m_sh2_state->pc & SH34_AM); - const uint16_t opcode = m_direct->read_word(m_pc & AM, WORD_XOR_LE(6)); + const uint16_t opcode = m_direct->read_word(m_sh2_state->pc & SH34_AM, WORD_XOR_LE(6)); - if (m_delay) + if (m_sh2_state->m_delay) { - m_pc = m_delay; - m_delay = 0; + m_sh2_state->pc = m_sh2_state->m_delay; + m_sh2_state->m_delay = 0; } else - m_pc += 2; + m_sh2_state->pc += 2; execute_one(opcode); - if (m_test_irq && !m_delay) + if (m_test_irq && !m_sh2_state->m_delay) { sh4_check_pending_irq("mame_sh4_execute"); } - m_sh4_icount--; - } while( m_sh4_icount > 0 ); + m_sh2_state->icount--; + } while (m_sh2_state->icount > 0); } void sh4_base_device::device_start() @@ -4185,7 +1990,7 @@ void sh4_base_device::device_start() sh34_base_device::device_start(); int i; - for (i=0;i<64;i++) + for (i = 0;i < 64;i++) { m_utlb[i].ASID = 0; m_utlb[i].VPN = 0; @@ -4201,7 +2006,7 @@ void sh4_base_device::device_start() m_utlb[i].TC = 0; } - for (i=0;i<64;i++) + for (i = 0;i < 64;i++) { save_item(NAME(m_utlb[i].ASID), i); save_item(NAME(m_utlb[i].VPN), i); @@ -4216,20 +2021,23 @@ void sh4_base_device::device_start() save_item(NAME(m_utlb[i].SA), i); save_item(NAME(m_utlb[i].TC), i); } - } void sh34_base_device::device_start() { - for (int i=0; i<3; i++) + m_isdrc = allow_drc(); + + sh_common_execution::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]->adjust(attotime::never, i); } - for (int i=0; i<4; 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]->adjust(attotime::never, i); @@ -4247,19 +2055,12 @@ void sh34_base_device::device_start() m_internal = &space(AS_PROGRAM); m_program = &space(AS_PROGRAM); m_io = &space(AS_IO); - m_direct = &m_program->direct(); + m_direct = m_program->direct<0>(); sh4_default_exception_priorities(); m_irln = 15; m_test_irq = 0; - save_item(NAME(m_pc)); - save_item(NAME(m_r)); - save_item(NAME(m_sr)); - save_item(NAME(m_pr)); - save_item(NAME(m_gbr)); - save_item(NAME(m_vbr)); - save_item(NAME(m_mach)); - save_item(NAME(m_macl)); + save_item(NAME(m_spc)); save_item(NAME(m_ssr)); save_item(NAME(m_sgr)); @@ -4267,8 +2068,7 @@ void sh34_base_device::device_start() save_item(NAME(m_rbnk)); save_item(NAME(m_fr)); save_item(NAME(m_xf)); - save_item(NAME(m_ea)); - save_item(NAME(m_delay)); + save_item(NAME(m_cpu_off)); save_item(NAME(m_pending_irq)); save_item(NAME(m_test_irq)); @@ -4306,7 +2106,7 @@ void sh34_base_device::device_start() save_item(NAME(m_SH4_DMATCR3)); save_item(NAME(m_SH4_DMAOR)); save_item(NAME(m_nmi_line_state)); - save_item(NAME(m_sleep_mode)); + save_item(NAME(m_frt_input)); save_item(NAME(m_irln)); save_item(NAME(m_internal_irq_level)); @@ -4320,11 +2120,12 @@ void sh34_base_device::device_start() save_item(NAME(m_dma_source_increment)); save_item(NAME(m_dma_destination_increment)); save_item(NAME(m_dma_mode)); - save_item(NAME(m_sh4_icount)); + + save_item(NAME(m_fpu_sz)); save_item(NAME(m_fpu_pr)); save_item(NAME(m_ioport16_pullup)); - save_item(NAME( m_ioport16_direction)); + save_item(NAME(m_ioport16_direction)); save_item(NAME(m_ioport4_pullup)); save_item(NAME(m_ioport4_direction)); save_item(NAME(m_sh4_mmu_enabled)); @@ -4333,92 +2134,70 @@ void sh34_base_device::device_start() // Debugger state - state_add(SH4_PC, "PC", m_pc).formatstr("%08X").callimport(); - state_add(SH4_SR, "SR", m_sr).formatstr("%08X").callimport(); - state_add(SH4_PR, "PR", m_pr).formatstr("%08X"); - state_add(SH4_GBR, "GBR", m_gbr).formatstr("%08X"); - state_add(SH4_VBR, "VBR", m_vbr).formatstr("%08X"); - state_add(SH4_DBR, "DBR", m_dbr).formatstr("%08X"); - state_add(SH4_MACH, "MACH", m_mach).formatstr("%08X"); - state_add(SH4_MACL, "MACL", m_macl).formatstr("%08X"); - state_add(SH4_R0, "R0", m_r[ 0]).formatstr("%08X"); - state_add(SH4_R1, "R1", m_r[ 1]).formatstr("%08X"); - state_add(SH4_R2, "R2", m_r[ 2]).formatstr("%08X"); - state_add(SH4_R3, "R3", m_r[ 3]).formatstr("%08X"); - state_add(SH4_R4, "R4", m_r[ 4]).formatstr("%08X"); - state_add(SH4_R5, "R5", m_r[ 5]).formatstr("%08X"); - state_add(SH4_R6, "R6", m_r[ 6]).formatstr("%08X"); - state_add(SH4_R7, "R7", m_r[ 7]).formatstr("%08X"); - state_add(SH4_R8, "R8", m_r[ 8]).formatstr("%08X"); - state_add(SH4_R9, "R9", m_r[ 9]).formatstr("%08X"); - state_add(SH4_R10, "R10", m_r[10]).formatstr("%08X"); - state_add(SH4_R11, "R11", m_r[11]).formatstr("%08X"); - state_add(SH4_R12, "R12", m_r[12]).formatstr("%08X"); - state_add(SH4_R13, "R13", m_r[13]).formatstr("%08X"); - state_add(SH4_R14, "R14", m_r[14]).formatstr("%08X"); - state_add(SH4_R15, "R15", m_r[15]).formatstr("%08X"); - state_add(SH4_EA, "EA", m_ea).formatstr("%08X"); - state_add(SH4_R0_BK0, "R0 BK 0", m_rbnk[0][0]).formatstr("%08X"); - state_add(SH4_R1_BK0, "R1 BK 0", m_rbnk[0][1]).formatstr("%08X"); - state_add(SH4_R2_BK0, "R2 BK 0", m_rbnk[0][2]).formatstr("%08X"); - state_add(SH4_R3_BK0, "R3 BK 0", m_rbnk[0][3]).formatstr("%08X"); - state_add(SH4_R4_BK0, "R4 BK 0", m_rbnk[0][4]).formatstr("%08X"); - state_add(SH4_R5_BK0, "R5 BK 0", m_rbnk[0][5]).formatstr("%08X"); - state_add(SH4_R6_BK0, "R6 BK 0", m_rbnk[0][6]).formatstr("%08X"); - state_add(SH4_R7_BK0, "R7 BK 0", m_rbnk[0][7]).formatstr("%08X"); - state_add(SH4_R0_BK1, "R0 BK 1", m_rbnk[1][0]).formatstr("%08X"); - state_add(SH4_R1_BK1, "R1 BK 1", m_rbnk[1][1]).formatstr("%08X"); - state_add(SH4_R2_BK1, "R2 BK 1", m_rbnk[1][2]).formatstr("%08X"); - state_add(SH4_R3_BK1, "R3 BK 1", m_rbnk[1][3]).formatstr("%08X"); - state_add(SH4_R4_BK1, "R4 BK 1", m_rbnk[1][4]).formatstr("%08X"); - state_add(SH4_R5_BK1, "R5 BK 1", m_rbnk[1][5]).formatstr("%08X"); - state_add(SH4_R6_BK1, "R6 BK 1", m_rbnk[1][6]).formatstr("%08X"); - state_add(SH4_R7_BK1, "R7 BK 1", m_rbnk[1][7]).formatstr("%08X"); - state_add(SH4_SPC, "SPC", m_spc).formatstr("%08X"); - state_add(SH4_SSR, "SSR", m_ssr).formatstr("%08X"); - state_add(SH4_SGR, "SGR", m_sgr).formatstr("%08X"); - state_add(SH4_FPSCR, "FPSCR", m_fpscr).formatstr("%08X"); - state_add(SH4_FPUL, "FPUL", m_fpul).formatstr("%08X"); - - state_add(SH4_FR0, "FR0", m_debugger_temp).callimport().formatstr("%25s"); - state_add(SH4_FR1, "FR1", m_debugger_temp).callimport().formatstr("%25s"); - state_add(SH4_FR2, "FR2", m_debugger_temp).callimport().formatstr("%25s"); - state_add(SH4_FR3, "FR3", m_debugger_temp).callimport().formatstr("%25s"); - state_add(SH4_FR4, "FR4", m_debugger_temp).callimport().formatstr("%25s"); - state_add(SH4_FR5, "FR5", m_debugger_temp).callimport().formatstr("%25s"); - state_add(SH4_FR6, "FR6", m_debugger_temp).callimport().formatstr("%25s"); - state_add(SH4_FR7, "FR7", m_debugger_temp).callimport().formatstr("%25s"); - state_add(SH4_FR8, "FR8", m_debugger_temp).callimport().formatstr("%25s"); - state_add(SH4_FR9, "FR9", m_debugger_temp).callimport().formatstr("%25s"); - state_add(SH4_FR10, "FR10", m_debugger_temp).callimport().formatstr("%25s"); - state_add(SH4_FR11, "FR11", m_debugger_temp).callimport().formatstr("%25s"); - state_add(SH4_FR12, "FR12", m_debugger_temp).callimport().formatstr("%25s"); - state_add(SH4_FR13, "FR13", m_debugger_temp).callimport().formatstr("%25s"); - state_add(SH4_FR14, "FR14", m_debugger_temp).callimport().formatstr("%25s"); - state_add(SH4_FR15, "FR15", m_debugger_temp).callimport().formatstr("%25s"); - state_add(SH4_XF0, "XF0", m_debugger_temp).callimport().formatstr("%25s"); - state_add(SH4_XF1, "XF1", m_debugger_temp).callimport().formatstr("%25s"); - state_add(SH4_XF2, "XF2", m_debugger_temp).callimport().formatstr("%25s"); - state_add(SH4_XF3, "XF3", m_debugger_temp).callimport().formatstr("%25s"); - state_add(SH4_XF4, "XF4", m_debugger_temp).callimport().formatstr("%25s"); - state_add(SH4_XF5, "XF5", m_debugger_temp).callimport().formatstr("%25s"); - state_add(SH4_XF6, "XF6", m_debugger_temp).callimport().formatstr("%25s"); - state_add(SH4_XF7, "XF7", m_debugger_temp).callimport().formatstr("%25s"); - state_add(SH4_XF8, "XF8", m_debugger_temp).callimport().formatstr("%25s"); - state_add(SH4_XF9, "XF9", m_debugger_temp).callimport().formatstr("%25s"); - state_add(SH4_XF10, "XF10", m_debugger_temp).callimport().formatstr("%25s"); - state_add(SH4_XF11, "XF11", m_debugger_temp).callimport().formatstr("%25s"); - state_add(SH4_XF12, "XF12", m_debugger_temp).callimport().formatstr("%25s"); - state_add(SH4_XF13, "XF13", m_debugger_temp).callimport().formatstr("%25s"); - state_add(SH4_XF14, "XF14", m_debugger_temp).callimport().formatstr("%25s"); - state_add(SH4_XF15, "XF15", m_debugger_temp).callimport().formatstr("%25s"); + + state_add(SH4_DBR, "DBR", m_dbr).formatstr("%08X"); + + state_add(SH4_R0_BK0, "R0 BK 0", m_rbnk[0][0]).formatstr("%08X"); + state_add(SH4_R1_BK0, "R1 BK 0", m_rbnk[0][1]).formatstr("%08X"); + state_add(SH4_R2_BK0, "R2 BK 0", m_rbnk[0][2]).formatstr("%08X"); + state_add(SH4_R3_BK0, "R3 BK 0", m_rbnk[0][3]).formatstr("%08X"); + state_add(SH4_R4_BK0, "R4 BK 0", m_rbnk[0][4]).formatstr("%08X"); + state_add(SH4_R5_BK0, "R5 BK 0", m_rbnk[0][5]).formatstr("%08X"); + state_add(SH4_R6_BK0, "R6 BK 0", m_rbnk[0][6]).formatstr("%08X"); + state_add(SH4_R7_BK0, "R7 BK 0", m_rbnk[0][7]).formatstr("%08X"); + state_add(SH4_R0_BK1, "R0 BK 1", m_rbnk[1][0]).formatstr("%08X"); + state_add(SH4_R1_BK1, "R1 BK 1", m_rbnk[1][1]).formatstr("%08X"); + state_add(SH4_R2_BK1, "R2 BK 1", m_rbnk[1][2]).formatstr("%08X"); + state_add(SH4_R3_BK1, "R3 BK 1", m_rbnk[1][3]).formatstr("%08X"); + state_add(SH4_R4_BK1, "R4 BK 1", m_rbnk[1][4]).formatstr("%08X"); + state_add(SH4_R5_BK1, "R5 BK 1", m_rbnk[1][5]).formatstr("%08X"); + state_add(SH4_R6_BK1, "R6 BK 1", m_rbnk[1][6]).formatstr("%08X"); + state_add(SH4_R7_BK1, "R7 BK 1", m_rbnk[1][7]).formatstr("%08X"); + state_add(SH4_SPC, "SPC", m_spc).formatstr("%08X"); + state_add(SH4_SSR, "SSR", m_ssr).formatstr("%08X"); + state_add(SH4_SGR, "SGR", m_sgr).formatstr("%08X"); + state_add(SH4_FPSCR, "FPSCR", m_fpscr).formatstr("%08X"); + state_add(SH4_FPUL, "FPUL", m_fpul).formatstr("%08X"); + + state_add(SH4_FR0, "FR0", m_debugger_temp).callimport().formatstr("%25s"); + state_add(SH4_FR1, "FR1", m_debugger_temp).callimport().formatstr("%25s"); + state_add(SH4_FR2, "FR2", m_debugger_temp).callimport().formatstr("%25s"); + state_add(SH4_FR3, "FR3", m_debugger_temp).callimport().formatstr("%25s"); + state_add(SH4_FR4, "FR4", m_debugger_temp).callimport().formatstr("%25s"); + state_add(SH4_FR5, "FR5", m_debugger_temp).callimport().formatstr("%25s"); + state_add(SH4_FR6, "FR6", m_debugger_temp).callimport().formatstr("%25s"); + state_add(SH4_FR7, "FR7", m_debugger_temp).callimport().formatstr("%25s"); + state_add(SH4_FR8, "FR8", m_debugger_temp).callimport().formatstr("%25s"); + state_add(SH4_FR9, "FR9", m_debugger_temp).callimport().formatstr("%25s"); + state_add(SH4_FR10, "FR10", m_debugger_temp).callimport().formatstr("%25s"); + state_add(SH4_FR11, "FR11", m_debugger_temp).callimport().formatstr("%25s"); + state_add(SH4_FR12, "FR12", m_debugger_temp).callimport().formatstr("%25s"); + state_add(SH4_FR13, "FR13", m_debugger_temp).callimport().formatstr("%25s"); + state_add(SH4_FR14, "FR14", m_debugger_temp).callimport().formatstr("%25s"); + state_add(SH4_FR15, "FR15", m_debugger_temp).callimport().formatstr("%25s"); + state_add(SH4_XF0, "XF0", m_debugger_temp).callimport().formatstr("%25s"); + state_add(SH4_XF1, "XF1", m_debugger_temp).callimport().formatstr("%25s"); + state_add(SH4_XF2, "XF2", m_debugger_temp).callimport().formatstr("%25s"); + state_add(SH4_XF3, "XF3", m_debugger_temp).callimport().formatstr("%25s"); + state_add(SH4_XF4, "XF4", m_debugger_temp).callimport().formatstr("%25s"); + state_add(SH4_XF5, "XF5", m_debugger_temp).callimport().formatstr("%25s"); + state_add(SH4_XF6, "XF6", m_debugger_temp).callimport().formatstr("%25s"); + state_add(SH4_XF7, "XF7", m_debugger_temp).callimport().formatstr("%25s"); + state_add(SH4_XF8, "XF8", m_debugger_temp).callimport().formatstr("%25s"); + state_add(SH4_XF9, "XF9", m_debugger_temp).callimport().formatstr("%25s"); + state_add(SH4_XF10, "XF10", m_debugger_temp).callimport().formatstr("%25s"); + state_add(SH4_XF11, "XF11", m_debugger_temp).callimport().formatstr("%25s"); + state_add(SH4_XF12, "XF12", m_debugger_temp).callimport().formatstr("%25s"); + state_add(SH4_XF13, "XF13", m_debugger_temp).callimport().formatstr("%25s"); + state_add(SH4_XF14, "XF14", m_debugger_temp).callimport().formatstr("%25s"); + state_add(SH4_XF15, "XF15", m_debugger_temp).callimport().formatstr("%25s"); state_add(STATE_GENPC, "GENPC", m_debugger_temp).callimport().callexport().noshow(); - state_add(STATE_GENPCBASE, "CURPC", m_ppc).noshow(); - state_add(STATE_GENSP, "GENSP", m_r[15]).noshow(); - state_add(STATE_GENFLAGS, "GENFLAGS", m_sr).formatstr("%20s").noshow(); + //state_add(STATE_GENPCBASE, "CURPC", m_ppc).noshow(); + state_add( STATE_GENPCBASE, "CURPC", m_sh2_state->pc ).callimport().noshow(); - m_icountptr = &m_sh4_icount; + + drc_start(); } void sh34_base_device::state_import(const device_state_entry &entry) @@ -4432,12 +2211,12 @@ void sh34_base_device::state_import(const device_state_entry &entry) switch (entry.index()) { case STATE_GENPC: - m_pc = m_debugger_temp; + m_sh2_state->pc = m_debugger_temp; case SH4_PC: - m_delay = 0; + m_sh2_state->m_delay = 0; break; - case SH4_SR: + case SH_SR: sh4_exception_recompute(); sh4_check_pending_irq("sh4_set_info"); break; @@ -4577,7 +2356,7 @@ void sh34_base_device::state_export(const device_state_entry &entry) switch (entry.index()) { case STATE_GENPC: - m_debugger_temp = (m_pc & AM); + m_debugger_temp = (m_sh2_state->pc & SH34_AM); break; } } @@ -4594,15 +2373,15 @@ void sh34_base_device::state_string_export(const device_state_entry &entry, std: { case STATE_GENFLAGS: str = string_format("%s%s%s%s%c%c%d%c%c", - m_sr & MD ? "MD ":" ", - m_sr & sRB ? "RB ":" ", - m_sr & BL ? "BL ":" ", - m_sr & FD ? "FD ":" ", - m_sr & M ? 'M':'.', - m_sr & Q ? 'Q':'.', - (m_sr & I) >> 4, - m_sr & S ? 'S':'.', - m_sr & T ? 'T':'.'); + m_sh2_state->sr & MD ? "MD ":" ", + m_sh2_state->sr & sRB ? "RB ":" ", + m_sh2_state->sr & BL ? "BL ":" ", + m_sh2_state->sr & FD ? "FD ":" ", + m_sh2_state->sr & SH_M ? 'M':'.', + m_sh2_state->sr & SH_Q ? 'Q':'.', + (m_sh2_state->sr & SH_I) >> 4, + m_sh2_state->sr & SH_S ? 'S':'.', + m_sh2_state->sr & SH_T ? 'T':'.'); break; case SH4_FR0: @@ -4736,8 +2515,1384 @@ void sh34_base_device::state_string_export(const device_state_entry &entry, std: } } - +/* void sh34_base_device::sh4_set_ftcsr_callback(sh4_ftcsr_callback callback) { - m_ftcsr_read_callback = callback; + m_ftcsr_read_callback = callback; +} +*/ + +using namespace uml; + +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) +{ + return m_drcfe->describe_code(pc); +} + +void sh4_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) +{ + 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() +{ + m_drcfe = std::make_unique<sh4_frontend>(this, COMPILE_BACKWARDS_BYTES, COMPILE_FORWARDS_BYTES, SINGLE_INSTRUCTION_MODE ? 1 : COMPILE_MAX_SEQUENCE); +} + +/*------------------------------------------------- + generate_update_cycles - generate code to + subtract cycles from the icount and generate + an exception if out +-------------------------------------------------*/ + +void sh34_base_device::func_CHECKIRQ() { if (m_test_irq) sh4_check_pending_irq("mame_sh4_execute"); } +static void cfunc_CHECKIRQ(void *param) { ((sh34_base_device *)param)->func_CHECKIRQ(); }; + +void sh34_base_device::generate_update_cycles(drcuml_block *block, compiler_state *compiler, uml::parameter param, bool allow_exception) +{ + /* check full interrupts if pending */ + if (compiler->checkints) + { + compiler->checkints = false; + + /* param is pc + 2 (the opcode after the current one) + as we're calling from opcode handlers here that will point to the current opcode instead + but I believe the exception function requires it to point to the next one so update the + local copy of the PC variable here for that? */ + UML_MOV(block, mem(&m_sh2_state->pc), param); + + // save_fast_iregs(block); + UML_CALLC(block, cfunc_CHECKIRQ, this); + load_fast_iregs(block); + + /* generate a hash jump via the current mode and PC + pc should be pointing to either the exception address + or have been left on the next PC set above? */ + UML_HASHJMP(block, 0, mem(&m_sh2_state->pc), *m_nocode); // hashjmp <mode>,<pc>,nocode + } + + /* account for cycles */ + if (compiler->cycles > 0) + { + UML_SUB(block, mem(&m_sh2_state->icount), mem(&m_sh2_state->icount), MAPVAR_CYCLES); // sub icount,icount,cycles + UML_MAPVAR(block, MAPVAR_CYCLES, 0); // mapvar cycles,0 + if (allow_exception) + UML_EXHc(block, COND_S, *m_out_of_cycles, param); + // exh out_of_cycles,nextpc + } + compiler->cycles = 0; +} + +/*------------------------------------------------- + static_generate_entry_point - generate a + static entry point +-------------------------------------------------*/ + + +void sh34_base_device::static_generate_entry_point() +{ + + drcuml_state *drcuml = m_drcuml.get(); + //code_label skip = 1; + drcuml_block *block; + + /* begin generating */ + block = drcuml->begin_block(200); + + /* forward references */ + alloc_handle(drcuml, &m_nocode, "nocode"); + alloc_handle(drcuml, &m_write32, "write32"); // necessary? + alloc_handle(drcuml, &m_entry, "entry"); + UML_HANDLE(block, *m_entry); // handle entry + + UML_CALLC(block, cfunc_CHECKIRQ, this); + load_fast_iregs(block); + + /* generate a hash jump via the current mode and PC */ + UML_HASHJMP(block, 0, mem(&m_sh2_state->pc), *m_nocode); // hashjmp <mode>,<pc>,nocode + + block->end(); + +} + + +/*------------------------------------------------------------------ + static_generate_memory_accessor +------------------------------------------------------------------*/ + +void sh34_base_device::static_generate_memory_accessor(int size, int iswrite, const char *name, code_handle **handleptr) +{ + /* on entry, address is in I0; data for writes is in I1 */ + /* on exit, read result is in I0 */ + /* routine trashes I0 */ + drcuml_state *drcuml = m_drcuml.get(); + drcuml_block *block; + int label = 1; + + /* begin generating */ + block = drcuml->begin_block(1024); + + /* add a global entry for this */ + alloc_handle(drcuml, handleptr, name); + UML_HANDLE(block, **handleptr); // handle *handleptr + +#if 0 + if (A >= 0xe0000000) + { + m_program->write_word(A, V); + return; + } + + if (A >= 0x80000000) // P1/P2/P3 region + { + m_program->write_word(A & SH34_AM, V); + } + else + { + // MMU handling + m_program->write_word(A & SH34_AM, V); + } +#endif + + UML_CMP(block, I0, 0xe0000000); + UML_JMPc(block, COND_AE, label); + + UML_AND(block, I0, I0, SH34_AM); // and r0, r0, #AM (0x1fffffff) + + UML_LABEL(block, label++); // label: + + for (auto & elem : m_fastram) + { + if (elem.base != nullptr && (!iswrite || !elem.readonly)) + { + void *fastbase = (uint8_t *)elem.base - elem.start; + uint32_t skip = label++; + if (elem.end != 0xffffffff) + { + UML_CMP(block, I0, elem.end); // cmp i0,end + UML_JMPc(block, COND_A, skip); // ja skip + } + if (elem.start != 0x00000000) + { + UML_CMP(block, I0, elem.start);// cmp i0,fastram_start + UML_JMPc(block, COND_B, skip); // jb skip + } + + if (!iswrite) + { + if (size == 1) + { + UML_XOR(block, I0, I0, m_bigendian ? BYTE8_XOR_BE(0) : BYTE8_XOR_LE(0)); + UML_LOAD(block, I0, fastbase, I0, SIZE_BYTE, SCALE_x1); // load i0,fastbase,i0,byte + } + else if (size == 2) + { + UML_XOR(block, I0, I0, m_bigendian ? WORD2_XOR_BE(0) : WORD2_XOR_LE(0)); + UML_LOAD(block, I0, fastbase, I0, SIZE_WORD, SCALE_x1); // load i0,fastbase,i0,word_x1 + } + else if (size == 4) + { + + UML_XOR(block, I0, I0, m_bigendian ? DWORD_XOR_BE(0) : DWORD_XOR_LE(0)); + UML_LOAD(block, I0, fastbase, I0, SIZE_DWORD, SCALE_x1); // load i0,fastbase,i0,dword_x1 + } + UML_RET(block); // ret + } + else + { + if (size == 1) + { + UML_XOR(block, I0, I0, m_bigendian ? BYTE8_XOR_BE(0) : BYTE8_XOR_LE(0)); + UML_STORE(block, fastbase, I0, I1, SIZE_BYTE, SCALE_x1);// store fastbase,i0,i1,byte + } + else if (size == 2) + { + UML_XOR(block, I0, I0, m_bigendian ? WORD2_XOR_BE(0) : WORD2_XOR_LE(0)); + UML_STORE(block, fastbase, I0, I1, SIZE_WORD, SCALE_x1);// store fastbase,i0,i1,word_x1 + } + else if (size == 4) + { + UML_XOR(block, I0, I0, m_bigendian ? DWORD_XOR_BE(0) : DWORD_XOR_LE(0)); + UML_STORE(block, fastbase, I0, I1, SIZE_DWORD, SCALE_x1); // store fastbase,i0,i1,dword_x1 + } + UML_RET(block); // ret + } + + UML_LABEL(block, skip); // skip: + } + } + + if (iswrite) + { + switch (size) + { + case 1: + UML_WRITE(block, I0, I1, SIZE_BYTE, SPACE_PROGRAM); // write r0, r1, program_byte + break; + + case 2: + UML_WRITE(block, I0, I1, SIZE_WORD, SPACE_PROGRAM); // write r0, r1, program_word + break; + + case 4: + UML_WRITE(block, I0, I1, SIZE_DWORD, SPACE_PROGRAM); // write r0, r1, program_dword + break; + } + } + else + { + switch (size) + { + case 1: + UML_READ(block, I0, I0, SIZE_BYTE, SPACE_PROGRAM); // read r0, program_byte + break; + + case 2: + UML_READ(block, I0, I0, SIZE_WORD, SPACE_PROGRAM); // read r0, program_word + break; + + case 4: + UML_READ(block, I0, I0, SIZE_DWORD, SPACE_PROGRAM); // read r0, program_dword + break; + } + } + + UML_RET(block); // ret + + block->end(); +} + +bool sh34_base_device::generate_group_0(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, uint16_t opcode, int in_delay_slot, uint32_t ovrpc) +{ + switch (opcode & 0xff) + { + default: + // fall through to SH2 handlers + return sh_common_execution::generate_group_0(block, compiler, desc, opcode, in_delay_slot, ovrpc); + + case 0x52: + case 0x62: + case 0x43: + case 0x63: + case 0xe3: + case 0x68: + case 0xe8: + case 0x4a: + case 0xca: + return true; // ILLEGAL(); break; // illegal on sh4 + + case 0x93: + case 0xa3: + case 0xb3: + return true; // TODO(opcode); break; + + case 0x82: + case 0x92: + case 0xa2: + case 0xb2: + case 0xc2: + case 0xd2: + case 0xe2: + case 0xf2: + return generate_group_0_STCRBANK(block, compiler, desc, opcode, in_delay_slot, ovrpc); + + case 0x32: return generate_group_0_STCSSR(block, compiler, desc, opcode, in_delay_slot, ovrpc); // sh4 only + case 0x42: return generate_group_0_STCSPC(block, compiler, desc, opcode, in_delay_slot, ovrpc); // sh4 only + case 0x83: return generate_group_0_PREFM(block, compiler, desc, opcode, in_delay_slot, ovrpc); // sh4 only + case 0xc3: return generate_group_0_MOVCAL(block, compiler, desc, opcode, in_delay_slot, ovrpc); // sh4 only + + case 0x38: + case 0xb8: + return generate_group_0_LDTLB(block, compiler, desc, opcode, in_delay_slot, ovrpc); // sh4 only + + case 0x48: + case 0xc8: + return generate_group_0_CLRS(block, compiler, desc, opcode, in_delay_slot, ovrpc); // sh4 only + + case 0x58: + case 0xd8: + return generate_group_0_SETS(block, compiler, desc, opcode, in_delay_slot, ovrpc); // sh4 only + + case 0x3a: + case 0xba: + return generate_group_0_STCSGR(block, compiler, desc, opcode, in_delay_slot, ovrpc); // sh4 only + + case 0x5a: + case 0xda: + return generate_group_0_STSFPUL(block, compiler, desc, opcode, in_delay_slot, ovrpc); // sh4 only + + case 0x6a: + case 0xea: + return generate_group_0_STSFPSCR(block, compiler, desc, opcode, in_delay_slot, ovrpc); // sh4 only + + case 0x7a: + case 0xfa: + return generate_group_0_STCDBR(block, compiler, desc, opcode, in_delay_slot, ovrpc); // sh4 only + } + + return false; +} + +void sh34_base_device::func_STCRBANK() { STCRBANK(m_sh2_state->arg0); } +static void cfunc_STCRBANK(void *param) { ((sh34_base_device *)param)->func_STCRBANK(); }; + +bool sh34_base_device::generate_group_0_STCRBANK(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, uint16_t opcode, int in_delay_slot, uint32_t ovrpc) +{ + save_fast_iregs(block); + UML_MOV(block, mem(&m_sh2_state->arg0), desc->opptr.w[0]); + UML_CALLC(block, cfunc_STCRBANK, this); + load_fast_iregs(block); + return true; +} + +void sh34_base_device::func_STCSSR() { STCSSR(m_sh2_state->arg0); } +static void cfunc_STCSSR(void *param) { ((sh34_base_device *)param)->func_STCSSR(); }; + +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) +{ + save_fast_iregs(block); + UML_MOV(block, mem(&m_sh2_state->arg0), desc->opptr.w[0]); + UML_CALLC(block, cfunc_STCSSR, this); + load_fast_iregs(block); + return true; +} + +void sh34_base_device::func_STCSPC() { STCSPC(m_sh2_state->arg0); } +static void cfunc_STCSPC(void *param) { ((sh34_base_device *)param)->func_STCSPC(); }; + +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) +{ + save_fast_iregs(block); + UML_MOV(block, mem(&m_sh2_state->arg0), desc->opptr.w[0]); + UML_CALLC(block, cfunc_STCSPC, this); + load_fast_iregs(block); + return true; +} + +void sh34_base_device::func_PREFM() { PREFM(m_sh2_state->arg0); } +static void cfunc_PREFM(void *param) { ((sh34_base_device *)param)->func_PREFM(); }; + +bool sh34_base_device::generate_group_0_PREFM(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, uint16_t opcode, int in_delay_slot, uint32_t ovrpc) +{ + save_fast_iregs(block); + UML_MOV(block, mem(&m_sh2_state->arg0), desc->opptr.w[0]); + UML_CALLC(block, cfunc_PREFM, this); + load_fast_iregs(block); + return true; +} + +void sh34_base_device::func_MOVCAL() { MOVCAL(m_sh2_state->arg0); } +static void cfunc_MOVCAL(void *param) { ((sh34_base_device *)param)->func_MOVCAL(); }; + +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) +{ + save_fast_iregs(block); + UML_MOV(block, mem(&m_sh2_state->arg0), desc->opptr.w[0]); + UML_CALLC(block, cfunc_MOVCAL, this); + load_fast_iregs(block); + return true; +} + +void sh34_base_device::func_LDTLB() { LDTLB(m_sh2_state->arg0); } +static void cfunc_LDTLB(void *param) { ((sh34_base_device *)param)->func_LDTLB(); }; + +bool sh34_base_device::generate_group_0_LDTLB(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, uint16_t opcode, int in_delay_slot, uint32_t ovrpc) +{ + save_fast_iregs(block); + UML_MOV(block, mem(&m_sh2_state->arg0), desc->opptr.w[0]); + UML_CALLC(block, cfunc_LDTLB, this); + load_fast_iregs(block); + return true; +} + +void sh34_base_device::func_CLRS() { CLRS(m_sh2_state->arg0); } +static void cfunc_CLRS(void *param) { ((sh34_base_device *)param)->func_CLRS(); }; + +bool sh34_base_device::generate_group_0_CLRS(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, uint16_t opcode, int in_delay_slot, uint32_t ovrpc) +{ + save_fast_iregs(block); + UML_MOV(block, mem(&m_sh2_state->arg0), desc->opptr.w[0]); + UML_CALLC(block, cfunc_CLRS, this); + load_fast_iregs(block); + return true; +} + +void sh34_base_device::func_SETS() { SETS(m_sh2_state->arg0); } +static void cfunc_SETS(void *param) { ((sh34_base_device *)param)->func_SETS(); }; + +bool sh34_base_device::generate_group_0_SETS(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, uint16_t opcode, int in_delay_slot, uint32_t ovrpc) +{ + save_fast_iregs(block); + UML_MOV(block, mem(&m_sh2_state->arg0), desc->opptr.w[0]); + UML_CALLC(block, cfunc_SETS, this); + load_fast_iregs(block); + return true; +} + +void sh34_base_device::func_STCSGR() { STCSGR(m_sh2_state->arg0); } +static void cfunc_STCSGR(void *param) { ((sh34_base_device *)param)->func_STCSGR(); }; + +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) +{ + save_fast_iregs(block); + UML_MOV(block, mem(&m_sh2_state->arg0), desc->opptr.w[0]); + UML_CALLC(block, cfunc_STCSGR, this); + load_fast_iregs(block); + return true; + +} + +void sh34_base_device::func_STSFPUL() { STSFPUL(m_sh2_state->arg0); } +static void cfunc_STSFPUL(void *param) { ((sh34_base_device *)param)->func_STSFPUL(); }; + +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) +{ + save_fast_iregs(block); + UML_MOV(block, mem(&m_sh2_state->arg0), desc->opptr.w[0]); + UML_CALLC(block, cfunc_STSFPUL, this); + load_fast_iregs(block); + return true; +} + +void sh34_base_device::func_STSFPSCR() { STSFPSCR(m_sh2_state->arg0); } +static void cfunc_STSFPSCR(void *param) { ((sh34_base_device *)param)->func_STSFPSCR(); }; + +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) +{ + save_fast_iregs(block); + UML_MOV(block, mem(&m_sh2_state->arg0), desc->opptr.w[0]); + UML_CALLC(block, cfunc_STSFPSCR, this); + load_fast_iregs(block); + return true; +} + +void sh34_base_device::func_STCDBR() { STCDBR(m_sh2_state->arg0); } +static void cfunc_STCDBR(void *param) { ((sh34_base_device *)param)->func_STCDBR(); }; + +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) +{ + save_fast_iregs(block); + UML_MOV(block, mem(&m_sh2_state->arg0), desc->opptr.w[0]); + UML_CALLC(block, cfunc_STCDBR, this); + load_fast_iregs(block); + return true; +} + +void sh34_base_device::func_RTE() { RTE(); } +static void cfunc_RTE(void *param) { ((sh34_base_device *)param)->func_RTE(); }; + +bool sh34_base_device::generate_group_0_RTE(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, uint16_t opcode, int in_delay_slot, uint32_t ovrpc) +{ + generate_delay_slot(block, compiler, desc, 0xffffffff); + save_fast_iregs(block); + UML_CALLC(block, cfunc_RTE, this); + load_fast_iregs(block); + + compiler->checkints = true; + + UML_MOV(block, mem(&m_sh2_state->pc), mem(&m_sh2_state->m_delay)); + generate_update_cycles(block, compiler, mem(&m_sh2_state->ea), true); // <subtract cycles> + UML_HASHJMP(block, 0, mem(&m_sh2_state->pc), *m_nocode); // and jump to the "resume PC" + return true; +} + +void sh34_base_device::func_TRAPA() { TRAPA(m_sh2_state->arg0 & 0xff); } +static void cfunc_TRAPA(void *param) { ((sh34_base_device *)param)->func_TRAPA(); }; + +bool sh34_base_device::generate_group_12_TRAPA(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, uint16_t opcode, int in_delay_slot, uint32_t ovrpc) +{ + save_fast_iregs(block); + UML_MOV(block, mem(&m_sh2_state->arg0), desc->opptr.w[0]); + UML_MOV(block, mem(&m_sh2_state->pc), desc->pc + 2); // copy the PC because we need to use it + UML_CALLC(block, cfunc_TRAPA, this); + load_fast_iregs(block); + UML_HASHJMP(block, 0, mem(&m_sh2_state->pc), *m_nocode); + return true; +} + +void sh34_base_device::func_LDCSR() { LDCSR(m_sh2_state->arg0); } +static void cfunc_LDCSR(void *param) { ((sh34_base_device *)param)->func_LDCSR(); }; + +bool sh34_base_device::generate_group_4_LDCSR(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, uint16_t opcode, int in_delay_slot, uint32_t ovrpc) +{ + save_fast_iregs(block); + UML_MOV(block, mem(&m_sh2_state->arg0), desc->opptr.w[0]); + UML_CALLC(block, cfunc_LDCSR, this); + load_fast_iregs(block); + + compiler->checkints = true; + + return true; +} + +void sh34_base_device::func_LDCMSR() { LDCMSR(m_sh2_state->arg0); } +static void cfunc_LDCMSR(void *param) { ((sh34_base_device *)param)->func_LDCMSR(); }; + +bool sh34_base_device::generate_group_4_LDCMSR(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, uint16_t opcode, int in_delay_slot, uint32_t ovrpc) +{ + save_fast_iregs(block); + UML_MOV(block, mem(&m_sh2_state->arg0), desc->opptr.w[0]); + UML_CALLC(block, cfunc_LDCMSR, this); + load_fast_iregs(block); + + compiler->checkints = true; + if (!in_delay_slot) + generate_update_cycles(block, compiler, desc->pc + 2, true); + + return true; +} + +void sh34_base_device::func_SHAD() { SHAD(m_sh2_state->arg0); } +static void cfunc_SHAD(void *param) { ((sh34_base_device *)param)->func_SHAD(); }; + +bool sh34_base_device::generate_group_4_SHAD(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, uint16_t opcode, int in_delay_slot, uint32_t ovrpc) +{ + save_fast_iregs(block); + UML_MOV(block, mem(&m_sh2_state->arg0), desc->opptr.w[0]); + UML_CALLC(block, cfunc_SHAD, this); + load_fast_iregs(block); + return true; +} + +void sh34_base_device::func_SHLD() { SHLD(m_sh2_state->arg0); } +static void cfunc_SHLD(void *param) { ((sh34_base_device *)param)->func_SHLD(); }; + +bool sh34_base_device::generate_group_4_SHLD(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, uint16_t opcode, int in_delay_slot, uint32_t ovrpc) +{ + save_fast_iregs(block); + UML_MOV(block, mem(&m_sh2_state->arg0), desc->opptr.w[0]); + UML_CALLC(block, cfunc_SHLD, this); + load_fast_iregs(block); + return true; +} + +bool sh34_base_device::generate_group_4(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, uint16_t opcode, int in_delay_slot, uint32_t ovrpc) +{ + switch (opcode & 0xff) + { + default: // LDCMSR (0x0e) has sh2/4 flag difference + // fall through to SH2 handlers + return sh_common_execution::generate_group_4(block, compiler, desc, opcode, in_delay_slot, ovrpc); break; + + case 0x42: + case 0x46: + case 0x4a: + case 0x53: + case 0x57: + case 0x5e: + case 0x63: + case 0x67: + case 0x6e: + case 0x82: + case 0x86: + case 0x8a: + case 0x92: + case 0x96: + case 0x9a: + case 0xa2: + case 0xa6: + case 0xaa: + case 0xc2: + case 0xc6: + case 0xca: + case 0xd2: + case 0xd6: + case 0xda: + case 0xe2: + case 0xe6: + case 0xea: + return true; // ILLEGAL(); break; // defined as illegal on SH4 + + case 0x0c: + case 0x1c: + case 0x2c: + case 0x3c: + case 0x4c: + case 0x5c: + case 0x6c: + case 0x7c: + case 0x8c: + case 0x9c: + case 0xac: + case 0xbc: + case 0xcc: + case 0xdc: + case 0xec: + case 0xfc: + return generate_group_4_SHAD(block, compiler, desc, opcode, in_delay_slot, ovrpc); break; + + case 0x0d: + case 0x1d: + case 0x2d: + case 0x3d: + case 0x4d: + case 0x5d: + case 0x6d: + case 0x7d: + case 0x8d: + case 0x9d: + case 0xad: + case 0xbd: + case 0xcd: + case 0xdd: + case 0xed: + case 0xfd: + return generate_group_4_SHLD(block, compiler, desc, opcode, in_delay_slot, ovrpc); break; + + case 0x8e: + case 0x9e: + case 0xae: + case 0xbe: + case 0xce: + case 0xde: + case 0xee: + case 0xfe: + return generate_group_4_LDCRBANK(block, compiler, desc, opcode, in_delay_slot, ovrpc); // sh3/4 only + + case 0x83: + case 0x93: + case 0xa3: + case 0xb3: + case 0xc3: + case 0xd3: + case 0xe3: + case 0xf3: + return generate_group_4_STCMRBANK(block, compiler, desc, opcode, in_delay_slot, ovrpc); // sh3/4 only + + case 0x87: + case 0x97: + case 0xa7: + case 0xb7: + case 0xc7: + case 0xd7: + case 0xe7: + case 0xf7: + return generate_group_4_LDCMRBANK(block, compiler, desc, opcode, in_delay_slot, ovrpc); // sh4 only + + case 0x32: return generate_group_4_STCMSGR(block, compiler, desc, opcode, in_delay_slot, ovrpc); + case 0x33: return generate_group_4_STCMSSR(block, compiler, desc, opcode, in_delay_slot, ovrpc); + case 0x37: return generate_group_4_LDCMSSR(block, compiler, desc, opcode, in_delay_slot, ovrpc); + case 0x3e: return generate_group_4_LDCSSR(block, compiler, desc, opcode, in_delay_slot, ovrpc); + case 0x43: return generate_group_4_STCMSPC(block, compiler, desc, opcode, in_delay_slot, ovrpc); + case 0x47: return generate_group_4_LDCMSPC(block, compiler, desc, opcode, in_delay_slot, ovrpc); + case 0x4e: return generate_group_4_LDCSPC(block, compiler, desc, opcode, in_delay_slot, ovrpc); + case 0x52: return generate_group_4_STSMFPUL(block, compiler, desc, opcode, in_delay_slot, ovrpc); + case 0x56: return generate_group_4_LDSMFPUL(block, compiler, desc, opcode, in_delay_slot, ovrpc); + case 0x5a: return generate_group_4_LDSFPUL(block, compiler, desc, opcode, in_delay_slot, ovrpc); + case 0x62: return generate_group_4_STSMFPSCR(block, compiler, desc, opcode, in_delay_slot, ovrpc); + case 0x66: return generate_group_4_LDSMFPSCR(block, compiler, desc, opcode, in_delay_slot, ovrpc); + case 0x6a: return generate_group_4_LDSFPSCR(block, compiler, desc, opcode, in_delay_slot, ovrpc); + case 0xf2: return generate_group_4_STCMDBR(block, compiler, desc, opcode, in_delay_slot, ovrpc); + case 0xf6: return generate_group_4_LDCMDBR(block, compiler, desc, opcode, in_delay_slot, ovrpc); + case 0xfa: return generate_group_4_LDCDBR(block, compiler, desc, opcode, in_delay_slot, ovrpc); + } + return false; +} + + +void sh34_base_device::func_LDCRBANK() { LDCRBANK(m_sh2_state->arg0); } +static void cfunc_LDCRBANK(void *param) { ((sh34_base_device *)param)->func_LDCRBANK(); }; + +bool sh34_base_device::generate_group_4_LDCRBANK(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, uint16_t opcode, int in_delay_slot, uint32_t ovrpc) +{ + save_fast_iregs(block); + UML_MOV(block, mem(&m_sh2_state->arg0), desc->opptr.w[0]); + UML_CALLC(block, cfunc_LDCRBANK, this); + load_fast_iregs(block); + return true; +} + +void sh34_base_device::func_STCMRBANK() { STCMRBANK(m_sh2_state->arg0); } +static void cfunc_STCMRBANK(void *param) { ((sh34_base_device *)param)->func_STCMRBANK(); }; + +bool sh34_base_device::generate_group_4_STCMRBANK(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, uint16_t opcode, int in_delay_slot, uint32_t ovrpc) +{ + save_fast_iregs(block); + UML_MOV(block, mem(&m_sh2_state->arg0), desc->opptr.w[0]); + UML_CALLC(block, cfunc_STCMRBANK, this); + load_fast_iregs(block); + return true; +} + +void sh34_base_device::func_LDCMRBANK() { LDCMRBANK(m_sh2_state->arg0); } +static void cfunc_LDCMRBANK(void *param) { ((sh34_base_device *)param)->func_LDCMRBANK(); }; + +bool sh34_base_device::generate_group_4_LDCMRBANK(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, uint16_t opcode, int in_delay_slot, uint32_t ovrpc) +{ + save_fast_iregs(block); + UML_MOV(block, mem(&m_sh2_state->arg0), desc->opptr.w[0]); + UML_CALLC(block, cfunc_LDCMRBANK, this); + load_fast_iregs(block); + return true; +} + +void sh34_base_device::func_STCMSGR() { STCMSGR(m_sh2_state->arg0); } +static void cfunc_STCMSGR(void *param) { ((sh34_base_device *)param)->func_STCMSGR(); }; + +bool sh34_base_device::generate_group_4_STCMSGR(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, uint16_t opcode, int in_delay_slot, uint32_t ovrpc) +{ + save_fast_iregs(block); + UML_MOV(block, mem(&m_sh2_state->arg0), desc->opptr.w[0]); + UML_CALLC(block, cfunc_STCMSGR, this); + load_fast_iregs(block); + return true; +} + +void sh34_base_device::func_STCMSSR() { STCMSSR(m_sh2_state->arg0); } +static void cfunc_STCMSSR(void *param) { ((sh34_base_device *)param)->func_STCMSSR(); }; + +bool sh34_base_device::generate_group_4_STCMSSR(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, uint16_t opcode, int in_delay_slot, uint32_t ovrpc) +{ + save_fast_iregs(block); + UML_MOV(block, mem(&m_sh2_state->arg0), desc->opptr.w[0]); + UML_CALLC(block, cfunc_STCMSSR, this); + load_fast_iregs(block); + return true; +} + +void sh34_base_device::func_LDCMSSR() { LDCMSSR(m_sh2_state->arg0); } +static void cfunc_LDCMSSR(void *param) { ((sh34_base_device *)param)->func_LDCMSSR(); }; + +bool sh34_base_device::generate_group_4_LDCMSSR(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, uint16_t opcode, int in_delay_slot, uint32_t ovrpc) +{ + save_fast_iregs(block); + UML_MOV(block, mem(&m_sh2_state->arg0), desc->opptr.w[0]); + UML_CALLC(block, cfunc_LDCMSSR, this); + load_fast_iregs(block); + return true; +} + +void sh34_base_device::func_LDCSSR() { LDCSSR(m_sh2_state->arg0); } +static void cfunc_LDCSSR(void *param) { ((sh34_base_device *)param)->func_LDCSSR(); }; + +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) +{ + save_fast_iregs(block); + UML_MOV(block, mem(&m_sh2_state->arg0), desc->opptr.w[0]); + UML_CALLC(block, cfunc_LDCSSR, this); + load_fast_iregs(block); + return true; +} + +void sh34_base_device::func_STCMSPC() { STCMSPC(m_sh2_state->arg0); } +static void cfunc_STCMSPC(void *param) { ((sh34_base_device *)param)->func_STCMSPC(); }; + +bool sh34_base_device::generate_group_4_STCMSPC(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, uint16_t opcode, int in_delay_slot, uint32_t ovrpc) +{ + save_fast_iregs(block); + UML_MOV(block, mem(&m_sh2_state->arg0), desc->opptr.w[0]); + UML_CALLC(block, cfunc_STCMSPC, this); + load_fast_iregs(block); + return true; +} + +void sh34_base_device::func_LDCMSPC() { LDCMSPC(m_sh2_state->arg0); } +static void cfunc_LDCMSPC(void *param) { ((sh34_base_device *)param)->func_LDCMSPC(); }; + +bool sh34_base_device::generate_group_4_LDCMSPC(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, uint16_t opcode, int in_delay_slot, uint32_t ovrpc) +{ + save_fast_iregs(block); + UML_MOV(block, mem(&m_sh2_state->arg0), desc->opptr.w[0]); + UML_CALLC(block, cfunc_LDCMSPC, this); + load_fast_iregs(block); + return true; +} + +void sh34_base_device::func_LDCSPC() { LDCSPC(m_sh2_state->arg0); } +static void cfunc_LDCSPC(void *param) { ((sh34_base_device *)param)->func_LDCSPC(); }; + +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) +{ + save_fast_iregs(block); + UML_MOV(block, mem(&m_sh2_state->arg0), desc->opptr.w[0]); + UML_CALLC(block, cfunc_LDCSPC, this); + load_fast_iregs(block); + return true; +} + +void sh34_base_device::func_STSMFPUL() { STSMFPUL(m_sh2_state->arg0); } +static void cfunc_STSMFPUL(void *param) { ((sh34_base_device *)param)->func_STSMFPUL(); }; + +bool sh34_base_device::generate_group_4_STSMFPUL(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, uint16_t opcode, int in_delay_slot, uint32_t ovrpc) +{ + save_fast_iregs(block); + UML_MOV(block, mem(&m_sh2_state->arg0), desc->opptr.w[0]); + UML_CALLC(block, cfunc_STSMFPUL, this); + load_fast_iregs(block); + return true; +} + +void sh34_base_device::func_LDSMFPUL() { LDSMFPUL(m_sh2_state->arg0); } +static void cfunc_LDSMFPUL(void *param) { ((sh34_base_device *)param)->func_LDSMFPUL(); }; + +bool sh34_base_device::generate_group_4_LDSMFPUL(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, uint16_t opcode, int in_delay_slot, uint32_t ovrpc) +{ + save_fast_iregs(block); + UML_MOV(block, mem(&m_sh2_state->arg0), desc->opptr.w[0]); + UML_CALLC(block, cfunc_LDSMFPUL, this); + load_fast_iregs(block); + return true; +} + +void sh34_base_device::func_LDSFPUL() { LDSFPUL(m_sh2_state->arg0); } +static void cfunc_LDSFPUL(void *param) { ((sh34_base_device *)param)->func_LDSFPUL(); }; + +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) +{ + save_fast_iregs(block); + UML_MOV(block, mem(&m_sh2_state->arg0), desc->opptr.w[0]); + UML_CALLC(block, cfunc_LDSFPUL, this); + load_fast_iregs(block); + return true; +} + +void sh34_base_device::func_STSMFPSCR() { STSMFPSCR(m_sh2_state->arg0); } +static void cfunc_STSMFPSCR(void *param) { ((sh34_base_device *)param)->func_STSMFPSCR(); }; + +bool sh34_base_device::generate_group_4_STSMFPSCR(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, uint16_t opcode, int in_delay_slot, uint32_t ovrpc) +{ + save_fast_iregs(block); + UML_MOV(block, mem(&m_sh2_state->arg0), desc->opptr.w[0]); + UML_CALLC(block, cfunc_STSMFPSCR, this); + load_fast_iregs(block); + return true; +} + +void sh34_base_device::func_LDSMFPSCR() { LDSMFPSCR(m_sh2_state->arg0); } +static void cfunc_LDSMFPSCR(void *param) { ((sh34_base_device *)param)->func_LDSMFPSCR(); }; + + +bool sh34_base_device::generate_group_4_LDSMFPSCR(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, uint16_t opcode, int in_delay_slot, uint32_t ovrpc) +{ + save_fast_iregs(block); + UML_MOV(block, mem(&m_sh2_state->arg0), desc->opptr.w[0]); + UML_CALLC(block, cfunc_LDSMFPSCR, this); + load_fast_iregs(block); + return true; +} + + +void sh34_base_device::func_LDSFPSCR() { LDSFPSCR(m_sh2_state->arg0); } +static void cfunc_LDSFPSCR(void *param) { ((sh34_base_device *)param)->func_LDSFPSCR(); }; + +bool sh34_base_device::generate_group_4_LDSFPSCR(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, uint16_t opcode, int in_delay_slot, uint32_t ovrpc) +{ + save_fast_iregs(block); + UML_MOV(block, mem(&m_sh2_state->arg0), desc->opptr.w[0]); + UML_CALLC(block, cfunc_LDSFPSCR, this); + load_fast_iregs(block); + return true; +} + +void sh34_base_device::func_STCMDBR() { STCMDBR(m_sh2_state->arg0); } +static void cfunc_STCMDBR(void *param) { ((sh34_base_device *)param)->func_STCMDBR(); }; + +bool sh34_base_device::generate_group_4_STCMDBR(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, uint16_t opcode, int in_delay_slot, uint32_t ovrpc) +{ + save_fast_iregs(block); + UML_MOV(block, mem(&m_sh2_state->arg0), desc->opptr.w[0]); + UML_CALLC(block, cfunc_STCMDBR, this); + load_fast_iregs(block); + return true; +} + +void sh34_base_device::func_LDCMDBR() { LDCMDBR(m_sh2_state->arg0); } +static void cfunc_LDCMDBR(void *param) { ((sh34_base_device *)param)->func_LDCMDBR(); }; + +bool sh34_base_device::generate_group_4_LDCMDBR(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, uint16_t opcode, int in_delay_slot, uint32_t ovrpc) +{ + save_fast_iregs(block); + UML_MOV(block, mem(&m_sh2_state->arg0), desc->opptr.w[0]); + UML_CALLC(block, cfunc_LDCMDBR, this); + load_fast_iregs(block); + return true; +} + +void sh34_base_device::func_LDCDBR() { LDCDBR(m_sh2_state->arg0); } +static void cfunc_LDCDBR(void *param) { ((sh34_base_device *)param)->func_LDCDBR(); }; + +bool sh34_base_device::generate_group_4_LDCDBR(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, uint16_t opcode, int in_delay_slot, uint32_t ovrpc) +{ + save_fast_iregs(block); + UML_MOV(block, mem(&m_sh2_state->arg0), desc->opptr.w[0]); + UML_CALLC(block, cfunc_LDCDBR, this); + load_fast_iregs(block); + return true; +} + +bool sh34_base_device::generate_group_15(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, uint16_t opcode, int in_delay_slot, uint32_t ovrpc) +{ + switch (opcode & 0x0f) + { + case 0x00: return generate_group_15_FADD(block, compiler, desc, opcode, in_delay_slot, ovrpc); + case 0x01: return generate_group_15_FSUB(block, compiler, desc, opcode, in_delay_slot, ovrpc); + case 0x02: return generate_group_15_FMUL(block, compiler, desc, opcode, in_delay_slot, ovrpc); + case 0x03: return generate_group_15_FDIV(block, compiler, desc, opcode, in_delay_slot, ovrpc); + case 0x04: return generate_group_15_FCMP_EQ(block, compiler, desc, opcode, in_delay_slot, ovrpc); + case 0x05: return generate_group_15_FCMP_GT(block, compiler, desc, opcode, in_delay_slot, ovrpc); + case 0x06: return generate_group_15_FMOVS0FR(block, compiler, desc, opcode, in_delay_slot, ovrpc); + case 0x07: return generate_group_15_FMOVFRS0(block, compiler, desc, opcode, in_delay_slot, ovrpc); + case 0x08: return generate_group_15_FMOVMRFR(block, compiler, desc, opcode, in_delay_slot, ovrpc); + case 0x09: return generate_group_15_FMOVMRIFR(block, compiler, desc, opcode, in_delay_slot, ovrpc); + case 0x0a: return generate_group_15_FMOVFRMR(block, compiler, desc, opcode, in_delay_slot, ovrpc); + case 0x0b: return generate_group_15_FMOVFRMDR(block, compiler, desc, opcode, in_delay_slot, ovrpc); + case 0x0c: return generate_group_15_FMOVFR(block, compiler, desc, opcode, in_delay_slot, ovrpc); + case 0x0d: return generate_group_15_op1111_0x13(block, compiler, desc, opcode, in_delay_slot, ovrpc); + case 0x0e: return generate_group_15_FMAC(block, compiler, desc, opcode, in_delay_slot, ovrpc); + case 0x0f: + return true; + //if (opcode == 0xffff) return true; // atomiswave uses ffff as NOP? + //return false; // dbreak(opcode); break; + } + return false; +} + +void sh34_base_device::func_FADD() { FADD(m_sh2_state->arg0); } +static void cfunc_FADD(void *param) { ((sh34_base_device *)param)->func_FADD(); }; + +bool sh34_base_device::generate_group_15_FADD(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, uint16_t opcode, int in_delay_slot, uint32_t ovrpc) +{ + save_fast_iregs(block); + UML_MOV(block, mem(&m_sh2_state->arg0), desc->opptr.w[0]); + UML_CALLC(block, cfunc_FADD, this); + load_fast_iregs(block); + return true; +} + +void sh34_base_device::func_FSUB() { FSUB(m_sh2_state->arg0); } +static void cfunc_FSUB(void *param) { ((sh34_base_device *)param)->func_FSUB(); }; + +bool sh34_base_device::generate_group_15_FSUB(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, uint16_t opcode, int in_delay_slot, uint32_t ovrpc) +{ + save_fast_iregs(block); + UML_MOV(block, mem(&m_sh2_state->arg0), desc->opptr.w[0]); + UML_CALLC(block, cfunc_FSUB, this); + load_fast_iregs(block); + return true; +} + +void sh34_base_device::func_FMUL() { FMUL(m_sh2_state->arg0); } +static void cfunc_FMUL(void *param) { ((sh34_base_device *)param)->func_FMUL(); }; + +bool sh34_base_device::generate_group_15_FMUL(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, uint16_t opcode, int in_delay_slot, uint32_t ovrpc) +{ + save_fast_iregs(block); + UML_MOV(block, mem(&m_sh2_state->arg0), desc->opptr.w[0]); + UML_CALLC(block, cfunc_FMUL, this); + load_fast_iregs(block); + return true; +} + +void sh34_base_device::func_FDIV() { FDIV(m_sh2_state->arg0); } +static void cfunc_FDIV(void *param) { ((sh34_base_device *)param)->func_FDIV(); }; + +bool sh34_base_device::generate_group_15_FDIV(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, uint16_t opcode, int in_delay_slot, uint32_t ovrpc) +{ + save_fast_iregs(block); + UML_MOV(block, mem(&m_sh2_state->arg0), desc->opptr.w[0]); + UML_CALLC(block, cfunc_FDIV, this); + load_fast_iregs(block); + return true; +} + +void sh34_base_device::func_FCMP_EQ() { FCMP_EQ(m_sh2_state->arg0); } +static void cfunc_FCMP_EQ(void *param) { ((sh34_base_device *)param)->func_FCMP_EQ(); }; + +bool sh34_base_device::generate_group_15_FCMP_EQ(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, uint16_t opcode, int in_delay_slot, uint32_t ovrpc) +{ + save_fast_iregs(block); + UML_MOV(block, mem(&m_sh2_state->arg0), desc->opptr.w[0]); + UML_CALLC(block, cfunc_FCMP_EQ, this); + load_fast_iregs(block); + return true; +} + +void sh34_base_device::func_FCMP_GT() { FCMP_GT(m_sh2_state->arg0); } +static void cfunc_FCMP_GT(void *param) { ((sh34_base_device *)param)->func_FCMP_GT(); }; + +bool sh34_base_device::generate_group_15_FCMP_GT(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, uint16_t opcode, int in_delay_slot, uint32_t ovrpc) +{ + save_fast_iregs(block); + UML_MOV(block, mem(&m_sh2_state->arg0), desc->opptr.w[0]); + UML_CALLC(block, cfunc_FCMP_GT, this); + load_fast_iregs(block); + return true; +} + +void sh34_base_device::func_FMOVS0FR() { FMOVS0FR(m_sh2_state->arg0); } +static void cfunc_FMOVS0FR(void *param) { ((sh34_base_device *)param)->func_FMOVS0FR(); }; + +bool sh34_base_device::generate_group_15_FMOVS0FR(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, uint16_t opcode, int in_delay_slot, uint32_t ovrpc) +{ + save_fast_iregs(block); + UML_MOV(block, mem(&m_sh2_state->arg0), desc->opptr.w[0]); + UML_CALLC(block, cfunc_FMOVS0FR, this); + load_fast_iregs(block); + return true; +} + +void sh34_base_device::func_FMOVFRS0() { FMOVFRS0(m_sh2_state->arg0); } +static void cfunc_FMOVFRS0(void *param) { ((sh34_base_device *)param)->func_FMOVFRS0(); }; + +bool sh34_base_device::generate_group_15_FMOVFRS0(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, uint16_t opcode, int in_delay_slot, uint32_t ovrpc) +{ + save_fast_iregs(block); + UML_MOV(block, mem(&m_sh2_state->arg0), desc->opptr.w[0]); + UML_CALLC(block, cfunc_FMOVFRS0, this); + load_fast_iregs(block); + return true; +} + +void sh34_base_device::func_FMOVMRFR() { FMOVMRFR(m_sh2_state->arg0); } +static void cfunc_FMOVMRFR(void *param) { ((sh34_base_device *)param)->func_FMOVMRFR(); }; + +bool sh34_base_device::generate_group_15_FMOVMRFR(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, uint16_t opcode, int in_delay_slot, uint32_t ovrpc) +{ + save_fast_iregs(block); + UML_MOV(block, mem(&m_sh2_state->arg0), desc->opptr.w[0]); + UML_CALLC(block, cfunc_FMOVMRFR, this); + load_fast_iregs(block); + return true; +} + +void sh34_base_device::func_FMOVMRIFR() { FMOVMRIFR(m_sh2_state->arg0); } +static void cfunc_FMOVMRIFR(void *param) { ((sh34_base_device *)param)->func_FMOVMRIFR(); }; + +bool sh34_base_device::generate_group_15_FMOVMRIFR(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, uint16_t opcode, int in_delay_slot, uint32_t ovrpc) +{ + save_fast_iregs(block); + UML_MOV(block, mem(&m_sh2_state->arg0), desc->opptr.w[0]); + UML_CALLC(block, cfunc_FMOVMRIFR, this); + load_fast_iregs(block); + return true; +} + +void sh34_base_device::func_FMOVFRMR() { FMOVFRMR(m_sh2_state->arg0); } +static void cfunc_FMOVFRMR(void *param) { ((sh34_base_device *)param)->func_FMOVFRMR(); }; + +bool sh34_base_device::generate_group_15_FMOVFRMR(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, uint16_t opcode, int in_delay_slot, uint32_t ovrpc) +{ + save_fast_iregs(block); + UML_MOV(block, mem(&m_sh2_state->arg0), desc->opptr.w[0]); + UML_CALLC(block, cfunc_FMOVFRMR, this); + load_fast_iregs(block); + return true; +} + +void sh34_base_device::func_FMOVFRMDR() { FMOVFRMDR(m_sh2_state->arg0); } +static void cfunc_FMOVFRMDR(void *param) { ((sh34_base_device *)param)->func_FMOVFRMDR(); }; + +bool sh34_base_device::generate_group_15_FMOVFRMDR(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, uint16_t opcode, int in_delay_slot, uint32_t ovrpc) +{ + save_fast_iregs(block); + UML_MOV(block, mem(&m_sh2_state->arg0), desc->opptr.w[0]); + UML_CALLC(block, cfunc_FMOVFRMDR, this); + load_fast_iregs(block); + return true; +} + +void sh34_base_device::func_FMOVFR() { FMOVFR(m_sh2_state->arg0); } +static void cfunc_FMOVFR(void *param) { ((sh34_base_device *)param)->func_FMOVFR(); }; + +bool sh34_base_device::generate_group_15_FMOVFR(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, uint16_t opcode, int in_delay_slot, uint32_t ovrpc) +{ + save_fast_iregs(block); + UML_MOV(block, mem(&m_sh2_state->arg0), desc->opptr.w[0]); + UML_CALLC(block, cfunc_FMOVFR, this); + load_fast_iregs(block); + return true; +} + +void sh34_base_device::func_FMAC() { FMAC(m_sh2_state->arg0); } +static void cfunc_FMAC(void *param) { ((sh34_base_device *)param)->func_FMAC(); }; + +bool sh34_base_device::generate_group_15_FMAC(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, uint16_t opcode, int in_delay_slot, uint32_t ovrpc) +{ + save_fast_iregs(block); + UML_MOV(block, mem(&m_sh2_state->arg0), desc->opptr.w[0]); + UML_CALLC(block, cfunc_FMAC, this); + load_fast_iregs(block); + return true; +} + +bool sh34_base_device::generate_group_15_op1111_0x13(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, uint16_t opcode, int in_delay_slot, uint32_t ovrpc) +{ + switch ((opcode >> 4) & 0x0f) + { + case 0x00: return generate_group_15_op1111_0x13_FSTS(block, compiler, desc, opcode, in_delay_slot, ovrpc); // FSTS(opcode); break; + case 0x01: return generate_group_15_op1111_0x13_FLDS(block, compiler, desc, opcode, in_delay_slot, ovrpc); // FLDS(opcode); break; + case 0x02: return generate_group_15_op1111_0x13_FLOAT(block, compiler, desc, opcode, in_delay_slot, ovrpc); // FLOAT(opcode); break; + case 0x03: return generate_group_15_op1111_0x13_FTRC(block, compiler, desc, opcode, in_delay_slot, ovrpc); // FTRC(opcode); break; + case 0x04: return generate_group_15_op1111_0x13_FNEG(block, compiler, desc, opcode, in_delay_slot, ovrpc); // FNEG(opcode); break; + case 0x05: return generate_group_15_op1111_0x13_FABS(block, compiler, desc, opcode, in_delay_slot, ovrpc); // FABS(opcode); break; + case 0x06: return generate_group_15_op1111_0x13_FSQRT(block, compiler, desc, opcode, in_delay_slot, ovrpc); // FSQRT(opcode); break; + case 0x07: return generate_group_15_op1111_0x13_FSRRA(block, compiler, desc, opcode, in_delay_slot, ovrpc); // FSRRA(opcode); break; + case 0x08: return generate_group_15_op1111_0x13_FLDI0(block, compiler, desc, opcode, in_delay_slot, ovrpc); // FLDI0(opcode); break; + case 0x09: return generate_group_15_op1111_0x13_FLDI1(block, compiler, desc, opcode, in_delay_slot, ovrpc); // FLDI1(opcode); break; + case 0x0a: return generate_group_15_op1111_0x13_FCNVSD(block, compiler, desc, opcode, in_delay_slot, ovrpc); // FCNVSD(opcode); break; + case 0x0b: return generate_group_15_op1111_0x13_FCNVDS(block, compiler, desc, opcode, in_delay_slot, ovrpc); // FCNVDS(opcode); break; + case 0x0c: return false; // dbreak(opcode); break; + case 0x0d: return false; //dbreak(opcode); break; + case 0x0e: return generate_group_15_op1111_0x13_FIPR(block, compiler, desc, opcode, in_delay_slot, ovrpc); // FIPR(opcode); break; + case 0x0f: return generate_group_15_op1111_0x13_op1111_0xf13(block, compiler, desc, opcode, in_delay_slot, ovrpc); // op1111_0xf13(opcode); break; + } + return false; +} + +void sh34_base_device::func_FSTS() { FSTS(m_sh2_state->arg0); } +static void cfunc_FSTS(void *param) { ((sh34_base_device *)param)->func_FSTS(); }; + +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) +{ + save_fast_iregs(block); + UML_MOV(block, mem(&m_sh2_state->arg0), desc->opptr.w[0]); + UML_CALLC(block, cfunc_FSTS, this); + load_fast_iregs(block); + return true; +} + +void sh34_base_device::func_FLDS() { FLDS(m_sh2_state->arg0); } +static void cfunc_FLDS(void *param) { ((sh34_base_device *)param)->func_FLDS(); }; + +bool sh34_base_device::generate_group_15_op1111_0x13_FLDS(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, uint16_t opcode, int in_delay_slot, uint32_t ovrpc) +{ + save_fast_iregs(block); + UML_MOV(block, mem(&m_sh2_state->arg0), desc->opptr.w[0]); + UML_CALLC(block, cfunc_FLDS, this); + load_fast_iregs(block); + return true; +} + +void sh34_base_device::func_FLOAT() { FLOAT(m_sh2_state->arg0); } +static void cfunc_FLOAT(void *param) { ((sh34_base_device *)param)->func_FLOAT(); }; + +bool sh34_base_device::generate_group_15_op1111_0x13_FLOAT(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, uint16_t opcode, int in_delay_slot, uint32_t ovrpc) +{ + save_fast_iregs(block); + UML_MOV(block, mem(&m_sh2_state->arg0), desc->opptr.w[0]); + UML_CALLC(block, cfunc_FLOAT, this); + load_fast_iregs(block); + return true; +} + +void sh34_base_device::func_FTRC() { FTRC(m_sh2_state->arg0); } +static void cfunc_FTRC(void *param) { ((sh34_base_device *)param)->func_FTRC(); }; + +bool sh34_base_device::generate_group_15_op1111_0x13_FTRC(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, uint16_t opcode, int in_delay_slot, uint32_t ovrpc) +{ + save_fast_iregs(block); + UML_MOV(block, mem(&m_sh2_state->arg0), desc->opptr.w[0]); + UML_CALLC(block, cfunc_FTRC, this); + load_fast_iregs(block); + return true; +} + +void sh34_base_device::func_FNEG() { FNEG(m_sh2_state->arg0); } +static void cfunc_FNEG(void *param) { ((sh34_base_device *)param)->func_FNEG(); }; + +bool sh34_base_device::generate_group_15_op1111_0x13_FNEG(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, uint16_t opcode, int in_delay_slot, uint32_t ovrpc) +{ + save_fast_iregs(block); + UML_MOV(block, mem(&m_sh2_state->arg0), desc->opptr.w[0]); + UML_CALLC(block, cfunc_FNEG, this); + load_fast_iregs(block); + return true; +} + +void sh34_base_device::func_FABS() { FABS(m_sh2_state->arg0); } +static void cfunc_FABS(void *param) { ((sh34_base_device *)param)->func_FABS(); }; + +bool sh34_base_device::generate_group_15_op1111_0x13_FABS(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, uint16_t opcode, int in_delay_slot, uint32_t ovrpc) +{ + save_fast_iregs(block); + UML_MOV(block, mem(&m_sh2_state->arg0), desc->opptr.w[0]); + UML_CALLC(block, cfunc_FABS, this); + load_fast_iregs(block); + return true; +} + +void sh34_base_device::func_FSQRT() { FSQRT(m_sh2_state->arg0); } +static void cfunc_FSQRT(void *param) { ((sh34_base_device *)param)->func_FSQRT(); }; + +bool sh34_base_device::generate_group_15_op1111_0x13_FSQRT(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, uint16_t opcode, int in_delay_slot, uint32_t ovrpc) +{ + save_fast_iregs(block); + UML_MOV(block, mem(&m_sh2_state->arg0), desc->opptr.w[0]); + UML_CALLC(block, cfunc_FSQRT, this); + load_fast_iregs(block); + return true; +} + +void sh34_base_device::func_FSRRA() { FSRRA(m_sh2_state->arg0); } +static void cfunc_FSRRA(void *param) { ((sh34_base_device *)param)->func_FSRRA(); }; + +bool sh34_base_device::generate_group_15_op1111_0x13_FSRRA(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, uint16_t opcode, int in_delay_slot, uint32_t ovrpc) +{ + save_fast_iregs(block); + UML_MOV(block, mem(&m_sh2_state->arg0), desc->opptr.w[0]); + UML_CALLC(block, cfunc_FSRRA, this); + load_fast_iregs(block); + return true; +} + +void sh34_base_device::func_FLDI0() { FLDI0(m_sh2_state->arg0); } +static void cfunc_FLDI0(void *param) { ((sh34_base_device *)param)->func_FLDI0(); }; + +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) +{ + save_fast_iregs(block); + UML_MOV(block, mem(&m_sh2_state->arg0), desc->opptr.w[0]); + UML_CALLC(block, cfunc_FLDI0, this); + load_fast_iregs(block); + return true; +} + +void sh34_base_device::func_FLDI1() { FLDI1(m_sh2_state->arg0); } +static void cfunc_FLDI1(void *param) { ((sh34_base_device *)param)->func_FLDI1(); }; + +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) +{ + save_fast_iregs(block); + UML_MOV(block, mem(&m_sh2_state->arg0), desc->opptr.w[0]); + UML_CALLC(block, cfunc_FLDI1, this); + load_fast_iregs(block); + return true; +} + +void sh34_base_device::func_FCNVSD() { FCNVSD(m_sh2_state->arg0); } +static void cfunc_FCNVSD(void *param) { ((sh34_base_device *)param)->func_FCNVSD(); }; + +bool sh34_base_device::generate_group_15_op1111_0x13_FCNVSD(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, uint16_t opcode, int in_delay_slot, uint32_t ovrpc) +{ + save_fast_iregs(block); + UML_MOV(block, mem(&m_sh2_state->arg0), desc->opptr.w[0]); + UML_CALLC(block, cfunc_FCNVSD, this); + load_fast_iregs(block); + return true; +} + +void sh34_base_device::func_FCNVDS() { FCNVDS(m_sh2_state->arg0); } +static void cfunc_FCNVDS(void *param) { ((sh34_base_device *)param)->func_FCNVDS(); }; + +bool sh34_base_device::generate_group_15_op1111_0x13_FCNVDS(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, uint16_t opcode, int in_delay_slot, uint32_t ovrpc) +{ + save_fast_iregs(block); + UML_MOV(block, mem(&m_sh2_state->arg0), desc->opptr.w[0]); + UML_CALLC(block, cfunc_FCNVDS, this); + load_fast_iregs(block); + return true; +} + +void sh34_base_device::func_FIPR() { FIPR(m_sh2_state->arg0); } +static void cfunc_FIPR(void *param) { ((sh34_base_device *)param)->func_FIPR(); }; + +bool sh34_base_device::generate_group_15_op1111_0x13_FIPR(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, uint16_t opcode, int in_delay_slot, uint32_t ovrpc) +{ + save_fast_iregs(block); + UML_MOV(block, mem(&m_sh2_state->arg0), desc->opptr.w[0]); + UML_CALLC(block, cfunc_FIPR, this); + load_fast_iregs(block); + return true; +} + +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) { + switch (opcode & 0xC00) + { + case 0x000: + return generate_group_15_op1111_0x13_op1111_0xf13_FSCHG(block, compiler, desc, opcode, in_delay_slot, ovrpc); // FSCHG(); + break; + case 0x800: + return generate_group_15_op1111_0x13_op1111_0xf13_FRCHG(block, compiler, desc, opcode, in_delay_slot, ovrpc); // FRCHG(); + break; + default: + return false; //machine().debug_break(); + break; + } + } + else { + return generate_group_15_op1111_0x13_op1111_0xf13_FTRV(block, compiler, desc, opcode, in_delay_slot, ovrpc); // FTRV(opcode); + } + } + else { + return generate_group_15_op1111_0x13_op1111_0xf13_FSSCA(block, compiler, desc, opcode, in_delay_slot, ovrpc); // FSSCA(opcode); + } + return false; +} + +void sh34_base_device::func_FSCHG() { FSCHG(); } +static void cfunc_FSCHG(void *param) { ((sh34_base_device *)param)->func_FSCHG(); }; + +bool sh34_base_device::generate_group_15_op1111_0x13_op1111_0xf13_FSCHG(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, uint16_t opcode, int in_delay_slot, uint32_t ovrpc) +{ + save_fast_iregs(block); + //UML_MOV(block, mem(&m_sh2_state->arg0), desc->opptr.w[0]); + UML_CALLC(block, cfunc_FSCHG, this); + load_fast_iregs(block); + return true; +} + +void sh34_base_device::func_FRCHG() { FRCHG(); } +static void cfunc_FRCHG(void *param) { ((sh34_base_device *)param)->func_FRCHG(); }; + +bool sh34_base_device::generate_group_15_op1111_0x13_op1111_0xf13_FRCHG(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, uint16_t opcode, int in_delay_slot, uint32_t ovrpc) +{ + save_fast_iregs(block); + //UML_MOV(block, mem(&m_sh2_state->arg0), desc->opptr.w[0]); + UML_CALLC(block, cfunc_FRCHG, this); + load_fast_iregs(block); + return true; +} + +void sh34_base_device::func_FTRV() { FTRV(m_sh2_state->arg0); } +static void cfunc_FTRV(void *param) { ((sh34_base_device *)param)->func_FTRV(); }; + +bool sh34_base_device::generate_group_15_op1111_0x13_op1111_0xf13_FTRV(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, uint16_t opcode, int in_delay_slot, uint32_t ovrpc) +{ + save_fast_iregs(block); + UML_MOV(block, mem(&m_sh2_state->arg0), desc->opptr.w[0]); + UML_CALLC(block, cfunc_FTRV, this); + load_fast_iregs(block); + return true; +} + +void sh34_base_device::func_FSSCA() { FSSCA(m_sh2_state->arg0); } +static void cfunc_FSSCA(void *param) { ((sh34_base_device *)param)->func_FSSCA(); }; + +bool sh34_base_device::generate_group_15_op1111_0x13_op1111_0xf13_FSSCA(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, uint16_t opcode, int in_delay_slot, uint32_t ovrpc) +{ + save_fast_iregs(block); + UML_MOV(block, mem(&m_sh2_state->arg0), desc->opptr.w[0]); + UML_CALLC(block, cfunc_FSSCA, this); + load_fast_iregs(block); + return true; +} + diff --git a/src/devices/cpu/sh/sh4.h b/src/devices/cpu/sh/sh4.h index fad1d326750..6f3c37e862a 100644 --- a/src/devices/cpu/sh/sh4.h +++ b/src/devices/cpu/sh/sh4.h @@ -15,9 +15,7 @@ #pragma once -// doesn't actually seem to improve performance at all -#define SH4_USE_FASTRAM_OPTIMIZATION 0 -#define SH4_MAX_FASTRAM 3 +#include "sh.h" #define SH4_INT_NONE -1 enum @@ -27,10 +25,7 @@ enum enum { - SH4_PC=1, SH4_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_R0_BK0, SH4_R1_BK0, SH4_R2_BK0, SH4_R3_BK0, SH4_R4_BK0, SH4_R5_BK0, SH4_R6_BK0, SH4_R7_BK0, + SH4_R0_BK0 = SH4_EA+1, SH4_R1_BK0, SH4_R2_BK0, SH4_R3_BK0, SH4_R4_BK0, SH4_R5_BK0, SH4_R6_BK0, SH4_R7_BK0, SH4_R0_BK1, SH4_R1_BK1, SH4_R2_BK1, SH4_R3_BK1, SH4_R4_BK1, SH4_R5_BK1, SH4_R6_BK1, SH4_R7_BK1, SH4_SPC, SH4_SSR, SH4_SGR, SH4_FPSCR, SH4_FPUL, SH4_FR0, SH4_FR1, SH4_FR2, SH4_FR3, SH4_FR4, SH4_FR5, SH4_FR6, SH4_FR7, SH4_FR8, SH4_FR9, SH4_FR10, SH4_FR11, SH4_FR12, SH4_FR13, SH4_FR14, SH4_FR15, @@ -195,13 +190,12 @@ typedef void (*sh4_ftcsr_callback)(uint32_t); #define MCFG_MMU_HACK_TYPE(_hacktype) \ sh34_base_device::set_mmu_hacktype(*device, _hacktype); +class sh4_frontend; +class sh4be_frontend; -class sh34_base_device : public cpu_device +class sh34_base_device : public sh_common_execution { public: -//#if SH4_USE_FASTRAM_OPTIMIZATION - void add_fastram(offs_t start, offs_t end, uint8_t readonly, void *base); -//#endif static void set_md0(device_t &device, int md0) { downcast<sh34_base_device &>(device).c_md0 = md0; } static void set_md1(device_t &device, int md0) { downcast<sh34_base_device &>(device).c_md1 = md0; } @@ -223,10 +217,81 @@ public: void sh4_set_frt_input(int state); void sh4_set_irln_input(int value); - void sh4_set_ftcsr_callback(sh4_ftcsr_callback callback); + //void sh4_set_ftcsr_callback(sh4_ftcsr_callback callback); int sh4_dma_data(struct sh4_device_dma *s); void sh4_dma_ddt(struct sh4_ddt_dma *s); + // DRC C-substitute ops + void func_STCRBANK(); + void func_TRAPA(); + void func_LDCSR(); + void func_LDCMSR(); + void func_RTE(); + void func_SHAD(); + void func_SHLD(); + void func_CHECKIRQ(); + void func_LDCRBANK(); + void func_STCMSPC(); + void func_LDCMSPC(); + void func_STCMSSR(); + void func_LDCMSSR(); + void func_STCMRBANK(); + void func_LDCMRBANK(); + void func_PREFM(); + void func_FADD(); + void func_FSUB(); + void func_FMUL(); + void func_FDIV(); + void func_FCMP_EQ(); + void func_FCMP_GT(); + void func_LDSFPSCR(); + void func_LDCDBR(); + void func_FMOVMRIFR(); + void func_FRCHG(); + void func_FSCHG(); + void func_LDSMFPUL(); + void func_LDSMFPSCR(); + void func_FMOVFRMDR(); + void func_LDCSSR(); + void func_STSFPSCR(); + void func_FLDI0(); + void func_FLDI1(); + void func_FMOVFR(); + void func_FMOVFRS0(); + void func_FTRC(); + void func_FMOVMRFR(); + void func_FMOVS0FR(); + void func_STSFPUL(); + void func_FMOVFRMR(); + void func_LDSFPUL(); + void func_FLOAT(); + void func_STSMFPSCR(); + void func_STSMFPUL(); + void func_FNEG(); + void func_FMAC(); + void func_FABS(); + void func_FLDS(); + void func_FTRV(); + void func_FSTS(); + void func_FSSCA(); + void func_FCNVSD(); + void func_FIPR(); + void func_FSRRA(); + void func_FSQRT(); + void func_FCNVDS(); + void func_LDCMDBR(); + void func_STCMDBR(); + void func_LDCSPC(); + void func_STCMSGR(); + void func_STCDBR(); + void func_STCSGR(); + void func_SETS(); + void func_CLRS(); + void func_LDTLB(); + void func_MOVCAL(); + void func_STCSSR(); + void func_STCSPC(); + protected: // construction/destruction 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); @@ -251,9 +316,7 @@ protected: virtual void state_string_export(const device_state_entry &entry, std::string &str) const override; // device_disasm_interface overrides - virtual uint32_t disasm_min_opcode_bytes() const override { return 2; } - virtual uint32_t disasm_max_opcode_bytes() const override { return 2; } - virtual offs_t disasm_disassemble(std::ostream &stream, offs_t pc, const uint8_t *oprom, const uint8_t *opram, uint32_t options) override; + virtual util::disasm_interface *create_disassembler() override; address_space_config m_program_config; address_space_config m_io_config; @@ -273,22 +336,12 @@ protected: int m_mmuhack; uint32_t m_ppc; - uint32_t m_pc; uint32_t m_spc; - uint32_t m_pr; - uint32_t m_sr; uint32_t m_ssr; - uint32_t m_gbr; - uint32_t m_vbr; - uint32_t m_mach; - uint32_t m_macl; - uint32_t m_r[16]; uint32_t m_rbnk[2][8]; uint32_t m_sgr; uint32_t m_fr[16]; uint32_t m_xf[16]; - uint32_t m_ea; - uint32_t m_delay; uint32_t m_cpu_off; uint32_t m_pending_irq; uint32_t m_test_irq; @@ -302,7 +355,6 @@ protected: int8_t m_irq_line_state[17]; address_space *m_internal; address_space *m_program; - direct_read_data *m_direct; address_space *m_io; // sh4 internal @@ -352,8 +404,6 @@ protected: int8_t m_nmi_line_state; - uint8_t m_sleep_mode; - int m_frt_input; int m_irln; int m_internal_irq_level; @@ -373,7 +423,6 @@ protected: int m_dma_destination_increment[4]; int m_dma_mode[4]; - int m_sh4_icount; int m_is_slave; int m_cpu_clock; int m_bus_clock; @@ -385,27 +434,25 @@ protected: int m_ioport4_pullup; int m_ioport4_direction; - void (*m_ftcsr_read_callback)(uint32_t data); + int m_willjump; + + //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; - int m_cpu_type; - // sh3 internal uint32_t m_sh3internal_upper[0x3000/4]; uint32_t m_sh3internal_lower[0x1000]; uint64_t m_debugger_temp; - - void execute_one_0000(const uint16_t opcode); - void execute_one_4000(const uint16_t opcode); - void execute_one(const uint16_t opcode); 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++) @@ -425,222 +472,6 @@ protected: } } - void TODO(const uint16_t opcode); - void WB(offs_t A, uint8_t V); - void WW(offs_t A, uint16_t V); - void WL(offs_t A, uint32_t V); - void ADD(const uint16_t opcode); - void ADDI(const uint16_t opcode); - void ADDC(const uint16_t opcode); - void ADDV(const uint16_t opcode); - void AND(const uint16_t opcode); - void ANDI(const uint16_t opcode); - void ANDM(const uint16_t opcode); - void BF(const uint16_t opcode); - void BFS(const uint16_t opcode); - void BRA(const uint16_t opcode); - void BRAF(const uint16_t opcode); - void BSR(const uint16_t opcode); - void BSRF(const uint16_t opcode); - void BT(const uint16_t opcode); - void BTS(const uint16_t opcode); - void CLRMAC(const uint16_t opcode); - void CLRT(const uint16_t opcode); - void CMPEQ(const uint16_t opcode); - void CMPGE(const uint16_t opcode); - void CMPGT(const uint16_t opcode); - void CMPHI(const uint16_t opcode); - void CMPHS(const uint16_t opcode); - void CMPPL(const uint16_t opcode); - void CMPPZ(const uint16_t opcode); - void CMPSTR(const uint16_t opcode); - void CMPIM(const uint16_t opcode); - void DIV0S(const uint16_t opcode); - void DIV0U(const uint16_t opcode); - void DIV1(const uint16_t opcode); - void DMULS(const uint16_t opcode); - void DMULU(const uint16_t opcode); - void DT(const uint16_t opcode); - void EXTSB(const uint16_t opcode); - void EXTSW(const uint16_t opcode); - void EXTUB(const uint16_t opcode); - void EXTUW(const uint16_t opcode); - void JMP(const uint16_t opcode); - void JSR(const uint16_t opcode); - void LDCSR(const uint16_t opcode); - void LDCGBR(const uint16_t opcode); - void LDCVBR(const uint16_t opcode); - void LDCMSR(const uint16_t opcode); - void LDCMGBR(const uint16_t opcode); - void LDCMVBR(const uint16_t opcode); - void LDSMACH(const uint16_t opcode); - void LDSMACL(const uint16_t opcode); - void LDSPR(const uint16_t opcode); - void LDSMMACH(const uint16_t opcode); - void LDSMMACL(const uint16_t opcode); - void LDSMPR(const uint16_t opcode); - virtual void LDTLB(const uint16_t opcode); - void MAC_L(const uint16_t opcode); - void MAC_W(const uint16_t opcode); - void MOV(const uint16_t opcode); - void MOVBS(const uint16_t opcode); - void MOVWS(const uint16_t opcode); - void MOVLS(const uint16_t opcode); - void MOVBL(const uint16_t opcode); - void MOVWL(const uint16_t opcode); - void MOVLL(const uint16_t opcode); - void MOVBM(const uint16_t opcode); - void MOVWM(const uint16_t opcode); - void MOVLM(const uint16_t opcode); - void MOVBP(const uint16_t opcode); - void MOVWP(const uint16_t opcode); - void MOVLP(const uint16_t opcode); - void MOVBS0(const uint16_t opcode); - void MOVWS0(const uint16_t opcode); - void MOVLS0(const uint16_t opcode); - void MOVBL0(const uint16_t opcode); - void MOVWL0(const uint16_t opcode); - void MOVLL0(const uint16_t opcode); - void MOVI(const uint16_t opcode); - void MOVWI(const uint16_t opcode); - void MOVLI(const uint16_t opcode); - void MOVBLG(const uint16_t opcode); - void MOVWLG(const uint16_t opcode); - void MOVLLG(const uint16_t opcode); - void MOVBSG(const uint16_t opcode); - void MOVWSG(const uint16_t opcode); - void MOVLSG(const uint16_t opcode); - void MOVBS4(const uint16_t opcode); - void MOVWS4(const uint16_t opcode); - void MOVLS4(const uint16_t opcode); - void MOVBL4(const uint16_t opcode); - void MOVWL4(const uint16_t opcode); - void MOVLL4(const uint16_t opcode); - void MOVA(const uint16_t opcode); - void MOVT(const uint16_t opcode); - void MULL(const uint16_t opcode); - void MULS(const uint16_t opcode); - void MULU(const uint16_t opcode); - void NEG(const uint16_t opcode); - void NEGC(const uint16_t opcode); - void NOP(const uint16_t opcode); - void NOT(const uint16_t opcode); - void OR(const uint16_t opcode); - void ORI(const uint16_t opcode); - void ORM(const uint16_t opcode); - void ROTCL(const uint16_t opcode); - void ROTCR(const uint16_t opcode); - void ROTL(const uint16_t opcode); - void ROTR(const uint16_t opcode); - void RTE(const uint16_t opcode); - void RTS(const uint16_t opcode); - void SETT(const uint16_t opcode); - void SHAL(const uint16_t opcode); - void SHAR(const uint16_t opcode); - void SHLL(const uint16_t opcode); - void SHLL2(const uint16_t opcode); - void SHLL8(const uint16_t opcode); - void SHLL16(const uint16_t opcode); - void SHLR(const uint16_t opcode); - void SHLR2(const uint16_t opcode); - void SHLR8(const uint16_t opcode); - void SHLR16(const uint16_t opcode); - void SLEEP(const uint16_t opcode); - void STCSR(const uint16_t opcode); - void STCGBR(const uint16_t opcode); - void STCVBR(const uint16_t opcode); - void STCMSR(const uint16_t opcode); - void STCMGBR(const uint16_t opcode); - void STCMVBR(const uint16_t opcode); - void STSMACH(const uint16_t opcode); - void STSMACL(const uint16_t opcode); - void STSPR(const uint16_t opcode); - void STSMMACH(const uint16_t opcode); - void STSMMACL(const uint16_t opcode); - void STSMPR(const uint16_t opcode); - void SUB(const uint16_t opcode); - void SUBC(const uint16_t opcode); - void SUBV(const uint16_t opcode); - void SWAPB(const uint16_t opcode); - void SWAPW(const uint16_t opcode); - void TAS(const uint16_t opcode); - void TRAPA(const uint16_t opcode); - void TST(const uint16_t opcode); - void TSTI(const uint16_t opcode); - void TSTM(const uint16_t opcode); - void XOR(const uint16_t opcode); - void XORI(const uint16_t opcode); - void XORM(const uint16_t opcode); - void XTRCT(const uint16_t opcode); - void STCSSR(const uint16_t opcode); - void STCSPC(const uint16_t opcode); - void STCSGR(const uint16_t opcode); - void STSFPUL(const uint16_t opcode); - void STSFPSCR(const uint16_t opcode); - void STCDBR(const uint16_t opcode); - void STCRBANK(const uint16_t opcode); - void STCMRBANK(const uint16_t opcode); - void MOVCAL(const uint16_t opcode); - void CLRS(const uint16_t opcode); - void SETS(const uint16_t opcode); - void STCMSGR(const uint16_t opcode); - void STSMFPUL(const uint16_t opcode); - void STSMFPSCR(const uint16_t opcode); - void STCMDBR(const uint16_t opcode); - void STCMSSR(const uint16_t opcode); - void STCMSPC(const uint16_t opcode); - void LDSMFPUL(const uint16_t opcode); - void LDSMFPSCR(const uint16_t opcode); - void LDCMDBR(const uint16_t opcode); - void LDCMRBANK(const uint16_t opcode); - void LDCMSSR(const uint16_t opcode); - void LDCMSPC(const uint16_t opcode); - void LDSFPUL(const uint16_t opcode); - void LDSFPSCR(const uint16_t opcode); - void LDCDBR(const uint16_t opcode); - void SHAD(const uint16_t opcode); - void SHLD(const uint16_t opcode); - void LDCRBANK(const uint16_t opcode); - void LDCSSR(const uint16_t opcode); - void LDCSPC(const uint16_t opcode); - void PREFM(const uint16_t opcode); - void FMOVMRIFR(const uint16_t opcode); - void FMOVFRMR(const uint16_t opcode); - void FMOVFRMDR(const uint16_t opcode); - void FMOVFRS0(const uint16_t opcode); - void FMOVS0FR(const uint16_t opcode); - void FMOVMRFR(const uint16_t opcode); - void FMOVFR(const uint16_t opcode); - void FLDI1(const uint16_t opcode); - void FLDI0(const uint16_t opcode); - void FLDS(const uint16_t opcode); - void FSTS(const uint16_t opcode); - void FRCHG(); - void FSCHG(); - void FTRC(const uint16_t opcode); - void FLOAT(const uint16_t opcode); - void FNEG(const uint16_t opcode); - void FABS(const uint16_t opcode); - void FCMP_EQ(const uint16_t opcode); - void FCMP_GT(const uint16_t opcode); - void FCNVDS(const uint16_t opcode); - void FCNVSD(const uint16_t opcode); - void FADD(const uint16_t opcode); - void FSUB(const uint16_t opcode); - void FMUL(const uint16_t opcode); - void FDIV(const uint16_t opcode); - void FMAC(const uint16_t opcode); - void FSQRT(const uint16_t opcode); - void FSRRA(const uint16_t opcode); - void FSSCA(const uint16_t opcode); - void FIPR(const uint16_t opcode); - void FTRV(const uint16_t opcode); - void op1111_0xf13(const uint16_t opcode); - void dbreak(const uint16_t opcode); - void op1111_0x13(uint16_t opcode); - uint8_t RB(offs_t A); - uint16_t RW(offs_t A); - uint32_t RL(offs_t A); void sh4_change_register_bank(int to); void sh4_swap_fp_registers(); void sh4_swap_fp_couples(); @@ -650,6 +481,7 @@ protected: void sh4_exception_request(int exception); void sh4_exception_unrequest(int exception); 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(); @@ -722,21 +554,189 @@ protected: 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; } -#if SH4_USE_FASTRAM_OPTIMIZATION - /* fast RAM */ + // 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; + + // 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; + virtual void LDCMSR(const uint16_t opcode) override; + virtual void RTE() override; + virtual void TRAPA(uint32_t i) override; + virtual void ILLEGAL() override; + + // regular handelrs for sh3/4 specific opcodes + virtual void LDTLB(const uint16_t opcode); + void TODO(const uint16_t opcode); + void MOVCAL(const uint16_t opcode); + void CLRS(const uint16_t opcode); + void SETS(const uint16_t opcode); + void STCRBANK(const uint16_t opcode); + void STCMRBANK(const uint16_t opcode); + void STCSSR(const uint16_t opcode); + void STCSPC(const uint16_t opcode); + void STCSGR(const uint16_t opcode); + void STSFPUL(const uint16_t opcode); + void STSFPSCR(const uint16_t opcode); + void STCDBR(const uint16_t opcode); + void STCMSGR(const uint16_t opcode); + void STSMFPUL(const uint16_t opcode); + void STSMFPSCR(const uint16_t opcode); + void STCMDBR(const uint16_t opcode); + void STCMSSR(const uint16_t opcode); + void STCMSPC(const uint16_t opcode); + void LDSMFPUL(const uint16_t opcode); + void LDSMFPSCR(const uint16_t opcode); + void LDCMDBR(const uint16_t opcode); + void LDCMRBANK(const uint16_t opcode); + void LDCMSSR(const uint16_t opcode); + void LDCMSPC(const uint16_t opcode); + void LDSFPUL(const uint16_t opcode); + void LDSFPSCR(const uint16_t opcode); + void LDCDBR(const uint16_t opcode); + void SHAD(const uint16_t opcode); + void SHLD(const uint16_t opcode); + void LDCRBANK(const uint16_t opcode); + void LDCSSR(const uint16_t opcode); + void LDCSPC(const uint16_t opcode); + void PREFM(const uint16_t opcode); + void FMOVMRIFR(const uint16_t opcode); + void FMOVFRMR(const uint16_t opcode); + void FMOVFRMDR(const uint16_t opcode); + void FMOVFRS0(const uint16_t opcode); + void FMOVS0FR(const uint16_t opcode); + void FMOVMRFR(const uint16_t opcode); + void FMOVFR(const uint16_t opcode); + void FLDI1(const uint16_t opcode); + void FLDI0(const uint16_t opcode); + void FLDS(const uint16_t opcode); + void FSTS(const uint16_t opcode); + void FRCHG(); + void FSCHG(); + void FTRC(const uint16_t opcode); + void FLOAT(const uint16_t opcode); + void FNEG(const uint16_t opcode); + void FABS(const uint16_t opcode); + void FCMP_EQ(const uint16_t opcode); + void FCMP_GT(const uint16_t opcode); + void FCNVDS(const uint16_t opcode); + void FCNVSD(const uint16_t opcode); + void FADD(const uint16_t opcode); + void FSUB(const uint16_t opcode); + void FMUL(const uint16_t opcode); + void FDIV(const uint16_t opcode); + void FMAC(const uint16_t opcode); + void FSQRT(const uint16_t opcode); + void FSRRA(const uint16_t opcode); + void FSSCA(const uint16_t opcode); + void FIPR(const uint16_t opcode); + void FTRV(const uint16_t opcode); + + void op1111_0xf13(const uint16_t opcode); + void dbreak(const uint16_t opcode); + void op1111_0x13(uint16_t opcode); + + // group dispatchers to allow for new opcodes + virtual void execute_one_0000(uint16_t opcode) override; + virtual void execute_one_4000(uint16_t opcode) override; + virtual void execute_one_f000(uint16_t opcode) override; + + // DRC related parts + + virtual void generate_update_cycles(drcuml_block *block, compiler_state *compiler, uml::parameter param, bool allow_exception) override; + + // code generators for sh3/4 specific opcodes + bool generate_group_0_STCRBANK(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, uint16_t opcode, int in_delay_slot, uint32_t ovrpc); + bool generate_group_0_STCSSR(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, uint16_t opcode, int in_delay_slot, uint32_t ovrpc); + bool generate_group_0_STCSPC(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, uint16_t opcode, int in_delay_slot, uint32_t ovrpc); + bool generate_group_0_PREFM(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, uint16_t opcode, int in_delay_slot, uint32_t ovrpc); + bool generate_group_0_MOVCAL(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, uint16_t opcode, int in_delay_slot, uint32_t ovrpc); + bool generate_group_0_LDTLB(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, uint16_t opcode, int in_delay_slot, uint32_t ovrpc); + bool generate_group_0_CLRS(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, uint16_t opcode, int in_delay_slot, uint32_t ovrpc); + bool generate_group_0_SETS(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, uint16_t opcode, int in_delay_slot, uint32_t ovrpc); + bool generate_group_0_STCSGR(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, uint16_t opcode, int in_delay_slot, uint32_t ovrpc); + bool generate_group_0_STSFPUL(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, uint16_t opcode, int in_delay_slot, uint32_t ovrpc); + bool generate_group_0_STSFPSCR(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, uint16_t opcode, int in_delay_slot, uint32_t ovrpc); + bool generate_group_0_STCDBR(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, uint16_t opcode, int in_delay_slot, uint32_t ovrpc); + + bool generate_group_4_SHAD(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, uint16_t opcode, int in_delay_slot, uint32_t ovrpc); + bool generate_group_4_SHLD(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, uint16_t opcode, int in_delay_slot, uint32_t ovrpc); + bool generate_group_4_LDCRBANK(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, uint16_t opcode, int in_delay_slot, uint32_t ovrpc); + bool generate_group_4_STCMRBANK(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, uint16_t opcode, int in_delay_slot, uint32_t ovrpc); + bool generate_group_4_LDCMRBANK(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, uint16_t opcode, int in_delay_slot, uint32_t ovrpc); + bool generate_group_4_STCMSGR(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, uint16_t opcode, int in_delay_slot, uint32_t ovrpc); + bool generate_group_4_STCMSSR(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, uint16_t opcode, int in_delay_slot, uint32_t ovrpc); + bool generate_group_4_LDCMSSR(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, uint16_t opcode, int in_delay_slot, uint32_t ovrpc); + bool generate_group_4_LDCSSR(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, uint16_t opcode, int in_delay_slot, uint32_t ovrpc); + bool generate_group_4_STCMSPC(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, uint16_t opcode, int in_delay_slot, uint32_t ovrpc); + bool generate_group_4_LDCMSPC(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, uint16_t opcode, int in_delay_slot, uint32_t ovrpc); + bool generate_group_4_LDCSPC(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, uint16_t opcode, int in_delay_slot, uint32_t ovrpc); + bool generate_group_4_STSMFPUL(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, uint16_t opcode, int in_delay_slot, uint32_t ovrpc); + bool generate_group_4_LDSMFPUL(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, uint16_t opcode, int in_delay_slot, uint32_t ovrpc); + bool generate_group_4_LDSFPUL(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, uint16_t opcode, int in_delay_slot, uint32_t ovrpc); + bool generate_group_4_STSMFPSCR(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, uint16_t opcode, int in_delay_slot, uint32_t ovrpc); + bool generate_group_4_LDSMFPSCR(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, uint16_t opcode, int in_delay_slot, uint32_t ovrpc); + bool generate_group_4_LDSFPSCR(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, uint16_t opcode, int in_delay_slot, uint32_t ovrpc); + bool generate_group_4_STCMDBR(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, uint16_t opcode, int in_delay_slot, uint32_t ovrpc); + bool generate_group_4_LDCMDBR(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, uint16_t opcode, int in_delay_slot, uint32_t ovrpc); + bool generate_group_4_LDCDBR(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, uint16_t opcode, int in_delay_slot, uint32_t ovrpc); + + bool generate_group_15_FADD(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, uint16_t opcode, int in_delay_slot, uint32_t ovrpc); + bool generate_group_15_FSUB(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, uint16_t opcode, int in_delay_slot, uint32_t ovrpc); + bool generate_group_15_FMUL(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, uint16_t opcode, int in_delay_slot, uint32_t ovrpc); + bool generate_group_15_FDIV(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, uint16_t opcode, int in_delay_slot, uint32_t ovrpc); + bool generate_group_15_FCMP_EQ(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, uint16_t opcode, int in_delay_slot, uint32_t ovrpc); + bool generate_group_15_FCMP_GT(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, uint16_t opcode, int in_delay_slot, uint32_t ovrpc); + bool generate_group_15_FMOVS0FR(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, uint16_t opcode, int in_delay_slot, uint32_t ovrpc); + bool generate_group_15_FMOVFRS0(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, uint16_t opcode, int in_delay_slot, uint32_t ovrpc); + bool generate_group_15_FMOVMRFR(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, uint16_t opcode, int in_delay_slot, uint32_t ovrpc); + bool generate_group_15_FMOVMRIFR(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, uint16_t opcode, int in_delay_slot, uint32_t ovrpc); + bool generate_group_15_FMOVFRMR(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, uint16_t opcode, int in_delay_s_0xf13_FTRVlot, uint32_t ovrpc); + bool generate_group_15_FMOVFRMDR(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, uint16_t opcode, int in_delay_slot, uint32_t ovrpc); + bool generate_group_15_FMOVFR(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, uint16_t opcode, int in_delay_slot, uint32_t ovrpc); + bool generate_group_15_op1111_0x13(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, uint16_t opcode, int in_delay_slot, uint32_t ovrpc); + bool generate_group_15_FMAC(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, uint16_t opcode, int in_delay_slot, uint32_t ovrpc); + + bool 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); + bool generate_group_15_op1111_0x13_FLDS(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, uint16_t opcode, int in_delay_slot, uint32_t ovrpc); + bool generate_group_15_op1111_0x13_FLOAT(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, uint16_t opcode, int in_delay_slot, uint32_t ovrpc); + bool generate_group_15_op1111_0x13_FTRC(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, uint16_t opcode, int in_delay_slot, uint32_t ovrpc); + bool generate_group_15_op1111_0x13_FNEG(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, uint16_t opcode, int in_delay_slot, uint32_t ovrpc); + bool generate_group_15_op1111_0x13_FABS(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, uint16_t opcode, int in_delay_slot, uint32_t ovrpc); + bool generate_group_15_op1111_0x13_FSQRT(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, uint16_t opcode, int in_delay_slot, uint32_t ovrpc); + bool generate_group_15_op1111_0x13_FSRRA(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, uint16_t opcode, int in_delay_slot, uint32_t ovrpc); + bool 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); + bool 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); + bool generate_group_15_op1111_0x13_FCNVSD(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, uint16_t opcode, int in_delay_slot, uint32_t ovrpc); + bool generate_group_15_op1111_0x13_FCNVDS(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, uint16_t opcode, int in_delay_slot, uint32_t ovrpc); + bool generate_group_15_op1111_0x13_FIPR(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, uint16_t opcode, int in_delay_slot, uint32_t ovrpc); + bool 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); + + bool generate_group_15_op1111_0x13_op1111_0xf13_FSCHG(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, uint16_t opcode, int in_delay_slot, uint32_t ovrpc); + bool generate_group_15_op1111_0x13_op1111_0xf13_FRCHG(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, uint16_t opcode, int in_delay_slot, uint32_t ovrpc); + bool generate_group_15_op1111_0x13_op1111_0xf13_FTRV(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, uint16_t opcode, int in_delay_slot, uint32_t ovrpc); + bool generate_group_15_op1111_0x13_op1111_0xf13_FSSCA(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, uint16_t opcode, int in_delay_slot, uint32_t ovrpc); + + // code generators for opcodes which need to differ on sh3/4 due to different interrupt / exception handling and register banking + virtual bool generate_group_0_RTE(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, uint16_t opcode, int in_delay_slot, uint32_t ovrpc) override; + virtual bool generate_group_4_LDCSR(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, uint16_t opcode, int in_delay_slot, uint32_t ovrpc) override; + virtual bool generate_group_4_LDCMSR(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, uint16_t opcode, int in_delay_slot, uint32_t ovrpc) override; + virtual bool generate_group_12_TRAPA(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, uint16_t opcode, int in_delay_slot, uint32_t ovrpc) override; + + // group generators to allow for new opcodes + virtual bool generate_group_0(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, uint16_t opcode, int in_delay_slot, uint32_t ovrpc) override; + virtual bool generate_group_4(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, uint16_t opcode, int in_delay_slot, uint32_t ovrpc) override; + virtual bool generate_group_15(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, uint16_t opcode, int in_delay_slot, uint32_t ovrpc) override; + + 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; + +private: bool m_bigendian; - uint32_t m_byte_xor; - uint32_t m_word_xor; - uint32_t m_dword_xor; - uint32_t m_fastram_select; - struct - { - offs_t start; /* start of the RAM block */ - offs_t end; /* end of the RAM block */ - bool readonly; /* true if read-only */ - void * base; /* base in memory where the RAM lives */ - } m_fastram[SH4_MAX_FASTRAM]; -#endif }; @@ -787,39 +787,82 @@ protected: 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; }; class sh3be_device : public sh3_base_device { + friend class sh4be_frontend; + 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; protected: virtual void execute_run() override; - virtual offs_t disasm_disassemble(std::ostream &stream, offs_t pc, const uint8_t *oprom, const uint8_t *opram, uint32_t options) override; }; 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); + 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; + }; class sh4be_device : public sh4_base_device { + friend class sh4be_frontend; + 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; protected: virtual void execute_run() override; - virtual offs_t disasm_disassemble(std::ostream &stream, offs_t pc, const uint8_t *oprom, const uint8_t *opram, uint32_t options) override; }; +class sh4_frontend : public sh_frontend +{ +public: + sh4_frontend(sh_common_execution *device, uint32_t window_start, uint32_t window_end, uint32_t max_sequence); + +protected: + virtual uint16_t read_word(opcode_desc &desc) override; + +private: + virtual bool describe_group_0(opcode_desc &desc, const opcode_desc *prev, uint16_t opcode) override; + virtual bool describe_group_4(opcode_desc &desc, const opcode_desc *prev, uint16_t opcode) override; + virtual bool describe_group_15(opcode_desc &desc, const opcode_desc *prev, uint16_t opcode) override; + bool describe_op1111_0x13(opcode_desc &desc, const opcode_desc *prev, uint16_t opcode); + 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) @@ -827,18 +870,4 @@ DECLARE_DEVICE_TYPE(SH4LE, sh4_device) DECLARE_DEVICE_TYPE(SH4BE, sh4be_device) -/*************************************************************************** - COMPILER-SPECIFIC OPTIONS -***************************************************************************/ - -#define SH4DRC_STRICT_VERIFY 0x0001 /* verify all instructions */ -#define SH4DRC_FLUSH_PC 0x0002 /* flush the PC value before each memory access */ -#define SH4DRC_STRICT_PCREL 0x0004 /* do actual loads on MOVLI/MOVWI instead of collapsing to immediates */ - -#define SH4DRC_COMPATIBLE_OPTIONS (SH4DRC_STRICT_VERIFY | SH4DRC_FLUSH_PC | SH4DRC_STRICT_PCREL) -#define SH4DRC_FASTEST_OPTIONS (0) - -void sh4drc_set_options(device_t *device, uint32_t options); -void sh4drc_add_pcflush(device_t *device, offs_t address); - #endif // MAME_CPU_SH4_SH4_H diff --git a/src/devices/cpu/sh/sh4comn.cpp b/src/devices/cpu/sh/sh4comn.cpp index 4f7ae411e7d..1e7061c7d54 100644 --- a/src/devices/cpu/sh/sh4comn.cpp +++ b/src/devices/cpu/sh/sh4comn.cpp @@ -233,30 +233,6 @@ static const int sh3_intevt2_exception_codes[] = -1 /* SH4_INTC_ROVI */ }; - - -void sh34_base_device::sh4_change_register_bank(int to) -{ - int s; - - if (to) // 0 -> 1 - { - for (s = 0;s < 8;s++) - { - m_rbnk[0][s] = m_r[s]; - m_r[s] = m_rbnk[1][s]; - } - } - else // 1 -> 0 - { - for (s = 0;s < 8;s++) - { - m_rbnk[1][s] = m_r[s]; - m_r[s] = m_rbnk[0][s]; - } - } -} - void sh34_base_device::sh4_swap_fp_registers() { int s; @@ -286,13 +262,36 @@ 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++) + { + m_rbnk[0][s] = m_sh2_state->r[s]; + m_sh2_state->r[s] = m_rbnk[1][s]; + } + } + else // 1 -> 0 + { + for (s = 0;s < 8;s++) + { + m_rbnk[1][s] = m_sh2_state->r[s]; + m_sh2_state->r[s] = m_rbnk[0][s]; + } + } +} + void sh34_base_device::sh4_syncronize_register_bank(int to) { int s; for (s = 0;s < 8;s++) { - m_rbnk[to][s] = m_r[s]; + m_rbnk[to][s] = m_sh2_state->r[s]; } } @@ -317,9 +316,9 @@ void sh34_base_device::sh4_exception_recompute() // checks if there is any inter int a,z; m_test_irq = 0; - if ((!m_pending_irq) || ((m_sr & BL) && (m_exception_requesting[SH4_INTC_NMI] == 0))) + if ((!m_pending_irq) || ((m_sh2_state->sr & BL) && (m_exception_requesting[SH4_INTC_NMI] == 0))) return; - z = (m_sr >> 4) & 15; + z = (m_sh2_state->sr >> 4) & 15; for (a=0;a <= SH4_INTC_ROVI;a++) { if (m_exception_requesting[a]) @@ -367,17 +366,43 @@ void sh34_base_device::sh4_exception_checkunrequest(int exception) sh4_exception_unrequest(exception); } + +void sh34_base_device::sh4_exception_process(int exception, uint32_t vector) +{ + sh4_exception_checkunrequest(exception); + + m_spc = m_sh2_state->pc; + m_ssr = m_sh2_state->sr; + m_sgr = m_sh2_state->r[15]; + + //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) + sh4_syncronize_register_bank((m_sh2_state->sr & sRB) >> 29); + if (!(m_sh2_state->sr & sRB)) + sh4_change_register_bank(1); + m_sh2_state->sr |= sRB; + m_sh2_state->sr |= BL; + sh4_exception_recompute(); + + /* fetch PC */ + 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; } +} + void sh34_base_device::sh4_exception(const char *message, int exception) // handle exception { uint32_t vector; - if (m_cpu_type == CPU_TYPE_SH4) { if (exception < SH4_INTC_NMI) return; // Not yet supported if (exception == SH4_INTC_NMI) { - if ((m_sr & BL) && (!(m_m[ICR] & 0x200))) + if ((m_sh2_state->sr & BL) && (!(m_m[ICR] & 0x200))) return; m_m[ICR] &= ~0x200; @@ -390,9 +415,9 @@ void sh34_base_device::sh4_exception(const char *message, int exception) // hand } else { // if ((m_m[ICR] & 0x4000) && (m_nmi_line_state == ASSERT_LINE)) // return; - if (m_sr & BL) + if (m_sh2_state->sr & BL) return; - if (((m_exception_priority[exception] >> 8) & 255) <= ((m_sr >> 4) & 15)) + if (((m_exception_priority[exception] >> 8) & 255) <= ((m_sh2_state->sr >> 4) & 15)) return; m_m[INTEVT] = exception_codes[exception]; vector = 0x600; @@ -415,9 +440,9 @@ void sh34_base_device::sh4_exception(const char *message, int exception) // hand } else { - if (m_sr & BL) + if (m_sh2_state->sr & BL) return; - if (((m_exception_priority[exception] >> 8) & 255) <= ((m_sr >> 4) & 15)) + if (((m_exception_priority[exception] >> 8) & 255) <= ((m_sh2_state->sr >> 4) & 15)) return; @@ -440,25 +465,7 @@ void sh34_base_device::sh4_exception(const char *message, int exception) // hand /***** END ASSUME THIS TO BE WRONG FOR NOW *****/ } - sh4_exception_checkunrequest(exception); - - m_spc = m_pc; - m_ssr = m_sr; - m_sgr = m_r[15]; - - m_sr |= MD; - if ((machine().debug_flags & DEBUG_FLAG_ENABLED) != 0) - sh4_syncronize_register_bank((m_sr & sRB) >> 29); - if (!(m_sr & sRB)) - sh4_change_register_bank(1); - m_sr |= sRB; - m_sr |= BL; - sh4_exception_recompute(); - - /* fetch PC */ - m_pc = m_vbr + vector; - /* wake up if a sleep opcode is triggered */ - if(m_sleep_mode == 1) { m_sleep_mode = 2; } + sh4_exception_process(exception, vector); } @@ -1098,7 +1105,7 @@ void sh34_base_device::sh4_set_frt_input(int state) sh4_timer_resync(); m_icr = m_frc; m_m[4] |= ICF; - logerror("SH4 '%s': ICF activated (%x)\n", tag(), m_pc & AM); + logerror("SH4 '%s': ICF activated (%x)\n", tag(), m_sh2_state->pc & AM); sh4_recalc_irq(); #endif } @@ -1211,7 +1218,7 @@ void sh34_base_device::execute_set_input(int irqline, int state) // set state of LOG(("SH-4 '%s' IRLn0-IRLn3 level #%d\n", tag(), m_irln)); } } - if (m_test_irq && (!m_delay)) + if (m_test_irq && (!m_sh2_state->m_delay)) sh4_check_pending_irq("sh4_set_irq_line"); } } diff --git a/src/devices/cpu/sh/sh4comn.h b/src/devices/cpu/sh/sh4comn.h index 230207652d6..ded2e5645f1 100644 --- a/src/devices/cpu/sh/sh4comn.h +++ b/src/devices/cpu/sh/sh4comn.h @@ -13,24 +13,10 @@ #ifndef __SH4COMN_H__ #define __SH4COMN_H__ -//#define USE_SH4DRC - -/* speed up delay loops, bail out of tight loops */ -#define BUSY_LOOP_HACKS 0 +#include "sh.h" #define VERBOSE 0 -#ifdef USE_SH4DRC -#include "cpu/drcfe.h" -#include "cpu/drcuml.h" -#include "cpu/drcumlsh.h" - -class sh4_frontend; -#endif - -#define CPU_TYPE_SH3 (2) -#define CPU_TYPE_SH4 (3) - #define LOG(x) do { if (VERBOSE) logerror x; } while (0) #define EXPPRI(pl,po,p,n) (((4-(pl)) << 24) | ((15-(po)) << 16) | ((p) << 8) | (255-(n))) @@ -50,74 +36,6 @@ class sh4_frontend; #define FP_XFS2(r) *( (float *)(m_xf+((r) ^ m_fpu_pr)) ) #endif - -#ifdef USE_SH4DRC -struct sh4_state -{ - int icount; - - int pcfsel; // last pcflush entry set - int maxpcfsel; // highest valid pcflush entry - uint32_t pcflushes[16]; // pcflush entries - - drc_cache * cache; /* pointer to the DRC code cache */ - drcuml_state * drcuml; /* DRC UML generator state */ - sh4_frontend * drcfe; /* pointer to the DRC front-end class */ - uint32_t drcoptions; /* configurable DRC options */ - - /* internal stuff */ - uint8_t cache_dirty; /* true if we need to flush the cache */ - - /* parameters for subroutines */ - uint64_t numcycles; /* return value from gettotalcycles */ - uint32_t arg0; /* print_debug argument 1 */ - uint32_t arg1; /* print_debug argument 2 */ - uint32_t irq; /* irq we're taking */ - - /* register mappings */ - uml::parameter regmap[16]; /* parameter to register mappings for all 16 integer registers */ - - uml::code_handle * entry; /* entry point */ - uml::code_handle * read8; /* read byte */ - uml::code_handle * write8; /* write byte */ - uml::code_handle * read16; /* read half */ - uml::code_handle * write16; /* write half */ - uml::code_handle * read32; /* read word */ - uml::code_handle * write32; /* write word */ - - uml::code_handle * interrupt; /* interrupt */ - uml::code_handle * nocode; /* nocode */ - uml::code_handle * out_of_cycles; /* out of cycles exception handler */ - - uint32_t prefadr; - uint32_t target; -}; -#endif - -#ifdef USE_SH4DRC -class sh4_frontend : public drc_frontend -{ -public: - sh4_frontend(sh4_state &state, uint32_t window_start, uint32_t window_end, uint32_t max_sequence); - -protected: - virtual bool describe(opcode_desc &desc, const opcode_desc *prev); - -private: - bool describe_group_0(opcode_desc &desc, const opcode_desc *prev, uint16_t opcode); - bool describe_group_2(opcode_desc &desc, const opcode_desc *prev, uint16_t opcode); - bool describe_group_3(opcode_desc &desc, const opcode_desc *prev, uint16_t opcode); - bool describe_group_4(opcode_desc &desc, const opcode_desc *prev, uint16_t opcode); - bool describe_group_6(opcode_desc &desc, const opcode_desc *prev, uint16_t opcode); - bool describe_group_8(opcode_desc &desc, const opcode_desc *prev, uint16_t opcode); - bool describe_group_12(opcode_desc &desc, const opcode_desc *prev, uint16_t opcode); - bool describe_group_15(opcode_desc &desc, const opcode_desc *prev, uint16_t opcode); - - sh4_state &m_context; -}; -#endif - - enum { ICF = 0x00800000, @@ -126,21 +44,15 @@ enum OVF = 0x00020000 }; -/* Bits in SR */ -#define T 0x00000001 -#define S 0x00000002 -#define I 0x000000f0 -#define Q 0x00000100 -#define M 0x00000200 #define FD 0x00008000 #define BL 0x10000000 #define sRB 0x20000000 #define MD 0x40000000 /* 29 bits */ -#define AM 0x1fffffff +#define SH34_AM 0x1fffffff -#define FLAGS (MD|sRB|BL|FD|M|Q|I|S|T) +#define SH34_FLAGS (MD|sRB|BL|FD|SH_M|SH_Q|SH_I|SH_S|SH_T) /* Bits in FPSCR */ #define RM 0x00000003 @@ -149,20 +61,9 @@ enum #define SZ 0x00100000 #define FR 0x00200000 -#define Rn ((opcode>>8)&15) -#define Rm ((opcode>>4)&15) - #define REGFLAG_R(n) (1 << (n)) -#define REGFLAG_FR(n) (1 << (n)) -#define REGFLAG_XR(n) (1 << (n)) -/* register flags 1 */ -#define REGFLAG_PR (1 << 0) -#define REGFLAG_MACL (1 << 1) -#define REGFLAG_MACH (1 << 2) -#define REGFLAG_GBR (1 << 3) -#define REGFLAG_VBR (1 << 4) -#define REGFLAG_SR (1 << 5) +/* additional register flags 1 */ #define REGFLAG_SGR (1 << 6) #define REGFLAG_FPUL (1 << 7) #define REGFLAG_FPSCR (1 << 8) @@ -170,5 +71,4 @@ enum #define REGFLAG_SSR (1 << 10) #define REGFLAG_SPC (1 << 11) - #endif /* __SH4COMN_H__ */ diff --git a/src/devices/cpu/sh/sh4dmac.cpp b/src/devices/cpu/sh/sh4dmac.cpp index c06ffb034dd..ba727d324c5 100644 --- a/src/devices/cpu/sh/sh4dmac.cpp +++ b/src/devices/cpu/sh/sh4dmac.cpp @@ -89,8 +89,8 @@ int sh34_base_device::sh4_dma_transfer(int channel, int timermode, uint32_t chcr m_dma_timer[channel]->adjust(attotime::zero, channel); } - src &= AM; - dst &= AM; + src &= SH34_AM; + dst &= SH34_AM; switch(size) { @@ -178,8 +178,8 @@ int sh34_base_device::sh4_dma_transfer(int channel, int timermode, uint32_t chcr } break; } - *sar = (*sar & ~AM) | src; - *dar = (*dar & ~AM) | dst; + *sar = (*sar & ~SH34_AM) | src; + *dar = (*dar & ~SH34_AM) | dst; *dmatcr = count; return 1; } @@ -218,8 +218,8 @@ int sh34_base_device::sh4_dma_transfer_device(int channel, uint32_t chcr, uint32 m_dma_timer_active[channel] = 1; - src &= AM; - dst &= AM; + src &= SH34_AM; + dst &= SH34_AM; // remember parameters m_dma_source[channel]=src; diff --git a/src/devices/cpu/sh/sh4fe.cpp b/src/devices/cpu/sh/sh4fe.cpp new file mode 100644 index 00000000000..ca122cd4eb4 --- /dev/null +++ b/src/devices/cpu/sh/sh4fe.cpp @@ -0,0 +1,317 @@ +// license:BSD-3-Clause +// copyright-holders:R. Belmont, David Haywood +/*************************************************************************** + + sh4fe.c + + Front end for SH-4 recompiler + +***************************************************************************/ + +#include "emu.h" +#include "sh4.h" +#include "sh4comn.h" +#include "cpu/drcfe.h" + + +/*************************************************************************** + INSTRUCTION PARSERS +***************************************************************************/ + +sh4_frontend::sh4_frontend(sh_common_execution *device, uint32_t window_start, uint32_t window_end, uint32_t max_sequence) + : sh_frontend(device, window_start, window_end, max_sequence) +{ +} + +uint16_t sh4_frontend::read_word(opcode_desc &desc) +{ + if (desc.physpc >= 0xe0000000) + return m_sh->m_direct->read_word(desc.physpc, SH34LE_CODE_XOR(0)); + + return m_sh->m_direct->read_word(desc.physpc & SH34_AM, SH34LE_CODE_XOR(0)); +} + +uint16_t sh4be_frontend::read_word(opcode_desc &desc) +{ + if (desc.physpc >= 0xe0000000) + return m_sh->m_direct->read_word(desc.physpc, SH34BE_CODE_XOR(0)); + + return m_sh->m_direct->read_word(desc.physpc & SH34_AM, SH34BE_CODE_XOR(0)); +} + + +bool sh4_frontend::describe_group_0(opcode_desc &desc, const opcode_desc *prev, uint16_t opcode) +{ + switch (opcode & 0xff) + { + default: + // fall through to SH2 handlers + return sh_frontend::describe_group_0(desc, prev, opcode); + + case 0x52: + case 0x62: + case 0x43: + case 0x63: + case 0xe3: + case 0x68: + case 0xe8: + case 0x4a: + case 0xca: + return true; // ILLEGAL(); break; // illegal on sh4 + + case 0x93: + case 0xa3: + case 0xb3: + return true; // TODO(opcode); break; + + case 0x82: + case 0x92: + case 0xa2: + case 0xb2: + case 0xc2: + case 0xd2: + case 0xe2: + case 0xf2: + return true; // STC RBANK(opcode); break; // sh3/4 only + + case 0x32: return true; // STCSSR(opcode); break; // sh3/4 only + case 0x42: return true; // STCSPC(opcode); break; // sh3/4 only + case 0x83: return true; // PREFM(opcode); break; // sh3/4 only + case 0xc3: return true; // MOVCAL(opcode); break; // sh4 only + + case 0x38: + case 0xb8: + return true; // LDTLB(opcode); break; // sh3/4 only + + case 0x48: + case 0xc8: + return true; // CLRS(opcode); break; // sh3/4 only + + case 0x58: + case 0xd8: + return true; // SETS(opcode); break; // sh3/4 only + + case 0x3a: + case 0xba: + return true; // STCSGR(opcode); break; // sh4 only + + case 0x5a: + case 0xda: + return true; // STSFPUL(opcode); break; // sh4 only + + case 0x6a: + case 0xea: + return true; // STSFPSCR(opcode); break; // sh4 only + + case 0x7a: + case 0xfa: + return true; // STCDBR(opcode); break; // sh4 only + } + + return false; +} + + +bool sh4_frontend::describe_group_4(opcode_desc &desc, const opcode_desc *prev, uint16_t opcode) +{ + switch (opcode & 0xff) + { + + default: // LDCMSR (0x0e) has sh2/4 flag difference + // fall through to SH2 handlers + return sh_frontend::describe_group_4(desc, prev, opcode); + + case 0x42: + case 0x46: + case 0x4a: + case 0x53: + case 0x57: + case 0x5e: + case 0x63: + case 0x67: + case 0x6e: + case 0x82: + case 0x86: + case 0x8a: + case 0x92: + case 0x96: + case 0x9a: + case 0xa2: + case 0xa6: + case 0xaa: + case 0xc2: + case 0xc6: + case 0xca: + case 0xd2: + case 0xd6: + case 0xda: + case 0xe2: + case 0xe6: + case 0xea: + return true; // ILLEGAL(); break; // defined as illegal on SH4 + + case 0x0c: + case 0x1c: + case 0x2c: + case 0x3c: + case 0x4c: + case 0x5c: + case 0x6c: + case 0x7c: + case 0x8c: + case 0x9c: + case 0xac: + case 0xbc: + case 0xcc: + case 0xdc: + case 0xec: + case 0xfc: + return true; // SHAD(opcode); break; // sh3/4 only needed + + case 0x0d: + case 0x1d: + case 0x2d: + case 0x3d: + case 0x4d: + case 0x5d: + case 0x6d: + case 0x7d: + case 0x8d: + case 0x9d: + case 0xad: + case 0xbd: + case 0xcd: + case 0xdd: + case 0xed: + case 0xfd: + return true; // SHLD(opcode); break; // sh3/4 only needed + + case 0x8e: + case 0x9e: + case 0xae: + case 0xbe: + case 0xce: + case 0xde: + case 0xee: + case 0xfe: + return true; // LDCRBANK(opcode); break; // sh3/4 only + + case 0x83: + case 0x93: + case 0xa3: + case 0xb3: + case 0xc3: + case 0xd3: + case 0xe3: + case 0xf3: + return true; // STCMRBANK(opcode); break; // sh3/4 only + + case 0x87: + case 0x97: + case 0xa7: + case 0xb7: + case 0xc7: + case 0xd7: + case 0xe7: + case 0xf7: + return true; // LDCMRBANK(opcode); break; // sh3/4 only + + case 0x32: return true; // STCMSGR(opcode); break; // sh4 only + case 0x33: return true; // STCMSSR(opcode); break; // sh4 only + case 0x37: return true; // LDCMSSR(opcode); break; // sh3/4 only + case 0x3e: return true; // LDCSSR(opcode); break; // sh3/4 only + case 0x43: return true; // STCMSPC(opcode); break; // sh3/4 only + case 0x47: return true; // LDCMSPC(opcode); break; // sh3/4 only + case 0x4e: return true; // LDCSPC(opcode); break; // sh3/4 only + case 0x52: return true; // STSMFPUL(opcode); break; // sh4 only + case 0x56: return true; // LDSMFPUL(opcode); break; // sh4 only + case 0x5a: return true; // LDSFPUL(opcode); break; // sh4 only + case 0x62: return true; // STSMFPSCR(opcode); break; // sh4 only + case 0x66: return true; // LDSMFPSCR(opcode); break; // sh4 only + case 0x6a: return true; // LDSFPSCR(opcode); break; // sh4 only + case 0xf2: return true; // STCMDBR(opcode); break; // sh4 only + case 0xf6: return true; // LDCMDBR(opcode); break; // sh4 only + case 0xfa: return true; // LDCDBR(opcode); break; // sh4 only + } + + return false; +} + +// SH4 only (FPU ops) +bool sh4_frontend::describe_group_15(opcode_desc &desc, const opcode_desc *prev, uint16_t opcode) +{ + switch (opcode & 0x0f) + { + case 0x00: return true; // FADD(opcode); break; + case 0x01: return true; // FSUB(opcode); break; + case 0x02: return true; // FMUL(opcode); break; + case 0x03: return true; // FDIV(opcode); break; + case 0x04: return true; // FCMP_EQ(opcode); break; + case 0x05: return true; // FCMP_GT(opcode); break; + case 0x06: return true; // FMOVS0FR(opcode); break; + case 0x07: return true; // FMOVFRS0(opcode); break; + case 0x08: return true; // FMOVMRFR(opcode); break; + case 0x09: return true; // FMOVMRIFR(opcode); break; + case 0x0a: return true; // FMOVFRMR(opcode); break; + case 0x0b: return true; // FMOVFRMDR(opcode); break; + case 0x0c: return true; // FMOVFR(opcode); break; + case 0x0d: return describe_op1111_0x13(desc, prev, opcode); // break; + case 0x0e: return true; // FMAC(opcode); break; + case 0x0f: + return true; + //if (opcode == 0xffff) return true; // atomiswave uses ffff as NOP? + //return false; // dbreak(opcode); break; + } + return false; +} + +bool sh4_frontend::describe_op1111_0x13(opcode_desc &desc, const opcode_desc *prev, uint16_t opcode) +{ + switch ((opcode >> 4) & 0x0f) + { + case 0x00: return true; // FSTS(opcode); break; + case 0x01: return true; // FLDS(opcode); break; + case 0x02: return true; // FLOAT(opcode); break; + case 0x03: return true; // FTRC(opcode); break; + case 0x04: return true; // FNEG(opcode); break; + case 0x05: return true; // FABS(opcode); break; + case 0x06: return true; // FSQRT(opcode); break; + case 0x07: return true; // FSRRA(opcode); break; + case 0x08: return true; // FLDI0(opcode); break; + case 0x09: return true; // FLDI1(opcode); break; + case 0x0a: return true; // FCNVSD(opcode); break; + case 0x0b: return true; // FCNVDS(opcode); break; + case 0x0c: return false; // dbreak(opcode); break; + case 0x0d: return false; // dbreak(opcode); break; + case 0x0e: return true; // FIPR(opcode); break; + case 0x0f: return describe_op1111_0xf13(desc, prev, opcode); // break; + } + return false; +} + +bool sh4_frontend::describe_op1111_0xf13(opcode_desc &desc, const opcode_desc *prev, uint16_t opcode) +{ + if (opcode & 0x100) { + if (opcode & 0x200) { + switch (opcode & 0xC00) + { + case 0x000: + return true; //FSCHG(); + break; + case 0x800: + return true; //FRCHG(); + break; + default: + return false; //machine().debug_break(); + break; + } + } + else { + return true; // FTRV(opcode); + } + } + else { + return true; // FSSCA(opcode); + } + return false; +} diff --git a/src/devices/cpu/sh/sh4dasm.cpp b/src/devices/cpu/sh/sh_dasm.cpp index faff895f3a5..a2e6dd67496 100644 --- a/src/devices/cpu/sh/sh4dasm.cpp +++ b/src/devices/cpu/sh/sh_dasm.cpp @@ -1,21 +1,587 @@ // license:BSD-3-Clause -// copyright-holders:R. Belmont +// copyright-holders:Juergen Buchmueller, R. Belmont #include "emu.h" -#include "debugger.h" -#include "sh4.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) -#define Rn ((opcode >> 8) & 15) -#define Rm ((opcode >> 4) & 15) - -static const char *const regname[16] = { +const char *const sh_disassembler::regname[16] = { "R0", "R1", "R2", "R3", "R4", "R5", "R6", "R7", - "R8", "R9", "R10","R11","R12","R13","R14","R15" + "R8", "R9", "R10","R11","R12","R13","R14", + // The old SH2 dasm used 'SP' here, the old SH4 used 'R15' + //"SP" + "R15" }; -static uint32_t op0000(std::ostream &stream, uint32_t pc, uint16_t opcode) +uint32_t sh_disassembler::op0000(std::ostream &stream, uint32_t pc, uint16_t opcode) +{ + uint32_t flags = 0; + switch(opcode & 0x3f) + { + case 0x02: + util::stream_format(stream, "STC SR,%s", regname[Rn]); + break; + case 0x03: + util::stream_format(stream, "BSRF %s", regname[Rn]); + break; + case 0x08: + stream << "CLRT"; + break; + case 0x09: + stream << "NOP"; + break; + case 0x0A: + util::stream_format(stream, "STS MACH,%s", regname[Rn]); + break; + case 0x0B: + stream << "RTS"; + flags = STEP_OUT; + break; + case 0x12: + util::stream_format(stream, "STS GBR,%s", regname[Rn]); + break; + case 0x18: + stream << "SETT"; + break; + case 0x19: + stream << "DIV0U"; + break; + case 0x1A: + util::stream_format(stream, "STS MACL,%s", regname[Rn]); + break; + case 0x1B: + stream << "SLEEP"; + break; + case 0x22: + util::stream_format(stream, "STC VBR,%s", regname[Rn]); + break; + case 0x23: + util::stream_format(stream, "BRAF %s", regname[Rn]); + break; + case 0x28: + stream << "CLRMAC"; + break; + case 0x29: + util::stream_format(stream, "MOVT %s", regname[Rn]); + break; + case 0x2A: + util::stream_format(stream, "STS PR,%s", regname[Rn]); + break; + case 0x2B: + stream << "RTE"; + flags = STEP_OUT; + break; + default: + switch(opcode & 15) + { + case 0: + util::stream_format(stream, "?????? $%04X", opcode); + break; + case 1: + util::stream_format(stream, "?????? $%04X", opcode); + break; + case 2: + util::stream_format(stream, "?????? $%04X", opcode); + break; + case 3: + util::stream_format(stream, "?????? $%04X", opcode); + break; + case 4: + util::stream_format(stream, "MOV.B %s,@(R0,%s)", regname[Rm], regname[Rn]); + break; + case 5: + util::stream_format(stream, "MOV.W %s,@(R0,%s)", regname[Rm], regname[Rn]); + break; + case 6: + util::stream_format(stream, "MOV.L %s,@(R0,%s)", regname[Rm], regname[Rn]); + break; + case 7: + util::stream_format(stream, "MUL.L %s,%s", regname[Rm], regname[Rn]); + break; + case 8: + util::stream_format(stream, "?????? $%04X", opcode); + break; + case 9: + util::stream_format(stream, "?????? $%04X", opcode); + break; + case 10: + util::stream_format(stream, "?????? $%04X", opcode); + break; + case 11: + util::stream_format(stream, "?????? $%04X", opcode); + break; + case 12: + util::stream_format(stream, "MOV.B @(R0,%s),%s", regname[Rm], regname[Rn]); + break; + case 13: + util::stream_format(stream, "MOV.W @(R0,%s),%s", regname[Rm], regname[Rn]); + break; + case 14: + 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]); + break; + } + } + return flags; +} + +uint32_t sh_disassembler::op0001(std::ostream &stream, uint32_t pc, uint16_t opcode) +{ + util::stream_format(stream, "MOV.L %s,@($%02X,%s)", regname[Rm], (opcode & 15) * 4, regname[Rn]); + return 0; +} + +uint32_t sh_disassembler::op0010(std::ostream &stream, uint32_t pc, uint16_t opcode) +{ + switch (opcode & 15) + { + case 0: + util::stream_format(stream, "MOV.B %s,@%s", regname[Rm], regname[Rn]); + break; + case 1: + util::stream_format(stream, "MOV.W %s,@%s", regname[Rm], regname[Rn]); + break; + case 2: + util::stream_format(stream, "MOV.L %s,@%s", regname[Rm], regname[Rn]); + break; + case 3: + util::stream_format(stream, "?????? $%04X", opcode); + break; + case 4: + util::stream_format(stream, "MOV.B %s,@-%s", regname[Rm], regname[Rn]); + break; + case 5: + util::stream_format(stream, "MOV.W %s,@-%s", regname[Rm], regname[Rn]); + break; + case 6: + util::stream_format(stream, "MOV.L %s,@-%s", regname[Rm], regname[Rn]); + break; + case 7: + util::stream_format(stream, "DIV0S %s,%s", regname[Rm], regname[Rn]); + break; + case 8: + util::stream_format(stream, "TST %s,%s", regname[Rm], regname[Rn]); + break; + case 9: + util::stream_format(stream, "AND %s,%s", regname[Rm], regname[Rn]); + break; + case 10: + util::stream_format(stream, "XOR %s,%s", regname[Rm], regname[Rn]); + break; + case 11: + util::stream_format(stream, "OR %s,%s", regname[Rm], regname[Rn]); + break; + case 12: + util::stream_format(stream, "CMP/STR %s,%s", regname[Rm], regname[Rn]); + break; + case 13: + util::stream_format(stream, "XTRCT %s,%s", regname[Rm], regname[Rn]); + break; + case 14: + util::stream_format(stream, "MULU.W %s,%s", regname[Rm], regname[Rn]); + break; + case 15: + util::stream_format(stream, "MULS.W %s,%s", regname[Rm], regname[Rn]); + break; + } + return 0; +} + +uint32_t sh_disassembler::op0011(std::ostream &stream, uint32_t pc, uint16_t opcode) +{ + switch (opcode & 15) + { + case 0: + util::stream_format(stream, "CMP/EQ %s,%s", regname[Rm], regname[Rn]); + break; + case 1: + util::stream_format(stream, "?????? %s,%s", regname[Rm], regname[Rn]); + break; + case 2: + util::stream_format(stream, "CMP/HS %s,%s", regname[Rm], regname[Rn]); + break; + case 3: + util::stream_format(stream, "CMP/GE %s,%s", regname[Rm], regname[Rn]); + break; + case 4: + util::stream_format(stream, "DIV1 %s,%s", regname[Rm], regname[Rn]); + break; + case 5: + util::stream_format(stream, "DMULU.L %s,%s", regname[Rm], regname[Rn]); + break; + case 6: + util::stream_format(stream, "CMP/HI %s,%s", regname[Rm], regname[Rn]); + break; + case 7: + util::stream_format(stream, "CMP/GT %s,%s", regname[Rm], regname[Rn]); + break; + case 8: + util::stream_format(stream, "SUB %s,%s", regname[Rm], regname[Rn]); + break; + case 9: + util::stream_format(stream, "?????? %s,%s", regname[Rm], regname[Rn]); + break; + case 10: + util::stream_format(stream, "SUBC %s,%s", regname[Rm], regname[Rn]); + break; + case 11: + util::stream_format(stream, "SUBV %s,%s", regname[Rm], regname[Rn]); + break; + case 12: + util::stream_format(stream, "ADD %s,%s", regname[Rm], regname[Rn]); + break; + case 13: + util::stream_format(stream, "DMULS.L %s,%s", regname[Rm], regname[Rn]); + break; + case 14: + util::stream_format(stream, "ADDC %s,%s", regname[Rm], regname[Rn]); + break; + case 15: + util::stream_format(stream, "ADDV %s,%s", regname[Rm], regname[Rn]); + break; + } + return 0; +} + +uint32_t sh_disassembler::op0100(std::ostream &stream, uint32_t pc, uint16_t opcode) +{ + uint32_t flags = 0; + switch(opcode & 0x3F) + { + case 0x00: + util::stream_format(stream, "SHLL %s", regname[Rn]); + break; + case 0x01: + util::stream_format(stream, "SHLR %s", regname[Rn]); + break; + case 0x02: + util::stream_format(stream, "STS.L MACH,@-%s", regname[Rn]); + break; + case 0x03: + util::stream_format(stream, "STC.L SR,@-%s", regname[Rn]); + break; + case 0x04: + util::stream_format(stream, "ROTL %s", regname[Rn]); + break; + case 0x05: + util::stream_format(stream, "ROTR %s", regname[Rn]); + break; + case 0x06: + util::stream_format(stream, "LDS.L @%s+,MACH", regname[Rn]); + break; + case 0x07: + util::stream_format(stream, "LDC.L @%s+,SR", regname[Rn]); + break; + case 0x08: + util::stream_format(stream, "SHLL2 %s", regname[Rn]); + break; + case 0x09: + util::stream_format(stream, "SHLR2 %s", regname[Rn]); + break; + case 0x0a: + util::stream_format(stream, "LDS %s,MACH", regname[Rn]); + break; + case 0x0b: + util::stream_format(stream, "JSR %s", regname[Rn]); + flags = STEP_OVER | step_over_extra(1); + break; + case 0x0e: + util::stream_format(stream, "LDC %s,SR", regname[Rn]); + break; + case 0x10: + util::stream_format(stream, "DT %s", regname[Rn]); + break; + case 0x11: + util::stream_format(stream, "CMP/PZ %s", regname[Rn]); + break; + case 0x12: + util::stream_format(stream, "STS.L MACL,@-%s", regname[Rn]); + break; + case 0x13: + util::stream_format(stream, "STC.L GBR,@-%s", regname[Rn]); + break; + case 0x15: + util::stream_format(stream, "CMP/PL %s", regname[Rn]); + break; + case 0x16: + util::stream_format(stream, "LDS.L @%s+,MACL", regname[Rn]); + break; + case 0x17: + util::stream_format(stream, "LDC.L @%s+,GBR", regname[Rn]); + break; + case 0x18: + util::stream_format(stream, "SHLL8 %s", regname[Rn]); + break; + case 0x19: + util::stream_format(stream, "SHLR8 %s", regname[Rn]); + break; + case 0x1a: + util::stream_format(stream, "LDS %s,MACL", regname[Rn]); + break; + case 0x1b: + util::stream_format(stream, "TAS %s", regname[Rn]); + break; + case 0x1e: + util::stream_format(stream, "LDC %s,GBR", regname[Rn]); + break; + case 0x20: + util::stream_format(stream, "SHAL %s", regname[Rn]); + break; + case 0x21: + util::stream_format(stream, "SHAR %s", regname[Rn]); + break; + case 0x22: + util::stream_format(stream, "STS.L PR,@-%s", regname[Rn]); + break; + case 0x23: + util::stream_format(stream, "STC.L VBR,@-%s", regname[Rn]); + break; + case 0x24: + util::stream_format(stream, "ROTCL %s", regname[Rn]); + break; + case 0x25: + util::stream_format(stream, "ROTCR %s", regname[Rn]); + break; + case 0x26: + util::stream_format(stream, "LDS.L @%s+,PR", regname[Rn]); + break; + case 0x27: + util::stream_format(stream, "LDC.L @%s+,VBR", regname[Rn]); + break; + case 0x28: + util::stream_format(stream, "SHLL16 %s", regname[Rn]); + break; + case 0x29: + util::stream_format(stream, "SHLR16 %s", regname[Rn]); + break; + case 0x2a: + util::stream_format(stream, "LDS %s,PR", regname[Rn]); + break; + case 0x2b: + util::stream_format(stream, "JMP %s", regname[Rn]); + break; + case 0x2e: + util::stream_format(stream, "LDC %s,VBR", regname[Rn]); + break; + default: + if ((opcode & 15) == 15) + util::stream_format(stream, "MAC.W @%s+,@%s+", regname[Rm], regname[Rn]); + else + util::stream_format(stream, "?????? $%04X", opcode); + } + return flags; +} + +uint32_t sh_disassembler::op0101(std::ostream &stream, uint32_t pc, uint16_t opcode) +{ + util::stream_format(stream, "MOV.L @($%02X,%s),%s", (opcode & 15) * 4, regname[Rm], regname[Rn]); + return 0; +} + +uint32_t sh_disassembler::op0110(std::ostream &stream, uint32_t pc, uint16_t opcode) + +{ + switch(opcode & 0xF) + { + case 0x00: + util::stream_format(stream, "MOV.B @%s,%s", regname[Rm], regname[Rn]); + break; + case 0x01: + util::stream_format(stream, "MOV.W @%s,%s", regname[Rm], regname[Rn]); + break; + case 0x02: + util::stream_format(stream, "MOV.L @%s,%s", regname[Rm], regname[Rn]); + break; + case 0x03: + util::stream_format(stream, "MOV %s,%s", regname[Rm], regname[Rn]); + break; + case 0x04: + util::stream_format(stream, "MOV.B @%s+,%s", regname[Rm], regname[Rn]); + break; + case 0x05: + util::stream_format(stream, "MOV.W @%s+,%s", regname[Rm], regname[Rn]); + break; + case 0x06: + util::stream_format(stream, "MOV.L @%s+,%s", regname[Rm], regname[Rn]); + break; + case 0x07: + util::stream_format(stream, "NOT %s,%s", regname[Rm], regname[Rn]); + break; + case 0x08: + util::stream_format(stream, "SWAP.B %s,%s", regname[Rm], regname[Rn]); + break; + case 0x09: + util::stream_format(stream, "SWAP.W %s,%s", regname[Rm], regname[Rn]); + break; + case 0x0a: + util::stream_format(stream, "NEGC %s,%s", regname[Rm], regname[Rn]); + break; + case 0x0b: + util::stream_format(stream, "NEG %s,%s", regname[Rm], regname[Rn]); + break; + case 0x0c: + util::stream_format(stream, "EXTU.B %s,%s", regname[Rm], regname[Rn]); + break; + case 0x0d: + util::stream_format(stream, "EXTU.W %s,%s", regname[Rm], regname[Rn]); + break; + case 0x0e: + util::stream_format(stream, "EXTS.B %s,%s", regname[Rm], regname[Rn]); + break; + case 0x0f: + util::stream_format(stream, "EXTS.W %s,%s", regname[Rm], regname[Rn]); + break; + } + return 0; +} + +uint32_t sh_disassembler::op0111(std::ostream &stream, uint32_t pc, uint16_t opcode) +{ + util::stream_format(stream, "ADD #$%02X,%s", opcode & 0xff, regname[Rn]); + return 0; +} + +uint32_t sh_disassembler::op1000(std::ostream &stream, uint32_t pc, uint16_t opcode) +{ + switch((opcode >> 8) & 15) + { + case 0: + util::stream_format(stream, "MOV.B R0,@($%02X,%s)", (opcode & 15), regname[Rm]); + break; + case 1: + util::stream_format(stream, "MOV.W R0,@($%02X,%s)", (opcode & 15) * 2, regname[Rm]); + break; + case 4: + util::stream_format(stream, "MOV.B @($%02X,%s),R0", (opcode & 15), regname[Rm]); + break; + case 5: + util::stream_format(stream, "MOV.W @($%02X,%s),R0", (opcode & 15) * 2, regname[Rm]); + break; + case 8: + 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; + case 11: + util::stream_format(stream, "BF $%08X", pc + SIGNX8(opcode & 0xff) * 2 + 2); + break; + case 13: + util::stream_format(stream, "BTS $%08X", pc + SIGNX8(opcode & 0xff) * 2 + 2); + break; + case 15: + util::stream_format(stream, "BFS $%08X", pc + SIGNX8(opcode & 0xff) * 2 + 2); + break; + default : + util::stream_format(stream, "invalid $%04X", opcode); + } + return 0; +} + +uint32_t sh_disassembler::op1001(std::ostream &stream, uint32_t pc, uint16_t opcode) +{ + util::stream_format(stream, "MOV.W @($%04X,PC),%s [%08X]", (opcode & 0xff) * 2, regname[Rn], pc+((opcode & 0xff) * 2)+2); + return 0; +} + +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); + 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); + 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) + { + case 0: + util::stream_format(stream, "MOV.B R0,@($%02X,GBR)", opcode & 0xff); + break; + case 1: + util::stream_format(stream, "MOV.W R0,@($%04X,GBR)", (opcode & 0xff) * 2); + break; + case 2: + util::stream_format(stream, "MOV.L R0,@($%04X,GBR)", (opcode & 0xff) * 4); + break; + case 3: + util::stream_format(stream, "TRAPA #$%02X", opcode & 0xff); + flags = STEP_OVER; + break; + case 4: + util::stream_format(stream, "MOV.B @($%02X,GBR),R0", opcode & 0xff); + break; + case 5: + util::stream_format(stream, "MOV.W @($%04X,GBR),R0", (opcode & 0xff) * 2); + break; + case 6: + util::stream_format(stream, "MOV.L @($%04X,GBR),R0", (opcode & 0xff) * 4); + break; + case 7: + util::stream_format(stream, "MOVA @($%04X,PC),R0 [%08X]", (opcode & 0xff) * 4, ((pc + 2) & ~3) + (opcode & 0xff) * 4); + break; + case 8: + util::stream_format(stream, "TST #$%02X,R0", opcode & 0xff); + break; + case 9: + util::stream_format(stream, "AND #$%02X,R0", opcode & 0xff); + break; + case 10: + util::stream_format(stream, "XOR #$%02X,R0", opcode & 0xff); + break; + case 11: + util::stream_format(stream, "OR #$%02X,R0", opcode & 0xff); + break; + case 12: + util::stream_format(stream, "TST.B #$%02X,@(R0,GBR)", opcode & 0xff); + break; + case 13: + util::stream_format(stream, "AND.B #$%02X,@(R0,GBR)", opcode & 0xff); + break; + case 14: + util::stream_format(stream, "XOR.B #$%02X,@(R0,GBR)", opcode & 0xff); + break; + case 15: + util::stream_format(stream, "OR.B #$%02X,@(R0,GBR)", opcode & 0xff); + break; + } + return flags; +} + +uint32_t sh_disassembler::op1101(std::ostream &stream, uint32_t pc, uint16_t opcode) +{ + util::stream_format(stream, "MOV.L @($%04X,PC),%s [%08X]", (opcode & 0xff) * 4, regname[Rn], ((pc + 2) & ~3) + (opcode & 0xff) * 4); + return 0; +} + +uint32_t sh_disassembler::op1110(std::ostream &stream, uint32_t pc, uint16_t opcode) +{ + util::stream_format(stream, "MOV #$%02X,%s", (opcode & 0xff), regname[Rn]); + return 0; +} + +uint32_t sh_disassembler::op1111(std::ostream &stream, uint32_t pc, uint16_t opcode) +{ + util::stream_format(stream, "unknown $%04X", opcode); + return 0; +} + + +/* SH4 specifics */ + + +uint32_t sh_disassembler::op0000_sh34(std::ostream &stream, uint32_t pc, uint16_t opcode) { uint32_t flags = 0; switch (opcode & 0xF) @@ -142,14 +708,14 @@ static uint32_t op0000(std::ostream &stream, uint32_t pc, uint16_t opcode) { case 0x00: stream << "RTS"; - flags = DASMFLAG_STEP_OUT; + flags = STEP_OUT; break; case 0x10: stream << "SLEEP"; break; case 0x20: stream << "RTE"; - flags = DASMFLAG_STEP_OUT; + flags = STEP_OUT; break; } break; @@ -169,125 +735,8 @@ static uint32_t op0000(std::ostream &stream, uint32_t pc, uint16_t opcode) return flags; } -static uint32_t op0001(std::ostream &stream, uint32_t pc, uint16_t opcode) -{ - util::stream_format(stream, "MOV.L %s,@($%02X,%s)", regname[Rm], (opcode & 15) * 4, regname[Rn]); - return 0; -} -static uint32_t op0010(std::ostream &stream, uint32_t pc, uint16_t opcode) -{ - switch (opcode & 15) - { - case 0: - util::stream_format(stream, "MOV.B %s,@%s", regname[Rm], regname[Rn]); - break; - case 1: - util::stream_format(stream, "MOV.W %s,@%s", regname[Rm], regname[Rn]); - break; - case 2: - util::stream_format(stream, "MOV.L %s,@%s", regname[Rm], regname[Rn]); - break; - case 3: - util::stream_format(stream, "?????? $%04X", opcode); - break; - case 4: - util::stream_format(stream, "MOV.B %s,@-%s", regname[Rm], regname[Rn]); - break; - case 5: - util::stream_format(stream, "MOV.W %s,@-%s", regname[Rm], regname[Rn]); - break; - case 6: - util::stream_format(stream, "MOV.L %s,@-%s", regname[Rm], regname[Rn]); - break; - case 7: - util::stream_format(stream, "DIV0S %s,%s", regname[Rm], regname[Rn]); - break; - case 8: - util::stream_format(stream, "TST %s,%s", regname[Rm], regname[Rn]); - break; - case 9: - util::stream_format(stream, "AND %s,%s", regname[Rm], regname[Rn]); - break; - case 10: - util::stream_format(stream, "XOR %s,%s", regname[Rm], regname[Rn]); - break; - case 11: - util::stream_format(stream, "OR %s,%s", regname[Rm], regname[Rn]); - break; - case 12: - util::stream_format(stream, "CMP/STR %s,%s", regname[Rm], regname[Rn]); - break; - case 13: - util::stream_format(stream, "XTRCT %s,%s", regname[Rm], regname[Rn]); - break; - case 14: - util::stream_format(stream, "MULU.W %s,%s", regname[Rm], regname[Rn]); - break; - case 15: - util::stream_format(stream, "MULS.W %s,%s", regname[Rm], regname[Rn]); - break; - } - return 0; -} - -static uint32_t op0011(std::ostream &stream, uint32_t pc, uint16_t opcode) -{ - switch (opcode & 15) - { - case 0: - util::stream_format(stream, "CMP/EQ %s,%s", regname[Rm], regname[Rn]); - break; - case 1: - util::stream_format(stream, "?????? %s,%s", regname[Rm], regname[Rn]); - break; - case 2: - util::stream_format(stream, "CMP/HS %s,%s", regname[Rm], regname[Rn]); - break; - case 3: - util::stream_format(stream, "CMP/GE %s,%s", regname[Rm], regname[Rn]); - break; - case 4: - util::stream_format(stream, "DIV1 %s,%s", regname[Rm], regname[Rn]); - break; - case 5: - util::stream_format(stream, "DMULU.L %s,%s", regname[Rm], regname[Rn]); - break; - case 6: - util::stream_format(stream, "CMP/HI %s,%s", regname[Rm], regname[Rn]); - break; - case 7: - util::stream_format(stream, "CMP/GT %s,%s", regname[Rm], regname[Rn]); - break; - case 8: - util::stream_format(stream, "SUB %s,%s", regname[Rm], regname[Rn]); - break; - case 9: - util::stream_format(stream, "?????? %s,%s", regname[Rm], regname[Rn]); - break; - case 10: - util::stream_format(stream, "SUBC %s,%s", regname[Rm], regname[Rn]); - break; - case 11: - util::stream_format(stream, "SUBV %s,%s", regname[Rm], regname[Rn]); - break; - case 12: - util::stream_format(stream, "ADD %s,%s", regname[Rm], regname[Rn]); - break; - case 13: - util::stream_format(stream, "DMULS.L %s,%s", regname[Rm], regname[Rn]); - break; - case 14: - util::stream_format(stream, "ADDC %s,%s", regname[Rm], regname[Rn]); - break; - case 15: - util::stream_format(stream, "ADDV %s,%s", regname[Rm], regname[Rn]); - break; - } - return 0; -} - -static uint32_t op0100(std::ostream &stream, uint32_t pc, uint16_t opcode) +uint32_t sh_disassembler::op0100_sh34(std::ostream &stream, uint32_t pc, uint16_t opcode) { uint32_t flags = 0; switch (opcode & 0xF) @@ -498,7 +947,7 @@ static uint32_t op0100(std::ostream &stream, uint32_t pc, uint16_t opcode) { case 0x00: util::stream_format(stream, "JSR %s", regname[Rn]); - flags = DASMFLAG_STEP_OVER | DASMFLAG_STEP_OVER_EXTRA(1); + flags = STEP_OVER | step_over_extra(1); break; case 0x10: util::stream_format(stream, "TAS %s", regname[Rn]); @@ -545,205 +994,8 @@ static uint32_t op0100(std::ostream &stream, uint32_t pc, uint16_t opcode) return flags; } -static uint32_t op0101(std::ostream &stream, uint32_t pc, uint16_t opcode) -{ - util::stream_format(stream, "MOV.L @($%02X,%s),%s", (opcode & 15) * 4, regname[Rm], regname[Rn]); - return 0; -} - -static uint32_t op0110(std::ostream &stream, uint32_t pc, uint16_t opcode) - -{ - switch(opcode & 0xF) - { - case 0x00: - util::stream_format(stream, "MOV.B @%s,%s", regname[Rm], regname[Rn]); - break; - case 0x01: - util::stream_format(stream, "MOV.W @%s,%s", regname[Rm], regname[Rn]); - break; - case 0x02: - util::stream_format(stream, "MOV.L @%s,%s", regname[Rm], regname[Rn]); - break; - case 0x03: - util::stream_format(stream, "MOV %s,%s", regname[Rm], regname[Rn]); - break; - case 0x04: - util::stream_format(stream, "MOV.B @%s+,%s", regname[Rm], regname[Rn]); - break; - case 0x05: - util::stream_format(stream, "MOV.W @%s+,%s", regname[Rm], regname[Rn]); - break; - case 0x06: - util::stream_format(stream, "MOV.L @%s+,%s", regname[Rm], regname[Rn]); - break; - case 0x07: - util::stream_format(stream, "NOT %s,%s", regname[Rm], regname[Rn]); - break; - case 0x08: - util::stream_format(stream, "SWAP.B %s,%s", regname[Rm], regname[Rn]); - break; - case 0x09: - util::stream_format(stream, "SWAP.W %s,%s", regname[Rm], regname[Rn]); - break; - case 0x0a: - util::stream_format(stream, "NEGC %s,%s", regname[Rm], regname[Rn]); - break; - case 0x0b: - util::stream_format(stream, "NEG %s,%s", regname[Rm], regname[Rn]); - break; - case 0x0c: - util::stream_format(stream, "EXTU.B %s,%s", regname[Rm], regname[Rn]); - break; - case 0x0d: - util::stream_format(stream, "EXTU.W %s,%s", regname[Rm], regname[Rn]); - break; - case 0x0e: - util::stream_format(stream, "EXTS.B %s,%s", regname[Rm], regname[Rn]); - break; - case 0x0f: - util::stream_format(stream, "EXTS.W %s,%s", regname[Rm], regname[Rn]); - break; - } - return 0; -} - -static uint32_t op0111(std::ostream &stream, uint32_t pc, uint16_t opcode) -{ - util::stream_format(stream, "ADD #$%02X,%s", opcode & 0xff, regname[Rn]); - return 0; -} - -static uint32_t op1000(std::ostream &stream, uint32_t pc, uint16_t opcode) -{ - switch((opcode >> 8) & 15) - { - case 0: - util::stream_format(stream, "MOV.B R0,@($%02X,%s)", (opcode & 15), regname[Rm]); - break; - case 1: - util::stream_format(stream, "MOV.W R0,@($%02X,%s)", (opcode & 15) * 2, regname[Rm]); - break; - case 4: - util::stream_format(stream, "MOV.B @($%02X,%s),R0", (opcode & 15), regname[Rm]); - break; - case 5: - util::stream_format(stream, "MOV.W @($%02X,%s),R0", (opcode & 15) * 2, regname[Rm]); - break; - case 8: - 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; - case 11: - util::stream_format(stream, "BF $%08X", pc + SIGNX8(opcode & 0xff) * 2 + 2); - break; - case 13: - util::stream_format(stream, "BTS $%08X", pc + SIGNX8(opcode & 0xff) * 2 + 2); - break; - case 15: - util::stream_format(stream, "BFS $%08X", pc + SIGNX8(opcode & 0xff) * 2 + 2); - break; - default : - util::stream_format(stream, "invalid $%04X", opcode); - } - return 0; -} - -static uint32_t op1001(std::ostream &stream, uint32_t pc, uint16_t opcode) -{ -uint32_t ea=(pc+((opcode & 0xff) * 2)+2); - - util::stream_format(stream, "MOV.W @($%04X,PC),%s [%08X]", (opcode & 0xff) * 2, regname[Rn], ea); - return 0; -} - -static uint32_t op1010(std::ostream &stream, uint32_t pc, uint16_t opcode) -{ - util::stream_format(stream, "BRA $%08X", SIGNX12(opcode & 0xfff) * 2 + pc + 2); - return 0; -} - -static uint32_t op1011(std::ostream &stream, uint32_t pc, uint16_t opcode) -{ - util::stream_format(stream, "BSR $%08X", SIGNX12(opcode & 0xfff) * 2 + pc + 2); - return DASMFLAG_STEP_OVER | DASMFLAG_STEP_OVER_EXTRA(1); -} - -static uint32_t op1100(std::ostream &stream, uint32_t pc, uint16_t opcode) -{ - uint32_t flags = 0; - switch((opcode >> 8) & 15) - { - case 0: - util::stream_format(stream, "MOV.B R0,@($%02X,GBR)", opcode & 0xff); - break; - case 1: - util::stream_format(stream, "MOV.W R0,@($%04X,GBR)", (opcode & 0xff) * 2); - break; - case 2: - util::stream_format(stream, "MOV.L R0,@($%04X,GBR)", (opcode & 0xff) * 4); - break; - case 3: - util::stream_format(stream, "TRAPA #$%02X", opcode & 0xff); - flags = DASMFLAG_STEP_OVER; - break; - case 4: - util::stream_format(stream, "MOV.B @($%02X,GBR),R0", opcode & 0xff); - break; - case 5: - util::stream_format(stream, "MOV.W @($%04X,GBR),R0", (opcode & 0xff) * 2); - break; - case 6: - util::stream_format(stream, "MOV.L @($%04X,GBR),R0", (opcode & 0xff) * 4); - break; - case 7: - util::stream_format(stream, "MOVA @($%04X,PC),R0 [%08X]", (opcode & 0xff) * 4, ((pc + 2) & ~3) + (opcode & 0xff) * 4); - break; - case 8: - util::stream_format(stream, "TST #$%02X,R0", opcode & 0xff); - break; - case 9: - util::stream_format(stream, "AND #$%02X,R0", opcode & 0xff); - break; - case 10: - util::stream_format(stream, "XOR #$%02X,R0", opcode & 0xff); - break; - case 11: - util::stream_format(stream, "OR #$%02X,R0", opcode & 0xff); - break; - case 12: - util::stream_format(stream, "TST.B #$%02X,@(R0,GBR)", opcode & 0xff); - break; - case 13: - util::stream_format(stream, "AND.B #$%02X,@(R0,GBR)", opcode & 0xff); - break; - case 14: - util::stream_format(stream, "XOR.B #$%02X,@(R0,GBR)", opcode & 0xff); - break; - case 15: - util::stream_format(stream, "OR.B #$%02X,@(R0,GBR)", opcode & 0xff); - break; - } - return flags; -} - -static uint32_t op1101(std::ostream &stream, uint32_t pc, uint16_t opcode) -{ -uint32_t ea=((pc + 2) & ~3) + (opcode & 0xff) * 4; - - util::stream_format(stream, "MOV.L @($%04X,PC),%s [%08X]", (opcode & 0xff) * 4, regname[Rn], ea); - return 0; -} -static uint32_t op1110(std::ostream &stream, uint32_t pc, uint16_t opcode) -{ - util::stream_format(stream, "MOV #$%02X,%s", (opcode & 0xff), regname[Rn]); - return 0; -} - -static uint32_t op1111(std::ostream &stream, uint32_t pc, uint16_t opcode) +uint32_t sh_disassembler::op1111_sh34(std::ostream &stream, uint32_t pc, uint16_t opcode) { switch (opcode & 0xf) { @@ -866,40 +1118,73 @@ static uint32_t op1111(std::ostream &stream, uint32_t pc, uint16_t opcode) return 0; } -unsigned DasmSH4(std::ostream &stream, unsigned pc, uint16_t opcode) +offs_t sh_disassembler::disassemble(std::ostream &stream, offs_t pc, const data_buffer &opcodes, const data_buffer ¶ms) +{ + u16 opcode = opcodes.r16(pc); + return dasm_one(stream, pc, opcode); +} + +offs_t sh_disassembler::dasm_one(std::ostream &stream, offs_t pc, u16 opcode) { uint32_t flags; pc += 2; - switch ((opcode >> 12) & 15) + if (m_is_sh34) { - case 0: flags = op0000(stream, pc, opcode); break; - case 1: flags = op0001(stream, pc, opcode); break; - case 2: flags = op0010(stream, pc, opcode); break; - case 3: flags = op0011(stream, pc, opcode); break; - case 4: flags = op0100(stream, pc, opcode); break; - case 5: flags = op0101(stream, pc, opcode); break; - case 6: flags = op0110(stream, pc, opcode); break; - case 7: flags = op0111(stream, pc, opcode); break; - case 8: flags = op1000(stream, pc, opcode); break; - case 9: flags = op1001(stream, pc, opcode); break; - case 10: flags = op1010(stream, pc, opcode); break; - case 11: flags = op1011(stream, pc, opcode); break; - case 12: flags = op1100(stream, pc, opcode); break; - case 13: flags = op1101(stream, pc, opcode); break; - case 14: flags = op1110(stream, pc, opcode); break; - default: flags = op1111(stream, pc, opcode); break; + switch ((opcode >> 12) & 15) + { + case 0: flags = op0000_sh34(stream, pc, opcode); break; + case 1: flags = op0001(stream, pc, opcode); break; + case 2: flags = op0010(stream, pc, opcode); break; + case 3: flags = op0011(stream, pc, opcode); break; + case 4: flags = op0100_sh34(stream, pc, opcode); break; + case 5: flags = op0101(stream, pc, opcode); break; + case 6: flags = op0110(stream, pc, opcode); break; + case 7: flags = op0111(stream, pc, opcode); break; + case 8: flags = op1000(stream, pc, opcode); break; + case 9: flags = op1001(stream, pc, opcode); break; + case 10: flags = op1010(stream, pc, opcode); break; + case 11: flags = op1011(stream, pc, opcode); break; + case 12: flags = op1100(stream, pc, opcode); break; + case 13: flags = op1101(stream, pc, opcode); break; + case 14: flags = op1110(stream, pc, opcode); break; + default: flags = op1111_sh34(stream, pc, opcode); break; + } } - return 2 | flags | DASMFLAG_SUPPORTED; + else + { + switch ((opcode >> 12) & 15) + { + case 0: flags = op0000(stream, pc, opcode); break; + case 1: flags = op0001(stream, pc, opcode); break; + case 2: flags = op0010(stream, pc, opcode); break; + case 3: flags = op0011(stream, pc, opcode); break; + case 4: flags = op0100(stream, pc, opcode); break; + case 5: flags = op0101(stream, pc, opcode); break; + case 6: flags = op0110(stream, pc, opcode); break; + case 7: flags = op0111(stream, pc, opcode); break; + case 8: flags = op1000(stream, pc, opcode); break; + case 9: flags = op1001(stream, pc, opcode); break; + case 10: flags = op1010(stream, pc, opcode); break; + case 11: flags = op1011(stream, pc, opcode); break; + case 12: flags = op1100(stream, pc, opcode); break; + case 13: flags = op1101(stream, pc, opcode); break; + case 14: flags = op1110(stream, pc, opcode); break; + default: flags = op1111(stream, pc, opcode); break; + } + } + + return 2 | flags | SUPPORTED; } -CPU_DISASSEMBLE(sh4) + +u32 sh_disassembler::opcode_alignment() const { - return DasmSH4(stream, pc, (oprom[1] << 8) | oprom[0]); + return 2; } -CPU_DISASSEMBLE(sh4be) +sh_disassembler::sh_disassembler(bool is_sh34) : m_is_sh34(is_sh34) { - return DasmSH4(stream, pc, (oprom[0] << 8) | oprom[1]); } + diff --git a/src/devices/cpu/sh/sh_dasm.h b/src/devices/cpu/sh/sh_dasm.h new file mode 100644 index 00000000000..52d6b2eb723 --- /dev/null +++ b/src/devices/cpu/sh/sh_dasm.h @@ -0,0 +1,45 @@ +// license:BSD-3-Clause +// copyright-holders:Juergen Buchmueller, R. Belmont + +#ifndef MAME_CPU_SH_SHDASM_H +#define MAME_CPU_SH_SHDASM_H + +#pragma once + +class sh_disassembler : public util::disasm_interface +{ +public: + sh_disassembler(bool is_sh34); + virtual ~sh_disassembler() = default; + + virtual u32 opcode_alignment() const override; + virtual offs_t disassemble(std::ostream &stream, offs_t pc, const data_buffer &opcodes, const data_buffer ¶ms) override; + + offs_t dasm_one(std::ostream &stream, offs_t pc, u16 opcode); + +private: + static const char *const regname[16]; + uint32_t op0000(std::ostream &stream, uint32_t pc, uint16_t opcode); + uint32_t op0001(std::ostream &stream, uint32_t pc, uint16_t opcode); + uint32_t op0010(std::ostream &stream, uint32_t pc, uint16_t opcode); + uint32_t op0011(std::ostream &stream, uint32_t pc, uint16_t opcode); + uint32_t op0100(std::ostream &stream, uint32_t pc, uint16_t opcode); + uint32_t op0101(std::ostream &stream, uint32_t pc, uint16_t opcode); + uint32_t op0110(std::ostream &stream, uint32_t pc, uint16_t opcode); + uint32_t op0111(std::ostream &stream, uint32_t pc, uint16_t opcode); + uint32_t op1000(std::ostream &stream, uint32_t pc, uint16_t opcode); + uint32_t op1001(std::ostream &stream, uint32_t pc, uint16_t opcode); + uint32_t op1010(std::ostream &stream, uint32_t pc, uint16_t opcode); + uint32_t op1011(std::ostream &stream, uint32_t pc, uint16_t opcode); + uint32_t op1100(std::ostream &stream, uint32_t pc, uint16_t opcode); + uint32_t op1101(std::ostream &stream, uint32_t pc, uint16_t opcode); + uint32_t op1110(std::ostream &stream, uint32_t pc, uint16_t opcode); + uint32_t op1111(std::ostream &stream, uint32_t pc, uint16_t opcode); + uint32_t op0000_sh34(std::ostream &stream, uint32_t pc, uint16_t opcode); + uint32_t op0100_sh34(std::ostream &stream, uint32_t pc, uint16_t opcode); + uint32_t op1111_sh34(std::ostream &stream, uint32_t pc, uint16_t opcode); + + bool m_is_sh34; +}; + +#endif diff --git a/src/devices/cpu/sh/sh_fe.cpp b/src/devices/cpu/sh/sh_fe.cpp new file mode 100644 index 00000000000..1abede64dc4 --- /dev/null +++ b/src/devices/cpu/sh/sh_fe.cpp @@ -0,0 +1,772 @@ +// license:BSD-3-Clause +// copyright-holders:David Haywood, R. Belmont +/*************************************************************************** + + sh_fe.c + + Front end for SH recompiler + +***************************************************************************/ + +#include "emu.h" +#include "sh2.h" +#include "sh2comn.h" +#include "cpu/drcfe.h" + + +/*************************************************************************** + INSTRUCTION PARSERS +***************************************************************************/ + +sh_frontend::sh_frontend(sh_common_execution *device, uint32_t window_start, uint32_t window_end, uint32_t max_sequence) + : drc_frontend(*device, window_start, window_end, max_sequence) + , m_sh(device) +{ +} + +/*------------------------------------------------- + describe_instruction - build a description + of a single instruction +-------------------------------------------------*/ + +inline uint16_t sh_frontend::read_word(opcode_desc &desc) +{ + return m_sh->m_direct->read_word(desc.physpc, SH2_CODE_XOR(0)); +} + +bool sh_frontend::describe(opcode_desc &desc, const opcode_desc *prev) +{ + uint16_t opcode; + + /* fetch the opcode */ + opcode = desc.opptr.w[0] = read_word(desc); + + /* all instructions are 2 bytes and most are a single cycle */ + desc.length = 2; + desc.cycles = 1; + + switch (opcode>>12) + { + case 0: + return describe_group_0(desc, prev, opcode); + + case 1: // MOVLS4 + desc.regin[0] |= REGFLAG_R(Rn) | REGFLAG_R(Rm); + desc.flags |= OPFLAG_WRITES_MEMORY; + return true; + + case 2: + return describe_group_2(desc, prev, opcode); + + case 3: + return describe_group_3(desc, prev, opcode); + + case 4: + return describe_group_4(desc, prev, opcode); + + case 5: // MOVLL4 + desc.regin[0] |= REGFLAG_R(Rm); + desc.regout[0] |= REGFLAG_R(Rn); + desc.flags |= OPFLAG_READS_MEMORY; + return true; + + case 6: + return describe_group_6(desc, prev, opcode); + + case 7: // ADDI + desc.regin[0] |= REGFLAG_R(Rn); + desc.regout[0] |= REGFLAG_R(Rn); + return true; + + case 8: + return describe_group_8(desc, prev, opcode); + + case 9: // MOVWI + desc.regout[0] |= REGFLAG_R(Rn); + 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) + case 10: // BRA + { + int32_t disp = ((int32_t)opcode << 20) >> 20; + + desc.flags |= OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE; + desc.targetpc = (desc.pc + 2) + disp * 2 + 2; + desc.delayslots = 1; + desc.cycles = 2; + return true; + } + + case 12: + return describe_group_12(desc, prev, opcode); + + case 13: // MOVLI + desc.regout[0] |= REGFLAG_R(Rn); + desc.flags |= OPFLAG_READS_MEMORY; + return true; + + case 14: // MOVI + desc.regout[0] |= REGFLAG_R(Rn); + return true; + + case 15: // NOP + return describe_group_15(desc, prev, opcode); + } + + return false; +} + + +bool sh_frontend::describe_group_2(opcode_desc &desc, const opcode_desc *prev, uint16_t opcode) +{ + switch (opcode & 15) + { + 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.flags |= OPFLAG_WRITES_MEMORY; + return true; + + case 3: // NOP(); + return true; + + case 4: // MOVBM(Rm, Rn); + 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.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.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); + return true; + + case 14: // MULU(Rm, Rn); + case 15: // MULS(Rm, Rn); + desc.regin[0] |= REGFLAG_R(Rm) | REGFLAG_R(Rn); + desc.regout[1] |= REGFLAG_MACL | REGFLAG_MACH; + desc.cycles = 2; + return true; + } + + return false; +} + +bool sh_frontend::describe_group_3(opcode_desc &desc, const opcode_desc *prev, uint16_t opcode) +{ + switch (opcode & 15) + { + case 0: // CMPEQ(Rm, Rn); + case 2: // CMPHS(Rm, Rn); + 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.regout[1] |= REGFLAG_SR; + return true; + + case 1: // NOP(); + case 9: // NOP(); + return true; + + case 4: // DIV1(Rm, Rn); + desc.regin[0] |= REGFLAG_R(Rm) | REGFLAG_R(Rn); + desc.regout[0] |= REGFLAG_R(Rn); + 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.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); + 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[1] |= REGFLAG_SR; + desc.regout[0] |= REGFLAG_R(Rn); + desc.regout[1] |= REGFLAG_SR; + return true; + } + return false; +} + + +bool sh_frontend::describe_group_6(opcode_desc &desc, const opcode_desc *prev, uint16_t opcode) +{ + switch (opcode & 15) + { + case 0: // MOVBL(Rm, Rn); + case 1: // MOVWL(Rm, Rn); + case 2: // MOVLL(Rm, Rn); + case 3: // MOV(Rm, Rn); + case 7: // NOT(Rm, Rn); + case 9: // SWAPW(Rm, Rn); + case 11: // NEG(Rm, Rn); + case 12: // EXTUB(Rm, Rn); + 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); + 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.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); + return true; + + case 10: // NEGC(Rm, Rn); + desc.regin[0] |= REGFLAG_R(Rm); + desc.regout[0] |= REGFLAG_R(Rn); + desc.regout[1] |= REGFLAG_SR; + return true; + } + return false; +} + +bool sh_frontend::describe_group_8(opcode_desc &desc, const opcode_desc *prev, uint16_t opcode) +{ + int32_t disp; + + 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.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(); + return true; + + case 4<< 8: // MOVBL4(Rm, opcode & 0x0f); + case 5<< 8: // MOVWL4(Rm, opcode & 0x0f); + desc.regin[0] |= REGFLAG_R(Rm); + 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); + desc.regin[1] |= REGFLAG_SR; + desc.regout[1] |= REGFLAG_SR; + return true; + + 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; + desc.targetpc = (desc.pc + 2) + disp * 2 + 2; + return true; + + 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; + desc.targetpc = (desc.pc + 2) + disp * 2 + 2; + desc.delayslots = 1; + return true; + } + + return false; +} + +bool sh_frontend::describe_group_12(opcode_desc &desc, const opcode_desc *prev, uint16_t opcode) +{ + switch (opcode & (15<<8)) + { + 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); + desc.regin[0] |= REGFLAG_R(15); + desc.regin[1] |= REGFLAG_VBR; + desc.regout[0] |= REGFLAG_R(15); + desc.cycles = 8; + desc.targetpc = BRANCH_TARGET_DYNAMIC; + 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); + desc.regout[0] |= REGFLAG_R(0); + desc.flags |= OPFLAG_READS_MEMORY; + return true; + + 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); + 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); + desc.regin[0] |= REGFLAG_R(0); + desc.regin[1] |= REGFLAG_SR | REGFLAG_GBR; + desc.regout[1] |= REGFLAG_SR; + desc.flags |= OPFLAG_READS_MEMORY; + return true; + } + + return false; +} + + + +bool sh_frontend::describe_group_0(opcode_desc &desc, const opcode_desc *prev, uint16_t opcode) +{ + switch (opcode & 0x3F) + { + case 0x00: // NOP(); + case 0x01: // NOP(); + case 0x09: // NOP(); + case 0x10: // NOP(); + case 0x11: // NOP(); + case 0x13: // NOP(); + case 0x20: // NOP(); + case 0x21: // NOP(); + case 0x30: // NOP(); + case 0x31: // NOP(); + case 0x32: // NOP(); + case 0x33: // NOP(); + case 0x38: // NOP(); + case 0x39: // NOP(); + case 0x3a: // NOP(); + case 0x3b: // NOP(); + return true; + + case 0x02: // STCSR(Rn); + desc.regout[0] |= REGFLAG_R(Rn); + return true; + + case 0x03: // BSRF(Rn); + desc.regout[1] |= REGFLAG_PR; + + desc.flags |= OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE; + desc.targetpc = BRANCH_TARGET_DYNAMIC; + desc.delayslots = 1; + + return true; + + case 0x04: // MOVBS0(Rm, Rn); + case 0x05: // MOVWS0(Rm, Rn); + case 0x06: // MOVLS0(Rm, Rn); + case 0x14: // MOVBS0(Rm, Rn); + case 0x15: // MOVWS0(Rm, Rn); + case 0x16: // MOVLS0(Rm, Rn); + case 0x24: // MOVBS0(Rm, Rn); + case 0x25: // MOVWS0(Rm, Rn); + case 0x26: // MOVLS0(Rm, Rn); + 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.flags |= OPFLAG_READS_MEMORY; + return true; + + case 0x07: // MULL(Rm, Rn); + 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.regout[1] |= REGFLAG_MACL; + desc.cycles = 2; + return true; + + case 0x08: // CLRT(); + desc.regout[1] |= REGFLAG_SR; + return true; + + case 0x0a: // STSMACH(Rn); + desc.regout[0] |= REGFLAG_R(Rn); + desc.regout[1] |= REGFLAG_MACH; + return true; + + case 0x0b: // RTS(); + desc.regin[1] |= REGFLAG_PR; + + desc.flags |= OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE; + desc.targetpc = BRANCH_TARGET_DYNAMIC; + desc.delayslots = 1; + desc.cycles = 2; + + return true; + + case 0x0c: // MOVBL0(Rm, Rn); + case 0x0d: // MOVWL0(Rm, Rn); + case 0x0e: // MOVLL0(Rm, Rn); + case 0x1c: // MOVBL0(Rm, Rn); + case 0x1d: // MOVWL0(Rm, Rn); + case 0x1e: // MOVLL0(Rm, Rn); + case 0x2c: // MOVBL0(Rm, Rn); + case 0x2d: // MOVWL0(Rm, Rn); + case 0x2e: // MOVLL0(Rm, Rn); + 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.flags |= OPFLAG_READS_MEMORY; + return true; + + case 0x0f: // MAC_L(Rm, Rn); + 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.regout[1] |= REGFLAG_MACL | REGFLAG_MACH; + desc.cycles = 3; + return true; + + case 0x12: // STCGBR(Rn); + desc.regout[0] |= REGFLAG_R(Rn); + desc.regin[1] |= REGFLAG_GBR; + return true; + + case 0x18: // SETT(); + desc.regout[1] |= REGFLAG_SR; + return true; + + case 0x19: // DIV0U(); + desc.regout[1] |= REGFLAG_SR; + return true; + + case 0x1a: // STSMACL(Rn); + desc.regin[1] |= REGFLAG_MACL; + desc.regout[0] |= REGFLAG_R(Rn); + return true; + + case 0x1b: // SLEEP(); + desc.cycles = 3; + return true; + + case 0x22: // STCVBR(Rn); + desc.regin[0] |= REGFLAG_R(Rn); + desc.regout[1] |= REGFLAG_VBR; + return true; + + case 0x23: // BRAF(Rn); + desc.regin[0] |= REGFLAG_R(Rm); + desc.flags |= OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE; + desc.targetpc = BRANCH_TARGET_DYNAMIC; + desc.delayslots = 1; + desc.cycles = 2; + return true; + + case 0x28: // CLRMAC(); + desc.regout[1] |= REGFLAG_MACL | REGFLAG_MACH; + return true; + + case 0x29: // MOVT(Rn); + desc.regin[1] |= REGFLAG_SR; + desc.regout[0] |= REGFLAG_R(Rn); + return true; + + case 0x2a: // STSPR(Rn); + desc.regin[1] |= REGFLAG_PR; + desc.regout[0] |= REGFLAG_R(Rn); + return true; + + case 0x2b: // RTE(); + desc.regin[0] |= REGFLAG_R(15); + desc.regout[0] |= REGFLAG_R(15); + + desc.flags |= OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE | OPFLAG_CAN_EXPOSE_EXTERNAL_INT; + desc.targetpc = BRANCH_TARGET_DYNAMIC; + desc.delayslots = 1; + desc.cycles = 4; + + return true; + } + + return false; +} + + +bool sh_frontend::describe_group_4(opcode_desc &desc, const opcode_desc *prev, uint16_t opcode) +{ + switch (opcode & 0x3F) + { + case 0x00: // SHLL(Rn); + 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.regout[1] |= REGFLAG_SR; + return true; + + case 0x02: // STSMMACH(Rn); + desc.regin[0] |= REGFLAG_R(Rn); + desc.regin[1] |= REGFLAG_MACH; + desc.regout[0] |= REGFLAG_R(Rn); + desc.flags |= OPFLAG_WRITES_MEMORY; + return true; + + case 0x03: // STCMSR(Rn); + desc.regin[0] |= REGFLAG_R(Rn); + desc.regout[0] |= REGFLAG_R(Rn); + 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.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.regout[1] |= REGFLAG_SR; + desc.cycles = 3; + desc.flags |= OPFLAG_READS_MEMORY | OPFLAG_CAN_EXPOSE_EXTERNAL_INT | OPFLAG_END_SEQUENCE; + return true; + + case 0x08: // SHLL2(Rn); + case 0x09: // SHLR2(Rn); + case 0x18: // SHLL8(Rn); + case 0x19: // SHLR8(Rn); + case 0x28: // SHLL16(Rn); + case 0x29: // SHLR16(Rn); + desc.regin[0] |= REGFLAG_R(Rn); + desc.regout[0] |= REGFLAG_R(Rn); + return true; + + case 0x0a: // LDSMACH(Rn); + desc.regin[0] |= REGFLAG_R(Rn); + desc.regout[1] |= REGFLAG_MACH; + return true; + + case 0x0b: // JSR(Rn); + desc.regin[0] |= REGFLAG_R(Rn); + desc.regout[1] |= REGFLAG_PR; + desc.flags |= OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE; + desc.targetpc = BRANCH_TARGET_DYNAMIC; + desc.delayslots = 1; + return true; + + case 0x0e: // LDCSR(Rn); + desc.regin[0] |= REGFLAG_R(Rn); + desc.regout[1] |= REGFLAG_SR; + desc.flags |= OPFLAG_CAN_EXPOSE_EXTERNAL_INT | OPFLAG_END_SEQUENCE; + return true; + + case 0x0f: // MAC_W(Rm, Rn); + 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[1] |= REGFLAG_MACL | REGFLAG_MACH; + desc.regout[0] |= REGFLAG_R(Rm) | REGFLAG_R(Rn); + desc.regout[1] |= REGFLAG_MACL | REGFLAG_MACH; + desc.cycles = 3; + return true; + + case 0x10: // DT(Rn); + desc.regin[0] |= REGFLAG_R(Rn); + desc.regin[1] |= REGFLAG_SR; + desc.regout[0] |= REGFLAG_R(Rn); + desc.regout[1] |= REGFLAG_SR; + return true; + + case 0x11: // CMPPZ(Rn); + case 0x15: // CMPPL(Rn); + desc.regin[0] |= REGFLAG_R(Rn); + desc.regin[1] |= REGFLAG_SR; + desc.regout[1] |= REGFLAG_SR; + return true; + + case 0x12: // STSMMACL(Rn); + desc.regin[0] |= REGFLAG_R(Rn); + desc.regin[1] |= REGFLAG_MACL; + desc.regout[0] |= REGFLAG_R(Rn); + desc.flags |= OPFLAG_WRITES_MEMORY; + return true; + + case 0x13: // STCMGBR(Rn); + desc.regin[0] |= REGFLAG_R(Rn); + desc.regin[1] |= REGFLAG_GBR; + desc.regout[0] |= REGFLAG_R(Rn); + 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.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.regout[1] |= REGFLAG_GBR; + desc.flags |= OPFLAG_READS_MEMORY; + return true; + + case 0x1a: // LDSMACL(Rn); + desc.regin[0] |= REGFLAG_R(Rn); + desc.regout[1] |= REGFLAG_MACL; + return true; + + case 0x1b: // TAS(Rn); + desc.regin[0] |= REGFLAG_R(Rn); + desc.regin[1] |= REGFLAG_SR; + desc.regout[1] |= REGFLAG_SR; + desc.cycles = 4; + desc.flags |= OPFLAG_READS_MEMORY | OPFLAG_WRITES_MEMORY; + return true; + + case 0x1e: // LDCGBR(Rn); + desc.regin[0] |= REGFLAG_R(Rn); + 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.regout[1] |= REGFLAG_SR; + return true; + + case 0x22: // STSMPR(Rn); + desc.regin[0] |= REGFLAG_R(Rn); + desc.regin[1] |= REGFLAG_PR; + desc.regout[0] |= REGFLAG_R(Rn); + desc.flags |= OPFLAG_WRITES_MEMORY; + return true; + + case 0x23: // STCMVBR(Rn); + desc.regin[0] |= REGFLAG_R(Rn); + desc.regin[1] |= REGFLAG_VBR; + desc.regout[0] |= REGFLAG_R(Rn); + desc.flags |= OPFLAG_WRITES_MEMORY; + return true; + + case 0x24: // ROTCL(Rn); + case 0x25: // ROTCR(Rn); + desc.regin[0] |= REGFLAG_R(Rn); + desc.regin[1] |= REGFLAG_SR; + desc.regout[0] |= REGFLAG_R(Rn); + desc.regout[1] |= REGFLAG_SR; + return true; + + case 0x26: // LDSMPR(Rn); + desc.regin[0] |= REGFLAG_R(Rn); + desc.regout[0] |= REGFLAG_R(Rn); + 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.regout[1] |= REGFLAG_VBR; + desc.flags |= OPFLAG_READS_MEMORY; + return true; + + case 0x2a: // LDSPR(Rn); + desc.regin[0] |= REGFLAG_R(Rn); + desc.regout[1] |= REGFLAG_PR; + return true; + + case 0x2b: // JMP(Rm); + desc.regin[0] |= REGFLAG_R(Rm); + 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.regout[1] |= REGFLAG_VBR; + return true; + + case 0x0c: // NOP(); + case 0x0d: // NOP(); + case 0x14: // NOP(); + case 0x1c: // NOP(); + case 0x1d: // NOP(); + case 0x2c: // NOP(); + case 0x2d: // NOP(); + case 0x30: // NOP(); + case 0x31: // NOP(); + case 0x32: // NOP(); + case 0x33: // NOP(); + case 0x34: // NOP(); + case 0x35: // NOP(); + case 0x36: // NOP(); + case 0x37: // NOP(); + case 0x38: // NOP(); + case 0x39: // NOP(); + case 0x3a: // NOP(); + case 0x3b: // NOP(); + case 0x3c: // NOP(); + case 0x3d: // NOP(); + case 0x3e: // NOP(); + return true; + } + + return false; +} |