summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/cpu/sh
diff options
context:
space:
mode:
Diffstat (limited to 'src/devices/cpu/sh')
-rw-r--r--src/devices/cpu/sh/sh.cpp4322
-rw-r--r--src/devices/cpu/sh/sh.h469
-rw-r--r--src/devices/cpu/sh/sh2.cpp2536
-rw-r--r--src/devices/cpu/sh/sh2.h366
-rw-r--r--src/devices/cpu/sh/sh2comn.cpp27
-rw-r--r--src/devices/cpu/sh/sh2comn.h36
-rw-r--r--src/devices/cpu/sh/sh2dasm.cpp610
-rw-r--r--src/devices/cpu/sh/sh2drc.cpp2982
-rw-r--r--src/devices/cpu/sh/sh2fe.cpp739
-rw-r--r--src/devices/cpu/sh/sh3comn.cpp144
-rw-r--r--src/devices/cpu/sh/sh4.cpp5093
-rw-r--r--src/devices/cpu/sh/sh4.h593
-rw-r--r--src/devices/cpu/sh/sh4comn.cpp115
-rw-r--r--src/devices/cpu/sh/sh4comn.h108
-rw-r--r--src/devices/cpu/sh/sh4dmac.cpp12
-rw-r--r--src/devices/cpu/sh/sh4fe.cpp317
-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.h45
-rw-r--r--src/devices/cpu/sh/sh_fe.cpp772
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 &params)
+{
+ 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 &params) 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;
+}