summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/cpu/sh4/sh4.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/devices/cpu/sh4/sh4.c')
-rw-r--r--src/devices/cpu/sh4/sh4.c4608
1 files changed, 4608 insertions, 0 deletions
diff --git a/src/devices/cpu/sh4/sh4.c b/src/devices/cpu/sh4/sh4.c
new file mode 100644
index 00000000000..e0835b1f9c0
--- /dev/null
+++ b/src/devices/cpu/sh4/sh4.c
@@ -0,0 +1,4608 @@
+// license:BSD-3-Clause
+// copyright-holders:R. Belmont
+/*****************************************************************************
+ *
+ * sh4.c
+ * Portable Hitachi SH-4 (SH7750 family) emulator
+ *
+ * By R. Belmont, based on sh2.c by Juergen Buchmueller, Mariusz Wojcieszek,
+ * Olivier Galibert, Sylvain Glaize, and James Forshaw.
+ *
+ *
+ * TODO: FPU
+ * DMA
+ * on-board peripherals
+ *
+ * DONE: boot/reset setup
+ * 64-bit data bus
+ * banked registers
+ * additional registers for supervisor mode
+ * FPU status and data registers
+ * state save for the new registers
+ * interrupts
+ * store queues
+ *
+ *****************************************************************************/
+
+#include "emu.h"
+#include "debugger.h"
+#include "sh4.h"
+#include "sh4regs.h"
+#include "sh4comn.h"
+#include "sh3comn.h"
+#include "sh4tmu.h"
+
+#if SH4_USE_FASTRAM_OPTIMIZATION
+void sh34_base_device::add_fastram(offs_t start, offs_t end, UINT8 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 readonly, void *base)
+{
+}
+#endif
+
+
+CPU_DISASSEMBLE( sh4 );
+CPU_DISASSEMBLE( sh4be );
+
+
+const device_type SH3LE = &device_creator<sh3_device>;
+const device_type SH3BE = &device_creator<sh3be_device>;
+const device_type SH4LE = &device_creator<sh4_device>;
+const device_type SH4BE = &device_creator<sh4be_device>;
+
+
+#if 0
+/*When OC index mode is off (CCR.OIX = 0)*/
+static ADDRESS_MAP_START( sh4_internal_map, AS_PROGRAM, 64, sh4_base_device )
+ AM_RANGE(0x1C000000, 0x1C000FFF) AM_RAM AM_MIRROR(0x03FFD000)
+ AM_RANGE(0x1C002000, 0x1C002FFF) AM_RAM AM_MIRROR(0x03FFD000)
+ AM_RANGE(0xE0000000, 0xE000003F) AM_RAM AM_MIRROR(0x03FFFFC0)
+ADDRESS_MAP_END
+#endif
+
+/*When OC index mode is on (CCR.OIX = 1)*/
+static ADDRESS_MAP_START( sh4_internal_map, AS_PROGRAM, 64, sh4_base_device )
+ AM_RANGE(0x1C000000, 0x1C000FFF) AM_RAM AM_MIRROR(0x01FFF000)
+ AM_RANGE(0x1E000000, 0x1E000FFF) AM_RAM AM_MIRROR(0x01FFF000)
+ AM_RANGE(0xE0000000, 0xE000003F) AM_RAM AM_MIRROR(0x03FFFFC0) // todo: store queues should be write only on DC's SH4, executing PREFM shouldn't cause an actual memory read access!
+ AM_RANGE(0xF6000000, 0xF7FFFFFF) AM_READWRITE(sh4_tlb_r,sh4_tlb_w)
+ AM_RANGE(0xFE000000, 0xFFFFFFFF) AM_READWRITE32(sh4_internal_r, sh4_internal_w, U64(0xffffffffffffffff))
+ADDRESS_MAP_END
+
+static ADDRESS_MAP_START( sh3_internal_map, AS_PROGRAM, 64, sh3_base_device )
+ AM_RANGE(SH3_LOWER_REGBASE, SH3_LOWER_REGEND) AM_READWRITE32(sh3_internal_r, sh3_internal_w, U64(0xffffffffffffffff))
+ AM_RANGE(SH3_UPPER_REGBASE, SH3_UPPER_REGEND) AM_READWRITE32(sh3_internal_high_r, sh3_internal_high_w, U64(0xffffffffffffffff))
+ADDRESS_MAP_END
+
+
+sh34_base_device::sh34_base_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock, const char *shortname, endianness_t endianness, address_map_constructor internal)
+ : cpu_device(mconfig, type, name, tag, owner, clock, shortname, __FILE__)
+ , m_program_config("program", endianness, 64, 32, 0, internal)
+ , m_io_config("io", endianness, 64, 8)
+ , c_md2(0)
+ , c_md1(0)
+ , c_md0(0)
+ , c_md6(0)
+ , c_md4(0)
+ , c_md3(0)
+ , c_md5(0)
+ , c_md7(0)
+ , c_md8(0)
+ , c_clock(0)
+#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
+}
+
+
+sh3_base_device::sh3_base_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock, const char *shortname, endianness_t endianness)
+ : sh34_base_device(mconfig, type, name, tag, owner, clock, shortname, endianness, ADDRESS_MAP_NAME(sh3_internal_map))
+{
+ m_cpu_type = CPU_TYPE_SH3;
+}
+
+
+sh4_base_device::sh4_base_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock, const char *shortname, endianness_t endianness)
+ : sh34_base_device(mconfig, type, name, tag, owner, clock, shortname, endianness, ADDRESS_MAP_NAME(sh4_internal_map))
+{
+ m_cpu_type = CPU_TYPE_SH4;
+}
+
+
+sh3_device::sh3_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+ : sh3_base_device(mconfig, SH3LE, "SH-3 (little)", tag, owner, clock, "sh3", ENDIANNESS_LITTLE)
+{
+}
+
+
+sh3be_device::sh3be_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+ : sh3_base_device(mconfig, SH3BE, "SH-3 (big)", tag, owner, clock, "sh3be", ENDIANNESS_BIG)
+{
+}
+
+
+sh4_device::sh4_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+ : sh4_base_device(mconfig, SH4LE, "SH-4 (little)", tag, owner, clock, "sh4", ENDIANNESS_LITTLE)
+{
+}
+
+
+sh4be_device::sh4be_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+ : sh4_base_device(mconfig, SH4BE, "SH-4 (big)", tag, owner, clock, "sh4be", ENDIANNESS_BIG)
+{
+}
+
+
+offs_t sh34_base_device::disasm_disassemble(char *buffer, offs_t pc, const UINT8 *oprom, const UINT8 *opram, UINT32 options)
+{
+ extern CPU_DISASSEMBLE( sh4 );
+
+ return CPU_DISASSEMBLE_NAME(sh4)(this, buffer, pc, oprom, opram, options);
+}
+
+
+offs_t sh3be_device::disasm_disassemble(char *buffer, offs_t pc, const UINT8 *oprom, const UINT8 *opram, UINT32 options)
+{
+ extern CPU_DISASSEMBLE( sh4be );
+
+ return CPU_DISASSEMBLE_NAME(sh4be)(this, buffer, pc, oprom, opram, options);
+}
+
+
+offs_t sh4be_device::disasm_disassemble(char *buffer, offs_t pc, const UINT8 *oprom, const UINT8 *opram, UINT32 options)
+{
+ extern CPU_DISASSEMBLE( sh4be );
+
+ return CPU_DISASSEMBLE_NAME(sh4be)(this, buffer, pc, oprom, opram, options);
+}
+
+
+/* Called for unimplemented opcodes */
+void sh34_base_device::TODO(const UINT16 opcode)
+{
+}
+
+#if 0
+int sign_of(int n)
+{
+ return(m_fr[n]>>31);
+}
+
+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;
+}
+
+int data_type_of(int n)
+{
+UINT32 abs;
+
+ abs = m_fr[n] & 0x7fffffff;
+ if ((m_fpscr & PR) == 0) { /* Single-precision */
+ if (abs < 0x00800000) {
+ if (((m_fpscr & DN) == 1) || (abs == 0x00000000)) {
+ if (sign_of(n) == 0) {
+ zero(n, 0);
+ return(SH4_FPU_PZERO);
+ } else {
+ zero(n, 1);
+ return(SH4_FPU_NZERO);
+ }
+ } else
+ return(SH4_FPU_DENORM);
+ } else
+ if (abs < 0x7f800000)
+ return(SH4_FPU_NORM);
+ else
+ if (abs == 0x7f800000) {
+ if (sign_of(n) == 0)
+ return(SH4_FPU_PINF);
+ else
+ return(SH4_FPU_NINF);
+ } else
+ if (abs < 0x7fc00000)
+ return(SH4_FPU_qNaN);
+ else
+ return(SH4_FPU_sNaN);
+ } else { /* Double-precision */
+ if (abs < 0x00100000) {
+ 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 {
+ zero(n, 1);
+ return(SH4_FPU_NZERO);
+ }
+ } else
+ return(SH4_FPU_DENORM);
+ } else
+ if (abs < 0x7ff00000)
+ return(SH4_FPU_NORM);
+ else
+ if ((abs == 0x7ff00000) && (m_fr[n+1] == 0x00000000)) {
+ if (sign_of(n) == 0)
+ return(SH4_FPU_PINF);
+ else
+ return(SH4_FPU_NINF);
+ } else
+ if (abs < 0x7ff80000)
+ return(SH4_FPU_qNaN);
+ else
+ return(SH4_FPU_sNaN);
+ }
+ return(SH4_FPU_NORM);
+}
+#endif
+
+inline UINT8 sh34_base_device::RB(offs_t A)
+{
+ if (A >= 0xe0000000)
+ return m_program->read_byte(A);
+
+#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 *fastbase = (UINT8*)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
+
+}
+
+inline UINT16 sh34_base_device::RW(offs_t A)
+{
+ if (A >= 0xe0000000)
+ return m_program->read_word(A);
+
+#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 *fastbase = (UINT8*)m_fastram[ramnum].base - m_fastram[ramnum].start;
+ return ((UINT16*)fastbase)[(_A ^ m_word_xor) >> 1];
+ }
+ return m_program->read_word(_A);
+#else
+ return m_program->read_word(A & AM);
+#endif
+
+}
+
+inline UINT32 sh34_base_device::RL(offs_t A)
+{
+ if (A >= 0xe0000000)
+ return m_program->read_dword(A);
+
+#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 *fastbase = (UINT8*)m_fastram[ramnum].base - m_fastram[ramnum].start;
+ return ((UINT32*)fastbase)[(_A^m_dword_xor) >> 2];
+ }
+ return m_program->read_dword(_A);
+#else
+ return m_program->read_dword(A & AM);
+#endif
+
+}
+
+inline void sh34_base_device::WB(offs_t A, UINT8 V)
+{
+ if (A >= 0xe0000000)
+ {
+ m_program->write_byte(A,V);
+ return;
+ }
+#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 *fastbase = (UINT8*)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
+
+}
+
+inline void sh34_base_device::WW(offs_t A, UINT16 V)
+{
+ if (A >= 0xe0000000)
+ {
+ m_program->write_word(A,V);
+ return;
+ }
+#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*)m_fastram[ramnum].base - m_fastram[ramnum].start;
+ ((UINT16*)fastbase)[(_A ^ m_word_xor) >> 1] = V;
+ return;
+ }
+ m_program->write_word(_A,V);
+#else
+ m_program->write_word(A & AM,V);
+#endif
+
+}
+
+inline void sh34_base_device::WL(offs_t A, UINT32 V)
+{
+ if (A >= 0xe0000000)
+ {
+ m_program->write_dword(A,V);
+ return;
+ }
+#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*)m_fastram[ramnum].base - m_fastram[ramnum].start;
+ ((UINT32*)fastbase)[(_A ^ m_dword_xor) >> 2] = V;
+ return;
+ }
+ m_program->write_dword(_A,V);
+#else
+ m_program->write_dword(A & AM,V);
+#endif
+}
+
+/* code cycles t-bit
+ * 0011 nnnn mmmm 1100 1 -
+ * ADD Rm,Rn
+ */
+inline void sh34_base_device::ADD(const UINT16 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 opcode)
+{
+ m_r[Rn] += (INT32)(INT16)(INT8)(opcode&0xff);
+}
+
+/* code cycles t-bit
+ * 0011 nnnn mmmm 1110 1 carry
+ * ADDC Rm,Rn
+ */
+inline void sh34_base_device::ADDC(const UINT16 opcode)
+{
+ UINT32 m = Rm; UINT32 n = Rn;
+ UINT32 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 opcode)
+{
+ UINT32 m = Rm; UINT32 n = Rn;
+ INT32 dest, src, ans;
+
+ if ((INT32) m_r[n] >= 0)
+ dest = 0;
+ else
+ dest = 1;
+ if ((INT32) m_r[m] >= 0)
+ src = 0;
+ else
+ src = 1;
+ src += dest;
+ m_r[n] += m_r[m];
+ if ((INT32) 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 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 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 opcode)
+{
+ UINT32 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 opcode)
+{
+ if ((m_sr & T) == 0)
+ {
+ INT32 disp = ((INT32)(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 opcode)
+{
+ if ((m_sr & T) == 0)
+ {
+ INT32 disp = ((INT32)(opcode&0xff) << 24) >> 24;
+ m_delay = m_pc;
+ m_pc = 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 opcode)
+{
+ INT32 disp = ((INT32)(opcode&0xfff) << 20) >> 20;
+
+#if BUSY_LOOP_HACKS
+ if (disp == -2)
+ {
+ UINT32 next_opcode = RW(m_ppc & AM);
+ /* BRA $
+ * NOP
+ */
+ if (next_opcode == 0x0009)
+ m_sh4_icount %= 3; /* cycles for BRA $ and NOP taken (3) */
+ }
+#endif
+ m_delay = m_pc;
+ m_pc = 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 opcode)
+{
+ m_delay = m_pc;
+ 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 opcode)
+{
+ INT32 disp = ((INT32)(opcode&0xfff) << 20) >> 20;
+
+ m_pr = m_pc + 2;
+ m_delay = m_pc;
+ m_pc = 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 opcode)
+{
+ m_pr = m_pc + 2;
+ m_delay = m_pc;
+ 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 opcode)
+{
+ if ((m_sr & T) != 0)
+ {
+ INT32 disp = ((INT32)(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 opcode)
+{
+ if ((m_sr & T) != 0)
+ {
+ INT32 disp = ((INT32)(opcode&0xff) << 24) >> 24;
+ m_delay = m_pc;
+ m_pc = 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 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 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 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 opcode)
+{
+ if ((INT32) m_r[Rn] >= (INT32) 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 opcode)
+{
+ if ((INT32) m_r[Rn] > (INT32) 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 opcode)
+{
+ if ((UINT32) m_r[Rn] > (UINT32) 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 opcode)
+{
+ if ((UINT32) m_r[Rn] >= (UINT32) 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 opcode)
+{
+ if ((INT32) 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 opcode)
+{
+ if ((INT32) 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 opcode)
+{
+ UINT32 temp;
+ INT32 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 opcode)
+{
+ UINT32 imm = (UINT32)(INT32)(INT16)(INT8)(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 opcode)
+{
+ UINT32 m = Rm; UINT32 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 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 opcode)
+{
+ UINT32 m = Rm; UINT32 n = Rn;
+
+ UINT32 tmp0;
+ UINT32 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 opcode)
+{
+ UINT32 m = Rm; UINT32 n = Rn;
+
+ UINT32 RnL, RnH, RmL, RmH, Res0, Res1, Res2;
+ UINT32 temp0, temp1, temp2, temp3;
+ INT32 tempm, tempn, fnLmL;
+
+ tempn = (INT32) m_r[n];
+ tempm = (INT32) m_r[m];
+ if (tempn < 0)
+ tempn = 0 - tempn;
+ if (tempm < 0)
+ tempm = 0 - tempm;
+ if ((INT32) (m_r[n] ^ m_r[m]) < 0)
+ fnLmL = -1;
+ else
+ fnLmL = 0;
+ temp1 = (UINT32) tempn;
+ temp2 = (UINT32) 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--;
+}
+
+/* DMULU.L Rm,Rn */
+inline void sh34_base_device::DMULU(const UINT16 opcode)
+{
+ UINT32 m = Rm; UINT32 n = Rn;
+
+ UINT32 RnL, RnH, RmL, RmH, Res0, Res1, Res2;
+ UINT32 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 opcode)
+{
+ UINT32 n = Rn;
+
+ m_r[n]--;
+ if (m_r[n] == 0)
+ m_sr |= T;
+ else
+ m_sr &= ~T;
+#if BUSY_LOOP_HACKS
+ {
+ UINT32 next_opcode = RW(m_ppc & 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 opcode)
+{
+ m_r[Rn] = ((INT32)m_r[Rm] << 24) >> 24;
+}
+
+/* EXTS.W Rm,Rn */
+inline void sh34_base_device::EXTSW(const UINT16 opcode)
+{
+ m_r[Rn] = ((INT32)m_r[Rm] << 16) >> 16;
+}
+
+/* EXTU.B Rm,Rn */
+inline void sh34_base_device::EXTUB(const UINT16 opcode)
+{
+ m_r[Rn] = m_r[Rm] & 0x000000ff;
+}
+
+/* EXTU.W Rm,Rn */
+inline void sh34_base_device::EXTUW(const UINT16 opcode)
+{
+ m_r[Rn] = m_r[Rm] & 0x0000ffff;
+}
+
+/* JMP @Rm */
+inline void sh34_base_device::JMP(const UINT16 opcode)
+{
+ m_delay = m_pc;
+ m_pc = m_ea = m_r[Rn];
+}
+
+/* JSR @Rm */
+inline void sh34_base_device::JSR(const UINT16 opcode)
+{
+ m_delay = m_pc;
+ m_pr = m_pc + 2;
+ m_pc = m_ea = m_r[Rn];
+ m_sh4_icount--;
+}
+
+
+/* LDC Rm,SR */
+inline void sh34_base_device::LDCSR(const UINT16 opcode)
+{
+ UINT32 reg;
+
+ 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();
+}
+
+/* LDC Rm,GBR */
+inline void sh34_base_device::LDCGBR(const UINT16 opcode)
+{
+ m_gbr = m_r[Rn];
+}
+
+/* LDC Rm,VBR */
+inline void sh34_base_device::LDCVBR(const UINT16 opcode)
+{
+ m_vbr = m_r[Rn];
+}
+
+/* LDC.L @Rm+,SR */
+inline void sh34_base_device::LDCMSR(const UINT16 opcode)
+{
+ UINT32 old;
+
+ old = m_sr;
+ m_ea = m_r[Rn];
+ m_sr = RL(m_ea ) & 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;
+ sh4_exception_recompute();
+}
+
+/* LDC.L @Rm+,GBR */
+inline void sh34_base_device::LDCMGBR(const UINT16 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 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 opcode)
+{
+ m_mach = m_r[Rn];
+}
+
+/* LDS Rm,MACL */
+inline void sh34_base_device::LDSMACL(const UINT16 opcode)
+{
+ m_macl = m_r[Rn];
+}
+
+/* LDS Rm,PR */
+inline void sh34_base_device::LDSPR(const UINT16 opcode)
+{
+ m_pr = m_r[Rn];
+}
+
+/* LDS.L @Rm+,MACH */
+inline void sh34_base_device::LDSMMACH(const UINT16 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 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 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 opcode)
+{
+ UINT32 m = Rm; UINT32 n = Rn;
+
+ UINT32 RnL, RnH, RmL, RmH, Res0, Res1, Res2;
+ UINT32 temp0, temp1, temp2, temp3;
+ INT32 tempm, tempn, fnLmL;
+
+ tempn = (INT32) RL(m_r[n] );
+ m_r[n] += 4;
+ tempm = (INT32) RL(m_r[m] );
+ m_r[m] += 4;
+ if ((INT32) (tempn ^ tempm) < 0)
+ fnLmL = -1;
+ else
+ fnLmL = 0;
+ if (tempn < 0)
+ tempn = 0 - tempn;
+ if (tempm < 0)
+ tempm = 0 - tempm;
+ temp1 = (UINT32) tempn;
+ temp2 = (UINT32) 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) Res2 < 0) && (Res2 < 0xffff8000))
+ {
+ Res2 = 0x00008000;
+ Res0 = 0x00000000;
+ }
+ else if (((INT32) 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 opcode)
+{
+ UINT32 m = Rm; UINT32 n = Rn;
+
+ INT32 tempm, tempn, dest, src, ans;
+ UINT32 templ;
+
+ tempn = (INT32) RW(m_r[n] );
+ m_r[n] += 2;
+ tempm = (INT32) RW(m_r[m] );
+ m_r[m] += 2;
+ templ = m_macl;
+ tempm = ((INT32) (short) tempn * (INT32) (short) tempm);
+ if ((INT32) m_macl >= 0)
+ dest = 0;
+ else
+ dest = 1;
+ if ((INT32) tempm >= 0)
+ {
+ src = 0;
+ tempn = 0;
+ }
+ else
+ {
+ src = 1;
+ tempn = 0xffffffff;
+ }
+ src += dest;
+ m_macl += tempm;
+ if ((INT32) 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 opcode)
+{
+ m_r[Rn] = m_r[Rm];
+}
+
+/* MOV.B Rm,@Rn */
+inline void sh34_base_device::MOVBS(const UINT16 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 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 opcode)
+{
+ m_ea = m_r[Rn];
+ WL(m_ea, m_r[Rm] );
+}
+
+/* MOV.B @Rm,Rn */
+inline void sh34_base_device::MOVBL(const UINT16 opcode)
+{
+ m_ea = m_r[Rm];
+ m_r[Rn] = (UINT32)(INT32)(INT16)(INT8) RB( m_ea );
+}
+
+/* MOV.W @Rm,Rn */
+inline void sh34_base_device::MOVWL(const UINT16 opcode)
+{
+ m_ea = m_r[Rm];
+ m_r[Rn] = (UINT32)(INT32)(INT16) RW(m_ea );
+}
+
+/* MOV.L @Rm,Rn */
+inline void sh34_base_device::MOVLL(const UINT16 opcode)
+{
+ m_ea = m_r[Rm];
+ m_r[Rn] = RL(m_ea );
+}
+
+/* MOV.B Rm,@-Rn */
+inline void sh34_base_device::MOVBM(const UINT16 opcode)
+{
+ UINT32 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 opcode)
+{
+ UINT32 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 opcode)
+{
+ UINT32 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 opcode)
+{
+ UINT32 m = Rm; UINT32 n = Rn;
+
+ m_r[n] = (UINT32)(INT32)(INT16)(INT8) RB( m_r[m] );
+ if (n != m)
+ m_r[m] += 1;
+}
+
+/* MOV.W @Rm+,Rn */
+inline void sh34_base_device::MOVWP(const UINT16 opcode)
+{
+ UINT32 m = Rm; UINT32 n = Rn;
+
+ m_r[n] = (UINT32)(INT32)(INT16) RW(m_r[m] );
+ if (n != m)
+ m_r[m] += 2;
+}
+
+/* MOV.L @Rm+,Rn */
+inline void sh34_base_device::MOVLP(const UINT16 opcode)
+{
+ UINT32 m = Rm; UINT32 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 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 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 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 opcode)
+{
+ m_ea = m_r[Rm] + m_r[0];
+ m_r[Rn] = (UINT32)(INT32)(INT16)(INT8) RB( m_ea );
+}
+
+/* MOV.W @(R0,Rm),Rn */
+inline void sh34_base_device::MOVWL0(const UINT16 opcode)
+{
+ m_ea = m_r[Rm] + m_r[0];
+ m_r[Rn] = (UINT32)(INT32)(INT16) RW(m_ea );
+}
+
+/* MOV.L @(R0,Rm),Rn */
+inline void sh34_base_device::MOVLL0(const UINT16 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 opcode)
+{
+ m_r[Rn] = (UINT32)(INT32)(INT16)(INT8)(opcode&0xff);
+}
+
+/* MOV.W @(disp8,PC),Rn */
+inline void sh34_base_device::MOVWI(const UINT16 opcode)
+{
+ UINT32 disp = opcode & 0xff;
+ m_ea = m_pc + disp * 2 + 2;
+ m_r[Rn] = (UINT32)(INT32)(INT16) RW(m_ea );
+}
+
+/* MOV.L @(disp8,PC),Rn */
+inline void sh34_base_device::MOVLI(const UINT16 opcode)
+{
+ UINT32 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 opcode)
+{
+ UINT32 disp = opcode & 0xff;
+ m_ea = m_gbr + disp;
+ m_r[0] = (UINT32)(INT32)(INT16)(INT8) RB( m_ea );
+}
+
+/* MOV.W @(disp8,GBR),R0 */
+inline void sh34_base_device::MOVWLG(const UINT16 opcode)
+{
+ UINT32 disp = opcode & 0xff;
+ m_ea = m_gbr + disp * 2;
+ m_r[0] = (INT32)(INT16) RW(m_ea );
+}
+
+/* MOV.L @(disp8,GBR),R0 */
+inline void sh34_base_device::MOVLLG(const UINT16 opcode)
+{
+ UINT32 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 opcode)
+{
+ UINT32 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 opcode)
+{
+ UINT32 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 opcode)
+{
+ UINT32 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 opcode)
+{
+ UINT32 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 opcode)
+{
+ UINT32 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 opcode)
+{
+ UINT32 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 opcode)
+{
+ UINT32 disp = opcode & 0x0f;
+ m_ea = m_r[Rm] + disp;
+ m_r[0] = (UINT32)(INT32)(INT16)(INT8) RB( m_ea );
+}
+
+/* MOV.W @(disp4,Rm),R0 */
+inline void sh34_base_device::MOVWL4(const UINT16 opcode)
+{
+ UINT32 disp = opcode & 0x0f;
+ m_ea = m_r[Rm] + disp * 2;
+ m_r[0] = (UINT32)(INT32)(INT16) RW(m_ea );
+}
+
+/* MOV.L @(disp4,Rm),Rn */
+inline void sh34_base_device::MOVLL4(const UINT16 opcode)
+{
+ UINT32 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 opcode)
+{
+ UINT32 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 opcode)
+{
+ m_r[Rn] = m_sr & T;
+}
+
+/* MUL.L Rm,Rn */
+inline void sh34_base_device::MULL(const UINT16 opcode)
+{
+ m_macl = m_r[Rn] * m_r[Rm];
+ m_sh4_icount--;
+}
+
+/* MULS Rm,Rn */
+inline void sh34_base_device::MULS(const UINT16 opcode)
+{
+ m_macl = (INT16) m_r[Rn] * (INT16) m_r[Rm];
+}
+
+/* MULU Rm,Rn */
+inline void sh34_base_device::MULU(const UINT16 opcode)
+{
+ m_macl = (UINT16) m_r[Rn] * (UINT16) m_r[Rm];
+}
+
+/* NEG Rm,Rn */
+inline void sh34_base_device::NEG(const UINT16 opcode)
+{
+ m_r[Rn] = 0 - m_r[Rm];
+}
+
+/* NEGC Rm,Rn */
+inline void sh34_base_device::NEGC(const UINT16 opcode)
+{
+ UINT32 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 opcode)
+{
+}
+
+/* NOT Rm,Rn */
+inline void sh34_base_device::NOT(const UINT16 opcode)
+{
+ m_r[Rn] = ~m_r[Rm];
+}
+
+/* OR Rm,Rn */
+inline void sh34_base_device::OR(const UINT16 opcode)
+{
+ m_r[Rn] |= m_r[Rm];
+}
+
+/* OR #imm,R0 */
+inline void sh34_base_device::ORI(const UINT16 opcode)
+{
+ m_r[0] |= (opcode&0xff);
+ m_sh4_icount -= 2;
+}
+
+/* OR.B #imm,@(R0,GBR) */
+inline void sh34_base_device::ORM(const UINT16 opcode)
+{
+ UINT32 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 opcode)
+{
+ UINT32 n = Rn;
+
+ UINT32 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 opcode)
+{
+ UINT32 n = Rn;
+
+ UINT32 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 opcode)
+{
+ UINT32 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 opcode)
+{
+ UINT32 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 opcode)
+{
+ m_delay = m_pc;
+ m_pc = m_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_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 opcode)
+{
+ m_delay = m_pc;
+ m_pc = m_ea = m_pr;
+ m_sh4_icount--;
+}
+
+/* SETT */
+inline void sh34_base_device::SETT(const UINT16 opcode)
+{
+ m_sr |= T;
+}
+
+/* SHAL Rn (same as SHLL) */
+inline void sh34_base_device::SHAL(const UINT16 opcode)
+{
+ UINT32 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 opcode)
+{
+ UINT32 n = Rn;
+
+ m_sr = (m_sr & ~T) | (m_r[n] & T);
+ m_r[n] = (UINT32)((INT32)m_r[n] >> 1);
+}
+
+/* SHLL Rn (same as SHAL) */
+inline void sh34_base_device::SHLL(const UINT16 opcode)
+{
+ UINT32 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 opcode)
+{
+ m_r[Rn] <<= 2;
+}
+
+/* SHLL8 Rn */
+inline void sh34_base_device::SHLL8(const UINT16 opcode)
+{
+ m_r[Rn] <<= 8;
+}
+
+/* SHLL16 Rn */
+inline void sh34_base_device::SHLL16(const UINT16 opcode)
+{
+ m_r[Rn] <<= 16;
+}
+
+/* SHLR Rn */
+inline void sh34_base_device::SHLR(const UINT16 opcode)
+{
+ UINT32 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 opcode)
+{
+ m_r[Rn] >>= 2;
+}
+
+/* SHLR8 Rn */
+inline void sh34_base_device::SHLR8(const UINT16 opcode)
+{
+ m_r[Rn] >>= 8;
+}
+
+/* SHLR16 Rn */
+inline void sh34_base_device::SHLR16(const UINT16 opcode)
+{
+ m_r[Rn] >>= 16;
+}
+
+/* SLEEP */
+inline void sh34_base_device::SLEEP(const UINT16 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 opcode)
+{
+ m_r[Rn] = m_sr;
+}
+
+/* STC GBR,Rn */
+inline void sh34_base_device::STCGBR(const UINT16 opcode)
+{
+ m_r[Rn] = m_gbr;
+}
+
+/* STC VBR,Rn */
+inline void sh34_base_device::STCVBR(const UINT16 opcode)
+{
+ m_r[Rn] = m_vbr;
+}
+
+/* STC.L SR,@-Rn */
+inline void sh34_base_device::STCMSR(const UINT16 opcode)
+{
+ UINT32 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 opcode)
+{
+ UINT32 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 opcode)
+{
+ UINT32 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 opcode)
+{
+ m_r[Rn] = m_mach;
+}
+
+/* STS MACL,Rn */
+inline void sh34_base_device::STSMACL(const UINT16 opcode)
+{
+ m_r[Rn] = m_macl;
+}
+
+/* STS PR,Rn */
+inline void sh34_base_device::STSPR(const UINT16 opcode)
+{
+ m_r[Rn] = m_pr;
+}
+
+/* STS.L MACH,@-Rn */
+inline void sh34_base_device::STSMMACH(const UINT16 opcode)
+{
+ UINT32 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 opcode)
+{
+ UINT32 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 opcode)
+{
+ UINT32 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 opcode)
+{
+ m_r[Rn] -= m_r[Rm];
+}
+
+/* SUBC Rm,Rn */
+inline void sh34_base_device::SUBC(const UINT16 opcode)
+{
+ UINT32 m = Rm; UINT32 n = Rn;
+
+ UINT32 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 opcode)
+{
+ UINT32 m = Rm; UINT32 n = Rn;
+
+ INT32 dest, src, ans;
+
+ if ((INT32) m_r[n] >= 0)
+ dest = 0;
+ else
+ dest = 1;
+ if ((INT32) m_r[m] >= 0)
+ src = 0;
+ else
+ src = 1;
+ src += dest;
+ m_r[n] -= m_r[m];
+ if ((INT32) 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 opcode)
+{
+ UINT32 m = Rm; UINT32 n = Rn;
+
+ UINT32 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 opcode)
+{
+ UINT32 m = Rm; UINT32 n = Rn;
+
+ UINT32 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 opcode)
+{
+ UINT32 n = Rn;
+
+ UINT32 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;
+}
+
+/* TRAPA #imm */
+inline void sh34_base_device::TRAPA(const UINT16 opcode)
+{
+ UINT32 imm = opcode & 0xff;
+
+ if (m_cpu_type == CPU_TYPE_SH4)
+ {
+ m_m[TRA] = imm << 2;
+ }
+ else /* SH3 */
+ {
+ m_sh3internal_upper[SH3_TRA_ADDR] = imm << 2;
+ }
+
+
+ m_ssr = m_sr;
+ m_spc = m_pc;
+ 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();
+
+ if (m_cpu_type == CPU_TYPE_SH4)
+ {
+ m_m[EXPEVT] = 0x00000160;
+ }
+ else /* SH3 */
+ {
+ 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 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 opcode)
+{
+ UINT32 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 opcode)
+{
+ UINT32 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;
+}
+
+/* XOR Rm,Rn */
+inline void sh34_base_device::XOR(const UINT16 opcode)
+{
+ m_r[Rn] ^= m_r[Rm];
+}
+
+/* XOR #imm,R0 */
+inline void sh34_base_device::XORI(const UINT16 opcode)
+{
+ UINT32 imm = opcode & 0xff;
+ m_r[0] ^= imm;
+}
+
+/* XOR.B #imm,@(R0,GBR) */
+inline void sh34_base_device::XORM(const UINT16 opcode)
+{
+ UINT32 imm = opcode & 0xff;
+ UINT32 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 opcode)
+{
+ UINT32 m = Rm; UINT32 n = Rn;
+
+ UINT32 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 opcode)
+{
+ m_r[Rn] = m_ssr;
+}
+
+/* STC SPC,Rn */
+inline void sh34_base_device::STCSPC(const UINT16 opcode)
+{
+ m_r[Rn] = m_spc;
+}
+
+/* STC SGR,Rn */
+inline void sh34_base_device::STCSGR(const UINT16 opcode)
+{
+ m_r[Rn] = m_sgr;
+}
+
+/* STS FPUL,Rn */
+inline void sh34_base_device::STSFPUL(const UINT16 opcode)
+{
+ m_r[Rn] = m_fpul;
+}
+
+/* STS FPSCR,Rn */
+inline void sh34_base_device::STSFPSCR(const UINT16 opcode)
+{
+ m_r[Rn] = m_fpscr & 0x003FFFFF;
+}
+
+/* STC DBR,Rn */
+inline void sh34_base_device::STCDBR(const UINT16 opcode)
+{
+ m_r[Rn] = m_dbr;
+}
+
+/* STCRBANK Rm_BANK,Rn */
+inline void sh34_base_device::STCRBANK(const UINT16 opcode)
+{
+ UINT32 m = Rm;
+
+ m_r[Rn] = m_rbnk[m_sr&sRB ? 0 : 1][m & 7];
+}
+
+/* STCMRBANK Rm_BANK,@-Rn */
+inline void sh34_base_device::STCMRBANK(const UINT16 opcode)
+{
+ UINT32 m = Rm; UINT32 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 opcode)
+{
+ m_ea = m_r[Rn];
+ WL(m_ea, m_r[0] );
+}
+
+inline void sh34_base_device::CLRS(const UINT16 opcode)
+{
+ m_sr &= ~S;
+}
+
+inline void sh34_base_device::SETS(const UINT16 opcode)
+{
+ m_sr |= S;
+}
+
+/* STS.L SGR,@-Rn */
+inline void sh34_base_device::STCMSGR(const UINT16 opcode)
+{
+ UINT32 n = Rn;
+
+ m_r[n] -= 4;
+ m_ea = m_r[n];
+ WL(m_ea, m_sgr );
+}
+
+/* STS.L FPUL,@-Rn */
+inline void sh34_base_device::STSMFPUL(const UINT16 opcode)
+{
+ UINT32 n = Rn;
+
+ m_r[n] -= 4;
+ m_ea = m_r[n];
+ WL(m_ea, m_fpul );
+}
+
+/* STS.L FPSCR,@-Rn */
+inline void sh34_base_device::STSMFPSCR(const UINT16 opcode)
+{
+ UINT32 n = Rn;
+
+ m_r[n] -= 4;
+ m_ea = m_r[n];
+ WL(m_ea, m_fpscr & 0x003FFFFF);
+}
+
+/* STC.L DBR,@-Rn */
+inline void sh34_base_device::STCMDBR(const UINT16 opcode)
+{
+ UINT32 n = Rn;
+
+ m_r[n] -= 4;
+ m_ea = m_r[n];
+ WL(m_ea, m_dbr );
+}
+
+/* STC.L SSR,@-Rn */
+inline void sh34_base_device::STCMSSR(const UINT16 opcode)
+{
+ UINT32 n = Rn;
+
+ m_r[n] -= 4;
+ m_ea = m_r[n];
+ WL(m_ea, m_ssr );
+}
+
+/* STC.L SPC,@-Rn */
+inline void sh34_base_device::STCMSPC(const UINT16 opcode)
+{
+ UINT32 n = Rn;
+
+ m_r[n] -= 4;
+ m_ea = m_r[n];
+ WL(m_ea, m_spc );
+}
+
+/* LDS.L @Rm+,FPUL */
+inline void sh34_base_device::LDSMFPUL(const UINT16 opcode)
+{
+ m_ea = m_r[Rn];
+ m_fpul = RL(m_ea );
+ m_r[Rn] += 4;
+}
+
+/* LDS.L @Rm+,FPSCR */
+inline void sh34_base_device::LDSMFPSCR(const UINT16 opcode)
+{
+ UINT32 s;
+
+ s = m_fpscr;
+ m_ea = m_r[Rn];
+ m_fpscr = RL(m_ea );
+ m_fpscr &= 0x003FFFFF;
+ m_r[Rn] += 4;
+ if ((s & FR) != (m_fpscr & FR))
+ sh4_swap_fp_registers();
+#ifdef LSB_FIRST
+ if ((s & PR) != (m_fpscr & PR))
+ sh4_swap_fp_couples();
+#endif
+ m_fpu_sz = (m_fpscr & SZ) ? 1 : 0;
+ m_fpu_pr = (m_fpscr & PR) ? 1 : 0;
+}
+
+/* LDC.L @Rm+,DBR */
+inline void sh34_base_device::LDCMDBR(const UINT16 opcode)
+{
+ m_ea = m_r[Rn];
+ m_dbr = RL(m_ea );
+ m_r[Rn] += 4;
+}
+
+/* LDC.L @Rn+,Rm_BANK */
+inline void sh34_base_device::LDCMRBANK(const UINT16 opcode)
+{
+ UINT32 m = Rm; UINT32 n = Rn;
+
+ m_ea = m_r[n];
+ m_rbnk[m_sr&sRB ? 0 : 1][m & 7] = RL(m_ea );
+ m_r[n] += 4;
+}
+
+/* LDC.L @Rm+,SSR */
+inline void sh34_base_device::LDCMSSR(const UINT16 opcode)
+{
+ m_ea = m_r[Rn];
+ m_ssr = RL(m_ea );
+ m_r[Rn] += 4;
+}
+
+/* LDC.L @Rm+,SPC */
+inline void sh34_base_device::LDCMSPC(const UINT16 opcode)
+{
+ m_ea = m_r[Rn];
+ m_spc = RL(m_ea );
+ m_r[Rn] += 4;
+}
+
+/* LDS Rm,FPUL */
+inline void sh34_base_device::LDSFPUL(const UINT16 opcode)
+{
+ m_fpul = m_r[Rn];
+}
+
+/* LDS Rm,FPSCR */
+inline void sh34_base_device::LDSFPSCR(const UINT16 opcode)
+{
+ UINT32 s;
+
+ s = m_fpscr;
+ m_fpscr = m_r[Rn] & 0x003FFFFF;
+ if ((s & FR) != (m_fpscr & FR))
+ sh4_swap_fp_registers();
+#ifdef LSB_FIRST
+ if ((s & PR) != (m_fpscr & PR))
+ sh4_swap_fp_couples();
+#endif
+ m_fpu_sz = (m_fpscr & SZ) ? 1 : 0;
+ m_fpu_pr = (m_fpscr & PR) ? 1 : 0;
+}
+
+/* LDC Rm,DBR */
+inline void sh34_base_device::LDCDBR(const UINT16 opcode)
+{
+ m_dbr = m_r[Rn];
+}
+
+/* SHAD Rm,Rn */
+inline void sh34_base_device::SHAD(const UINT16 opcode)
+{
+ UINT32 m = Rm; UINT32 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;
+ else
+ m_r[n] = 0xFFFFFFFF;
+ } else
+ m_r[n]=(INT32)m_r[n] >> ((~m_r[m] & 0x1F)+1);
+}
+
+/* SHLD Rm,Rn */
+inline void sh34_base_device::SHLD(const UINT16 opcode)
+{
+ UINT32 m = Rm; UINT32 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;
+ else
+ m_r[n] = m_r[n] >> ((~m_r[m] & 0x1F)+1);
+}
+
+/* LDCRBANK Rn,Rm_BANK */
+inline void sh34_base_device::LDCRBANK(const UINT16 opcode)
+{
+ UINT32 m = Rm;
+
+ m_rbnk[m_sr&sRB ? 0 : 1][m & 7] = m_r[Rn];
+}
+
+/* LDC Rm,SSR */
+inline void sh34_base_device::LDCSSR(const UINT16 opcode)
+{
+ m_ssr = m_r[Rn];
+}
+
+/* LDC Rm,SPC */
+inline void sh34_base_device::LDCSPC(const UINT16 opcode)
+{
+ m_spc = m_r[Rn];
+}
+
+/* PREF @Rn */
+inline void sh34_base_device::PREFM(const UINT16 opcode)
+{
+ int a;
+ UINT32 addr,dest,sq;
+
+ addr = m_r[Rn]; // address
+ if ((addr >= 0xE0000000) && (addr <= 0xE3FFFFFF))
+ {
+ if (m_sh4_mmu_enabled)
+ {
+ addr = addr & 0xFFFFFFE0;
+ dest = sh4_getsqremap(addr); // good enough for naomi-gd rom, probably not much else
+
+ }
+ else
+ {
+ sq = (addr & 0x20) >> 5;
+ dest = addr & 0x03FFFFE0;
+ if (sq == 0)
+ {
+ if (m_cpu_type == CPU_TYPE_SH4)
+ {
+ dest |= (m_m[QACR0] & 0x1C) << 24;
+ }
+ else
+ {
+ fatalerror("m_cpu_type != CPU_TYPE_SH4 but access internal regs\n");
+ }
+ }
+ else
+ {
+ if (m_cpu_type == CPU_TYPE_SH4)
+ {
+ dest |= (m_m[QACR1] & 0x1C) << 24;
+ }
+ else
+ {
+ fatalerror("m_cpu_type != CPU_TYPE_SH4 but access internal regs\n");
+ }
+
+ }
+ addr = addr & 0xFFFFFFE0;
+ }
+
+ for (a = 0;a < 4;a++)
+ {
+ // shouldn't be causing a memory read, should store sq writes in registers.
+ m_program->write_qword(dest, m_program->read_qword(addr));
+ addr += 8;
+ dest += 8;
+ }
+ }
+}
+
+/*****************************************************************************
+ * OPCODE DISPATCHERS
+ *****************************************************************************/
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+/* FMOV.S @Rm+,FRn PR=0 SZ=0 1111nnnnmmmm1001 */
+/* FMOV @Rm+,DRn PR=0 SZ=1 1111nnn0mmmm1001 */
+/* FMOV @Rm+,XDn PR=0 SZ=1 1111nnn1mmmm1001 */
+/* FMOV @Rm+,XDn PR=1 1111nnn1mmmm1001 */
+inline void sh34_base_device::FMOVMRIFR(const UINT16 opcode)
+{
+ UINT32 m = Rm; UINT32 n = Rn;
+
+ if (m_fpu_pr) { /* PR = 1 */
+ n = n & 14;
+ m_ea = m_r[m];
+ m_r[m] += 8;
+ m_xf[n+NATIVE_ENDIAN_VALUE_LE_BE(1,0)] = RL(m_ea );
+ m_xf[n+NATIVE_ENDIAN_VALUE_LE_BE(0,1)] = RL(m_ea+4 );
+ } else { /* PR = 0 */
+ if (m_fpu_sz) { /* SZ = 1 */
+ if (n & 1) {
+ n = n & 14;
+ 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_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;
+ }
+ } else { /* SZ = 0 */
+ m_ea = m_r[m];
+ m_fr[n] = RL(m_ea );
+ m_r[m] += 4;
+ }
+ }
+}
+
+/* FMOV.S FRm,@Rn PR=0 SZ=0 1111nnnnmmmm1010 */
+/* FMOV DRm,@Rn PR=0 SZ=1 1111nnnnmmm01010 */
+/* FMOV XDm,@Rn PR=0 SZ=1 1111nnnnmmm11010 */
+/* FMOV XDm,@Rn PR=1 1111nnnnmmm11010 */
+inline void sh34_base_device::FMOVFRMR(const UINT16 opcode)
+{
+ UINT32 m = Rm; UINT32 n = Rn;
+
+ if (m_fpu_pr) { /* PR = 1 */
+ m= m & 14;
+ m_ea = m_r[n];
+ WL(m_ea,m_xf[m+NATIVE_ENDIAN_VALUE_LE_BE(1,0)] );
+ WL(m_ea+4,m_xf[m+NATIVE_ENDIAN_VALUE_LE_BE(0,1)] );
+ } else { /* PR = 0 */
+ if (m_fpu_sz) { /* SZ = 1 */
+ if (m & 1) {
+ m= m & 14;
+ m_ea = m_r[n];
+ WL(m_ea,m_xf[m] );
+ WL(m_ea+4,m_xf[m+1] );
+ } else {
+ m_ea = m_r[n];
+ WL(m_ea,m_fr[m] );
+ WL(m_ea+4,m_fr[m+1] );
+ }
+ } else { /* SZ = 0 */
+ m_ea = m_r[n];
+ WL(m_ea,m_fr[m] );
+ }
+ }
+}
+
+/* FMOV.S FRm,@-Rn PR=0 SZ=0 1111nnnnmmmm1011 */
+/* FMOV DRm,@-Rn PR=0 SZ=1 1111nnnnmmm01011 */
+/* FMOV XDm,@-Rn PR=0 SZ=1 1111nnnnmmm11011 */
+/* FMOV XDm,@-Rn PR=1 1111nnnnmmm11011 */
+inline void sh34_base_device::FMOVFRMDR(const UINT16 opcode)
+{
+ UINT32 m = Rm; UINT32 n = Rn;
+
+ if (m_fpu_pr) { /* PR = 1 */
+ m= m & 14;
+ m_r[n] -= 8;
+ m_ea = m_r[n];
+ WL(m_ea,m_xf[m+NATIVE_ENDIAN_VALUE_LE_BE(1,0)] );
+ WL(m_ea+4,m_xf[m+NATIVE_ENDIAN_VALUE_LE_BE(0,1)] );
+ } else { /* PR = 0 */
+ if (m_fpu_sz) { /* SZ = 1 */
+ if (m & 1) {
+ m= m & 14;
+ 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_r[n] -= 8;
+ m_ea = m_r[n];
+ WL(m_ea,m_fr[m] );
+ WL(m_ea+4,m_fr[m+1] );
+ }
+ } else { /* SZ = 0 */
+ m_r[n] -= 4;
+ m_ea = m_r[n];
+ WL(m_ea,m_fr[m] );
+ }
+ }
+}
+
+/* FMOV.S FRm,@(R0,Rn) PR=0 SZ=0 1111nnnnmmmm0111 */
+/* FMOV DRm,@(R0,Rn) PR=0 SZ=1 1111nnnnmmm00111 */
+/* FMOV XDm,@(R0,Rn) PR=0 SZ=1 1111nnnnmmm10111 */
+/* FMOV XDm,@(R0,Rn) PR=1 1111nnnnmmm10111 */
+inline void sh34_base_device::FMOVFRS0(const UINT16 opcode)
+{
+ UINT32 m = Rm; UINT32 n = Rn;
+
+ if (m_fpu_pr) { /* PR = 1 */
+ m= m & 14;
+ m_ea = m_r[0] + m_r[n];
+ WL(m_ea,m_xf[m+NATIVE_ENDIAN_VALUE_LE_BE(1,0)] );
+ WL(m_ea+4,m_xf[m+NATIVE_ENDIAN_VALUE_LE_BE(0,1)] );
+ } else { /* PR = 0 */
+ if (m_fpu_sz) { /* SZ = 1 */
+ if (m & 1) {
+ m= m & 14;
+ m_ea = m_r[0] + m_r[n];
+ WL(m_ea,m_xf[m] );
+ WL(m_ea+4,m_xf[m+1] );
+ } else {
+ m_ea = m_r[0] + m_r[n];
+ WL(m_ea,m_fr[m] );
+ WL(m_ea+4,m_fr[m+1] );
+ }
+ } else { /* SZ = 0 */
+ m_ea = m_r[0] + m_r[n];
+ WL(m_ea,m_fr[m] );
+ }
+ }
+}
+
+/* FMOV.S @(R0,Rm),FRn PR=0 SZ=0 1111nnnnmmmm0110 */
+/* FMOV @(R0,Rm),DRn PR=0 SZ=1 1111nnn0mmmm0110 */
+/* FMOV @(R0,Rm),XDn PR=0 SZ=1 1111nnn1mmmm0110 */
+/* FMOV @(R0,Rm),XDn PR=1 1111nnn1mmmm0110 */
+inline void sh34_base_device::FMOVS0FR(const UINT16 opcode)
+{
+ UINT32 m = Rm; UINT32 n = Rn;
+
+ if (m_fpu_pr) { /* PR = 1 */
+ n= n & 14;
+ m_ea = m_r[0] + m_r[m];
+ m_xf[n+NATIVE_ENDIAN_VALUE_LE_BE(1,0)] = RL(m_ea );
+ m_xf[n+NATIVE_ENDIAN_VALUE_LE_BE(0,1)] = RL(m_ea+4 );
+ } else { /* PR = 0 */
+ if (m_fpu_sz) { /* SZ = 1 */
+ if (n & 1) {
+ n= n & 14;
+ m_ea = m_r[0] + m_r[m];
+ m_xf[n] = RL(m_ea );
+ m_xf[n+1] = RL(m_ea+4 );
+ } else {
+ m_ea = m_r[0] + m_r[m];
+ m_fr[n] = RL(m_ea );
+ m_fr[n+1] = RL(m_ea+4 );
+ }
+ } else { /* SZ = 0 */
+ m_ea = m_r[0] + m_r[m];
+ m_fr[n] = RL(m_ea );
+ }
+ }
+}
+
+/* FMOV.S @Rm,FRn PR=0 SZ=0 1111nnnnmmmm1000 */
+/* FMOV @Rm,DRn PR=0 SZ=1 1111nnn0mmmm1000 */
+/* FMOV @Rm,XDn PR=0 SZ=1 1111nnn1mmmm1000 */
+/* FMOV @Rm,XDn PR=1 1111nnn1mmmm1000 */
+/* FMOV @Rm,DRn PR=1 1111nnn0mmmm1000 */
+inline void sh34_base_device::FMOVMRFR(const UINT16 opcode)
+{
+ UINT32 m = Rm; UINT32 n = Rn;
+
+ if (m_fpu_pr) { /* PR = 1 */
+ if (n & 1) {
+ n= n & 14;
+ m_ea = m_r[m];
+ m_xf[n+NATIVE_ENDIAN_VALUE_LE_BE(1,0)] = RL(m_ea );
+ m_xf[n+NATIVE_ENDIAN_VALUE_LE_BE(0,1)] = RL(m_ea+4 );
+ } else {
+ n= n & 14;
+ m_ea = m_r[m];
+ m_fr[n+NATIVE_ENDIAN_VALUE_LE_BE(1,0)] = RL(m_ea );
+ m_fr[n+NATIVE_ENDIAN_VALUE_LE_BE(0,1)] = RL(m_ea+4 );
+ }
+ } else { /* PR = 0 */
+ if (m_fpu_sz) { /* SZ = 1 */
+ if (n & 1) {
+ n= n & 14;
+ m_ea = m_r[m];
+ m_xf[n] = RL(m_ea );
+ m_xf[n+1] = RL(m_ea+4 );
+ } else {
+ n= n & 14;
+ m_ea = m_r[m];
+ m_fr[n] = RL(m_ea );
+ m_fr[n+1] = RL(m_ea+4 );
+ }
+ } else { /* SZ = 0 */
+ m_ea = m_r[m];
+ m_fr[n] = RL(m_ea );
+ }
+ }
+}
+
+/* FMOV FRm,FRn PR=0 SZ=0 FRm -> FRn 1111nnnnmmmm1100 */
+/* FMOV DRm,DRn PR=0 SZ=1 DRm -> DRn 1111nnn0mmm01100 */
+/* FMOV XDm,DRn PR=1 XDm -> DRn 1111nnn0mmm11100 */
+/* FMOV DRm,XDn PR=1 DRm -> XDn 1111nnn1mmm01100 */
+/* FMOV XDm,XDn PR=1 XDm -> XDn 1111nnn1mmm11100 */
+inline void sh34_base_device::FMOVFR(const UINT16 opcode)
+{
+ UINT32 m = Rm; UINT32 n = Rn;
+
+ if ((m_fpu_sz == 0) && (m_fpu_pr == 0)) /* SZ = 0 */
+ m_fr[n] = m_fr[m];
+ else { /* SZ = 1 or PR = 1 */
+ if (m & 1) {
+ if (n & 1) {
+ m_xf[n & 14] = m_xf[m & 14];
+ m_xf[n | 1] = m_xf[m | 1];
+ } else {
+ m_fr[n] = m_xf[m & 14];
+ m_fr[n | 1] = m_xf[m | 1];
+ }
+ } 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 {
+ m_fr[n] = m_fr[m];
+ m_fr[n | 1] = m_fr[m | 1];
+ }
+ }
+ }
+}
+
+/* FLDI1 FRn 1111nnnn10011101 */
+inline void sh34_base_device::FLDI1(const UINT16 opcode)
+{
+ m_fr[Rn] = 0x3F800000;
+}
+
+/* FLDI0 FRn 1111nnnn10001101 */
+inline void sh34_base_device::FLDI0(const UINT16 opcode)
+{
+ m_fr[Rn] = 0;
+}
+
+/* FLDS FRm,FPUL 1111mmmm00011101 */
+inline void sh34_base_device:: FLDS(const UINT16 opcode)
+{
+ m_fpul = m_fr[Rn];
+}
+
+/* FSTS FPUL,FRn 1111nnnn00001101 */
+inline void sh34_base_device:: FSTS(const UINT16 opcode)
+{
+ m_fr[Rn] = m_fpul;
+}
+
+/* FRCHG 1111101111111101 */
+void sh34_base_device::FRCHG()
+{
+ m_fpscr ^= FR;
+ sh4_swap_fp_registers();
+}
+
+/* FSCHG 1111001111111101 */
+void sh34_base_device::FSCHG()
+{
+ m_fpscr ^= SZ;
+ m_fpu_sz = (m_fpscr & SZ) ? 1 : 0;
+}
+
+/* FTRC FRm,FPUL PR=0 1111mmmm00111101 */
+/* FTRC DRm,FPUL PR=1 1111mmm000111101 */
+inline void sh34_base_device::FTRC(const UINT16 opcode)
+{
+ UINT32 n = Rn;
+
+ if (m_fpu_pr) { /* PR = 1 */
+ if(n & 1)
+ fatalerror("SH-4: FTRC opcode used with n %d",n);
+
+ n = n & 14;
+ *((INT32 *)&m_fpul) = (INT32)FP_RFD(n);
+ } else { /* PR = 0 */
+ /* read m_fr[n] as float -> truncate -> fpul(32) */
+ *((INT32 *)&m_fpul) = (INT32)FP_RFS(n);
+ }
+}
+
+/* FLOAT FPUL,FRn PR=0 1111nnnn00101101 */
+/* FLOAT FPUL,DRn PR=1 1111nnn000101101 */
+inline void sh34_base_device::FLOAT(const UINT16 opcode)
+{
+ UINT32 n = Rn;
+
+ if (m_fpu_pr) { /* PR = 1 */
+ if(n & 1)
+ fatalerror("SH-4: FLOAT opcode used with n %d",n);
+
+ n = n & 14;
+ FP_RFD(n) = (double)*((INT32 *)&m_fpul);
+ } else { /* PR = 0 */
+ FP_RFS(n) = (float)*((INT32 *)&m_fpul);
+ }
+}
+
+/* FNEG FRn PR=0 1111nnnn01001101 */
+/* FNEG DRn PR=1 1111nnn001001101 */
+inline void sh34_base_device::FNEG(const UINT16 opcode)
+{
+ UINT32 n = Rn;
+
+ if (m_fpu_pr) { /* PR = 1 */
+ FP_RFD(n) = -FP_RFD(n);
+ } else { /* PR = 0 */
+ FP_RFS(n) = -FP_RFS(n);
+ }
+}
+
+/* FABS FRn PR=0 1111nnnn01011101 */
+/* FABS DRn PR=1 1111nnn001011101 */
+inline void sh34_base_device::FABS(const UINT16 opcode)
+{
+ UINT32 n = Rn;
+
+ if (m_fpu_pr) { /* PR = 1 */
+#ifdef LSB_FIRST
+ n = n | 1; // n & 14 + 1
+ m_fr[n] = m_fr[n] & 0x7fffffff;
+#else
+ n = n & 14;
+ m_fr[n] = m_fr[n] & 0x7fffffff;
+#endif
+ } else { /* PR = 0 */
+ m_fr[n] = m_fr[n] & 0x7fffffff;
+ }
+}
+
+/* FCMP/EQ FRm,FRn PR=0 1111nnnnmmmm0100 */
+/* FCMP/EQ DRm,DRn PR=1 1111nnn0mmm00100 */
+inline void sh34_base_device::FCMP_EQ(const UINT16 opcode)
+{
+ UINT32 m = Rm; UINT32 n = Rn;
+
+ if (m_fpu_pr) { /* PR = 1 */
+ n = n & 14;
+ m = m & 14;
+ if (FP_RFD(n) == FP_RFD(m))
+ m_sr |= T;
+ else
+ m_sr &= ~T;
+ } else { /* PR = 0 */
+ if (FP_RFS(n) == FP_RFS(m))
+ m_sr |= T;
+ else
+ m_sr &= ~T;
+ }
+}
+
+/* FCMP/GT FRm,FRn PR=0 1111nnnnmmmm0101 */
+/* FCMP/GT DRm,DRn PR=1 1111nnn0mmm00101 */
+inline void sh34_base_device::FCMP_GT(const UINT16 opcode)
+{
+ UINT32 m = Rm; UINT32 n = Rn;
+
+ if (m_fpu_pr) { /* PR = 1 */
+ n = n & 14;
+ m = m & 14;
+ if (FP_RFD(n) > FP_RFD(m))
+ m_sr |= T;
+ else
+ m_sr &= ~T;
+ } else { /* PR = 0 */
+ if (FP_RFS(n) > FP_RFS(m))
+ m_sr |= T;
+ else
+ m_sr &= ~T;
+ }
+}
+
+/* FCNVDS DRm,FPUL PR=1 1111mmm010111101 */
+inline void sh34_base_device::FCNVDS(const UINT16 opcode)
+{
+ UINT32 n = Rn;
+
+ 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*/
+ *((float *)&m_fpul) = (float)FP_RFD(n);
+ }
+}
+
+/* FCNVSD FPUL, DRn PR=1 1111nnn010101101 */
+inline void sh34_base_device::FCNVSD(const UINT16 opcode)
+{
+ UINT32 n = Rn;
+
+ if (m_fpu_pr) { /* PR = 1 */
+ n = n & 14;
+ FP_RFD(n) = (double)*((float *)&m_fpul);
+ }
+}
+
+/* FADD FRm,FRn PR=0 1111nnnnmmmm0000 */
+/* FADD DRm,DRn PR=1 1111nnn0mmm00000 */
+inline void sh34_base_device::FADD(const UINT16 opcode)
+{
+ UINT32 m = Rm; UINT32 n = Rn;
+
+ if (m_fpu_pr) { /* PR = 1 */
+ n = n & 14;
+ m = m & 14;
+ FP_RFD(n) = FP_RFD(n) + FP_RFD(m);
+ } else { /* PR = 0 */
+ FP_RFS(n) = FP_RFS(n) + FP_RFS(m);
+ }
+}
+
+/* FSUB FRm,FRn PR=0 1111nnnnmmmm0001 */
+/* FSUB DRm,DRn PR=1 1111nnn0mmm00001 */
+inline void sh34_base_device::FSUB(const UINT16 opcode)
+{
+ UINT32 m = Rm; UINT32 n = Rn;
+
+ if (m_fpu_pr) { /* PR = 1 */
+ n = n & 14;
+ m = m & 14;
+ FP_RFD(n) = FP_RFD(n) - FP_RFD(m);
+ } else { /* PR = 0 */
+ FP_RFS(n) = FP_RFS(n) - FP_RFS(m);
+ }
+}
+
+
+/* FMUL FRm,FRn PR=0 1111nnnnmmmm0010 */
+/* FMUL DRm,DRn PR=1 1111nnn0mmm00010 */
+inline void sh34_base_device::FMUL(const UINT16 opcode)
+{
+ UINT32 m = Rm; UINT32 n = Rn;
+
+ if (m_fpu_pr) { /* PR = 1 */
+ n = n & 14;
+ m = m & 14;
+ FP_RFD(n) = FP_RFD(n) * FP_RFD(m);
+ } else { /* PR = 0 */
+ FP_RFS(n) = FP_RFS(n) * FP_RFS(m);
+ }
+}
+
+/* FDIV FRm,FRn PR=0 1111nnnnmmmm0011 */
+/* FDIV DRm,DRn PR=1 1111nnn0mmm00011 */
+inline void sh34_base_device::FDIV(const UINT16 opcode)
+{
+ UINT32 m = Rm; UINT32 n = Rn;
+
+ if (m_fpu_pr) { /* PR = 1 */
+ n = n & 14;
+ m = m & 14;
+ if (FP_RFD(m) == 0)
+ return;
+ FP_RFD(n) = FP_RFD(n) / FP_RFD(m);
+ } else { /* PR = 0 */
+ if (FP_RFS(m) == 0)
+ return;
+ FP_RFS(n) = FP_RFS(n) / FP_RFS(m);
+ }
+}
+
+/* FMAC FR0,FRm,FRn PR=0 1111nnnnmmmm1110 */
+inline void sh34_base_device::FMAC(const UINT16 opcode)
+{
+ UINT32 m = Rm; UINT32 n = Rn;
+
+ if (m_fpu_pr == 0) { /* PR = 0 */
+ FP_RFS(n) = (FP_RFS(0) * FP_RFS(m)) + FP_RFS(n);
+ }
+}
+
+/* FSQRT FRn PR=0 1111nnnn01101101 */
+/* FSQRT DRn PR=1 1111nnnn01101101 */
+inline void sh34_base_device::FSQRT(const UINT16 opcode)
+{
+ UINT32 n = Rn;
+
+ if (m_fpu_pr) { /* PR = 1 */
+ n = n & 14;
+ if (FP_RFD(n) < 0)
+ return;
+ FP_RFD(n) = sqrtf(FP_RFD(n));
+ } else { /* PR = 0 */
+ if (FP_RFS(n) < 0)
+ return;
+ FP_RFS(n) = sqrtf(FP_RFS(n));
+ }
+}
+
+/* FSRRA FRn PR=0 1111nnnn01111101 */
+inline void sh34_base_device::FSRRA(const UINT16 opcode)
+{
+ UINT32 n = Rn;
+
+ if (FP_RFS(n) < 0)
+ return;
+ FP_RFS(n) = 1.0f / sqrtf(FP_RFS(n));
+}
+
+/* FSSCA FPUL,FRn PR=0 1111nnn011111101 */
+void sh34_base_device::FSSCA(const UINT16 opcode)
+{
+ UINT32 n = Rn;
+
+ float angle;
+
+ angle = (((float)(m_fpul & 0xFFFF)) / 65536.0f) * 2.0f * (float) M_PI;
+ FP_RFS(n) = sinf(angle);
+ FP_RFS(n+1) = cosf(angle);
+}
+
+/* FIPR FVm,FVn PR=0 1111nnmm11101101 */
+inline void sh34_base_device::FIPR(const UINT16 opcode)
+{
+ UINT32 n = Rn;
+
+UINT32 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];
+}
+
+/* FTRV XMTRX,FVn PR=0 1111nn0111111101 */
+void sh34_base_device::FTRV(const UINT16 opcode)
+{
+ UINT32 n = Rn;
+
+int i,j;
+float sum[4];
+
+ n = n & 12;
+ for (i = 0;i < 4;i++) {
+ sum[i] = 0;
+ for (j=0;j < 4;j++)
+ sum[i] += FP_XFS((j << 2) + i)*FP_RFS(n + j);
+ }
+ for (i = 0;i < 4;i++)
+ FP_RFS(n + i) = sum[i];
+}
+
+inline void sh34_base_device::op1111_0xf13(const UINT16 opcode)
+{
+ if (opcode & 0x100) {
+ if (opcode & 0x200) {
+ switch (opcode & 0xC00)
+ {
+ case 0x000:
+ FSCHG();
+ break;
+ case 0x800:
+ FRCHG();
+ break;
+ default:
+ debugger_break(machine());
+ break;
+ }
+ } else {
+ FTRV(opcode);
+ }
+ } else {
+ FSSCA(opcode);
+ }
+}
+
+void sh34_base_device::dbreak(const UINT16 opcode)
+{
+ debugger_break(machine());
+}
+
+
+inline void sh34_base_device::op1111_0x13(UINT16 opcode)
+{
+ 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;
+ }
+}
+
+
+/*****************************************************************************
+ * MAME CPU INTERFACE
+ *****************************************************************************/
+
+void sh34_base_device::device_reset()
+{
+ m_ppc = 0;
+ m_spc = 0;
+ m_pr = 0;
+ m_sr = 0;
+ m_ssr = 0;
+ m_gbr = 0;
+ m_vbr = 0;
+ m_mach = 0;
+ m_macl = 0;
+ memset(m_r, 0, sizeof(m_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_cpu_off = 0;
+ m_pending_irq = 0;
+ m_test_irq = 0;
+ memset(m_exception_priority, 0, sizeof(m_exception_priority));
+ memset(m_exception_requesting, 0, sizeof(m_exception_requesting));
+ memset(m_m, 0, sizeof(m_m));
+ memset(m_sh3internal_upper, 0, sizeof(m_sh3internal_upper));
+ memset(m_sh3internal_lower, 0, sizeof(m_sh3internal_lower));
+ memset(m_irq_line_state, 0, sizeof(m_irq_line_state));
+ m_SH4_TSTR = 0;
+ m_SH4_TCNT0 = 0;
+ m_SH4_TCNT1 = 0;
+ m_SH4_TCNT2 = 0;
+ m_SH4_TCR0 = 0;
+ m_SH4_TCR1 = 0;
+ m_SH4_TCR2 = 0;
+ m_SH4_TCOR0 = 0;
+ m_SH4_TCOR1 = 0;
+ m_SH4_TCOR2 = 0;
+ m_SH4_TOCR = 0;
+ m_SH4_TCPR2 = 0;
+ m_SH4_IPRA = 0;
+ m_SH4_IPRC = 0;
+ m_SH4_SAR0 = 0;
+ m_SH4_SAR1 = 0;
+ m_SH4_SAR2 = 0;
+ m_SH4_SAR3 = 0;
+ m_SH4_DAR0 = 0;
+ m_SH4_DAR1 = 0;
+ m_SH4_DAR2 = 0;
+ m_SH4_DAR3 = 0;
+ m_SH4_CHCR0 = 0;
+ m_SH4_CHCR1 = 0;
+ m_SH4_CHCR2 = 0;
+ m_SH4_CHCR3 = 0;
+ m_SH4_DMATCR0 = 0;
+ m_SH4_DMATCR1 = 0;
+ m_SH4_DMATCR2 = 0;
+ m_SH4_DMATCR3 = 0;
+ m_SH4_DMAOR = 0;
+ m_nmi_line_state = 0;
+ m_frt_input = 0;
+ m_internal_irq_vector = 0;
+ m_refresh_timer_base = 0;
+ memset(m_dma_timer_active, 0, sizeof(m_dma_timer_active));
+ memset(m_dma_source, 0, sizeof(m_dma_source));
+ memset(m_dma_destination, 0, sizeof(m_dma_destination));
+ memset(m_dma_count, 0, sizeof(m_dma_count));
+ memset(m_dma_wordsize, 0, sizeof(m_dma_wordsize));
+ memset(m_dma_source_increment, 0, sizeof(m_dma_source_increment));
+ memset(m_dma_destination_increment, 0, sizeof(m_dma_destination_increment));
+ memset(m_dma_mode, 0, sizeof(m_dma_mode));
+ m_ioport16_pullup = 0;
+ m_ioport16_direction = 0;
+ m_ioport4_pullup = 0;
+ m_ioport4_direction = 0;
+
+ sh4_default_exception_priorities();
+
+ m_rtc_timer->adjust(attotime::from_hz(128));
+
+ m_pc = 0xa0000000;
+ m_r[15] = RL(4);
+ m_sr = 0x700000f0;
+ m_fpscr = 0x00040001;
+ m_fpu_sz = (m_fpscr & SZ) ? 1 : 0;
+ m_fpu_pr = (m_fpscr & PR) ? 1 : 0;
+ m_fpul = 0;
+ m_dbr = 0;
+
+ m_internal_irq_level = -1;
+ m_irln = 15;
+ m_sleep_mode = 0;
+
+ m_sh4_mmu_enabled = 0;
+}
+
+/*-------------------------------------------------
+ sh3_reset - reset the processor
+-------------------------------------------------*/
+
+void sh3_base_device::device_reset()
+{
+ sh34_base_device::device_reset();
+
+ m_SH4_TCOR0 = 0xffffffff;
+ m_SH4_TCNT0 = 0xffffffff;
+ m_SH4_TCOR1 = 0xffffffff;
+ m_SH4_TCNT1 = 0xffffffff;
+ m_SH4_TCOR2 = 0xffffffff;
+ m_SH4_TCNT2 = 0xffffffff;
+}
+
+void sh4_base_device::device_reset()
+{
+ sh34_base_device::device_reset();
+
+ m_m[RCR2] = 0x09;
+ m_SH4_TCOR0 = 0xffffffff;
+ m_SH4_TCNT0 = 0xffffffff;
+ m_SH4_TCOR1 = 0xffffffff;
+ m_SH4_TCNT1 = 0xffffffff;
+ m_SH4_TCOR2 = 0xffffffff;
+ m_SH4_TCNT2 = 0xffffffff;
+}
+
+inline void sh34_base_device::execute_one_0000(const UINT16 opcode)
+{
+ 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: TODO(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: TODO(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;
+ }
+}
+
+inline void sh34_base_device::execute_one_4000(const UINT16 opcode)
+{
+ 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 opcode)
+{
+ switch(opcode & 0xf000)
+ {
+ 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;
+ }
+}
+
+
+/* Execute cycles - returns number of cycles actually run */
+void sh34_base_device::execute_run()
+{
+ if (m_cpu_off)
+ {
+ m_sh4_icount = 0;
+ return;
+ }
+
+ do
+ {
+ if (m_delay)
+ {
+ const UINT16 opcode = m_direct->read_word((UINT32)(m_delay & AM), WORD2_XOR_LE(0));
+
+ debugger_instruction_hook(this, (m_pc-2) & AM);
+
+ m_delay = 0;
+ m_ppc = m_pc;
+
+ execute_one(opcode);
+
+ if (m_test_irq && !m_delay)
+ {
+ sh4_check_pending_irq("mame_sh4_execute");
+ }
+ }
+ else
+ {
+ const UINT16 opcode = m_direct->read_word((UINT32)(m_pc & AM), WORD2_XOR_LE(0));
+
+ debugger_instruction_hook(this, m_pc & AM);
+
+ m_pc += 2;
+ m_ppc = m_pc;
+
+ execute_one(opcode);
+
+ if (m_test_irq && !m_delay)
+ {
+ sh4_check_pending_irq("mame_sh4_execute");
+ }
+ }
+
+ m_sh4_icount--;
+ } while( m_sh4_icount > 0 );
+}
+
+void sh3be_device::execute_run()
+{
+ if (m_cpu_off)
+ {
+ m_sh4_icount = 0;
+ return;
+ }
+
+ do
+ {
+ if (m_delay)
+ {
+ const UINT16 opcode = m_direct->read_word((UINT32)(m_delay & AM), WORD_XOR_LE(6));
+
+ debugger_instruction_hook(this, m_delay & AM);
+
+ m_delay = 0;
+ m_ppc = m_pc;
+
+ execute_one(opcode);
+
+
+ if (m_test_irq && !m_delay)
+ {
+ sh4_check_pending_irq("mame_sh4_execute");
+ }
+
+
+ }
+ else
+ {
+ const UINT16 opcode = m_direct->read_word((UINT32)(m_pc & AM), WORD_XOR_LE(6));
+
+ debugger_instruction_hook(this, m_pc & AM);
+
+ m_pc += 2;
+ m_ppc = m_pc;
+
+ execute_one(opcode);
+
+ if (m_test_irq && !m_delay)
+ {
+ sh4_check_pending_irq("mame_sh4_execute");
+ }
+ }
+
+ m_sh4_icount--;
+ } while( m_sh4_icount > 0 );
+}
+
+void sh4be_device::execute_run()
+{
+ if (m_cpu_off)
+ {
+ m_sh4_icount = 0;
+ return;
+ }
+
+ do
+ {
+ if (m_delay)
+ {
+ const UINT16 opcode = m_direct->read_word((UINT32)(m_delay & AM), WORD_XOR_LE(6));
+
+ debugger_instruction_hook(this, m_delay & AM);
+
+ m_delay = 0;
+ m_ppc = m_pc;
+
+ execute_one(opcode);
+
+
+ if (m_test_irq && !m_delay)
+ {
+ sh4_check_pending_irq("mame_sh4_execute");
+ }
+
+
+ }
+ else
+ {
+ const UINT16 opcode = m_direct->read_word((UINT32)(m_pc & AM), WORD_XOR_LE(6));
+
+ debugger_instruction_hook(this, m_pc & AM);
+
+ m_pc += 2;
+ m_ppc = m_pc;
+
+ execute_one(opcode);
+
+ if (m_test_irq && !m_delay)
+ {
+ sh4_check_pending_irq("mame_sh4_execute");
+ }
+ }
+
+ m_sh4_icount--;
+ } while( m_sh4_icount > 0 );
+}
+
+void sh34_base_device::device_start()
+{
+ for (int i=0; i<3; i++)
+ {
+ m_timer[i] = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(sh34_base_device::sh4_timer_callback), this));
+ m_timer[i]->adjust(attotime::never, i);
+ }
+
+ for (int i=0; i<4; i++)
+ {
+ m_dma_timer[i] = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(sh34_base_device::sh4_dmac_callback), this));
+ m_dma_timer[i]->adjust(attotime::never, i);
+ }
+
+ m_refresh_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(sh34_base_device::sh4_refresh_timer_callback), this));
+ m_refresh_timer->adjust(attotime::never);
+ m_refresh_timer_base = 0;
+
+ m_rtc_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(sh34_base_device::sh4_rtc_timer_callback), this));
+ m_rtc_timer->adjust(attotime::never);
+
+ sh4_parse_configuration();
+
+ m_internal = &space(AS_PROGRAM);
+ m_program = &space(AS_PROGRAM);
+ m_io = &space(AS_IO);
+ m_direct = &m_program->direct();
+ sh4_default_exception_priorities();
+ m_irln = 15;
+ m_test_irq = 0;
+
+ save_item(NAME(m_pc));
+ save_item(NAME(m_r[15]));
+ 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));
+ save_item(NAME(m_fpscr));
+ save_item(NAME(m_r[ 0]));
+ save_item(NAME(m_r[ 1]));
+ save_item(NAME(m_r[ 2]));
+ save_item(NAME(m_r[ 3]));
+ save_item(NAME(m_r[ 4]));
+ save_item(NAME(m_r[ 5]));
+ save_item(NAME(m_r[ 6]));
+ save_item(NAME(m_r[ 7]));
+ save_item(NAME(m_r[ 8]));
+ save_item(NAME(m_r[ 9]));
+ save_item(NAME(m_r[10]));
+ save_item(NAME(m_r[11]));
+ save_item(NAME(m_r[12]));
+ save_item(NAME(m_r[13]));
+ save_item(NAME(m_r[14]));
+ save_item(NAME(m_fr[ 0]));
+ save_item(NAME(m_fr[ 1]));
+ save_item(NAME(m_fr[ 2]));
+ save_item(NAME(m_fr[ 3]));
+ save_item(NAME(m_fr[ 4]));
+ save_item(NAME(m_fr[ 5]));
+ save_item(NAME(m_fr[ 6]));
+ save_item(NAME(m_fr[ 7]));
+ save_item(NAME(m_fr[ 8]));
+ save_item(NAME(m_fr[ 9]));
+ save_item(NAME(m_fr[10]));
+ save_item(NAME(m_fr[11]));
+ save_item(NAME(m_fr[12]));
+ save_item(NAME(m_fr[13]));
+ save_item(NAME(m_fr[14]));
+ save_item(NAME(m_fr[15]));
+ save_item(NAME(m_xf[ 0]));
+ save_item(NAME(m_xf[ 1]));
+ save_item(NAME(m_xf[ 2]));
+ save_item(NAME(m_xf[ 3]));
+ save_item(NAME(m_xf[ 4]));
+ save_item(NAME(m_xf[ 5]));
+ save_item(NAME(m_xf[ 6]));
+ save_item(NAME(m_xf[ 7]));
+ save_item(NAME(m_xf[ 8]));
+ save_item(NAME(m_xf[ 9]));
+ save_item(NAME(m_xf[10]));
+ save_item(NAME(m_xf[11]));
+ save_item(NAME(m_xf[12]));
+ save_item(NAME(m_xf[13]));
+ save_item(NAME(m_xf[14]));
+ save_item(NAME(m_xf[15]));
+ save_item(NAME(m_ea));
+ save_item(NAME(m_fpul));
+ save_item(NAME(m_dbr));
+ save_item(NAME(m_exception_priority));
+ save_item(NAME(m_exception_requesting));
+
+ save_item(NAME(m_SH4_TSTR));
+ save_item(NAME(m_SH4_TCNT0));
+ save_item(NAME(m_SH4_TCNT1));
+ save_item(NAME(m_SH4_TCNT2));
+ save_item(NAME(m_SH4_TCR0));
+ save_item(NAME(m_SH4_TCR1));
+ save_item(NAME(m_SH4_TCR2));
+ save_item(NAME(m_SH4_TCOR0));
+ save_item(NAME(m_SH4_TCOR1));
+ save_item(NAME(m_SH4_TCOR2));
+ save_item(NAME(m_SH4_TOCR));
+ save_item(NAME(m_SH4_TCPR2));
+
+ save_item(NAME(m_SH4_IPRA));
+
+ save_item(NAME(m_SH4_IPRC));
+
+ // 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(STATE_GENPC, "GENPC", m_debugger_temp).callimport().callexport().noshow();
+ state_add(STATE_GENSP, "GENSP", m_r[15]).noshow();
+ state_add(STATE_GENPCBASE, "GENPCBASE", m_ppc).noshow();
+ state_add(STATE_GENFLAGS, "GENFLAGS", m_sr).formatstr("%20s").noshow();
+
+ m_icountptr = &m_sh4_icount;
+}
+
+void sh34_base_device::state_import(const device_state_entry &entry)
+{
+#ifdef LSB_FIRST
+ UINT8 fpu_xor = m_fpu_pr;
+#else
+ UINT8 fpu_xor = 0;
+#endif
+
+ switch (entry.index())
+ {
+ case STATE_GENPC:
+ m_pc = m_debugger_temp;
+ case SH4_PC:
+ m_delay = 0;
+ break;
+
+ case SH4_SR:
+ sh4_exception_recompute();
+ sh4_check_pending_irq("sh4_set_info");
+ break;
+
+ case SH4_FR0:
+ m_fr[0 ^ fpu_xor] = m_debugger_temp;
+ break;
+
+ case SH4_FR1:
+ m_fr[1 ^ fpu_xor] = m_debugger_temp;
+ break;
+
+ case SH4_FR2:
+ m_fr[2 ^ fpu_xor] = m_debugger_temp;
+ break;
+
+ case SH4_FR3:
+ m_fr[3 ^ fpu_xor] = m_debugger_temp;
+ break;
+
+ case SH4_FR4:
+ m_fr[4 ^ fpu_xor] = m_debugger_temp;
+ break;
+
+ case SH4_FR5:
+ m_fr[5 ^ fpu_xor] = m_debugger_temp;
+ break;
+
+ case SH4_FR6:
+ m_fr[6 ^ fpu_xor] = m_debugger_temp;
+ break;
+
+ case SH4_FR7:
+ m_fr[7 ^ fpu_xor] = m_debugger_temp;
+ break;
+
+ case SH4_FR8:
+ m_fr[8 ^ fpu_xor] = m_debugger_temp;
+ break;
+
+ case SH4_FR9:
+ m_fr[9 ^ fpu_xor] = m_debugger_temp;
+ break;
+
+ case SH4_FR10:
+ m_fr[10 ^ fpu_xor] = m_debugger_temp;
+ break;
+
+ case SH4_FR11:
+ m_fr[11 ^ fpu_xor] = m_debugger_temp;
+ break;
+
+ case SH4_FR12:
+ m_fr[12 ^ fpu_xor] = m_debugger_temp;
+ break;
+
+ case SH4_FR13:
+ m_fr[13 ^ fpu_xor] = m_debugger_temp;
+ break;
+
+ case SH4_FR14:
+ m_fr[14 ^ fpu_xor] = m_debugger_temp;
+ break;
+
+ case SH4_FR15:
+ m_fr[15 ^ fpu_xor] = m_debugger_temp;
+ break;
+
+ case SH4_XF0:
+ m_xf[0 ^ fpu_xor] = m_debugger_temp;
+ break;
+
+ case SH4_XF1:
+ m_xf[1 ^ fpu_xor] = m_debugger_temp;
+ break;
+
+ case SH4_XF2:
+ m_xf[2 ^ fpu_xor] = m_debugger_temp;
+ break;
+
+ case SH4_XF3:
+ m_xf[3 ^ fpu_xor] = m_debugger_temp;
+ break;
+
+ case SH4_XF4:
+ m_xf[4 ^ fpu_xor] = m_debugger_temp;
+ break;
+
+ case SH4_XF5:
+ m_xf[5 ^ fpu_xor] = m_debugger_temp;
+ break;
+
+ case SH4_XF6:
+ m_xf[6 ^ fpu_xor] = m_debugger_temp;
+ break;
+
+ case SH4_XF7:
+ m_xf[7 ^ fpu_xor] = m_debugger_temp;
+ break;
+
+ case SH4_XF8:
+ m_xf[8 ^ fpu_xor] = m_debugger_temp;
+ break;
+
+ case SH4_XF9:
+ m_xf[9 ^ fpu_xor] = m_debugger_temp;
+ break;
+
+ case SH4_XF10:
+ m_xf[10 ^ fpu_xor] = m_debugger_temp;
+ break;
+
+ case SH4_XF11:
+ m_xf[11 ^ fpu_xor] = m_debugger_temp;
+ break;
+
+ case SH4_XF12:
+ m_xf[12 ^ fpu_xor] = m_debugger_temp;
+ break;
+
+ case SH4_XF13:
+ m_xf[13 ^ fpu_xor] = m_debugger_temp;
+ break;
+
+ case SH4_XF14:
+ m_xf[14 ^ fpu_xor] = m_debugger_temp;
+ break;
+
+ case SH4_XF15:
+ m_xf[15 ^ fpu_xor] = m_debugger_temp;
+ break;
+ }
+}
+
+void sh34_base_device::state_export(const device_state_entry &entry)
+{
+ switch (entry.index())
+ {
+ case STATE_GENPC:
+ m_debugger_temp = (m_delay) ? (m_delay & AM) : (m_pc & AM);
+ break;
+ }
+}
+
+void sh34_base_device::state_string_export(const device_state_entry &entry, std::string &str)
+{
+#ifdef LSB_FIRST
+ UINT8 fpu_xor = m_fpu_pr;
+#else
+ UINT8 fpu_xor = 0;
+#endif
+
+ switch (entry.index())
+ {
+ case STATE_GENFLAGS:
+ strprintf(str, "%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':'.');
+ break;
+
+ case SH4_FR0:
+ strprintf(str, "%08X %f", m_fr[0 ^ fpu_xor], (double)FP_RFS(0 ^ fpu_xor));
+ break;
+
+ case SH4_FR1:
+ strprintf(str, "%08X %f", m_fr[1 ^ fpu_xor], (double)FP_RFS(1 ^ fpu_xor));
+ break;
+
+ case SH4_FR2:
+ strprintf(str, "%08X %f", m_fr[2 ^ fpu_xor], (double)FP_RFS(2 ^ fpu_xor));
+ break;
+
+ case SH4_FR3:
+ strprintf(str, "%08X %f", m_fr[3 ^ fpu_xor], (double)FP_RFS(3 ^ fpu_xor));
+ break;
+
+ case SH4_FR4:
+ strprintf(str, "%08X %f", m_fr[4 ^ fpu_xor], (double)FP_RFS(4 ^ fpu_xor));
+ break;
+
+ case SH4_FR5:
+ strprintf(str, "%08X %f", m_fr[5 ^ fpu_xor], (double)FP_RFS(5 ^ fpu_xor));
+ break;
+
+ case SH4_FR6:
+ strprintf(str, "%08X %f", m_fr[6 ^ fpu_xor], (double)FP_RFS(6 ^ fpu_xor));
+ break;
+
+ case SH4_FR7:
+ strprintf(str, "%08X %f", m_fr[7 ^ fpu_xor], (double)FP_RFS(7 ^ fpu_xor));
+ break;
+
+ case SH4_FR8:
+ strprintf(str, "%08X %f", m_fr[8 ^ fpu_xor], (double)FP_RFS(8 ^ fpu_xor));
+ break;
+
+ case SH4_FR9:
+ strprintf(str, "%08X %f", m_fr[9 ^ fpu_xor], (double)FP_RFS(9 ^ fpu_xor));
+ break;
+
+ case SH4_FR10:
+ strprintf(str, "%08X %f", m_fr[10 ^ fpu_xor], (double)FP_RFS(10 ^ fpu_xor));
+ break;
+
+ case SH4_FR11:
+ strprintf(str, "%08X %f", m_fr[11 ^ fpu_xor], (double)FP_RFS(11 ^ fpu_xor));
+ break;
+
+ case SH4_FR12:
+ strprintf(str, "%08X %f", m_fr[12 ^ fpu_xor], (double)FP_RFS(12 ^ fpu_xor));
+ break;
+
+ case SH4_FR13:
+ strprintf(str, "%08X %f", m_fr[13 ^ fpu_xor], (double)FP_RFS(13 ^ fpu_xor));
+ break;
+
+ case SH4_FR14:
+ strprintf(str, "%08X %f", m_fr[14 ^ fpu_xor], (double)FP_RFS(14 ^ fpu_xor));
+ break;
+
+ case SH4_FR15:
+ strprintf(str, "%08X %f", m_fr[15 ^ fpu_xor], (double)FP_RFS(15 ^ fpu_xor));
+ break;
+
+ case SH4_XF0:
+ strprintf(str, "%08X %f", m_xf[0 ^ fpu_xor], (double)FP_XFS(0 ^ fpu_xor));
+ break;
+
+ case SH4_XF1:
+ strprintf(str, "%08X %f", m_xf[1 ^ fpu_xor], (double)FP_XFS(1 ^ fpu_xor));
+ break;
+
+ case SH4_XF2:
+ strprintf(str, "%08X %f", m_xf[2 ^ fpu_xor], (double)FP_XFS(2 ^ fpu_xor));
+ break;
+
+ case SH4_XF3:
+ strprintf(str, "%08X %f", m_xf[3 ^ fpu_xor], (double)FP_XFS(3 ^ fpu_xor));
+ break;
+
+ case SH4_XF4:
+ strprintf(str, "%08X %f", m_xf[4 ^ fpu_xor], (double)FP_XFS(4 ^ fpu_xor));
+ break;
+
+ case SH4_XF5:
+ strprintf(str, "%08X %f", m_xf[5 ^ fpu_xor], (double)FP_XFS(5 ^ fpu_xor));
+ break;
+
+ case SH4_XF6:
+ strprintf(str, "%08X %f", m_xf[6 ^ fpu_xor], (double)FP_XFS(6 ^ fpu_xor));
+ break;
+
+ case SH4_XF7:
+ strprintf(str, "%08X %f", m_xf[7 ^ fpu_xor], (double)FP_XFS(7 ^ fpu_xor));
+ break;
+
+ case SH4_XF8:
+ strprintf(str, "%08X %f", m_xf[8 ^ fpu_xor], (double)FP_XFS(8 ^ fpu_xor));
+ break;
+
+ case SH4_XF9:
+ strprintf(str, "%08X %f", m_xf[9 ^ fpu_xor], (double)FP_XFS(9 ^ fpu_xor));
+ break;
+
+ case SH4_XF10:
+ strprintf(str, "%08X %f", m_xf[10 ^ fpu_xor], (double)FP_XFS(10 ^ fpu_xor));
+ break;
+
+ case SH4_XF11:
+ strprintf(str, "%08X %f", m_xf[11 ^ fpu_xor], (double)FP_XFS(11 ^ fpu_xor));
+ break;
+
+ case SH4_XF12:
+ strprintf(str, "%08X %f", m_xf[12 ^ fpu_xor], (double)FP_XFS(12 ^ fpu_xor));
+ break;
+
+ case SH4_XF13:
+ strprintf(str, "%08X %f", m_xf[13 ^ fpu_xor], (double)FP_XFS(13 ^ fpu_xor));
+ break;
+
+ case SH4_XF14:
+ strprintf(str, "%08X %f", m_xf[14 ^ fpu_xor], (double)FP_XFS(14 ^ fpu_xor));
+ break;
+
+ case SH4_XF15:
+ strprintf(str, "%08X %f", m_xf[15 ^ fpu_xor], (double)FP_XFS(15 ^ fpu_xor));
+ break;
+
+ }
+}
+
+
+void sh34_base_device::sh4_set_ftcsr_callback(sh4_ftcsr_callback callback)
+{
+ m_ftcsr_read_callback = callback;
+}