summaryrefslogtreecommitdiffstatshomepage
path: root/trunk/src/emu/cpu/sh4/sh4.c
diff options
context:
space:
mode:
Diffstat (limited to 'trunk/src/emu/cpu/sh4/sh4.c')
-rw-r--r--trunk/src/emu/cpu/sh4/sh4.c3852
1 files changed, 3852 insertions, 0 deletions
diff --git a/trunk/src/emu/cpu/sh4/sh4.c b/trunk/src/emu/cpu/sh4/sh4.c
new file mode 100644
index 00000000000..bf74d97941b
--- /dev/null
+++ b/trunk/src/emu/cpu/sh4/sh4.c
@@ -0,0 +1,3852 @@
+/*****************************************************************************
+ *
+ * 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"
+
+#ifndef USE_SH4DRC
+
+CPU_DISASSEMBLE( sh4 );
+
+/* Called for unimplemented opcodes */
+static void TODO(sh4_state *sh4)
+{
+}
+
+#if 0
+int sign_of(int n)
+{
+ return(sh4->fr[n]>>31);
+}
+
+void zero(int n,int sign)
+{
+if (sign == 0)
+ sh4->fr[n] = 0x00000000;
+else
+ sh4->fr[n] = 0x80000000;
+if ((sh4->fpscr & PR) == 1)
+ sh4->fr[n+1] = 0x00000000;
+}
+
+int data_type_of(int n)
+{
+UINT32 abs;
+
+ abs = sh4->fr[n] & 0x7fffffff;
+ if ((sh4->fpscr & PR) == 0) { /* Single-precision */
+ if (abs < 0x00800000) {
+ if (((sh4->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 (((sh4->fpscr & DN) == 1) || ((abs == 0x00000000) && (sh4->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) && (sh4->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 RB(sh4_state *sh4, offs_t A)
+{
+ if (A >= 0xe0000000)
+ return sh4->program->read_byte(A);
+
+ return sh4->program->read_byte(A & AM);
+}
+
+INLINE UINT16 RW(sh4_state *sh4, offs_t A)
+{
+ if (A >= 0xe0000000)
+ return sh4->program->read_word(A);
+
+ return sh4->program->read_word(A & AM);
+}
+
+INLINE UINT32 RL(sh4_state *sh4, offs_t A)
+{
+ if (A >= 0xe0000000)
+ return sh4->program->read_dword(A);
+
+ return sh4->program->read_dword(A & AM);
+}
+
+INLINE void WB(sh4_state *sh4, offs_t A, UINT8 V)
+{
+ if (A >= 0xe0000000)
+ {
+ sh4->program->write_byte(A,V);
+ return;
+ }
+
+ sh4->program->write_byte(A & AM,V);
+}
+
+INLINE void WW(sh4_state *sh4, offs_t A, UINT16 V)
+{
+ if (A >= 0xe0000000)
+ {
+ sh4->program->write_word(A,V);
+ return;
+ }
+
+ sh4->program->write_word(A & AM,V);
+}
+
+INLINE void WL(sh4_state *sh4, offs_t A, UINT32 V)
+{
+ if (A >= 0xe0000000)
+ {
+ sh4->program->write_dword(A,V);
+ return;
+ }
+
+ sh4->program->write_dword(A & AM,V);
+}
+
+/* code cycles t-bit
+ * 0011 nnnn mmmm 1100 1 -
+ * ADD Rm,Rn
+ */
+INLINE void ADD(sh4_state *sh4, UINT32 m, UINT32 n)
+{
+ sh4->r[n] += sh4->r[m];
+}
+
+/* code cycles t-bit
+ * 0111 nnnn iiii iiii 1 -
+ * ADD #imm,Rn
+ */
+INLINE void ADDI(sh4_state *sh4, UINT32 i, UINT32 n)
+{
+ sh4->r[n] += (INT32)(INT16)(INT8)i;
+}
+
+/* code cycles t-bit
+ * 0011 nnnn mmmm 1110 1 carry
+ * ADDC Rm,Rn
+ */
+INLINE void ADDC(sh4_state *sh4, UINT32 m, UINT32 n)
+{
+ UINT32 tmp0, tmp1;
+
+ tmp1 = sh4->r[n] + sh4->r[m];
+ tmp0 = sh4->r[n];
+ sh4->r[n] = tmp1 + (sh4->sr & T);
+ if (tmp0 > tmp1)
+ sh4->sr |= T;
+ else
+ sh4->sr &= ~T;
+ if (tmp1 > sh4->r[n])
+ sh4->sr |= T;
+}
+
+/* code cycles t-bit
+ * 0011 nnnn mmmm 1111 1 overflow
+ * ADDV Rm,Rn
+ */
+INLINE void ADDV(sh4_state *sh4, UINT32 m, UINT32 n)
+{
+ INT32 dest, src, ans;
+
+ if ((INT32) sh4->r[n] >= 0)
+ dest = 0;
+ else
+ dest = 1;
+ if ((INT32) sh4->r[m] >= 0)
+ src = 0;
+ else
+ src = 1;
+ src += dest;
+ sh4->r[n] += sh4->r[m];
+ if ((INT32) sh4->r[n] >= 0)
+ ans = 0;
+ else
+ ans = 1;
+ ans += dest;
+ if (src == 0 || src == 2)
+ {
+ if (ans == 1)
+ sh4->sr |= T;
+ else
+ sh4->sr &= ~T;
+ }
+ else
+ sh4->sr &= ~T;
+}
+
+/* code cycles t-bit
+ * 0010 nnnn mmmm 1001 1 -
+ * AND Rm,Rn
+ */
+INLINE void AND(sh4_state *sh4, UINT32 m, UINT32 n)
+{
+ sh4->r[n] &= sh4->r[m];
+}
+
+
+/* code cycles t-bit
+ * 1100 1001 iiii iiii 1 -
+ * AND #imm,R0
+ */
+INLINE void ANDI(sh4_state *sh4, UINT32 i)
+{
+ sh4->r[0] &= i;
+}
+
+/* code cycles t-bit
+ * 1100 1101 iiii iiii 1 -
+ * AND.B #imm,@(R0,GBR)
+ */
+INLINE void ANDM(sh4_state *sh4, UINT32 i)
+{
+ UINT32 temp;
+
+ sh4->ea = sh4->gbr + sh4->r[0];
+ temp = i & RB(sh4, sh4->ea );
+ WB(sh4, sh4->ea, temp );
+ sh4->sh4_icount -= 2;
+}
+
+/* code cycles t-bit
+ * 1000 1011 dddd dddd 3/1 -
+ * BF disp8
+ */
+INLINE void BF(sh4_state *sh4, UINT32 d)
+{
+ if ((sh4->sr & T) == 0)
+ {
+ INT32 disp = ((INT32)d << 24) >> 24;
+ sh4->pc = sh4->ea = sh4->pc + disp * 2 + 2;
+ sh4->sh4_icount -= 2;
+ }
+}
+
+/* code cycles t-bit
+ * 1000 1111 dddd dddd 3/1 -
+ * BFS disp8
+ */
+INLINE void BFS(sh4_state *sh4, UINT32 d)
+{
+ if ((sh4->sr & T) == 0)
+ {
+ INT32 disp = ((INT32)d << 24) >> 24;
+ sh4->delay = sh4->pc;
+ sh4->pc = sh4->ea = sh4->pc + disp * 2 + 2;
+ sh4->sh4_icount--;
+ }
+}
+
+/* code cycles t-bit
+ * 1010 dddd dddd dddd 2 -
+ * BRA disp12
+ */
+INLINE void BRA(sh4_state *sh4, UINT32 d)
+{
+ INT32 disp = ((INT32)d << 20) >> 20;
+
+#if BUSY_LOOP_HACKS
+ if (disp == -2)
+ {
+ UINT32 next_opcode = RW(sh4,sh4->ppc & AM);
+ /* BRA $
+ * NOP
+ */
+ if (next_opcode == 0x0009)
+ sh4->sh4_icount %= 3; /* cycles for BRA $ and NOP taken (3) */
+ }
+#endif
+ sh4->delay = sh4->pc;
+ sh4->pc = sh4->ea = sh4->pc + disp * 2 + 2;
+ sh4->sh4_icount--;
+}
+
+/* code cycles t-bit
+ * 0000 mmmm 0010 0011 2 -
+ * BRAF Rm
+ */
+INLINE void BRAF(sh4_state *sh4, UINT32 m)
+{
+ sh4->delay = sh4->pc;
+ sh4->pc += sh4->r[m] + 2;
+ sh4->sh4_icount--;
+}
+
+/* code cycles t-bit
+ * 1011 dddd dddd dddd 2 -
+ * BSR disp12
+ */
+INLINE void BSR(sh4_state *sh4, UINT32 d)
+{
+ INT32 disp = ((INT32)d << 20) >> 20;
+
+ sh4->pr = sh4->pc + 2;
+ sh4->delay = sh4->pc;
+ sh4->pc = sh4->ea = sh4->pc + disp * 2 + 2;
+ sh4->sh4_icount--;
+}
+
+/* code cycles t-bit
+ * 0000 mmmm 0000 0011 2 -
+ * BSRF Rm
+ */
+INLINE void BSRF(sh4_state *sh4, UINT32 m)
+{
+ sh4->pr = sh4->pc + 2;
+ sh4->delay = sh4->pc;
+ sh4->pc += sh4->r[m] + 2;
+ sh4->sh4_icount--;
+}
+
+/* code cycles t-bit
+ * 1000 1001 dddd dddd 3/1 -
+ * BT disp8
+ */
+INLINE void BT(sh4_state *sh4, UINT32 d)
+{
+ if ((sh4->sr & T) != 0)
+ {
+ INT32 disp = ((INT32)d << 24) >> 24;
+ sh4->pc = sh4->ea = sh4->pc + disp * 2 + 2;
+ sh4->sh4_icount -= 2;
+ }
+}
+
+/* code cycles t-bit
+ * 1000 1101 dddd dddd 2/1 -
+ * BTS disp8
+ */
+INLINE void BTS(sh4_state *sh4, UINT32 d)
+{
+ if ((sh4->sr & T) != 0)
+ {
+ INT32 disp = ((INT32)d << 24) >> 24;
+ sh4->delay = sh4->pc;
+ sh4->pc = sh4->ea = sh4->pc + disp * 2 + 2;
+ sh4->sh4_icount--;
+ }
+}
+
+/* code cycles t-bit
+ * 0000 0000 0010 1000 1 -
+ * CLRMAC
+ */
+INLINE void CLRMAC(sh4_state *sh4)
+{
+ sh4->mach = 0;
+ sh4->macl = 0;
+}
+
+/* code cycles t-bit
+ * 0000 0000 0000 1000 1 -
+ * CLRT
+ */
+INLINE void CLRT(sh4_state *sh4)
+{
+ sh4->sr &= ~T;
+}
+
+/* code cycles t-bit
+ * 0011 nnnn mmmm 0000 1 comparison result
+ * CMP_EQ Rm,Rn
+ */
+INLINE void CMPEQ(sh4_state *sh4, UINT32 m, UINT32 n)
+{
+ if (sh4->r[n] == sh4->r[m])
+ sh4->sr |= T;
+ else
+ sh4->sr &= ~T;
+}
+
+/* code cycles t-bit
+ * 0011 nnnn mmmm 0011 1 comparison result
+ * CMP_GE Rm,Rn
+ */
+INLINE void CMPGE(sh4_state *sh4, UINT32 m, UINT32 n)
+{
+ if ((INT32) sh4->r[n] >= (INT32) sh4->r[m])
+ sh4->sr |= T;
+ else
+ sh4->sr &= ~T;
+}
+
+/* code cycles t-bit
+ * 0011 nnnn mmmm 0111 1 comparison result
+ * CMP_GT Rm,Rn
+ */
+INLINE void CMPGT(sh4_state *sh4, UINT32 m, UINT32 n)
+{
+ if ((INT32) sh4->r[n] > (INT32) sh4->r[m])
+ sh4->sr |= T;
+ else
+ sh4->sr &= ~T;
+}
+
+/* code cycles t-bit
+ * 0011 nnnn mmmm 0110 1 comparison result
+ * CMP_HI Rm,Rn
+ */
+INLINE void CMPHI(sh4_state *sh4, UINT32 m, UINT32 n)
+{
+ if ((UINT32) sh4->r[n] > (UINT32) sh4->r[m])
+ sh4->sr |= T;
+ else
+ sh4->sr &= ~T;
+}
+
+/* code cycles t-bit
+ * 0011 nnnn mmmm 0010 1 comparison result
+ * CMP_HS Rm,Rn
+ */
+INLINE void CMPHS(sh4_state *sh4, UINT32 m, UINT32 n)
+{
+ if ((UINT32) sh4->r[n] >= (UINT32) sh4->r[m])
+ sh4->sr |= T;
+ else
+ sh4->sr &= ~T;
+}
+
+
+/* code cycles t-bit
+ * 0100 nnnn 0001 0101 1 comparison result
+ * CMP_PL Rn
+ */
+INLINE void CMPPL(sh4_state *sh4, UINT32 n)
+{
+ if ((INT32) sh4->r[n] > 0)
+ sh4->sr |= T;
+ else
+ sh4->sr &= ~T;
+}
+
+/* code cycles t-bit
+ * 0100 nnnn 0001 0001 1 comparison result
+ * CMP_PZ Rn
+ */
+INLINE void CMPPZ(sh4_state *sh4, UINT32 n)
+{
+ if ((INT32) sh4->r[n] >= 0)
+ sh4->sr |= T;
+ else
+ sh4->sr &= ~T;
+}
+
+/* code cycles t-bit
+ * 0010 nnnn mmmm 1100 1 comparison result
+ * CMP_STR Rm,Rn
+ */
+INLINE void CMPSTR(sh4_state *sh4, UINT32 m, UINT32 n)
+ {
+ UINT32 temp;
+ INT32 HH, HL, LH, LL;
+ temp = sh4->r[n] ^ sh4->r[m];
+ HH = (temp >> 24) & 0xff;
+ HL = (temp >> 16) & 0xff;
+ LH = (temp >> 8) & 0xff;
+ LL = temp & 0xff;
+ if (HH && HL && LH && LL)
+ sh4->sr &= ~T;
+ else
+ sh4->sr |= T;
+ }
+
+
+/* code cycles t-bit
+ * 1000 1000 iiii iiii 1 comparison result
+ * CMP/EQ #imm,R0
+ */
+INLINE void CMPIM(sh4_state *sh4, UINT32 i)
+{
+ UINT32 imm = (UINT32)(INT32)(INT16)(INT8)i;
+
+ if (sh4->r[0] == imm)
+ sh4->sr |= T;
+ else
+ sh4->sr &= ~T;
+}
+
+/* code cycles t-bit
+ * 0010 nnnn mmmm 0111 1 calculation result
+ * DIV0S Rm,Rn
+ */
+INLINE void DIV0S(sh4_state *sh4, UINT32 m, UINT32 n)
+{
+ if ((sh4->r[n] & 0x80000000) == 0)
+ sh4->sr &= ~Q;
+ else
+ sh4->sr |= Q;
+ if ((sh4->r[m] & 0x80000000) == 0)
+ sh4->sr &= ~M;
+ else
+ sh4->sr |= M;
+ if ((sh4->r[m] ^ sh4->r[n]) & 0x80000000)
+ sh4->sr |= T;
+ else
+ sh4->sr &= ~T;
+}
+
+/* code cycles t-bit
+ * 0000 0000 0001 1001 1 0
+ * DIV0U
+ */
+INLINE void DIV0U(sh4_state *sh4)
+{
+ sh4->sr &= ~(M | Q | T);
+}
+
+/* code cycles t-bit
+ * 0011 nnnn mmmm 0100 1 calculation result
+ * DIV1 Rm,Rn
+ */
+INLINE void DIV1(sh4_state *sh4, UINT32 m, UINT32 n)
+{
+ UINT32 tmp0;
+ UINT32 old_q;
+
+ old_q = sh4->sr & Q;
+ if (0x80000000 & sh4->r[n])
+ sh4->sr |= Q;
+ else
+ sh4->sr &= ~Q;
+
+ sh4->r[n] = (sh4->r[n] << 1) | (sh4->sr & T);
+
+ if (!old_q)
+ {
+ if (!(sh4->sr & M))
+ {
+ tmp0 = sh4->r[n];
+ sh4->r[n] -= sh4->r[m];
+ if(!(sh4->sr & Q))
+ if(sh4->r[n] > tmp0)
+ sh4->sr |= Q;
+ else
+ sh4->sr &= ~Q;
+ else
+ if(sh4->r[n] > tmp0)
+ sh4->sr &= ~Q;
+ else
+ sh4->sr |= Q;
+ }
+ else
+ {
+ tmp0 = sh4->r[n];
+ sh4->r[n] += sh4->r[m];
+ if(!(sh4->sr & Q))
+ {
+ if(sh4->r[n] < tmp0)
+ sh4->sr &= ~Q;
+ else
+ sh4->sr |= Q;
+ }
+ else
+ {
+ if(sh4->r[n] < tmp0)
+ sh4->sr |= Q;
+ else
+ sh4->sr &= ~Q;
+ }
+ }
+ }
+ else
+ {
+ if (!(sh4->sr & M))
+ {
+ tmp0 = sh4->r[n];
+ sh4->r[n] += sh4->r[m];
+ if(!(sh4->sr & Q))
+ if(sh4->r[n] < tmp0)
+ sh4->sr |= Q;
+ else
+ sh4->sr &= ~Q;
+ else
+ if(sh4->r[n] < tmp0)
+ sh4->sr &= ~Q;
+ else
+ sh4->sr |= Q;
+ }
+ else
+ {
+ tmp0 = sh4->r[n];
+ sh4->r[n] -= sh4->r[m];
+ if(!(sh4->sr & Q))
+ if(sh4->r[n] > tmp0)
+ sh4->sr &= ~Q;
+ else
+ sh4->sr |= Q;
+ else
+ if(sh4->r[n] > tmp0)
+ sh4->sr |= Q;
+ else
+ sh4->sr &= ~Q;
+ }
+ }
+
+ tmp0 = (sh4->sr & (Q | M));
+ if((!tmp0) || (tmp0 == 0x300)) /* if Q == M set T else clear T */
+ sh4->sr |= T;
+ else
+ sh4->sr &= ~T;
+}
+
+/* DMULS.L Rm,Rn */
+INLINE void DMULS(sh4_state *sh4, UINT32 m, UINT32 n)
+{
+ UINT32 RnL, RnH, RmL, RmH, Res0, Res1, Res2;
+ UINT32 temp0, temp1, temp2, temp3;
+ INT32 tempm, tempn, fnLmL;
+
+ tempn = (INT32) sh4->r[n];
+ tempm = (INT32) sh4->r[m];
+ if (tempn < 0)
+ tempn = 0 - tempn;
+ if (tempm < 0)
+ tempm = 0 - tempm;
+ if ((INT32) (sh4->r[n] ^ sh4->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;
+ }
+ sh4->mach = Res2;
+ sh4->macl = Res0;
+ sh4->sh4_icount--;
+}
+
+/* DMULU.L Rm,Rn */
+INLINE void DMULU(sh4_state *sh4, UINT32 m, UINT32 n)
+{
+ UINT32 RnL, RnH, RmL, RmH, Res0, Res1, Res2;
+ UINT32 temp0, temp1, temp2, temp3;
+
+ RnL = sh4->r[n] & 0x0000ffff;
+ RnH = (sh4->r[n] >> 16) & 0x0000ffff;
+ RmL = sh4->r[m] & 0x0000ffff;
+ RmH = (sh4->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;
+ sh4->mach = Res2;
+ sh4->macl = Res0;
+ sh4->sh4_icount--;
+}
+
+/* DT Rn */
+INLINE void DT(sh4_state *sh4, UINT32 n)
+{
+ sh4->r[n]--;
+ if (sh4->r[n] == 0)
+ sh4->sr |= T;
+ else
+ sh4->sr &= ~T;
+#if BUSY_LOOP_HACKS
+ {
+ UINT32 next_opcode = RW(sh4,sh4->ppc & AM);
+ /* DT Rn
+ * BF $-2
+ */
+ if (next_opcode == 0x8bfd)
+ {
+ while (sh4->r[n] > 1 && sh4->sh4_icount > 4)
+ {
+ sh4->r[n]--;
+ sh4->sh4_icount -= 4; /* cycles for DT (1) and BF taken (3) */
+ }
+ }
+ }
+#endif
+}
+
+/* EXTS.B Rm,Rn */
+INLINE void EXTSB(sh4_state *sh4, UINT32 m, UINT32 n)
+{
+ sh4->r[n] = ((INT32)sh4->r[m] << 24) >> 24;
+}
+
+/* EXTS.W Rm,Rn */
+INLINE void EXTSW(sh4_state *sh4, UINT32 m, UINT32 n)
+{
+ sh4->r[n] = ((INT32)sh4->r[m] << 16) >> 16;
+}
+
+/* EXTU.B Rm,Rn */
+INLINE void EXTUB(sh4_state *sh4, UINT32 m, UINT32 n)
+{
+ sh4->r[n] = sh4->r[m] & 0x000000ff;
+}
+
+/* EXTU.W Rm,Rn */
+INLINE void EXTUW(sh4_state *sh4, UINT32 m, UINT32 n)
+{
+ sh4->r[n] = sh4->r[m] & 0x0000ffff;
+}
+
+/* JMP @Rm */
+INLINE void JMP(sh4_state *sh4, UINT32 m)
+{
+ sh4->delay = sh4->pc;
+ sh4->pc = sh4->ea = sh4->r[m];
+}
+
+/* JSR @Rm */
+INLINE void JSR(sh4_state *sh4, UINT32 m)
+{
+ sh4->delay = sh4->pc;
+ sh4->pr = sh4->pc + 2;
+ sh4->pc = sh4->ea = sh4->r[m];
+ sh4->sh4_icount--;
+}
+
+
+/* LDC Rm,SR */
+INLINE void LDCSR(sh4_state *sh4, UINT32 m)
+{
+UINT32 reg;
+
+ reg = sh4->r[m];
+ if ((sh4->device->machine().debug_flags & DEBUG_FLAG_ENABLED) != 0)
+ sh4_syncronize_register_bank(sh4, (sh4->sr & sRB) >> 29);
+ if ((sh4->r[m] & sRB) != (sh4->sr & sRB))
+ sh4_change_register_bank(sh4, sh4->r[m] & sRB ? 1 : 0);
+ sh4->sr = reg & FLAGS;
+ sh4_exception_recompute(sh4);
+}
+
+/* LDC Rm,GBR */
+INLINE void LDCGBR(sh4_state *sh4, UINT32 m)
+{
+ sh4->gbr = sh4->r[m];
+}
+
+/* LDC Rm,VBR */
+INLINE void LDCVBR(sh4_state *sh4, UINT32 m)
+{
+ sh4->vbr = sh4->r[m];
+}
+
+/* LDC.L @Rm+,SR */
+INLINE void LDCMSR(sh4_state *sh4, UINT32 m)
+{
+UINT32 old;
+
+ old = sh4->sr;
+ sh4->ea = sh4->r[m];
+ sh4->sr = RL(sh4, sh4->ea ) & FLAGS;
+ if ((sh4->device->machine().debug_flags & DEBUG_FLAG_ENABLED) != 0)
+ sh4_syncronize_register_bank(sh4, (old & sRB) >> 29);
+ if ((old & sRB) != (sh4->sr & sRB))
+ sh4_change_register_bank(sh4, sh4->sr & sRB ? 1 : 0);
+ sh4->r[m] += 4;
+ sh4->sh4_icount -= 2;
+ sh4_exception_recompute(sh4);
+}
+
+/* LDC.L @Rm+,GBR */
+INLINE void LDCMGBR(sh4_state *sh4, UINT32 m)
+{
+ sh4->ea = sh4->r[m];
+ sh4->gbr = RL(sh4, sh4->ea );
+ sh4->r[m] += 4;
+ sh4->sh4_icount -= 2;
+}
+
+/* LDC.L @Rm+,VBR */
+INLINE void LDCMVBR(sh4_state *sh4, UINT32 m)
+{
+ sh4->ea = sh4->r[m];
+ sh4->vbr = RL(sh4, sh4->ea );
+ sh4->r[m] += 4;
+ sh4->sh4_icount -= 2;
+}
+
+/* LDS Rm,MACH */
+INLINE void LDSMACH(sh4_state *sh4, UINT32 m)
+{
+ sh4->mach = sh4->r[m];
+}
+
+/* LDS Rm,MACL */
+INLINE void LDSMACL(sh4_state *sh4, UINT32 m)
+{
+ sh4->macl = sh4->r[m];
+}
+
+/* LDS Rm,PR */
+INLINE void LDSPR(sh4_state *sh4, UINT32 m)
+{
+ sh4->pr = sh4->r[m];
+}
+
+/* LDS.L @Rm+,MACH */
+INLINE void LDSMMACH(sh4_state *sh4, UINT32 m)
+{
+ sh4->ea = sh4->r[m];
+ sh4->mach = RL(sh4, sh4->ea );
+ sh4->r[m] += 4;
+}
+
+/* LDS.L @Rm+,MACL */
+INLINE void LDSMMACL(sh4_state *sh4, UINT32 m)
+{
+ sh4->ea = sh4->r[m];
+ sh4->macl = RL(sh4, sh4->ea );
+ sh4->r[m] += 4;
+}
+
+/* LDS.L @Rm+,PR */
+INLINE void LDSMPR(sh4_state *sh4, UINT32 m)
+{
+ sh4->ea = sh4->r[m];
+ sh4->pr = RL(sh4, sh4->ea );
+ sh4->r[m] += 4;
+}
+
+/* MAC.L @Rm+,@Rn+ */
+INLINE void MAC_L(sh4_state *sh4, UINT32 m, UINT32 n)
+{
+ UINT32 RnL, RnH, RmL, RmH, Res0, Res1, Res2;
+ UINT32 temp0, temp1, temp2, temp3;
+ INT32 tempm, tempn, fnLmL;
+
+ tempn = (INT32) RL(sh4, sh4->r[n] );
+ sh4->r[n] += 4;
+ tempm = (INT32) RL(sh4, sh4->r[m] );
+ sh4->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 (sh4->sr & S)
+ {
+ Res0 = sh4->macl + Res0;
+ if (sh4->macl > Res0)
+ Res2++;
+ Res2 += (sh4->mach & 0x0000ffff);
+ if (((INT32) Res2 < 0) && (Res2 < 0xffff8000))
+ {
+ Res2 = 0x00008000;
+ Res0 = 0x00000000;
+ }
+ else if (((INT32) Res2 > 0) && (Res2 > 0x00007fff))
+ {
+ Res2 = 0x00007fff;
+ Res0 = 0xffffffff;
+ }
+ sh4->mach = Res2;
+ sh4->macl = Res0;
+ }
+ else
+ {
+ Res0 = sh4->macl + Res0;
+ if (sh4->macl > Res0)
+ Res2++;
+ Res2 += sh4->mach;
+ sh4->mach = Res2;
+ sh4->macl = Res0;
+ }
+ sh4->sh4_icount -= 2;
+}
+
+/* MAC.W @Rm+,@Rn+ */
+INLINE void MAC_W(sh4_state *sh4, UINT32 m, UINT32 n)
+{
+ INT32 tempm, tempn, dest, src, ans;
+ UINT32 templ;
+
+ tempn = (INT32) RW(sh4, sh4->r[n] );
+ sh4->r[n] += 2;
+ tempm = (INT32) RW(sh4, sh4->r[m] );
+ sh4->r[m] += 2;
+ templ = sh4->macl;
+ tempm = ((INT32) (short) tempn * (INT32) (short) tempm);
+ if ((INT32) sh4->macl >= 0)
+ dest = 0;
+ else
+ dest = 1;
+ if ((INT32) tempm >= 0)
+ {
+ src = 0;
+ tempn = 0;
+ }
+ else
+ {
+ src = 1;
+ tempn = 0xffffffff;
+ }
+ src += dest;
+ sh4->macl += tempm;
+ if ((INT32) sh4->macl >= 0)
+ ans = 0;
+ else
+ ans = 1;
+ ans += dest;
+ if (sh4->sr & S)
+ {
+ if (ans == 1)
+ {
+ if (src == 0)
+ sh4->macl = 0x7fffffff;
+ if (src == 2)
+ sh4->macl = 0x80000000;
+ }
+ }
+ else
+ {
+ sh4->mach += tempn;
+ if (templ > sh4->macl)
+ sh4->mach += 1;
+ }
+ sh4->sh4_icount -= 2;
+}
+
+/* MOV Rm,Rn */
+INLINE void MOV(sh4_state *sh4, UINT32 m, UINT32 n)
+{
+ sh4->r[n] = sh4->r[m];
+}
+
+/* MOV.B Rm,@Rn */
+INLINE void MOVBS(sh4_state *sh4, UINT32 m, UINT32 n)
+{
+ sh4->ea = sh4->r[n];
+ WB(sh4, sh4->ea, sh4->r[m] & 0x000000ff);
+}
+
+/* MOV.W Rm,@Rn */
+INLINE void MOVWS(sh4_state *sh4, UINT32 m, UINT32 n)
+{
+ sh4->ea = sh4->r[n];
+ WW(sh4, sh4->ea, sh4->r[m] & 0x0000ffff);
+}
+
+/* MOV.L Rm,@Rn */
+INLINE void MOVLS(sh4_state *sh4, UINT32 m, UINT32 n)
+{
+ sh4->ea = sh4->r[n];
+ WL(sh4, sh4->ea, sh4->r[m] );
+}
+
+/* MOV.B @Rm,Rn */
+INLINE void MOVBL(sh4_state *sh4, UINT32 m, UINT32 n)
+{
+ sh4->ea = sh4->r[m];
+ sh4->r[n] = (UINT32)(INT32)(INT16)(INT8) RB(sh4, sh4->ea );
+}
+
+/* MOV.W @Rm,Rn */
+INLINE void MOVWL(sh4_state *sh4, UINT32 m, UINT32 n)
+{
+ sh4->ea = sh4->r[m];
+ sh4->r[n] = (UINT32)(INT32)(INT16) RW(sh4, sh4->ea );
+}
+
+/* MOV.L @Rm,Rn */
+INLINE void MOVLL(sh4_state *sh4, UINT32 m, UINT32 n)
+{
+ sh4->ea = sh4->r[m];
+ sh4->r[n] = RL(sh4, sh4->ea );
+}
+
+/* MOV.B Rm,@-Rn */
+INLINE void MOVBM(sh4_state *sh4, UINT32 m, UINT32 n)
+{
+ /* SMG : bug fix, was reading sh4->r[n] */
+ UINT32 data = sh4->r[m] & 0x000000ff;
+
+ sh4->r[n] -= 1;
+ WB(sh4, sh4->r[n], data );
+}
+
+/* MOV.W Rm,@-Rn */
+INLINE void MOVWM(sh4_state *sh4, UINT32 m, UINT32 n)
+{
+ UINT32 data = sh4->r[m] & 0x0000ffff;
+
+ sh4->r[n] -= 2;
+ WW(sh4, sh4->r[n], data );
+}
+
+/* MOV.L Rm,@-Rn */
+INLINE void MOVLM(sh4_state *sh4, UINT32 m, UINT32 n)
+{
+ UINT32 data = sh4->r[m];
+
+ sh4->r[n] -= 4;
+ WL(sh4, sh4->r[n], data );
+}
+
+/* MOV.B @Rm+,Rn */
+INLINE void MOVBP(sh4_state *sh4, UINT32 m, UINT32 n)
+{
+ sh4->r[n] = (UINT32)(INT32)(INT16)(INT8) RB(sh4, sh4->r[m] );
+ if (n != m)
+ sh4->r[m] += 1;
+}
+
+/* MOV.W @Rm+,Rn */
+INLINE void MOVWP(sh4_state *sh4, UINT32 m, UINT32 n)
+{
+ sh4->r[n] = (UINT32)(INT32)(INT16) RW(sh4, sh4->r[m] );
+ if (n != m)
+ sh4->r[m] += 2;
+}
+
+/* MOV.L @Rm+,Rn */
+INLINE void MOVLP(sh4_state *sh4, UINT32 m, UINT32 n)
+{
+ sh4->r[n] = RL(sh4, sh4->r[m] );
+ if (n != m)
+ sh4->r[m] += 4;
+}
+
+/* MOV.B Rm,@(R0,Rn) */
+INLINE void MOVBS0(sh4_state *sh4, UINT32 m, UINT32 n)
+{
+ sh4->ea = sh4->r[n] + sh4->r[0];
+ WB(sh4, sh4->ea, sh4->r[m] & 0x000000ff );
+}
+
+/* MOV.W Rm,@(R0,Rn) */
+INLINE void MOVWS0(sh4_state *sh4, UINT32 m, UINT32 n)
+{
+ sh4->ea = sh4->r[n] + sh4->r[0];
+ WW(sh4, sh4->ea, sh4->r[m] & 0x0000ffff );
+}
+
+/* MOV.L Rm,@(R0,Rn) */
+INLINE void MOVLS0(sh4_state *sh4, UINT32 m, UINT32 n)
+{
+ sh4->ea = sh4->r[n] + sh4->r[0];
+ WL(sh4, sh4->ea, sh4->r[m] );
+}
+
+/* MOV.B @(R0,Rm),Rn */
+INLINE void MOVBL0(sh4_state *sh4, UINT32 m, UINT32 n)
+{
+ sh4->ea = sh4->r[m] + sh4->r[0];
+ sh4->r[n] = (UINT32)(INT32)(INT16)(INT8) RB(sh4, sh4->ea );
+}
+
+/* MOV.W @(R0,Rm),Rn */
+INLINE void MOVWL0(sh4_state *sh4, UINT32 m, UINT32 n)
+{
+ sh4->ea = sh4->r[m] + sh4->r[0];
+ sh4->r[n] = (UINT32)(INT32)(INT16) RW(sh4, sh4->ea );
+}
+
+/* MOV.L @(R0,Rm),Rn */
+INLINE void MOVLL0(sh4_state *sh4, UINT32 m, UINT32 n)
+{
+ sh4->ea = sh4->r[m] + sh4->r[0];
+ sh4->r[n] = RL(sh4, sh4->ea );
+}
+
+/* MOV #imm,Rn */
+INLINE void MOVI(sh4_state *sh4, UINT32 i, UINT32 n)
+{
+ sh4->r[n] = (UINT32)(INT32)(INT16)(INT8) i;
+}
+
+/* MOV.W @(disp8,PC),Rn */
+INLINE void MOVWI(sh4_state *sh4, UINT32 d, UINT32 n)
+{
+ UINT32 disp = d & 0xff;
+ sh4->ea = sh4->pc + disp * 2 + 2;
+ sh4->r[n] = (UINT32)(INT32)(INT16) RW(sh4, sh4->ea );
+}
+
+/* MOV.L @(disp8,PC),Rn */
+INLINE void MOVLI(sh4_state *sh4, UINT32 d, UINT32 n)
+{
+ UINT32 disp = d & 0xff;
+ sh4->ea = ((sh4->pc + 2) & ~3) + disp * 4;
+ sh4->r[n] = RL(sh4, sh4->ea );
+}
+
+/* MOV.B @(disp8,GBR),R0 */
+INLINE void MOVBLG(sh4_state *sh4, UINT32 d)
+{
+ UINT32 disp = d & 0xff;
+ sh4->ea = sh4->gbr + disp;
+ sh4->r[0] = (UINT32)(INT32)(INT16)(INT8) RB(sh4, sh4->ea );
+}
+
+/* MOV.W @(disp8,GBR),R0 */
+INLINE void MOVWLG(sh4_state *sh4, UINT32 d)
+{
+ UINT32 disp = d & 0xff;
+ sh4->ea = sh4->gbr + disp * 2;
+ sh4->r[0] = (INT32)(INT16) RW(sh4, sh4->ea );
+}
+
+/* MOV.L @(disp8,GBR),R0 */
+INLINE void MOVLLG(sh4_state *sh4, UINT32 d)
+{
+ UINT32 disp = d & 0xff;
+ sh4->ea = sh4->gbr + disp * 4;
+ sh4->r[0] = RL(sh4, sh4->ea );
+}
+
+/* MOV.B R0,@(disp8,GBR) */
+INLINE void MOVBSG(sh4_state *sh4, UINT32 d)
+{
+ UINT32 disp = d & 0xff;
+ sh4->ea = sh4->gbr + disp;
+ WB(sh4, sh4->ea, sh4->r[0] & 0x000000ff );
+}
+
+/* MOV.W R0,@(disp8,GBR) */
+INLINE void MOVWSG(sh4_state *sh4, UINT32 d)
+{
+ UINT32 disp = d & 0xff;
+ sh4->ea = sh4->gbr + disp * 2;
+ WW(sh4, sh4->ea, sh4->r[0] & 0x0000ffff );
+}
+
+/* MOV.L R0,@(disp8,GBR) */
+INLINE void MOVLSG(sh4_state *sh4, UINT32 d)
+{
+ UINT32 disp = d & 0xff;
+ sh4->ea = sh4->gbr + disp * 4;
+ WL(sh4, sh4->ea, sh4->r[0] );
+}
+
+/* MOV.B R0,@(disp4,Rn) */
+INLINE void MOVBS4(sh4_state *sh4, UINT32 d, UINT32 n)
+{
+ UINT32 disp = d & 0x0f;
+ sh4->ea = sh4->r[n] + disp;
+ WB(sh4, sh4->ea, sh4->r[0] & 0x000000ff );
+}
+
+/* MOV.W R0,@(disp4,Rn) */
+INLINE void MOVWS4(sh4_state *sh4, UINT32 d, UINT32 n)
+{
+ UINT32 disp = d & 0x0f;
+ sh4->ea = sh4->r[n] + disp * 2;
+ WW(sh4, sh4->ea, sh4->r[0] & 0x0000ffff );
+}
+
+/* MOV.L Rm,@(disp4,Rn) */
+INLINE void MOVLS4(sh4_state *sh4, UINT32 m, UINT32 d, UINT32 n)
+{
+ UINT32 disp = d & 0x0f;
+ sh4->ea = sh4->r[n] + disp * 4;
+ WL(sh4, sh4->ea, sh4->r[m] );
+}
+
+/* MOV.B @(disp4,Rm),R0 */
+INLINE void MOVBL4(sh4_state *sh4, UINT32 m, UINT32 d)
+{
+ UINT32 disp = d & 0x0f;
+ sh4->ea = sh4->r[m] + disp;
+ sh4->r[0] = (UINT32)(INT32)(INT16)(INT8) RB(sh4, sh4->ea );
+}
+
+/* MOV.W @(disp4,Rm),R0 */
+INLINE void MOVWL4(sh4_state *sh4, UINT32 m, UINT32 d)
+{
+ UINT32 disp = d & 0x0f;
+ sh4->ea = sh4->r[m] + disp * 2;
+ sh4->r[0] = (UINT32)(INT32)(INT16) RW(sh4, sh4->ea );
+}
+
+/* MOV.L @(disp4,Rm),Rn */
+INLINE void MOVLL4(sh4_state *sh4, UINT32 m, UINT32 d, UINT32 n)
+{
+ UINT32 disp = d & 0x0f;
+ sh4->ea = sh4->r[m] + disp * 4;
+ sh4->r[n] = RL(sh4, sh4->ea );
+}
+
+/* MOVA @(disp8,PC),R0 */
+INLINE void MOVA(sh4_state *sh4, UINT32 d)
+{
+ UINT32 disp = d & 0xff;
+ sh4->ea = ((sh4->pc + 2) & ~3) + disp * 4;
+ sh4->r[0] = sh4->ea;
+}
+
+/* MOVT Rn */
+INLINE void MOVT(sh4_state *sh4, UINT32 n)
+{
+ sh4->r[n] = sh4->sr & T;
+}
+
+/* MUL.L Rm,Rn */
+INLINE void MULL(sh4_state *sh4, UINT32 m, UINT32 n)
+{
+ sh4->macl = sh4->r[n] * sh4->r[m];
+ sh4->sh4_icount--;
+}
+
+/* MULS Rm,Rn */
+INLINE void MULS(sh4_state *sh4, UINT32 m, UINT32 n)
+{
+ sh4->macl = (INT16) sh4->r[n] * (INT16) sh4->r[m];
+}
+
+/* MULU Rm,Rn */
+INLINE void MULU(sh4_state *sh4, UINT32 m, UINT32 n)
+{
+ sh4->macl = (UINT16) sh4->r[n] * (UINT16) sh4->r[m];
+}
+
+/* NEG Rm,Rn */
+INLINE void NEG(sh4_state *sh4, UINT32 m, UINT32 n)
+{
+ sh4->r[n] = 0 - sh4->r[m];
+}
+
+/* NEGC Rm,Rn */
+INLINE void NEGC(sh4_state *sh4, UINT32 m, UINT32 n)
+{
+ UINT32 temp;
+
+ temp = sh4->r[m];
+ sh4->r[n] = -temp - (sh4->sr & T);
+ if (temp || (sh4->sr & T))
+ sh4->sr |= T;
+ else
+ sh4->sr &= ~T;
+}
+
+/* NOP */
+INLINE void NOP(sh4_state *sh4)
+{
+}
+
+/* NOT Rm,Rn */
+INLINE void NOT(sh4_state *sh4, UINT32 m, UINT32 n)
+{
+ sh4->r[n] = ~sh4->r[m];
+}
+
+/* OR Rm,Rn */
+INLINE void OR(sh4_state *sh4, UINT32 m, UINT32 n)
+{
+ sh4->r[n] |= sh4->r[m];
+}
+
+/* OR #imm,R0 */
+INLINE void ORI(sh4_state *sh4, UINT32 i)
+{
+ sh4->r[0] |= i;
+ sh4->sh4_icount -= 2;
+}
+
+/* OR.B #imm,@(R0,GBR) */
+INLINE void ORM(sh4_state *sh4, UINT32 i)
+{
+ UINT32 temp;
+
+ sh4->ea = sh4->gbr + sh4->r[0];
+ temp = RB(sh4, sh4->ea );
+ temp |= i;
+ WB(sh4, sh4->ea, temp );
+}
+
+/* ROTCL Rn */
+INLINE void ROTCL(sh4_state *sh4, UINT32 n)
+{
+ UINT32 temp;
+
+ temp = (sh4->r[n] >> 31) & T;
+ sh4->r[n] = (sh4->r[n] << 1) | (sh4->sr & T);
+ sh4->sr = (sh4->sr & ~T) | temp;
+}
+
+/* ROTCR Rn */
+INLINE void ROTCR(sh4_state *sh4, UINT32 n)
+{
+ UINT32 temp;
+ temp = (sh4->sr & T) << 31;
+ if (sh4->r[n] & T)
+ sh4->sr |= T;
+ else
+ sh4->sr &= ~T;
+ sh4->r[n] = (sh4->r[n] >> 1) | temp;
+}
+
+/* ROTL Rn */
+INLINE void ROTL(sh4_state *sh4, UINT32 n)
+{
+ sh4->sr = (sh4->sr & ~T) | ((sh4->r[n] >> 31) & T);
+ sh4->r[n] = (sh4->r[n] << 1) | (sh4->r[n] >> 31);
+}
+
+/* ROTR Rn */
+INLINE void ROTR(sh4_state *sh4, UINT32 n)
+{
+ sh4->sr = (sh4->sr & ~T) | (sh4->r[n] & T);
+ sh4->r[n] = (sh4->r[n] >> 1) | (sh4->r[n] << 31);
+}
+
+/* RTE */
+INLINE void RTE(sh4_state *sh4)
+{
+ sh4->delay = sh4->pc;
+ sh4->pc = sh4->ea = sh4->spc;
+ if ((sh4->device->machine().debug_flags & DEBUG_FLAG_ENABLED) != 0)
+ sh4_syncronize_register_bank(sh4, (sh4->sr & sRB) >> 29);
+ if ((sh4->ssr & sRB) != (sh4->sr & sRB))
+ sh4_change_register_bank(sh4, sh4->ssr & sRB ? 1 : 0);
+ sh4->sr = sh4->ssr;
+ sh4->sh4_icount--;
+ sh4_exception_recompute(sh4);
+}
+
+/* RTS */
+INLINE void RTS(sh4_state *sh4)
+{
+ sh4->delay = sh4->pc;
+ sh4->pc = sh4->ea = sh4->pr;
+ sh4->sh4_icount--;
+}
+
+/* SETT */
+INLINE void SETT(sh4_state *sh4)
+{
+ sh4->sr |= T;
+}
+
+/* SHAL Rn (same as SHLL) */
+INLINE void SHAL(sh4_state *sh4, UINT32 n)
+{
+ sh4->sr = (sh4->sr & ~T) | ((sh4->r[n] >> 31) & T);
+ sh4->r[n] <<= 1;
+}
+
+/* SHAR Rn */
+INLINE void SHAR(sh4_state *sh4, UINT32 n)
+{
+ sh4->sr = (sh4->sr & ~T) | (sh4->r[n] & T);
+ sh4->r[n] = (UINT32)((INT32)sh4->r[n] >> 1);
+}
+
+/* SHLL Rn (same as SHAL) */
+INLINE void SHLL(sh4_state *sh4, UINT32 n)
+{
+ sh4->sr = (sh4->sr & ~T) | ((sh4->r[n] >> 31) & T);
+ sh4->r[n] <<= 1;
+}
+
+/* SHLL2 Rn */
+INLINE void SHLL2(sh4_state *sh4, UINT32 n)
+{
+ sh4->r[n] <<= 2;
+}
+
+/* SHLL8 Rn */
+INLINE void SHLL8(sh4_state *sh4, UINT32 n)
+{
+ sh4->r[n] <<= 8;
+}
+
+/* SHLL16 Rn */
+INLINE void SHLL16(sh4_state *sh4, UINT32 n)
+{
+ sh4->r[n] <<= 16;
+}
+
+/* SHLR Rn */
+INLINE void SHLR(sh4_state *sh4, UINT32 n)
+{
+ sh4->sr = (sh4->sr & ~T) | (sh4->r[n] & T);
+ sh4->r[n] >>= 1;
+}
+
+/* SHLR2 Rn */
+INLINE void SHLR2(sh4_state *sh4, UINT32 n)
+{
+ sh4->r[n] >>= 2;
+}
+
+/* SHLR8 Rn */
+INLINE void SHLR8(sh4_state *sh4, UINT32 n)
+{
+ sh4->r[n] >>= 8;
+}
+
+/* SHLR16 Rn */
+INLINE void SHLR16(sh4_state *sh4, UINT32 n)
+{
+ sh4->r[n] >>= 16;
+}
+
+/* SLEEP */
+INLINE void SLEEP(sh4_state *sh4)
+{
+ /* 0 = normal mode */
+ /* 1 = enters into power-down mode */
+ /* 2 = go out the power-down mode after an exception */
+ if(sh4->sleep_mode != 2)
+ sh4->pc -= 2;
+ sh4->sh4_icount -= 2;
+ /* Wait_for_exception; */
+ if(sh4->sleep_mode == 0)
+ sh4->sleep_mode = 1;
+ else if(sh4->sleep_mode == 2)
+ sh4->sleep_mode = 0;
+}
+
+/* STC SR,Rn */
+INLINE void STCSR(sh4_state *sh4, UINT32 n)
+{
+ sh4->r[n] = sh4->sr;
+}
+
+/* STC GBR,Rn */
+INLINE void STCGBR(sh4_state *sh4, UINT32 n)
+{
+ sh4->r[n] = sh4->gbr;
+}
+
+/* STC VBR,Rn */
+INLINE void STCVBR(sh4_state *sh4, UINT32 n)
+{
+ sh4->r[n] = sh4->vbr;
+}
+
+/* STC.L SR,@-Rn */
+INLINE void STCMSR(sh4_state *sh4, UINT32 n)
+{
+ sh4->r[n] -= 4;
+ sh4->ea = sh4->r[n];
+ WL(sh4, sh4->ea, sh4->sr );
+ sh4->sh4_icount--;
+}
+
+/* STC.L GBR,@-Rn */
+INLINE void STCMGBR(sh4_state *sh4, UINT32 n)
+{
+ sh4->r[n] -= 4;
+ sh4->ea = sh4->r[n];
+ WL(sh4, sh4->ea, sh4->gbr );
+ sh4->sh4_icount--;
+}
+
+/* STC.L VBR,@-Rn */
+INLINE void STCMVBR(sh4_state *sh4, UINT32 n)
+{
+ sh4->r[n] -= 4;
+ sh4->ea = sh4->r[n];
+ WL(sh4, sh4->ea, sh4->vbr );
+ sh4->sh4_icount--;
+}
+
+/* STS MACH,Rn */
+INLINE void STSMACH(sh4_state *sh4, UINT32 n)
+{
+ sh4->r[n] = sh4->mach;
+}
+
+/* STS MACL,Rn */
+INLINE void STSMACL(sh4_state *sh4, UINT32 n)
+{
+ sh4->r[n] = sh4->macl;
+}
+
+/* STS PR,Rn */
+INLINE void STSPR(sh4_state *sh4, UINT32 n)
+{
+ sh4->r[n] = sh4->pr;
+}
+
+/* STS.L MACH,@-Rn */
+INLINE void STSMMACH(sh4_state *sh4, UINT32 n)
+{
+ sh4->r[n] -= 4;
+ sh4->ea = sh4->r[n];
+ WL(sh4, sh4->ea, sh4->mach );
+}
+
+/* STS.L MACL,@-Rn */
+INLINE void STSMMACL(sh4_state *sh4, UINT32 n)
+{
+ sh4->r[n] -= 4;
+ sh4->ea = sh4->r[n];
+ WL(sh4, sh4->ea, sh4->macl );
+}
+
+/* STS.L PR,@-Rn */
+INLINE void STSMPR(sh4_state *sh4, UINT32 n)
+{
+ sh4->r[n] -= 4;
+ sh4->ea = sh4->r[n];
+ WL(sh4, sh4->ea, sh4->pr );
+}
+
+/* SUB Rm,Rn */
+INLINE void SUB(sh4_state *sh4, UINT32 m, UINT32 n)
+{
+ sh4->r[n] -= sh4->r[m];
+}
+
+/* SUBC Rm,Rn */
+INLINE void SUBC(sh4_state *sh4, UINT32 m, UINT32 n)
+{
+ UINT32 tmp0, tmp1;
+
+ tmp1 = sh4->r[n] - sh4->r[m];
+ tmp0 = sh4->r[n];
+ sh4->r[n] = tmp1 - (sh4->sr & T);
+ if (tmp0 < tmp1)
+ sh4->sr |= T;
+ else
+ sh4->sr &= ~T;
+ if (tmp1 < sh4->r[n])
+ sh4->sr |= T;
+}
+
+/* SUBV Rm,Rn */
+INLINE void SUBV(sh4_state *sh4, UINT32 m, UINT32 n)
+{
+ INT32 dest, src, ans;
+
+ if ((INT32) sh4->r[n] >= 0)
+ dest = 0;
+ else
+ dest = 1;
+ if ((INT32) sh4->r[m] >= 0)
+ src = 0;
+ else
+ src = 1;
+ src += dest;
+ sh4->r[n] -= sh4->r[m];
+ if ((INT32) sh4->r[n] >= 0)
+ ans = 0;
+ else
+ ans = 1;
+ ans += dest;
+ if (src == 1)
+ {
+ if (ans == 1)
+ sh4->sr |= T;
+ else
+ sh4->sr &= ~T;
+ }
+ else
+ sh4->sr &= ~T;
+}
+
+/* SWAP.B Rm,Rn */
+INLINE void SWAPB(sh4_state *sh4, UINT32 m, UINT32 n)
+{
+ UINT32 temp0, temp1;
+
+ temp0 = sh4->r[m] & 0xffff0000;
+ temp1 = (sh4->r[m] & 0x000000ff) << 8;
+ sh4->r[n] = (sh4->r[m] >> 8) & 0x000000ff;
+ sh4->r[n] = sh4->r[n] | temp1 | temp0;
+}
+
+/* SWAP.W Rm,Rn */
+INLINE void SWAPW(sh4_state *sh4, UINT32 m, UINT32 n)
+{
+ UINT32 temp;
+
+ temp = (sh4->r[m] >> 16) & 0x0000ffff;
+ sh4->r[n] = (sh4->r[m] << 16) | temp;
+}
+
+/* TAS.B @Rn */
+INLINE void TAS(sh4_state *sh4, UINT32 n)
+{
+ UINT32 temp;
+ sh4->ea = sh4->r[n];
+ /* Bus Lock enable */
+ temp = RB(sh4, sh4->ea );
+ if (temp == 0)
+ sh4->sr |= T;
+ else
+ sh4->sr &= ~T;
+ temp |= 0x80;
+ /* Bus Lock disable */
+ WB(sh4, sh4->ea, temp );
+ sh4->sh4_icount -= 3;
+}
+
+/* TRAPA #imm */
+INLINE void TRAPA(sh4_state *sh4, UINT32 i)
+{
+ UINT32 imm = i & 0xff;
+
+ sh4->m[TRA] = imm;
+ sh4->ssr = sh4->sr;
+ sh4->spc = sh4->pc;
+ sh4->sgr = sh4->r[15];
+
+ sh4->sr |= MD;
+ if ((sh4->device->machine().debug_flags & DEBUG_FLAG_ENABLED) != 0)
+ sh4_syncronize_register_bank(sh4, (sh4->sr & sRB) >> 29);
+ if (!(sh4->sr & sRB))
+ sh4_change_register_bank(sh4, 1);
+ sh4->sr |= sRB;
+ sh4->sr |= BL;
+ sh4_exception_recompute(sh4);
+
+ sh4->m[EXPEVT] = 0x00000160;
+ sh4->pc = sh4->vbr + 0x00000100;
+
+ sh4->sh4_icount -= 7;
+}
+
+/* TST Rm,Rn */
+INLINE void TST(sh4_state *sh4, UINT32 m, UINT32 n)
+{
+ if ((sh4->r[n] & sh4->r[m]) == 0)
+ sh4->sr |= T;
+ else
+ sh4->sr &= ~T;
+}
+
+/* TST #imm,R0 */
+INLINE void TSTI(sh4_state *sh4, UINT32 i)
+{
+ UINT32 imm = i & 0xff;
+
+ if ((imm & sh4->r[0]) == 0)
+ sh4->sr |= T;
+ else
+ sh4->sr &= ~T;
+}
+
+/* TST.B #imm,@(R0,GBR) */
+INLINE void TSTM(sh4_state *sh4, UINT32 i)
+{
+ UINT32 imm = i & 0xff;
+
+ sh4->ea = sh4->gbr + sh4->r[0];
+ if ((imm & RB(sh4, sh4->ea )) == 0)
+ sh4->sr |= T;
+ else
+ sh4->sr &= ~T;
+ sh4->sh4_icount -= 2;
+}
+
+/* XOR Rm,Rn */
+INLINE void XOR(sh4_state *sh4, UINT32 m, UINT32 n)
+{
+ sh4->r[n] ^= sh4->r[m];
+}
+
+/* XOR #imm,R0 */
+INLINE void XORI(sh4_state *sh4, UINT32 i)
+{
+ UINT32 imm = i & 0xff;
+ sh4->r[0] ^= imm;
+}
+
+/* XOR.B #imm,@(R0,GBR) */
+INLINE void XORM(sh4_state *sh4, UINT32 i)
+{
+ UINT32 imm = i & 0xff;
+ UINT32 temp;
+
+ sh4->ea = sh4->gbr + sh4->r[0];
+ temp = RB(sh4, sh4->ea );
+ temp ^= imm;
+ WB(sh4, sh4->ea, temp );
+ sh4->sh4_icount -= 2;
+}
+
+/* XTRCT Rm,Rn */
+INLINE void XTRCT(sh4_state *sh4, UINT32 m, UINT32 n)
+{
+ UINT32 temp;
+
+ temp = (sh4->r[m] << 16) & 0xffff0000;
+ sh4->r[n] = (sh4->r[n] >> 16) & 0x0000ffff;
+ sh4->r[n] |= temp;
+}
+
+/* STC SSR,Rn */
+INLINE void STCSSR(sh4_state *sh4, UINT32 n)
+{
+ sh4->r[n] = sh4->ssr;
+}
+
+/* STC SPC,Rn */
+INLINE void STCSPC(sh4_state *sh4, UINT32 n)
+{
+ sh4->r[n] = sh4->spc;
+}
+
+/* STC SGR,Rn */
+INLINE void STCSGR(sh4_state *sh4, UINT32 n)
+{
+ sh4->r[n] = sh4->sgr;
+}
+
+/* STS FPUL,Rn */
+INLINE void STSFPUL(sh4_state *sh4, UINT32 n)
+{
+ sh4->r[n] = sh4->fpul;
+}
+
+/* STS FPSCR,Rn */
+INLINE void STSFPSCR(sh4_state *sh4, UINT32 n)
+{
+ sh4->r[n] = sh4->fpscr & 0x003FFFFF;
+}
+
+/* STC DBR,Rn */
+INLINE void STCDBR(sh4_state *sh4, UINT32 n)
+{
+ sh4->r[n] = sh4->dbr;
+}
+
+/* STCRBANK Rm_BANK,Rn */
+INLINE void STCRBANK(sh4_state *sh4, UINT32 m, UINT32 n)
+{
+ sh4->r[n] = sh4->rbnk[sh4->sr&sRB ? 0 : 1][m & 7];
+}
+
+/* STCMRBANK Rm_BANK,@-Rn */
+INLINE void STCMRBANK(sh4_state *sh4, UINT32 m, UINT32 n)
+{
+ sh4->r[n] -= 4;
+ sh4->ea = sh4->r[n];
+ WL(sh4, sh4->ea, sh4->rbnk[sh4->sr&sRB ? 0 : 1][m & 7]);
+ sh4->sh4_icount--;
+}
+
+/* MOVCA.L R0,@Rn */
+INLINE void MOVCAL(sh4_state *sh4, UINT32 n)
+{
+ sh4->ea = sh4->r[n];
+ WL(sh4, sh4->ea, sh4->r[0] );
+}
+
+INLINE void CLRS(sh4_state *sh4)
+{
+ sh4->sr &= ~S;
+}
+
+INLINE void SETS(sh4_state *sh4)
+{
+ sh4->sr |= S;
+}
+
+/* STS.L SGR,@-Rn */
+INLINE void STCMSGR(sh4_state *sh4, UINT32 n)
+{
+ sh4->r[n] -= 4;
+ sh4->ea = sh4->r[n];
+ WL(sh4, sh4->ea, sh4->sgr );
+}
+
+/* STS.L FPUL,@-Rn */
+INLINE void STSMFPUL(sh4_state *sh4, UINT32 n)
+{
+ sh4->r[n] -= 4;
+ sh4->ea = sh4->r[n];
+ WL(sh4, sh4->ea, sh4->fpul );
+}
+
+/* STS.L FPSCR,@-Rn */
+INLINE void STSMFPSCR(sh4_state *sh4, UINT32 n)
+{
+ sh4->r[n] -= 4;
+ sh4->ea = sh4->r[n];
+ WL(sh4, sh4->ea, sh4->fpscr & 0x003FFFFF);
+}
+
+/* STC.L DBR,@-Rn */
+INLINE void STCMDBR(sh4_state *sh4, UINT32 n)
+{
+ sh4->r[n] -= 4;
+ sh4->ea = sh4->r[n];
+ WL(sh4, sh4->ea, sh4->dbr );
+}
+
+/* STC.L SSR,@-Rn */
+INLINE void STCMSSR(sh4_state *sh4, UINT32 n)
+{
+ sh4->r[n] -= 4;
+ sh4->ea = sh4->r[n];
+ WL(sh4, sh4->ea, sh4->ssr );
+}
+
+/* STC.L SPC,@-Rn */
+INLINE void STCMSPC(sh4_state *sh4, UINT32 n)
+{
+ sh4->r[n] -= 4;
+ sh4->ea = sh4->r[n];
+ WL(sh4, sh4->ea, sh4->spc );
+}
+
+/* LDS.L @Rm+,FPUL */
+INLINE void LDSMFPUL(sh4_state *sh4, UINT32 m)
+{
+ sh4->ea = sh4->r[m];
+ sh4->fpul = RL(sh4, sh4->ea );
+ sh4->r[m] += 4;
+}
+
+/* LDS.L @Rm+,FPSCR */
+INLINE void LDSMFPSCR(sh4_state *sh4, UINT32 m)
+{
+UINT32 s;
+
+ s = sh4->fpscr;
+ sh4->ea = sh4->r[m];
+ sh4->fpscr = RL(sh4, sh4->ea );
+ sh4->fpscr &= 0x003FFFFF;
+ sh4->r[m] += 4;
+ if ((s & FR) != (sh4->fpscr & FR))
+ sh4_swap_fp_registers(sh4);
+#ifdef LSB_FIRST
+ if ((s & PR) != (sh4->fpscr & PR))
+ sh4_swap_fp_couples(sh4);
+#endif
+ sh4->fpu_sz = (sh4->fpscr & SZ) ? 1 : 0;
+ sh4->fpu_pr = (sh4->fpscr & PR) ? 1 : 0;
+}
+
+/* LDC.L @Rm+,DBR */
+INLINE void LDCMDBR(sh4_state *sh4, UINT32 m)
+{
+ sh4->ea = sh4->r[m];
+ sh4->dbr = RL(sh4, sh4->ea );
+ sh4->r[m] += 4;
+}
+
+/* LDC.L @Rn+,Rm_BANK */
+INLINE void LDCMRBANK(sh4_state *sh4, UINT32 m, UINT32 n)
+{
+ sh4->ea = sh4->r[n];
+ sh4->rbnk[sh4->sr&sRB ? 0 : 1][m & 7] = RL(sh4, sh4->ea );
+ sh4->r[n] += 4;
+}
+
+/* LDC.L @Rm+,SSR */
+INLINE void LDCMSSR(sh4_state *sh4, UINT32 m)
+{
+ sh4->ea = sh4->r[m];
+ sh4->ssr = RL(sh4, sh4->ea );
+ sh4->r[m] += 4;
+}
+
+/* LDC.L @Rm+,SPC */
+INLINE void LDCMSPC(sh4_state *sh4, UINT32 m)
+{
+ sh4->ea = sh4->r[m];
+ sh4->spc = RL(sh4, sh4->ea );
+ sh4->r[m] += 4;
+}
+
+/* LDS Rm,FPUL */
+INLINE void LDSFPUL(sh4_state *sh4, UINT32 m)
+{
+ sh4->fpul = sh4->r[m];
+}
+
+/* LDS Rm,FPSCR */
+INLINE void LDSFPSCR(sh4_state *sh4, UINT32 m)
+{
+UINT32 s;
+
+ s = sh4->fpscr;
+ sh4->fpscr = sh4->r[m] & 0x003FFFFF;
+ if ((s & FR) != (sh4->fpscr & FR))
+ sh4_swap_fp_registers(sh4);
+#ifdef LSB_FIRST
+ if ((s & PR) != (sh4->fpscr & PR))
+ sh4_swap_fp_couples(sh4);
+#endif
+ sh4->fpu_sz = (sh4->fpscr & SZ) ? 1 : 0;
+ sh4->fpu_pr = (sh4->fpscr & PR) ? 1 : 0;
+}
+
+/* LDC Rm,DBR */
+INLINE void LDCDBR(sh4_state *sh4, UINT32 m)
+{
+ sh4->dbr = sh4->r[m];
+}
+
+/* SHAD Rm,Rn */
+INLINE void SHAD(sh4_state *sh4, UINT32 m,UINT32 n)
+{
+ if ((sh4->r[m] & 0x80000000) == 0)
+ sh4->r[n] = sh4->r[n] << (sh4->r[m] & 0x1F);
+ else if ((sh4->r[m] & 0x1F) == 0) {
+ if ((sh4->r[n] & 0x80000000) == 0)
+ sh4->r[n] = 0;
+ else
+ sh4->r[n] = 0xFFFFFFFF;
+ } else
+ sh4->r[n]=(INT32)sh4->r[n] >> ((~sh4->r[m] & 0x1F)+1);
+}
+
+/* SHLD Rm,Rn */
+INLINE void SHLD(sh4_state *sh4, UINT32 m,UINT32 n)
+{
+ if ((sh4->r[m] & 0x80000000) == 0)
+ sh4->r[n] = sh4->r[n] << (sh4->r[m] & 0x1F);
+ else if ((sh4->r[m] & 0x1F) == 0)
+ sh4->r[n] = 0;
+ else
+ sh4->r[n] = sh4->r[n] >> ((~sh4->r[m] & 0x1F)+1);
+}
+
+/* LDCRBANK Rn,Rm_BANK */
+INLINE void LDCRBANK(sh4_state *sh4, UINT32 m, UINT32 n)
+{
+ sh4->rbnk[sh4->sr&sRB ? 0 : 1][m & 7] = sh4->r[n];
+}
+
+/* LDC Rm,SSR */
+INLINE void LDCSSR(sh4_state *sh4, UINT32 m)
+{
+ sh4->ssr = sh4->r[m];
+}
+
+/* LDC Rm,SPC */
+INLINE void LDCSPC(sh4_state *sh4, UINT32 m)
+{
+ sh4->spc = sh4->r[m];
+}
+
+/* PREF @Rn */
+INLINE void PREFM(sh4_state *sh4, UINT32 n)
+{
+ int a;
+ UINT32 addr,dest,sq;
+
+ addr = sh4->r[n]; // address
+ if ((addr >= 0xE0000000) && (addr <= 0xE3FFFFFF))
+ {
+ if (sh4->sh4_mmu_enabled)
+ {
+ addr = addr & 0xFFFFFFE0;
+ dest = sh4_getsqremap(sh4, addr); // good enough for naomi-gd rom, probably not much else
+
+ }
+ else
+ {
+ sq = (addr & 0x20) >> 5;
+ dest = addr & 0x03FFFFE0;
+ if (sq == 0)
+ dest |= (sh4->m[QACR0] & 0x1C) << 24;
+ else
+ dest |= (sh4->m[QACR1] & 0x1C) << 24;
+ addr = addr & 0xFFFFFFE0;
+ }
+
+ for (a = 0;a < 4;a++)
+ {
+ // shouldn't be causing a memory read, should store sq writes in registers.
+ sh4->program->write_qword(dest, sh4->program->read_qword(addr));
+ addr += 8;
+ dest += 8;
+ }
+ }
+}
+
+/*****************************************************************************
+ * OPCODE DISPATCHERS
+ *****************************************************************************/
+INLINE void op0000(sh4_state *sh4, UINT16 opcode)
+{
+ switch (opcode & 0xF)
+ {
+ case 0x0:
+ case 0x1:
+ break;
+ case 0x2:
+ if (opcode & 0x80) {
+ STCRBANK(sh4, Rm, Rn); return;
+ }
+ switch (opcode & 0x70)
+ {
+ case 0x00:
+ STCSR(sh4, Rn); break;
+ case 0x10:
+ STCGBR(sh4, Rn); break;
+ case 0x20:
+ STCVBR(sh4, Rn); break;
+ case 0x30:
+ STCSSR(sh4, Rn); break;
+ case 0x40:
+ STCSPC(sh4, Rn); break;
+ }
+ break;
+ case 0x3:
+ switch (opcode & 0xF0)
+ {
+ case 0x00:
+ BSRF(sh4, Rn); break;
+ case 0x20:
+ BRAF(sh4, Rn); break;
+ case 0x80:
+ PREFM(sh4, Rn); break;
+ case 0x90:
+ TODO(sh4); break;
+ case 0xA0:
+ TODO(sh4); break;
+ case 0xB0:
+ TODO(sh4); break;
+ case 0xC0:
+ MOVCAL(sh4, Rn); break;
+ }
+ break;
+ case 0x4:
+ MOVBS0(sh4, Rm, Rn); break;
+ case 0x5:
+ MOVWS0(sh4, Rm, Rn); break;
+ case 0x6:
+ MOVLS0(sh4, Rm, Rn); break;
+ case 0x7:
+ MULL(sh4, Rm, Rn); break;
+ case 0x8:
+ switch (opcode & 0x70)
+ {
+ case 0x00:
+ CLRT(sh4); break;
+ case 0x10:
+ SETT(sh4); break;
+ case 0x20:
+ CLRMAC(sh4); break;
+ case 0x30:
+ TODO(sh4); break;
+ case 0x40:
+ CLRS(sh4); break;
+ case 0x50:
+ SETS(sh4); break;
+ }
+ break;
+ case 0x9:
+ switch (opcode & 0x30)
+ {
+ case 0x00:
+ NOP(sh4); break;
+ case 0x10:
+ DIV0U(sh4); break;
+ case 0x20:
+ MOVT(sh4, Rn); break;
+ }
+ break;
+ case 0xA:
+ switch (opcode & 0x70)
+ {
+ case 0x00:
+ STSMACH(sh4, Rn); break;
+ case 0x10:
+ STSMACL(sh4, Rn); break;
+ case 0x20:
+ STSPR(sh4, Rn); break;
+ case 0x30:
+ STCSGR(sh4, Rn); break;
+ case 0x50:
+ STSFPUL(sh4, Rn); break;
+ case 0x60:
+ STSFPSCR(sh4, Rn); break;
+ case 0x70:
+ STCDBR(sh4, Rn); break;
+ }
+ break;
+ case 0xB:
+ switch (opcode & 0x30)
+ {
+ case 0x00:
+ RTS(sh4); break;
+ case 0x10:
+ SLEEP(sh4); break;
+ case 0x20:
+ RTE(sh4); break;
+ }
+ break;
+ case 0xC:
+ MOVBL0(sh4, Rm, Rn); break;
+ case 0xD:
+ MOVWL0(sh4, Rm, Rn); break;
+ case 0xE:
+ MOVLL0(sh4, Rm, Rn); break;
+ case 0xF:
+ MAC_L(sh4, Rm, Rn); break;
+ }
+}
+
+INLINE void op0001(sh4_state *sh4, UINT16 opcode)
+{
+ MOVLS4(sh4, Rm, opcode & 0x0f, Rn);
+}
+
+INLINE void op0010(sh4_state *sh4, UINT16 opcode)
+{
+ switch (opcode & 15)
+ {
+ case 0: MOVBS(sh4, Rm, Rn); break;
+ case 1: MOVWS(sh4, Rm, Rn); break;
+ case 2: MOVLS(sh4, Rm, Rn); break;
+ case 3: NOP(sh4); break;
+ case 4: MOVBM(sh4, Rm, Rn); break;
+ case 5: MOVWM(sh4, Rm, Rn); break;
+ case 6: MOVLM(sh4, Rm, Rn); break;
+ case 7: DIV0S(sh4, Rm, Rn); break;
+ case 8: TST(sh4, Rm, Rn); break;
+ case 9: AND(sh4, Rm, Rn); break;
+ case 10: XOR(sh4, Rm, Rn); break;
+ case 11: OR(sh4, Rm, Rn); break;
+ case 12: CMPSTR(sh4, Rm, Rn); break;
+ case 13: XTRCT(sh4, Rm, Rn); break;
+ case 14: MULU(sh4, Rm, Rn); break;
+ case 15: MULS(sh4, Rm, Rn); break;
+ }
+}
+
+INLINE void op0011(sh4_state *sh4, UINT16 opcode)
+{
+ switch (opcode & 15)
+ {
+ case 0: CMPEQ(sh4, Rm, Rn); break;
+ case 1: NOP(sh4); break;
+ case 2: CMPHS(sh4, Rm, Rn); break;
+ case 3: CMPGE(sh4, Rm, Rn); break;
+ case 4: DIV1(sh4, Rm, Rn); break;
+ case 5: DMULU(sh4, Rm, Rn); break;
+ case 6: CMPHI(sh4, Rm, Rn); break;
+ case 7: CMPGT(sh4, Rm, Rn); break;
+ case 8: SUB(sh4, Rm, Rn); break;
+ case 9: NOP(sh4); break;
+ case 10: SUBC(sh4, Rm, Rn); break;
+ case 11: SUBV(sh4, Rm, Rn); break;
+ case 12: ADD(sh4, Rm, Rn); break;
+ case 13: DMULS(sh4, Rm, Rn); break;
+ case 14: ADDC(sh4, Rm, Rn); break;
+ case 15: ADDV(sh4, Rm, Rn); break;
+ }
+}
+
+INLINE void op0100(sh4_state *sh4, UINT16 opcode)
+{
+ switch (opcode & 0xF)
+ {
+ case 0x0:
+ switch (opcode & 0x30)
+ {
+ case 0x00:
+ SHLL(sh4, Rn); break;
+ case 0x10:
+ DT(sh4, Rn); break;
+ case 0x20:
+ SHAL(sh4, Rn); break;
+ }
+ break;
+ case 0x1:
+ switch (opcode & 0x30)
+ {
+ case 0x00:
+ SHLR(sh4, Rn); break;
+ case 0x10:
+ CMPPZ(sh4, Rn); break;
+ case 0x20:
+ SHAR(sh4, Rn); break;
+ }
+ break;
+ case 0x2:
+ switch (opcode & 0xF0)
+ {
+ case 0x00:
+ STSMMACH(sh4, Rn); break;
+ case 0x10:
+ STSMMACL(sh4, Rn); break;
+ case 0x20:
+ STSMPR(sh4, Rn); break;
+ case 0x30:
+ STCMSGR(sh4, Rn); break;
+ case 0x50:
+ STSMFPUL(sh4, Rn); break;
+ case 0x60:
+ STSMFPSCR(sh4, Rn); break;
+ case 0xF0:
+ STCMDBR(sh4, Rn); break;
+ }
+ break;
+ case 0x3:
+ if (opcode & 0x80) {
+ STCMRBANK(sh4, Rm, Rn); return;
+ }
+ switch (opcode & 0x70)
+ {
+ case 0x00:
+ STCMSR(sh4, Rn); break;
+ case 0x10:
+ STCMGBR(sh4, Rn); break;
+ case 0x20:
+ STCMVBR(sh4, Rn); break;
+ case 0x30:
+ STCMSSR(sh4, Rn); break;
+ case 0x40:
+ STCMSPC(sh4, Rn); break;
+ }
+ break;
+ case 0x4:
+ switch (opcode & 0x30)
+ {
+ case 0x00:
+ ROTL(sh4, Rn); break;
+ case 0x20:
+ ROTCL(sh4, Rn); break;
+ }
+ break;
+ case 0x5:
+ switch (opcode & 0x30)
+ {
+ case 0x00:
+ ROTR(sh4, Rn); break;
+ case 0x10:
+ CMPPL(sh4, Rn); break;
+ case 0x20:
+ ROTCR(sh4, Rn); break;
+ }
+ break;
+ case 0x6:
+ switch (opcode & 0xF0)
+ {
+ case 0x00:
+ LDSMMACH(sh4, Rn); break;
+ case 0x10:
+ LDSMMACL(sh4, Rn); break;
+ case 0x20:
+ LDSMPR(sh4, Rn); break;
+ case 0x50:
+ LDSMFPUL(sh4, Rn); break;
+ case 0x60:
+ LDSMFPSCR(sh4, Rn); break;
+ case 0xF0:
+ LDCMDBR(sh4, Rn); break;
+ }
+ break;
+ case 0x7:
+ if (opcode & 0x80) {
+ LDCMRBANK(sh4, Rm,Rn); return;
+ }
+ switch (opcode & 0x70)
+ {
+ case 0x00:
+ LDCMSR(sh4, Rn); break;
+ case 0x10:
+ LDCMGBR(sh4, Rn); break;
+ case 0x20:
+ LDCMVBR(sh4, Rn); break;
+ case 0x30:
+ LDCMSSR(sh4, Rn); break;
+ case 0x40:
+ LDCMSPC(sh4, Rn); break;
+ }
+ break;
+ case 0x8:
+ switch (opcode & 0x30)
+ {
+ case 0x00:
+ SHLL2(sh4, Rn); break;
+ case 0x10:
+ SHLL8(sh4, Rn); break;
+ case 0x20:
+ SHLL16(sh4, Rn); break;
+ }
+ break;
+ case 0x9:
+ switch (opcode & 0x30)
+ {
+ case 0x00:
+ SHLR2(sh4, Rn); break;
+ case 0x10:
+ SHLR8(sh4, Rn); break;
+ case 0x20:
+ SHLR16(sh4, Rn); break;
+ }
+ break;
+ case 0xA:
+ switch (opcode & 0xF0)
+ {
+ case 0x00:
+ LDSMACH(sh4, Rn); break;
+ case 0x10:
+ LDSMACL(sh4, Rn); break;
+ case 0x20:
+ LDSPR(sh4, Rn); break;
+ case 0x50:
+ LDSFPUL(sh4, Rn); break;
+ case 0x60:
+ LDSFPSCR(sh4, Rn); break;
+ case 0xF0:
+ LDCDBR(sh4, Rn); break;
+ }
+ break;
+ case 0xB:
+ switch (opcode & 0x30)
+ {
+ case 0x00:
+ JSR(sh4, Rn); break;
+ case 0x10:
+ TAS(sh4, Rn); break;
+ case 0x20:
+ JMP(sh4, Rn); break;
+ }
+ break;
+ case 0xC:
+ SHAD(sh4, Rm,Rn); break;
+ case 0xD:
+ SHLD(sh4, Rm,Rn); break;
+ case 0xE:
+ if (opcode & 0x80) {
+ LDCRBANK(sh4, Rm,Rn); return;
+ }
+ switch (opcode & 0x70)
+ {
+ case 0x00:
+ LDCSR(sh4, Rn); break;
+ case 0x10:
+ LDCGBR(sh4, Rn); break;
+ case 0x20:
+ LDCVBR(sh4, Rn); break;
+ case 0x30:
+ LDCSSR(sh4, Rn); break;
+ case 0x40:
+ LDCSPC(sh4, Rn); break;
+ }
+ break;
+ case 0xF:
+ MAC_W(sh4, Rm, Rn); break;
+ }
+}
+
+INLINE void op0101(sh4_state *sh4, UINT16 opcode)
+{
+ MOVLL4(sh4, Rm, opcode & 0x0f, Rn);
+}
+
+INLINE void op0110(sh4_state *sh4, UINT16 opcode)
+{
+ switch (opcode & 15)
+ {
+ case 0: MOVBL(sh4, Rm, Rn); break;
+ case 1: MOVWL(sh4, Rm, Rn); break;
+ case 2: MOVLL(sh4, Rm, Rn); break;
+ case 3: MOV(sh4, Rm, Rn); break;
+ case 4: MOVBP(sh4, Rm, Rn); break;
+ case 5: MOVWP(sh4, Rm, Rn); break;
+ case 6: MOVLP(sh4, Rm, Rn); break;
+ case 7: NOT(sh4, Rm, Rn); break;
+ case 8: SWAPB(sh4, Rm, Rn); break;
+ case 9: SWAPW(sh4, Rm, Rn); break;
+ case 10: NEGC(sh4, Rm, Rn); break;
+ case 11: NEG(sh4, Rm, Rn); break;
+ case 12: EXTUB(sh4, Rm, Rn); break;
+ case 13: EXTUW(sh4, Rm, Rn); break;
+ case 14: EXTSB(sh4, Rm, Rn); break;
+ case 15: EXTSW(sh4, Rm, Rn); break;
+ }
+}
+
+INLINE void op0111(sh4_state *sh4, UINT16 opcode)
+{
+ ADDI(sh4, opcode & 0xff, Rn);
+}
+
+INLINE void op1000(sh4_state *sh4, UINT16 opcode)
+{
+ switch ( opcode & (15<<8) )
+ {
+ case 0 << 8: MOVBS4(sh4, opcode & 0x0f, Rm); break;
+ case 1 << 8: MOVWS4(sh4, opcode & 0x0f, Rm); break;
+ case 2<< 8: NOP(sh4); break;
+ case 3<< 8: NOP(sh4); break;
+ case 4<< 8: MOVBL4(sh4, Rm, opcode & 0x0f); break;
+ case 5<< 8: MOVWL4(sh4, Rm, opcode & 0x0f); break;
+ case 6<< 8: NOP(sh4); break;
+ case 7<< 8: NOP(sh4); break;
+ case 8<< 8: CMPIM(sh4, opcode & 0xff); break;
+ case 9<< 8: BT(sh4, opcode & 0xff); break;
+ case 10<< 8: NOP(sh4); break;
+ case 11<< 8: BF(sh4, opcode & 0xff); break;
+ case 12<< 8: NOP(sh4); break;
+ case 13<< 8: BTS(sh4, opcode & 0xff); break;
+ case 14<< 8: NOP(sh4); break;
+ case 15<< 8: BFS(sh4, opcode & 0xff); break;
+ }
+}
+
+
+INLINE void op1001(sh4_state *sh4, UINT16 opcode)
+{
+ MOVWI(sh4, opcode & 0xff, Rn);
+}
+
+INLINE void op1010(sh4_state *sh4, UINT16 opcode)
+{
+ BRA(sh4, opcode & 0xfff);
+}
+
+INLINE void op1011(sh4_state *sh4, UINT16 opcode)
+{
+ BSR(sh4, opcode & 0xfff);
+}
+
+INLINE void op1100(sh4_state *sh4, UINT16 opcode)
+{
+ switch (opcode & (15<<8))
+ {
+ case 0<<8: MOVBSG(sh4, opcode & 0xff); break;
+ case 1<<8: MOVWSG(sh4, opcode & 0xff); break;
+ case 2<<8: MOVLSG(sh4, opcode & 0xff); break;
+ case 3<<8: TRAPA(sh4, opcode & 0xff); break;
+ case 4<<8: MOVBLG(sh4, opcode & 0xff); break;
+ case 5<<8: MOVWLG(sh4, opcode & 0xff); break;
+ case 6<<8: MOVLLG(sh4, opcode & 0xff); break;
+ case 7<<8: MOVA(sh4, opcode & 0xff); break;
+ case 8<<8: TSTI(sh4, opcode & 0xff); break;
+ case 9<<8: ANDI(sh4, opcode & 0xff); break;
+ case 10<<8: XORI(sh4, opcode & 0xff); break;
+ case 11<<8: ORI(sh4, opcode & 0xff); break;
+ case 12<<8: TSTM(sh4, opcode & 0xff); break;
+ case 13<<8: ANDM(sh4, opcode & 0xff); break;
+ case 14<<8: XORM(sh4, opcode & 0xff); break;
+ case 15<<8: ORM(sh4, opcode & 0xff); break;
+ }
+}
+
+INLINE void op1101(sh4_state *sh4, UINT16 opcode)
+{
+ MOVLI(sh4, opcode & 0xff, Rn);
+}
+
+INLINE void op1110(sh4_state *sh4, UINT16 opcode)
+{
+ MOVI(sh4, opcode & 0xff, Rn);
+}
+
+/* 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 FMOVMRIFR(sh4_state *sh4, UINT32 m,UINT32 n)
+{
+ if (sh4->fpu_pr) { /* PR = 1 */
+ n = n & 14;
+ sh4->ea = sh4->r[m];
+ sh4->r[m] += 8;
+ sh4->xf[n+NATIVE_ENDIAN_VALUE_LE_BE(1,0)] = RL(sh4, sh4->ea );
+ sh4->xf[n+NATIVE_ENDIAN_VALUE_LE_BE(0,1)] = RL(sh4, sh4->ea+4 );
+ } else { /* PR = 0 */
+ if (sh4->fpu_sz) { /* SZ = 1 */
+ if (n & 1) {
+ n = n & 14;
+ sh4->ea = sh4->r[m];
+ sh4->xf[n] = RL(sh4, sh4->ea );
+ sh4->r[m] += 4;
+ sh4->xf[n+1] = RL(sh4, sh4->ea+4 );
+ sh4->r[m] += 4;
+ } else {
+ sh4->ea = sh4->r[m];
+ sh4->fr[n] = RL(sh4, sh4->ea );
+ sh4->r[m] += 4;
+ sh4->fr[n+1] = RL(sh4, sh4->ea+4 );
+ sh4->r[m] += 4;
+ }
+ } else { /* SZ = 0 */
+ sh4->ea = sh4->r[m];
+ sh4->fr[n] = RL(sh4, sh4->ea );
+ sh4->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 FMOVFRMR(sh4_state *sh4,UINT32 m,UINT32 n)
+{
+ if (sh4->fpu_pr) { /* PR = 1 */
+ m= m & 14;
+ sh4->ea = sh4->r[n];
+ WL(sh4, sh4->ea,sh4->xf[m+NATIVE_ENDIAN_VALUE_LE_BE(1,0)] );
+ WL(sh4, sh4->ea+4,sh4->xf[m+NATIVE_ENDIAN_VALUE_LE_BE(0,1)] );
+ } else { /* PR = 0 */
+ if (sh4->fpu_sz) { /* SZ = 1 */
+ if (m & 1) {
+ m= m & 14;
+ sh4->ea = sh4->r[n];
+ WL(sh4, sh4->ea,sh4->xf[m] );
+ WL(sh4, sh4->ea+4,sh4->xf[m+1] );
+ } else {
+ sh4->ea = sh4->r[n];
+ WL(sh4, sh4->ea,sh4->fr[m] );
+ WL(sh4, sh4->ea+4,sh4->fr[m+1] );
+ }
+ } else { /* SZ = 0 */
+ sh4->ea = sh4->r[n];
+ WL(sh4, sh4->ea,sh4->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 FMOVFRMDR(sh4_state *sh4,UINT32 m,UINT32 n)
+{
+ if (sh4->fpu_pr) { /* PR = 1 */
+ m= m & 14;
+ sh4->r[n] -= 8;
+ sh4->ea = sh4->r[n];
+ WL(sh4, sh4->ea,sh4->xf[m+NATIVE_ENDIAN_VALUE_LE_BE(1,0)] );
+ WL(sh4, sh4->ea+4,sh4->xf[m+NATIVE_ENDIAN_VALUE_LE_BE(0,1)] );
+ } else { /* PR = 0 */
+ if (sh4->fpu_sz) { /* SZ = 1 */
+ if (m & 1) {
+ m= m & 14;
+ sh4->r[n] -= 8;
+ sh4->ea = sh4->r[n];
+ WL(sh4, sh4->ea,sh4->xf[m] );
+ WL(sh4, sh4->ea+4,sh4->xf[m+1] );
+ } else {
+ sh4->r[n] -= 8;
+ sh4->ea = sh4->r[n];
+ WL(sh4, sh4->ea,sh4->fr[m] );
+ WL(sh4, sh4->ea+4,sh4->fr[m+1] );
+ }
+ } else { /* SZ = 0 */
+ sh4->r[n] -= 4;
+ sh4->ea = sh4->r[n];
+ WL(sh4, sh4->ea,sh4->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 FMOVFRS0(sh4_state *sh4,UINT32 m,UINT32 n)
+{
+ if (sh4->fpu_pr) { /* PR = 1 */
+ m= m & 14;
+ sh4->ea = sh4->r[0] + sh4->r[n];
+ WL(sh4, sh4->ea,sh4->xf[m+NATIVE_ENDIAN_VALUE_LE_BE(1,0)] );
+ WL(sh4, sh4->ea+4,sh4->xf[m+NATIVE_ENDIAN_VALUE_LE_BE(0,1)] );
+ } else { /* PR = 0 */
+ if (sh4->fpu_sz) { /* SZ = 1 */
+ if (m & 1) {
+ m= m & 14;
+ sh4->ea = sh4->r[0] + sh4->r[n];
+ WL(sh4, sh4->ea,sh4->xf[m] );
+ WL(sh4, sh4->ea+4,sh4->xf[m+1] );
+ } else {
+ sh4->ea = sh4->r[0] + sh4->r[n];
+ WL(sh4, sh4->ea,sh4->fr[m] );
+ WL(sh4, sh4->ea+4,sh4->fr[m+1] );
+ }
+ } else { /* SZ = 0 */
+ sh4->ea = sh4->r[0] + sh4->r[n];
+ WL(sh4, sh4->ea,sh4->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 FMOVS0FR(sh4_state *sh4,UINT32 m,UINT32 n)
+{
+ if (sh4->fpu_pr) { /* PR = 1 */
+ n= n & 14;
+ sh4->ea = sh4->r[0] + sh4->r[m];
+ sh4->xf[n+NATIVE_ENDIAN_VALUE_LE_BE(1,0)] = RL(sh4, sh4->ea );
+ sh4->xf[n+NATIVE_ENDIAN_VALUE_LE_BE(0,1)] = RL(sh4, sh4->ea+4 );
+ } else { /* PR = 0 */
+ if (sh4->fpu_sz) { /* SZ = 1 */
+ if (n & 1) {
+ n= n & 14;
+ sh4->ea = sh4->r[0] + sh4->r[m];
+ sh4->xf[n] = RL(sh4, sh4->ea );
+ sh4->xf[n+1] = RL(sh4, sh4->ea+4 );
+ } else {
+ sh4->ea = sh4->r[0] + sh4->r[m];
+ sh4->fr[n] = RL(sh4, sh4->ea );
+ sh4->fr[n+1] = RL(sh4, sh4->ea+4 );
+ }
+ } else { /* SZ = 0 */
+ sh4->ea = sh4->r[0] + sh4->r[m];
+ sh4->fr[n] = RL(sh4, sh4->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 FMOVMRFR(sh4_state *sh4,UINT32 m,UINT32 n)
+{
+ if (sh4->fpu_pr) { /* PR = 1 */
+ if (n & 1) {
+ n= n & 14;
+ sh4->ea = sh4->r[m];
+ sh4->xf[n+NATIVE_ENDIAN_VALUE_LE_BE(1,0)] = RL(sh4, sh4->ea );
+ sh4->xf[n+NATIVE_ENDIAN_VALUE_LE_BE(0,1)] = RL(sh4, sh4->ea+4 );
+ } else {
+ n= n & 14;
+ sh4->ea = sh4->r[m];
+ sh4->fr[n+NATIVE_ENDIAN_VALUE_LE_BE(1,0)] = RL(sh4, sh4->ea );
+ sh4->fr[n+NATIVE_ENDIAN_VALUE_LE_BE(0,1)] = RL(sh4, sh4->ea+4 );
+ }
+ } else { /* PR = 0 */
+ if (sh4->fpu_sz) { /* SZ = 1 */
+ if (n & 1) {
+ n= n & 14;
+ sh4->ea = sh4->r[m];
+ sh4->xf[n] = RL(sh4, sh4->ea );
+ sh4->xf[n+1] = RL(sh4, sh4->ea+4 );
+ } else {
+ n= n & 14;
+ sh4->ea = sh4->r[m];
+ sh4->fr[n] = RL(sh4, sh4->ea );
+ sh4->fr[n+1] = RL(sh4, sh4->ea+4 );
+ }
+ } else { /* SZ = 0 */
+ sh4->ea = sh4->r[m];
+ sh4->fr[n] = RL(sh4, sh4->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 FMOVFR(sh4_state *sh4,UINT32 m,UINT32 n)
+{
+ if ((sh4->fpu_sz == 0) && (sh4->fpu_pr == 0)) /* SZ = 0 */
+ sh4->fr[n] = sh4->fr[m];
+ else { /* SZ = 1 or PR = 1 */
+ if (m & 1) {
+ if (n & 1) {
+ sh4->xf[n & 14] = sh4->xf[m & 14];
+ sh4->xf[n | 1] = sh4->xf[m | 1];
+ } else {
+ sh4->fr[n] = sh4->xf[m & 14];
+ sh4->fr[n | 1] = sh4->xf[m | 1];
+ }
+ } else {
+ if (n & 1) {
+ sh4->xf[n & 14] = sh4->fr[m];
+ sh4->xf[n | 1] = sh4->fr[m | 1]; // (a&14)+1 -> a|1
+ } else {
+ sh4->fr[n] = sh4->fr[m];
+ sh4->fr[n | 1] = sh4->fr[m | 1];
+ }
+ }
+ }
+}
+
+/* FLDI1 FRn 1111nnnn10011101 */
+INLINE void FLDI1(sh4_state *sh4, UINT32 n)
+{
+ sh4->fr[n] = 0x3F800000;
+}
+
+/* FLDI0 FRn 1111nnnn10001101 */
+INLINE void FLDI0(sh4_state *sh4, UINT32 n)
+{
+ sh4->fr[n] = 0;
+}
+
+/* FLDS FRm,FPUL 1111mmmm00011101 */
+INLINE void FLDS(sh4_state *sh4, UINT32 m)
+{
+ sh4->fpul = sh4->fr[m];
+}
+
+/* FSTS FPUL,FRn 1111nnnn00001101 */
+INLINE void FSTS(sh4_state *sh4, UINT32 n)
+{
+ sh4->fr[n] = sh4->fpul;
+}
+
+/* FRCHG 1111101111111101 */
+INLINE void FRCHG(sh4_state *sh4)
+{
+ sh4->fpscr ^= FR;
+ sh4_swap_fp_registers(sh4);
+}
+
+/* FSCHG 1111001111111101 */
+INLINE void FSCHG(sh4_state *sh4)
+{
+ sh4->fpscr ^= SZ;
+ sh4->fpu_sz = (sh4->fpscr & SZ) ? 1 : 0;
+}
+
+/* FTRC FRm,FPUL PR=0 1111mmmm00111101 */
+/* FTRC DRm,FPUL PR=1 1111mmm000111101 */
+INLINE void FTRC(sh4_state *sh4, UINT32 n)
+{
+ if (sh4->fpu_pr) { /* PR = 1 */
+ n = n & 14;
+ *((INT32 *)&sh4->fpul) = (INT32)FP_RFD(n);
+ } else { /* PR = 0 */
+ /* read sh4->fr[n] as float -> truncate -> fpul(32) */
+ *((INT32 *)&sh4->fpul) = (INT32)FP_RFS(n);
+ }
+}
+
+/* FLOAT FPUL,FRn PR=0 1111nnnn00101101 */
+/* FLOAT FPUL,DRn PR=1 1111nnn000101101 */
+INLINE void FLOAT(sh4_state *sh4, UINT32 n)
+{
+ if (sh4->fpu_pr) { /* PR = 1 */
+ n = n & 14;
+ FP_RFD(n) = (double)*((INT32 *)&sh4->fpul);
+ } else { /* PR = 0 */
+ FP_RFS(n) = (float)*((INT32 *)&sh4->fpul);
+ }
+}
+
+/* FNEG FRn PR=0 1111nnnn01001101 */
+/* FNEG DRn PR=1 1111nnn001001101 */
+INLINE void FNEG(sh4_state *sh4, UINT32 n)
+{
+ if (sh4->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 FABS(sh4_state *sh4, UINT32 n)
+{
+ if (sh4->fpu_pr) { /* PR = 1 */
+#ifdef LSB_FIRST
+ n = n | 1; // n & 14 + 1
+ sh4->fr[n] = sh4->fr[n] & 0x7fffffff;
+#else
+ n = n & 14;
+ sh4->fr[n] = sh4->fr[n] & 0x7fffffff;
+#endif
+ } else { /* PR = 0 */
+ sh4->fr[n] = sh4->fr[n] & 0x7fffffff;
+ }
+}
+
+/* FCMP/EQ FRm,FRn PR=0 1111nnnnmmmm0100 */
+/* FCMP/EQ DRm,DRn PR=1 1111nnn0mmm00100 */
+INLINE void FCMP_EQ(sh4_state *sh4, UINT32 m,UINT32 n)
+{
+ if (sh4->fpu_pr) { /* PR = 1 */
+ n = n & 14;
+ m = m & 14;
+ if (FP_RFD(n) == FP_RFD(m))
+ sh4->sr |= T;
+ else
+ sh4->sr &= ~T;
+ } else { /* PR = 0 */
+ if (FP_RFS(n) == FP_RFS(m))
+ sh4->sr |= T;
+ else
+ sh4->sr &= ~T;
+ }
+}
+
+/* FCMP/GT FRm,FRn PR=0 1111nnnnmmmm0101 */
+/* FCMP/GT DRm,DRn PR=1 1111nnn0mmm00101 */
+INLINE void FCMP_GT(sh4_state *sh4, UINT32 m,UINT32 n)
+{
+ if (sh4->fpu_pr) { /* PR = 1 */
+ n = n & 14;
+ m = m & 14;
+ if (FP_RFD(n) > FP_RFD(m))
+ sh4->sr |= T;
+ else
+ sh4->sr &= ~T;
+ } else { /* PR = 0 */
+ if (FP_RFS(n) > FP_RFS(m))
+ sh4->sr |= T;
+ else
+ sh4->sr &= ~T;
+ }
+}
+
+/* FCNVDS DRm,FPUL PR=1 1111mmm010111101 */
+INLINE void FCNVDS(sh4_state *sh4, UINT32 n)
+{
+ if (sh4->fpu_pr) { /* PR = 1 */
+ n = n & 14;
+ if (sh4->fpscr & RM)
+ sh4->fr[n | NATIVE_ENDIAN_VALUE_LE_BE(0,1)] &= 0xe0000000; /* round toward zero*/
+ *((float *)&sh4->fpul) = (float)FP_RFD(n);
+ }
+}
+
+/* FCNVSD FPUL, DRn PR=1 1111nnn010101101 */
+INLINE void FCNVSD(sh4_state *sh4, UINT32 n)
+{
+ if (sh4->fpu_pr) { /* PR = 1 */
+ n = n & 14;
+ FP_RFD(n) = (double)*((float *)&sh4->fpul);
+ }
+}
+
+/* FADD FRm,FRn PR=0 1111nnnnmmmm0000 */
+/* FADD DRm,DRn PR=1 1111nnn0mmm00000 */
+INLINE void FADD(sh4_state *sh4, UINT32 m,UINT32 n)
+{
+ if (sh4->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 FSUB(sh4_state *sh4, UINT32 m,UINT32 n)
+{
+ if (sh4->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 FMUL(sh4_state *sh4, UINT32 m,UINT32 n)
+{
+ if (sh4->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 FDIV(sh4_state *sh4, UINT32 m,UINT32 n)
+{
+ if (sh4->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 FMAC(sh4_state *sh4, UINT32 m,UINT32 n)
+{
+ if (sh4->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 FSQRT(sh4_state *sh4, UINT32 n)
+{
+ if (sh4->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 FSRRA(sh4_state *sh4, UINT32 n)
+{
+ if (FP_RFS(n) < 0)
+ return;
+ FP_RFS(n) = 1.0 / sqrtf(FP_RFS(n));
+}
+
+/* FSSCA FPUL,FRn PR=0 1111nnn011111101 */
+INLINE void FSSCA(sh4_state *sh4, UINT32 n)
+{
+float angle;
+
+ angle = (((float)(sh4->fpul & 0xFFFF)) / 65536.0) * 2.0 * M_PI;
+ FP_RFS(n) = sinf(angle);
+ FP_RFS(n+1) = cosf(angle);
+}
+
+/* FIPR FVm,FVn PR=0 1111nnmm11101101 */
+INLINE void FIPR(sh4_state *sh4, UINT32 n)
+{
+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 */
+INLINE void FTRV(sh4_state *sh4, UINT32 n)
+{
+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 op1111(sh4_state *sh4, UINT16 opcode)
+{
+ switch (opcode & 0xf)
+ {
+ case 0:
+ FADD(sh4, Rm,Rn);
+ break;
+ case 1:
+ FSUB(sh4, Rm,Rn);
+ break;
+ case 2:
+ FMUL(sh4, Rm,Rn);
+ break;
+ case 3:
+ FDIV(sh4, Rm,Rn);
+ break;
+ case 4:
+ FCMP_EQ(sh4, Rm,Rn);
+ break;
+ case 5:
+ FCMP_GT(sh4, Rm,Rn);
+ break;
+ case 6:
+ FMOVS0FR(sh4, Rm,Rn);
+ break;
+ case 7:
+ FMOVFRS0(sh4, Rm,Rn);
+ break;
+ case 8:
+ FMOVMRFR(sh4, Rm,Rn);
+ break;
+ case 9:
+ FMOVMRIFR(sh4, Rm,Rn);
+ break;
+ case 10:
+ FMOVFRMR(sh4, Rm,Rn);
+ break;
+ case 11:
+ FMOVFRMDR(sh4, Rm,Rn);
+ break;
+ case 12:
+ FMOVFR(sh4, Rm,Rn);
+ break;
+ case 13:
+ switch (opcode & 0xF0)
+ {
+ case 0x00:
+ FSTS(sh4, Rn);
+ break;
+ case 0x10:
+ FLDS(sh4, Rn);
+ break;
+ case 0x20:
+ FLOAT(sh4, Rn);
+ break;
+ case 0x30:
+ FTRC(sh4, Rn);
+ break;
+ case 0x40:
+ FNEG(sh4, Rn);
+ break;
+ case 0x50:
+ FABS(sh4, Rn);
+ break;
+ case 0x60:
+ FSQRT(sh4, Rn);
+ break;
+ case 0x70:
+ FSRRA(sh4, Rn);
+ break;
+ case 0x80:
+ FLDI0(sh4, Rn);
+ break;
+ case 0x90:
+ FLDI1(sh4, Rn);
+ break;
+ case 0xA0:
+ FCNVSD(sh4, Rn);
+ break;
+ case 0xB0:
+ FCNVDS(sh4, Rn);
+ break;
+ case 0xE0:
+ FIPR(sh4, Rn);
+ break;
+ case 0xF0:
+ if (opcode & 0x100) {
+ if (opcode & 0x200) {
+ switch (opcode & 0xC00)
+ {
+ case 0x000:
+ FSCHG(sh4);
+ break;
+ case 0x800:
+ FRCHG(sh4);
+ break;
+ default:
+ debugger_break(sh4->device->machine());
+ break;
+ }
+ } else {
+ FTRV(sh4, Rn);
+ }
+ } else {
+ FSSCA(sh4, Rn);
+ }
+ break;
+ default:
+ debugger_break(sh4->device->machine());
+ break;
+ }
+ break;
+ case 14:
+ FMAC(sh4, Rm,Rn);
+ break;
+ default:
+ debugger_break(sh4->device->machine());
+ break;
+ }
+}
+
+/*****************************************************************************
+ * MAME CPU INTERFACE
+ *****************************************************************************/
+
+static CPU_RESET( sh4 )
+{
+ sh4_state *sh4 = get_safe_token(device);
+ emu_timer *tsaved[4];
+ emu_timer *tsave[5];
+ UINT32 *m;
+ int save_is_slave;
+ int savecpu_clock, savebus_clock, savepm_clock;
+
+ void (*f)(UINT32 data);
+ device_irq_callback save_irqcallback;
+
+ m = sh4->m;
+ tsaved[0] = sh4->dma_timer[0];
+ tsaved[1] = sh4->dma_timer[1];
+ tsaved[2] = sh4->dma_timer[2];
+ tsaved[3] = sh4->dma_timer[3];
+ tsave[0] = sh4->refresh_timer;
+ tsave[1] = sh4->rtc_timer;
+ tsave[2] = sh4->timer[0];
+ tsave[3] = sh4->timer[1];
+ tsave[4] = sh4->timer[2];
+
+ f = sh4->ftcsr_read_callback;
+ save_irqcallback = sh4->irq_callback;
+ save_is_slave = sh4->is_slave;
+ savecpu_clock = sh4->cpu_clock;
+ savebus_clock = sh4->bus_clock;
+ savepm_clock = sh4->pm_clock;
+ memset(sh4, 0, sizeof(*sh4));
+ sh4->is_slave = save_is_slave;
+ sh4->cpu_clock = savecpu_clock;
+ sh4->bus_clock = savebus_clock;
+ sh4->pm_clock = savepm_clock;
+ sh4->ftcsr_read_callback = f;
+ sh4->irq_callback = save_irqcallback;
+ sh4->device = device;
+ sh4->internal = device->space(AS_PROGRAM);
+ sh4->program = device->space(AS_PROGRAM);
+ sh4->direct = &sh4->program->direct();
+ sh4->io = device->space(AS_IO);
+
+ sh4->dma_timer[0] = tsaved[0];
+ sh4->dma_timer[1] = tsaved[1];
+ sh4->dma_timer[2] = tsaved[2];
+ sh4->dma_timer[3] = tsaved[3];
+ sh4->refresh_timer = tsave[0];
+ sh4->rtc_timer = tsave[1];
+ sh4->timer[0] = tsave[2];
+ sh4->timer[1] = tsave[3];
+ sh4->timer[2] = tsave[4];
+ sh4->m = m;
+ memset(sh4->m, 0, 16384*4);
+ sh4_default_exception_priorities(sh4);
+ memset(sh4->exception_requesting, 0, sizeof(sh4->exception_requesting));
+
+ sh4->rtc_timer->adjust(attotime::from_hz(128));
+ sh4->m[RCR2] = 0x09;
+ sh4->m[TCOR0] = 0xffffffff;
+ sh4->m[TCNT0] = 0xffffffff;
+ sh4->m[TCOR1] = 0xffffffff;
+ sh4->m[TCNT1] = 0xffffffff;
+ sh4->m[TCOR2] = 0xffffffff;
+ sh4->m[TCNT2] = 0xffffffff;
+
+ sh4->pc = 0xa0000000;
+ sh4->r[15] = RL(sh4,4);
+ sh4->sr = 0x700000f0;
+ sh4->fpscr = 0x00040001;
+ sh4->fpu_sz = (sh4->fpscr & SZ) ? 1 : 0;
+ sh4->fpu_pr = (sh4->fpscr & PR) ? 1 : 0;
+ sh4->fpul = 0;
+ sh4->dbr = 0;
+
+ sh4->internal_irq_level = -1;
+ sh4->irln = 15;
+ sh4->sleep_mode = 0;
+
+ sh4->sh4_mmu_enabled = 0;
+
+ sh4->cpu_type = CPU_TYPE_SH4;
+}
+
+/*-------------------------------------------------
+ sh3_reset - reset the processor
+-------------------------------------------------*/
+
+static CPU_RESET( sh3 )
+{
+ sh4_state *sh4 = get_safe_token(device);
+ CPU_RESET_CALL(sh4);
+ sh4->cpu_type = CPU_TYPE_SH3;
+}
+
+/* Execute cycles - returns number of cycles actually run */
+static CPU_EXECUTE( sh4 )
+{
+ sh4_state *sh4 = get_safe_token(device);
+
+ if (sh4->cpu_off)
+ {
+ sh4->sh4_icount = 0;
+ return;
+ }
+
+ do
+ {
+ UINT32 opcode;
+
+ if (sh4->delay)
+ {
+ opcode = sh4->direct->read_decrypted_word((UINT32)(sh4->delay & AM), WORD2_XOR_LE(0));
+ sh4->pc -= 2;
+ }
+ else
+ opcode = sh4->direct->read_decrypted_word((UINT32)(sh4->pc & AM), WORD2_XOR_LE(0));
+
+ debugger_instruction_hook(device, sh4->pc & AM);
+
+ sh4->delay = 0;
+ sh4->pc += 2;
+ sh4->ppc = sh4->pc;
+
+ switch (opcode & ( 15 << 12))
+ {
+ case 0<<12: op0000(sh4, opcode); break;
+ case 1<<12: op0001(sh4, opcode); break;
+ case 2<<12: op0010(sh4, opcode); break;
+ case 3<<12: op0011(sh4, opcode); break;
+ case 4<<12: op0100(sh4, opcode); break;
+ case 5<<12: op0101(sh4, opcode); break;
+ case 6<<12: op0110(sh4, opcode); break;
+ case 7<<12: op0111(sh4, opcode); break;
+ case 8<<12: op1000(sh4, opcode); break;
+ case 9<<12: op1001(sh4, opcode); break;
+ case 10<<12: op1010(sh4, opcode); break;
+ case 11<<12: op1011(sh4, opcode); break;
+ case 12<<12: op1100(sh4, opcode); break;
+ case 13<<12: op1101(sh4, opcode); break;
+ case 14<<12: op1110(sh4, opcode); break;
+ default: op1111(sh4, opcode); break;
+ }
+
+ if (sh4->test_irq && !sh4->delay)
+ {
+ sh4_check_pending_irq(sh4, "mame_sh4_execute");
+ }
+ sh4->sh4_icount--;
+ } while( sh4->sh4_icount > 0 );
+}
+
+static CPU_INIT( sh4 )
+{
+ const struct sh4_config *conf = (const struct sh4_config *)device->static_config();
+ sh4_state *sh4 = get_safe_token(device);
+
+ sh4_common_init(device);
+
+ sh4_parse_configuration(sh4, conf);
+
+ sh4->irq_callback = irqcallback;
+ sh4->device = device;
+ sh4->internal = device->space(AS_PROGRAM);
+ sh4->program = device->space(AS_PROGRAM);
+ sh4->io = device->space(AS_IO);
+ sh4_default_exception_priorities(sh4);
+ sh4->irln = 15;
+ sh4->test_irq = 0;
+
+ device->save_item(NAME(sh4->pc));
+ device->save_item(NAME(sh4->r[15]));
+ device->save_item(NAME(sh4->sr));
+ device->save_item(NAME(sh4->pr));
+ device->save_item(NAME(sh4->gbr));
+ device->save_item(NAME(sh4->vbr));
+ device->save_item(NAME(sh4->mach));
+ device->save_item(NAME(sh4->macl));
+ device->save_item(NAME(sh4->spc));
+ device->save_item(NAME(sh4->ssr));
+ device->save_item(NAME(sh4->sgr));
+ device->save_item(NAME(sh4->fpscr));
+ device->save_item(NAME(sh4->r[ 0]));
+ device->save_item(NAME(sh4->r[ 1]));
+ device->save_item(NAME(sh4->r[ 2]));
+ device->save_item(NAME(sh4->r[ 3]));
+ device->save_item(NAME(sh4->r[ 4]));
+ device->save_item(NAME(sh4->r[ 5]));
+ device->save_item(NAME(sh4->r[ 6]));
+ device->save_item(NAME(sh4->r[ 7]));
+ device->save_item(NAME(sh4->r[ 8]));
+ device->save_item(NAME(sh4->r[ 9]));
+ device->save_item(NAME(sh4->r[10]));
+ device->save_item(NAME(sh4->r[11]));
+ device->save_item(NAME(sh4->r[12]));
+ device->save_item(NAME(sh4->r[13]));
+ device->save_item(NAME(sh4->r[14]));
+ device->save_item(NAME(sh4->fr[ 0]));
+ device->save_item(NAME(sh4->fr[ 1]));
+ device->save_item(NAME(sh4->fr[ 2]));
+ device->save_item(NAME(sh4->fr[ 3]));
+ device->save_item(NAME(sh4->fr[ 4]));
+ device->save_item(NAME(sh4->fr[ 5]));
+ device->save_item(NAME(sh4->fr[ 6]));
+ device->save_item(NAME(sh4->fr[ 7]));
+ device->save_item(NAME(sh4->fr[ 8]));
+ device->save_item(NAME(sh4->fr[ 9]));
+ device->save_item(NAME(sh4->fr[10]));
+ device->save_item(NAME(sh4->fr[11]));
+ device->save_item(NAME(sh4->fr[12]));
+ device->save_item(NAME(sh4->fr[13]));
+ device->save_item(NAME(sh4->fr[14]));
+ device->save_item(NAME(sh4->fr[15]));
+ device->save_item(NAME(sh4->xf[ 0]));
+ device->save_item(NAME(sh4->xf[ 1]));
+ device->save_item(NAME(sh4->xf[ 2]));
+ device->save_item(NAME(sh4->xf[ 3]));
+ device->save_item(NAME(sh4->xf[ 4]));
+ device->save_item(NAME(sh4->xf[ 5]));
+ device->save_item(NAME(sh4->xf[ 6]));
+ device->save_item(NAME(sh4->xf[ 7]));
+ device->save_item(NAME(sh4->xf[ 8]));
+ device->save_item(NAME(sh4->xf[ 9]));
+ device->save_item(NAME(sh4->xf[10]));
+ device->save_item(NAME(sh4->xf[11]));
+ device->save_item(NAME(sh4->xf[12]));
+ device->save_item(NAME(sh4->xf[13]));
+ device->save_item(NAME(sh4->xf[14]));
+ device->save_item(NAME(sh4->xf[15]));
+ device->save_item(NAME(sh4->ea));
+ device->save_item(NAME(sh4->fpul));
+ device->save_item(NAME(sh4->dbr));
+ device->save_item(NAME(sh4->exception_priority));
+ device->save_item(NAME(sh4->exception_requesting));
+
+}
+
+/**************************************************************************
+ * Generic set_info
+ **************************************************************************/
+
+static CPU_SET_INFO( sh4 )
+{
+ sh4_state *sh4 = get_safe_token(device);
+
+ switch (state)
+ {
+ /* --- the following bits of info are set as 64-bit signed integers --- */
+ case CPUINFO_INT_INPUT_STATE + SH4_IRL0: sh4_set_irq_line(sh4, SH4_IRL0, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + SH4_IRL1: sh4_set_irq_line(sh4, SH4_IRL1, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + SH4_IRL2: sh4_set_irq_line(sh4, SH4_IRL2, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + SH4_IRL3: sh4_set_irq_line(sh4, SH4_IRL3, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + SH4_IRLn: sh4_set_irq_line(sh4, SH4_IRLn, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + INPUT_LINE_NMI: sh4_set_irq_line(sh4, INPUT_LINE_NMI, info->i); break;
+
+ case CPUINFO_INT_REGISTER + SH4_PC:
+ case CPUINFO_INT_PC: sh4->pc = info->i; sh4->delay = 0; break;
+ case CPUINFO_INT_SP: sh4->r[15] = info->i; break;
+ case CPUINFO_INT_REGISTER + SH4_PR: sh4->pr = info->i; break;
+ case CPUINFO_INT_REGISTER + SH4_SR:
+ sh4->sr = info->i;
+ sh4_exception_recompute(sh4);
+ sh4_check_pending_irq(sh4, "sh4_set_info");
+ break;
+ case CPUINFO_INT_REGISTER + SH4_GBR: sh4->gbr = info->i; break;
+ case CPUINFO_INT_REGISTER + SH4_VBR: sh4->vbr = info->i; break;
+ case CPUINFO_INT_REGISTER + SH4_DBR: sh4->dbr = info->i; break;
+ case CPUINFO_INT_REGISTER + SH4_MACH: sh4->mach = info->i; break;
+ case CPUINFO_INT_REGISTER + SH4_MACL: sh4->macl = info->i; break;
+ case CPUINFO_INT_REGISTER + SH4_R0: sh4->r[ 0] = info->i; break;
+ case CPUINFO_INT_REGISTER + SH4_R1: sh4->r[ 1] = info->i; break;
+ case CPUINFO_INT_REGISTER + SH4_R2: sh4->r[ 2] = info->i; break;
+ case CPUINFO_INT_REGISTER + SH4_R3: sh4->r[ 3] = info->i; break;
+ case CPUINFO_INT_REGISTER + SH4_R4: sh4->r[ 4] = info->i; break;
+ case CPUINFO_INT_REGISTER + SH4_R5: sh4->r[ 5] = info->i; break;
+ case CPUINFO_INT_REGISTER + SH4_R6: sh4->r[ 6] = info->i; break;
+ case CPUINFO_INT_REGISTER + SH4_R7: sh4->r[ 7] = info->i; break;
+ case CPUINFO_INT_REGISTER + SH4_R8: sh4->r[ 8] = info->i; break;
+ case CPUINFO_INT_REGISTER + SH4_R9: sh4->r[ 9] = info->i; break;
+ case CPUINFO_INT_REGISTER + SH4_R10: sh4->r[10] = info->i; break;
+ case CPUINFO_INT_REGISTER + SH4_R11: sh4->r[11] = info->i; break;
+ case CPUINFO_INT_REGISTER + SH4_R12: sh4->r[12] = info->i; break;
+ case CPUINFO_INT_REGISTER + SH4_R13: sh4->r[13] = info->i; break;
+ case CPUINFO_INT_REGISTER + SH4_R14: sh4->r[14] = info->i; break;
+ case CPUINFO_INT_REGISTER + SH4_R15: sh4->r[15] = info->i; break;
+ case CPUINFO_INT_REGISTER + SH4_EA: sh4->ea = info->i; break;
+ case CPUINFO_STR_REGISTER + SH4_R0_BK0: sh4->rbnk[0][0] = info->i; break;
+ case CPUINFO_STR_REGISTER + SH4_R1_BK0: sh4->rbnk[0][1] = info->i; break;
+ case CPUINFO_STR_REGISTER + SH4_R2_BK0: sh4->rbnk[0][2] = info->i; break;
+ case CPUINFO_STR_REGISTER + SH4_R3_BK0: sh4->rbnk[0][3] = info->i; break;
+ case CPUINFO_STR_REGISTER + SH4_R4_BK0: sh4->rbnk[0][4] = info->i; break;
+ case CPUINFO_STR_REGISTER + SH4_R5_BK0: sh4->rbnk[0][5] = info->i; break;
+ case CPUINFO_STR_REGISTER + SH4_R6_BK0: sh4->rbnk[0][6] = info->i; break;
+ case CPUINFO_STR_REGISTER + SH4_R7_BK0: sh4->rbnk[0][7] = info->i; break;
+ case CPUINFO_STR_REGISTER + SH4_R0_BK1: sh4->rbnk[1][0] = info->i; break;
+ case CPUINFO_STR_REGISTER + SH4_R1_BK1: sh4->rbnk[1][1] = info->i; break;
+ case CPUINFO_STR_REGISTER + SH4_R2_BK1: sh4->rbnk[1][2] = info->i; break;
+ case CPUINFO_STR_REGISTER + SH4_R3_BK1: sh4->rbnk[1][3] = info->i; break;
+ case CPUINFO_STR_REGISTER + SH4_R4_BK1: sh4->rbnk[1][4] = info->i; break;
+ case CPUINFO_STR_REGISTER + SH4_R5_BK1: sh4->rbnk[1][5] = info->i; break;
+ case CPUINFO_STR_REGISTER + SH4_R6_BK1: sh4->rbnk[1][6] = info->i; break;
+ case CPUINFO_STR_REGISTER + SH4_R7_BK1: sh4->rbnk[1][7] = info->i; break;
+ case CPUINFO_STR_REGISTER + SH4_SPC: sh4->spc = info->i; break;
+ case CPUINFO_STR_REGISTER + SH4_SSR: sh4->ssr = info->i; break;
+ case CPUINFO_STR_REGISTER + SH4_SGR: sh4->sgr = info->i; break;
+ case CPUINFO_STR_REGISTER + SH4_FPSCR: sh4->fpscr = info->i; break;
+ case CPUINFO_STR_REGISTER + SH4_FPUL: sh4->fpul = info->i; break;
+#ifdef LSB_FIRST
+ case CPUINFO_STR_REGISTER + SH4_FR0: sh4->fr[ 0 ^ sh4->fpu_pr] = info->i; break;
+ case CPUINFO_STR_REGISTER + SH4_FR1: sh4->fr[ 1 ^ sh4->fpu_pr] = info->i; break;
+ case CPUINFO_STR_REGISTER + SH4_FR2: sh4->fr[ 2 ^ sh4->fpu_pr] = info->i; break;
+ case CPUINFO_STR_REGISTER + SH4_FR3: sh4->fr[ 3 ^ sh4->fpu_pr] = info->i; break;
+ case CPUINFO_STR_REGISTER + SH4_FR4: sh4->fr[ 4 ^ sh4->fpu_pr] = info->i; break;
+ case CPUINFO_STR_REGISTER + SH4_FR5: sh4->fr[ 5 ^ sh4->fpu_pr] = info->i; break;
+ case CPUINFO_STR_REGISTER + SH4_FR6: sh4->fr[ 6 ^ sh4->fpu_pr] = info->i; break;
+ case CPUINFO_STR_REGISTER + SH4_FR7: sh4->fr[ 7 ^ sh4->fpu_pr] = info->i; break;
+ case CPUINFO_STR_REGISTER + SH4_FR8: sh4->fr[ 8 ^ sh4->fpu_pr] = info->i; break;
+ case CPUINFO_STR_REGISTER + SH4_FR9: sh4->fr[ 9 ^ sh4->fpu_pr] = info->i; break;
+ case CPUINFO_STR_REGISTER + SH4_FR10: sh4->fr[10 ^ sh4->fpu_pr] = info->i; break;
+ case CPUINFO_STR_REGISTER + SH4_FR11: sh4->fr[11 ^ sh4->fpu_pr] = info->i; break;
+ case CPUINFO_STR_REGISTER + SH4_FR12: sh4->fr[12 ^ sh4->fpu_pr] = info->i; break;
+ case CPUINFO_STR_REGISTER + SH4_FR13: sh4->fr[13 ^ sh4->fpu_pr] = info->i; break;
+ case CPUINFO_STR_REGISTER + SH4_FR14: sh4->fr[14 ^ sh4->fpu_pr] = info->i; break;
+ case CPUINFO_STR_REGISTER + SH4_FR15: sh4->fr[15 ^ sh4->fpu_pr] = info->i; break;
+ case CPUINFO_STR_REGISTER + SH4_XF0: sh4->xf[ 0 ^ sh4->fpu_pr] = info->i; break;
+ case CPUINFO_STR_REGISTER + SH4_XF1: sh4->xf[ 1 ^ sh4->fpu_pr] = info->i; break;
+ case CPUINFO_STR_REGISTER + SH4_XF2: sh4->xf[ 2 ^ sh4->fpu_pr] = info->i; break;
+ case CPUINFO_STR_REGISTER + SH4_XF3: sh4->xf[ 3 ^ sh4->fpu_pr] = info->i; break;
+ case CPUINFO_STR_REGISTER + SH4_XF4: sh4->xf[ 4 ^ sh4->fpu_pr] = info->i; break;
+ case CPUINFO_STR_REGISTER + SH4_XF5: sh4->xf[ 5 ^ sh4->fpu_pr] = info->i; break;
+ case CPUINFO_STR_REGISTER + SH4_XF6: sh4->xf[ 6 ^ sh4->fpu_pr] = info->i; break;
+ case CPUINFO_STR_REGISTER + SH4_XF7: sh4->xf[ 7 ^ sh4->fpu_pr] = info->i; break;
+ case CPUINFO_STR_REGISTER + SH4_XF8: sh4->xf[ 8 ^ sh4->fpu_pr] = info->i; break;
+ case CPUINFO_STR_REGISTER + SH4_XF9: sh4->xf[ 9 ^ sh4->fpu_pr] = info->i; break;
+ case CPUINFO_STR_REGISTER + SH4_XF10: sh4->xf[10 ^ sh4->fpu_pr] = info->i; break;
+ case CPUINFO_STR_REGISTER + SH4_XF11: sh4->xf[11 ^ sh4->fpu_pr] = info->i; break;
+ case CPUINFO_STR_REGISTER + SH4_XF12: sh4->xf[12 ^ sh4->fpu_pr] = info->i; break;
+ case CPUINFO_STR_REGISTER + SH4_XF13: sh4->xf[13 ^ sh4->fpu_pr] = info->i; break;
+ case CPUINFO_STR_REGISTER + SH4_XF14: sh4->xf[14 ^ sh4->fpu_pr] = info->i; break;
+ case CPUINFO_STR_REGISTER + SH4_XF15: sh4->xf[15 ^ sh4->fpu_pr] = info->i; break;
+#else
+ case CPUINFO_STR_REGISTER + SH4_FR0: sh4->fr[ 0] = info->i; break;
+ case CPUINFO_STR_REGISTER + SH4_FR1: sh4->fr[ 1] = info->i; break;
+ case CPUINFO_STR_REGISTER + SH4_FR2: sh4->fr[ 2] = info->i; break;
+ case CPUINFO_STR_REGISTER + SH4_FR3: sh4->fr[ 3] = info->i; break;
+ case CPUINFO_STR_REGISTER + SH4_FR4: sh4->fr[ 4] = info->i; break;
+ case CPUINFO_STR_REGISTER + SH4_FR5: sh4->fr[ 5] = info->i; break;
+ case CPUINFO_STR_REGISTER + SH4_FR6: sh4->fr[ 6] = info->i; break;
+ case CPUINFO_STR_REGISTER + SH4_FR7: sh4->fr[ 7] = info->i; break;
+ case CPUINFO_STR_REGISTER + SH4_FR8: sh4->fr[ 8] = info->i; break;
+ case CPUINFO_STR_REGISTER + SH4_FR9: sh4->fr[ 9] = info->i; break;
+ case CPUINFO_STR_REGISTER + SH4_FR10: sh4->fr[10] = info->i; break;
+ case CPUINFO_STR_REGISTER + SH4_FR11: sh4->fr[11] = info->i; break;
+ case CPUINFO_STR_REGISTER + SH4_FR12: sh4->fr[12] = info->i; break;
+ case CPUINFO_STR_REGISTER + SH4_FR13: sh4->fr[13] = info->i; break;
+ case CPUINFO_STR_REGISTER + SH4_FR14: sh4->fr[14] = info->i; break;
+ case CPUINFO_STR_REGISTER + SH4_FR15: sh4->fr[15] = info->i; break;
+ case CPUINFO_STR_REGISTER + SH4_XF0: sh4->xf[ 0] = info->i; break;
+ case CPUINFO_STR_REGISTER + SH4_XF1: sh4->xf[ 1] = info->i; break;
+ case CPUINFO_STR_REGISTER + SH4_XF2: sh4->xf[ 2] = info->i; break;
+ case CPUINFO_STR_REGISTER + SH4_XF3: sh4->xf[ 3] = info->i; break;
+ case CPUINFO_STR_REGISTER + SH4_XF4: sh4->xf[ 4] = info->i; break;
+ case CPUINFO_STR_REGISTER + SH4_XF5: sh4->xf[ 5] = info->i; break;
+ case CPUINFO_STR_REGISTER + SH4_XF6: sh4->xf[ 6] = info->i; break;
+ case CPUINFO_STR_REGISTER + SH4_XF7: sh4->xf[ 7] = info->i; break;
+ case CPUINFO_STR_REGISTER + SH4_XF8: sh4->xf[ 8] = info->i; break;
+ case CPUINFO_STR_REGISTER + SH4_XF9: sh4->xf[ 9] = info->i; break;
+ case CPUINFO_STR_REGISTER + SH4_XF10: sh4->xf[10] = info->i; break;
+ case CPUINFO_STR_REGISTER + SH4_XF11: sh4->xf[11] = info->i; break;
+ case CPUINFO_STR_REGISTER + SH4_XF12: sh4->xf[12] = info->i; break;
+ case CPUINFO_STR_REGISTER + SH4_XF13: sh4->xf[13] = info->i; break;
+ case CPUINFO_STR_REGISTER + SH4_XF14: sh4->xf[14] = info->i; break;
+ case CPUINFO_STR_REGISTER + SH4_XF15: sh4->xf[15] = info->i; break;
+#endif
+ }
+}
+
+void sh4_set_ftcsr_callback(device_t *device, sh4_ftcsr_callback callback)
+{
+ sh4_state *sh4 = get_safe_token(device);
+ sh4->ftcsr_read_callback = callback;
+}
+
+
+#if 0
+/*When OC index mode is off (CCR.OIX = 0)*/
+static ADDRESS_MAP_START( sh4_internal_map, AS_PROGRAM, 64 )
+ 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 )
+ 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
+
+
+/**************************************************************************
+ * Generic get_info
+ **************************************************************************/
+
+CPU_GET_INFO( sh4 )
+{
+ sh4_state *sh4 = (device != NULL && device->token() != NULL) ? get_safe_token(device) : NULL;
+
+ switch (state)
+ {
+ /* --- the following bits of info are returned as 64-bit signed integers --- */
+ case CPUINFO_INT_CONTEXT_SIZE: info->i = sizeof(sh4_state); break;
+ case CPUINFO_INT_INPUT_LINES: info->i = 5; break;
+ case CPUINFO_INT_DEFAULT_IRQ_VECTOR: info->i = 0; break;
+ case DEVINFO_INT_ENDIANNESS: info->i = ENDIANNESS_LITTLE; break;
+ case CPUINFO_INT_CLOCK_MULTIPLIER: info->i = 1; break;
+ case CPUINFO_INT_CLOCK_DIVIDER: info->i = 1; break;
+ case CPUINFO_INT_MIN_INSTRUCTION_BYTES: info->i = 2; break;
+ case CPUINFO_INT_MAX_INSTRUCTION_BYTES: info->i = 2; break;
+ case CPUINFO_INT_MIN_CYCLES: info->i = 1; break;
+ case CPUINFO_INT_MAX_CYCLES: info->i = 4; break;
+
+ case DEVINFO_INT_DATABUS_WIDTH + AS_PROGRAM: info->i = 64; break;
+ case DEVINFO_INT_ADDRBUS_WIDTH + AS_PROGRAM: info->i = 32; break;
+ case DEVINFO_INT_ADDRBUS_SHIFT + AS_PROGRAM: info->i = 0; break;
+ case DEVINFO_INT_DATABUS_WIDTH + AS_DATA: info->i = 0; break;
+ case DEVINFO_INT_ADDRBUS_WIDTH + AS_DATA: info->i = 0; break;
+ case DEVINFO_INT_ADDRBUS_SHIFT + AS_DATA: info->i = 0; break;
+ case DEVINFO_INT_DATABUS_WIDTH + AS_IO: info->i = 64; break;
+ case DEVINFO_INT_ADDRBUS_WIDTH + AS_IO: info->i = 8; break;
+ case DEVINFO_INT_ADDRBUS_SHIFT + AS_IO: info->i = 0; break;
+
+ case DEVINFO_PTR_INTERNAL_MEMORY_MAP + AS_PROGRAM: info->internal_map64 = ADDRESS_MAP_NAME(sh4_internal_map); break;
+
+ case CPUINFO_INT_INPUT_STATE + SH4_IRL0: info->i = sh4->irq_line_state[SH4_IRL0]; break;
+ case CPUINFO_INT_INPUT_STATE + SH4_IRL1: info->i = sh4->irq_line_state[SH4_IRL1]; break;
+ case CPUINFO_INT_INPUT_STATE + SH4_IRL2: info->i = sh4->irq_line_state[SH4_IRL2]; break;
+ case CPUINFO_INT_INPUT_STATE + SH4_IRL3: info->i = sh4->irq_line_state[SH4_IRL3]; break;
+ case CPUINFO_INT_INPUT_STATE + INPUT_LINE_NMI: info->i = sh4->nmi_line_state; break;
+
+ case CPUINFO_INT_PREVIOUSPC: info->i = sh4->ppc; break;
+
+ case CPUINFO_INT_PC:
+ case CPUINFO_INT_REGISTER + SH4_PC: info->i = (sh4->delay) ? (sh4->delay & AM) : (sh4->pc & AM); break;
+ case CPUINFO_INT_SP: info->i = sh4->r[15]; break;
+ case CPUINFO_INT_REGISTER + SH4_PR: info->i = sh4->pr; break;
+ case CPUINFO_INT_REGISTER + SH4_SR: info->i = sh4->sr; break;
+ case CPUINFO_INT_REGISTER + SH4_GBR: info->i = sh4->gbr; break;
+ case CPUINFO_INT_REGISTER + SH4_VBR: info->i = sh4->vbr; break;
+ case CPUINFO_INT_REGISTER + SH4_DBR: info->i = sh4->dbr; break;
+ case CPUINFO_INT_REGISTER + SH4_MACH: info->i = sh4->mach; break;
+ case CPUINFO_INT_REGISTER + SH4_MACL: info->i = sh4->macl; break;
+ case CPUINFO_INT_REGISTER + SH4_R0: info->i = sh4->r[ 0]; break;
+ case CPUINFO_INT_REGISTER + SH4_R1: info->i = sh4->r[ 1]; break;
+ case CPUINFO_INT_REGISTER + SH4_R2: info->i = sh4->r[ 2]; break;
+ case CPUINFO_INT_REGISTER + SH4_R3: info->i = sh4->r[ 3]; break;
+ case CPUINFO_INT_REGISTER + SH4_R4: info->i = sh4->r[ 4]; break;
+ case CPUINFO_INT_REGISTER + SH4_R5: info->i = sh4->r[ 5]; break;
+ case CPUINFO_INT_REGISTER + SH4_R6: info->i = sh4->r[ 6]; break;
+ case CPUINFO_INT_REGISTER + SH4_R7: info->i = sh4->r[ 7]; break;
+ case CPUINFO_INT_REGISTER + SH4_R8: info->i = sh4->r[ 8]; break;
+ case CPUINFO_INT_REGISTER + SH4_R9: info->i = sh4->r[ 9]; break;
+ case CPUINFO_INT_REGISTER + SH4_R10: info->i = sh4->r[10]; break;
+ case CPUINFO_INT_REGISTER + SH4_R11: info->i = sh4->r[11]; break;
+ case CPUINFO_INT_REGISTER + SH4_R12: info->i = sh4->r[12]; break;
+ case CPUINFO_INT_REGISTER + SH4_R13: info->i = sh4->r[13]; break;
+ case CPUINFO_INT_REGISTER + SH4_R14: info->i = sh4->r[14]; break;
+ case CPUINFO_INT_REGISTER + SH4_R15: info->i = sh4->r[15]; break;
+ case CPUINFO_INT_REGISTER + SH4_EA: info->i = sh4->ea; break;
+
+ /* --- the following bits of info are returned as pointers to data or functions --- */
+ case CPUINFO_FCT_SET_INFO: info->setinfo = CPU_SET_INFO_NAME(sh4); break;
+ case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME(sh4); break;
+ case CPUINFO_FCT_RESET: info->reset = CPU_RESET_NAME(sh4); break;
+ case CPUINFO_FCT_EXECUTE: info->execute = CPU_EXECUTE_NAME(sh4); break;
+ case CPUINFO_FCT_BURN: info->burn = NULL; break;
+ case CPUINFO_FCT_DISASSEMBLE: info->disassemble = CPU_DISASSEMBLE_NAME(sh4); break;
+ case CPUINFO_PTR_INSTRUCTION_COUNTER: info->icount = &sh4->sh4_icount; break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case DEVINFO_STR_NAME: strcpy(info->s, "SH-4"); break;
+ case DEVINFO_STR_FAMILY: strcpy(info->s, "Hitachi SH7750"); break;
+ case DEVINFO_STR_VERSION: strcpy(info->s, "1.0"); break;
+ case DEVINFO_STR_SOURCE_FILE: strcpy(info->s, __FILE__); break;
+ case DEVINFO_STR_CREDITS: strcpy(info->s, "Copyright R. Belmont"); break;
+
+ case CPUINFO_STR_FLAGS:
+ sprintf(info->s, "%s%s%s%s%c%c%d%c%c",
+ sh4->sr & MD ? "MD ":" ",
+ sh4->sr & sRB ? "RB ":" ",
+ sh4->sr & BL ? "BL ":" ",
+ sh4->sr & FD ? "FD ":" ",
+ sh4->sr & M ? 'M':'.',
+ sh4->sr & Q ? 'Q':'.',
+ (sh4->sr & I) >> 4,
+ sh4->sr & S ? 'S':'.',
+ sh4->sr & T ? 'T':'.');
+ break;
+
+ case CPUINFO_STR_REGISTER + SH4_PC: sprintf(info->s, "PC :%08X", sh4->pc); break;
+ case CPUINFO_STR_REGISTER + SH4_SR: sprintf(info->s, "SR :%08X", sh4->sr); break;
+ case CPUINFO_STR_REGISTER + SH4_PR: sprintf(info->s, "PR :%08X", sh4->pr); break;
+ case CPUINFO_STR_REGISTER + SH4_GBR: sprintf(info->s, "GBR :%08X", sh4->gbr); break;
+ case CPUINFO_STR_REGISTER + SH4_VBR: sprintf(info->s, "VBR :%08X", sh4->vbr); break;
+ case CPUINFO_STR_REGISTER + SH4_DBR: sprintf(info->s, "DBR :%08X", sh4->dbr); break;
+ case CPUINFO_STR_REGISTER + SH4_MACH: sprintf(info->s, "MACH:%08X", sh4->mach); break;
+ case CPUINFO_STR_REGISTER + SH4_MACL: sprintf(info->s, "MACL:%08X", sh4->macl); break;
+ case CPUINFO_STR_REGISTER + SH4_R0: sprintf(info->s, "R0 :%08X", sh4->r[ 0]); break;
+ case CPUINFO_STR_REGISTER + SH4_R1: sprintf(info->s, "R1 :%08X", sh4->r[ 1]); break;
+ case CPUINFO_STR_REGISTER + SH4_R2: sprintf(info->s, "R2 :%08X", sh4->r[ 2]); break;
+ case CPUINFO_STR_REGISTER + SH4_R3: sprintf(info->s, "R3 :%08X", sh4->r[ 3]); break;
+ case CPUINFO_STR_REGISTER + SH4_R4: sprintf(info->s, "R4 :%08X", sh4->r[ 4]); break;
+ case CPUINFO_STR_REGISTER + SH4_R5: sprintf(info->s, "R5 :%08X", sh4->r[ 5]); break;
+ case CPUINFO_STR_REGISTER + SH4_R6: sprintf(info->s, "R6 :%08X", sh4->r[ 6]); break;
+ case CPUINFO_STR_REGISTER + SH4_R7: sprintf(info->s, "R7 :%08X", sh4->r[ 7]); break;
+ case CPUINFO_STR_REGISTER + SH4_R8: sprintf(info->s, "R8 :%08X", sh4->r[ 8]); break;
+ case CPUINFO_STR_REGISTER + SH4_R9: sprintf(info->s, "R9 :%08X", sh4->r[ 9]); break;
+ case CPUINFO_STR_REGISTER + SH4_R10: sprintf(info->s, "R10 :%08X", sh4->r[10]); break;
+ case CPUINFO_STR_REGISTER + SH4_R11: sprintf(info->s, "R11 :%08X", sh4->r[11]); break;
+ case CPUINFO_STR_REGISTER + SH4_R12: sprintf(info->s, "R12 :%08X", sh4->r[12]); break;
+ case CPUINFO_STR_REGISTER + SH4_R13: sprintf(info->s, "R13 :%08X", sh4->r[13]); break;
+ case CPUINFO_STR_REGISTER + SH4_R14: sprintf(info->s, "R14 :%08X", sh4->r[14]); break;
+ case CPUINFO_STR_REGISTER + SH4_R15: sprintf(info->s, "R15 :%08X", sh4->r[15]); break;
+ case CPUINFO_STR_REGISTER + SH4_EA: sprintf(info->s, "EA :%08X", sh4->ea); break;
+ case CPUINFO_STR_REGISTER + SH4_R0_BK0: sprintf(info->s, "R0 BK 0 :%08X", sh4->rbnk[0][0]); break;
+ case CPUINFO_STR_REGISTER + SH4_R1_BK0: sprintf(info->s, "R1 BK 0 :%08X", sh4->rbnk[0][1]); break;
+ case CPUINFO_STR_REGISTER + SH4_R2_BK0: sprintf(info->s, "R2 BK 0 :%08X", sh4->rbnk[0][2]); break;
+ case CPUINFO_STR_REGISTER + SH4_R3_BK0: sprintf(info->s, "R3 BK 0 :%08X", sh4->rbnk[0][3]); break;
+ case CPUINFO_STR_REGISTER + SH4_R4_BK0: sprintf(info->s, "R4 BK 0 :%08X", sh4->rbnk[0][4]); break;
+ case CPUINFO_STR_REGISTER + SH4_R5_BK0: sprintf(info->s, "R5 BK 0 :%08X", sh4->rbnk[0][5]); break;
+ case CPUINFO_STR_REGISTER + SH4_R6_BK0: sprintf(info->s, "R6 BK 0 :%08X", sh4->rbnk[0][6]); break;
+ case CPUINFO_STR_REGISTER + SH4_R7_BK0: sprintf(info->s, "R7 BK 0 :%08X", sh4->rbnk[0][7]); break;
+ case CPUINFO_STR_REGISTER + SH4_R0_BK1: sprintf(info->s, "R0 BK 1 :%08X", sh4->rbnk[1][0]); break;
+ case CPUINFO_STR_REGISTER + SH4_R1_BK1: sprintf(info->s, "R1 BK 1 :%08X", sh4->rbnk[1][1]); break;
+ case CPUINFO_STR_REGISTER + SH4_R2_BK1: sprintf(info->s, "R2 BK 1 :%08X", sh4->rbnk[1][2]); break;
+ case CPUINFO_STR_REGISTER + SH4_R3_BK1: sprintf(info->s, "R3 BK 1 :%08X", sh4->rbnk[1][3]); break;
+ case CPUINFO_STR_REGISTER + SH4_R4_BK1: sprintf(info->s, "R4 BK 1 :%08X", sh4->rbnk[1][4]); break;
+ case CPUINFO_STR_REGISTER + SH4_R5_BK1: sprintf(info->s, "R5 BK 1 :%08X", sh4->rbnk[1][5]); break;
+ case CPUINFO_STR_REGISTER + SH4_R6_BK1: sprintf(info->s, "R6 BK 1 :%08X", sh4->rbnk[1][6]); break;
+ case CPUINFO_STR_REGISTER + SH4_R7_BK1: sprintf(info->s, "R7 BK 1 :%08X", sh4->rbnk[1][7]); break;
+ case CPUINFO_STR_REGISTER + SH4_SPC: sprintf(info->s, "SPC :%08X", sh4->spc); break;
+ case CPUINFO_STR_REGISTER + SH4_SSR: sprintf(info->s, "SSR :%08X", sh4->ssr); break;
+ case CPUINFO_STR_REGISTER + SH4_SGR: sprintf(info->s, "SGR :%08X", sh4->sgr); break;
+ case CPUINFO_STR_REGISTER + SH4_FPSCR: sprintf(info->s, "FPSCR :%08X", sh4->fpscr); break;
+ case CPUINFO_STR_REGISTER + SH4_FPUL: sprintf(info->s, "FPUL :%08X", sh4->fpul); break;
+#ifdef LSB_FIRST
+ case CPUINFO_STR_REGISTER + SH4_FR0: sprintf(info->s, "FR0 :%08X %f", FP_RS2( 0),(double)FP_RFS2( 0)); break;
+ case CPUINFO_STR_REGISTER + SH4_FR1: sprintf(info->s, "FR1 :%08X %f", FP_RS2( 1),(double)FP_RFS2( 1)); break;
+ case CPUINFO_STR_REGISTER + SH4_FR2: sprintf(info->s, "FR2 :%08X %f", FP_RS2( 2),(double)FP_RFS2( 2)); break;
+ case CPUINFO_STR_REGISTER + SH4_FR3: sprintf(info->s, "FR3 :%08X %f", FP_RS2( 3),(double)FP_RFS2( 3)); break;
+ case CPUINFO_STR_REGISTER + SH4_FR4: sprintf(info->s, "FR4 :%08X %f", FP_RS2( 4),(double)FP_RFS2( 4)); break;
+ case CPUINFO_STR_REGISTER + SH4_FR5: sprintf(info->s, "FR5 :%08X %f", FP_RS2( 5),(double)FP_RFS2( 5)); break;
+ case CPUINFO_STR_REGISTER + SH4_FR6: sprintf(info->s, "FR6 :%08X %f", FP_RS2( 6),(double)FP_RFS2( 6)); break;
+ case CPUINFO_STR_REGISTER + SH4_FR7: sprintf(info->s, "FR7 :%08X %f", FP_RS2( 7),(double)FP_RFS2( 7)); break;
+ case CPUINFO_STR_REGISTER + SH4_FR8: sprintf(info->s, "FR8 :%08X %f", FP_RS2( 8),(double)FP_RFS2( 8)); break;
+ case CPUINFO_STR_REGISTER + SH4_FR9: sprintf(info->s, "FR9 :%08X %f", FP_RS2( 9),(double)FP_RFS2( 9)); break;
+ case CPUINFO_STR_REGISTER + SH4_FR10: sprintf(info->s, "FR10 :%08X %f", FP_RS2(10),(double)FP_RFS2(10)); break;
+ case CPUINFO_STR_REGISTER + SH4_FR11: sprintf(info->s, "FR11 :%08X %f", FP_RS2(11),(double)FP_RFS2(11)); break;
+ case CPUINFO_STR_REGISTER + SH4_FR12: sprintf(info->s, "FR12 :%08X %f", FP_RS2(12),(double)FP_RFS2(12)); break;
+ case CPUINFO_STR_REGISTER + SH4_FR13: sprintf(info->s, "FR13 :%08X %f", FP_RS2(13),(double)FP_RFS2(13)); break;
+ case CPUINFO_STR_REGISTER + SH4_FR14: sprintf(info->s, "FR14 :%08X %f", FP_RS2(14),(double)FP_RFS2(14)); break;
+ case CPUINFO_STR_REGISTER + SH4_FR15: sprintf(info->s, "FR15 :%08X %f", FP_RS2(15),(double)FP_RFS2(15)); break;
+ case CPUINFO_STR_REGISTER + SH4_XF0: sprintf(info->s, "XF0 :%08X %f", FP_XS2( 0),(double)FP_XFS2( 0)); break;
+ case CPUINFO_STR_REGISTER + SH4_XF1: sprintf(info->s, "XF1 :%08X %f", FP_XS2( 1),(double)FP_XFS2( 1)); break;
+ case CPUINFO_STR_REGISTER + SH4_XF2: sprintf(info->s, "XF2 :%08X %f", FP_XS2( 2),(double)FP_XFS2( 2)); break;
+ case CPUINFO_STR_REGISTER + SH4_XF3: sprintf(info->s, "XF3 :%08X %f", FP_XS2( 3),(double)FP_XFS2( 3)); break;
+ case CPUINFO_STR_REGISTER + SH4_XF4: sprintf(info->s, "XF4 :%08X %f", FP_XS2( 4),(double)FP_XFS2( 4)); break;
+ case CPUINFO_STR_REGISTER + SH4_XF5: sprintf(info->s, "XF5 :%08X %f", FP_XS2( 5),(double)FP_XFS2( 5)); break;
+ case CPUINFO_STR_REGISTER + SH4_XF6: sprintf(info->s, "XF6 :%08X %f", FP_XS2( 6),(double)FP_XFS2( 6)); break;
+ case CPUINFO_STR_REGISTER + SH4_XF7: sprintf(info->s, "XF7 :%08X %f", FP_XS2( 7),(double)FP_XFS2( 7)); break;
+ case CPUINFO_STR_REGISTER + SH4_XF8: sprintf(info->s, "XF8 :%08X %f", FP_XS2( 8),(double)FP_XFS2( 8)); break;
+ case CPUINFO_STR_REGISTER + SH4_XF9: sprintf(info->s, "XF9 :%08X %f", FP_XS2( 9),(double)FP_XFS2( 9)); break;
+ case CPUINFO_STR_REGISTER + SH4_XF10: sprintf(info->s, "XF10 :%08X %f", FP_XS2(10),(double)FP_XFS2(10)); break;
+ case CPUINFO_STR_REGISTER + SH4_XF11: sprintf(info->s, "XF11 :%08X %f", FP_XS2(11),(double)FP_XFS2(11)); break;
+ case CPUINFO_STR_REGISTER + SH4_XF12: sprintf(info->s, "XF12 :%08X %f", FP_XS2(12),(double)FP_XFS2(12)); break;
+ case CPUINFO_STR_REGISTER + SH4_XF13: sprintf(info->s, "XF13 :%08X %f", FP_XS2(13),(double)FP_XFS2(13)); break;
+ case CPUINFO_STR_REGISTER + SH4_XF14: sprintf(info->s, "XF14 :%08X %f", FP_XS2(14),(double)FP_XFS2(14)); break;
+ case CPUINFO_STR_REGISTER + SH4_XF15: sprintf(info->s, "XF15 :%08X %f", FP_XS2(15),(double)FP_XFS2(15)); break;
+#else
+ case CPUINFO_STR_REGISTER + SH4_FR0: sprintf(info->s, "FR0 :%08X %f", FP_RS( 0),(double)FP_RFS( 0)); break;
+ case CPUINFO_STR_REGISTER + SH4_FR1: sprintf(info->s, "FR1 :%08X %f", FP_RS( 1),(double)FP_RFS( 1)); break;
+ case CPUINFO_STR_REGISTER + SH4_FR2: sprintf(info->s, "FR2 :%08X %f", FP_RS( 2),(double)FP_RFS( 2)); break;
+ case CPUINFO_STR_REGISTER + SH4_FR3: sprintf(info->s, "FR3 :%08X %f", FP_RS( 3),(double)FP_RFS( 3)); break;
+ case CPUINFO_STR_REGISTER + SH4_FR4: sprintf(info->s, "FR4 :%08X %f", FP_RS( 4),(double)FP_RFS( 4)); break;
+ case CPUINFO_STR_REGISTER + SH4_FR5: sprintf(info->s, "FR5 :%08X %f", FP_RS( 5),(double)FP_RFS( 5)); break;
+ case CPUINFO_STR_REGISTER + SH4_FR6: sprintf(info->s, "FR6 :%08X %f", FP_RS( 6),(double)FP_RFS( 6)); break;
+ case CPUINFO_STR_REGISTER + SH4_FR7: sprintf(info->s, "FR7 :%08X %f", FP_RS( 7),(double)FP_RFS( 7)); break;
+ case CPUINFO_STR_REGISTER + SH4_FR8: sprintf(info->s, "FR8 :%08X %f", FP_RS( 8),(double)FP_RFS( 8)); break;
+ case CPUINFO_STR_REGISTER + SH4_FR9: sprintf(info->s, "FR9 :%08X %f", FP_RS( 9),(double)FP_RFS( 9)); break;
+ case CPUINFO_STR_REGISTER + SH4_FR10: sprintf(info->s, "FR10 :%08X %f", FP_RS(10),(double)FP_RFS(10)); break;
+ case CPUINFO_STR_REGISTER + SH4_FR11: sprintf(info->s, "FR11 :%08X %f", FP_RS(11),(double)FP_RFS(11)); break;
+ case CPUINFO_STR_REGISTER + SH4_FR12: sprintf(info->s, "FR12 :%08X %f", FP_RS(12),(double)FP_RFS(12)); break;
+ case CPUINFO_STR_REGISTER + SH4_FR13: sprintf(info->s, "FR13 :%08X %f", FP_RS(13),(double)FP_RFS(13)); break;
+ case CPUINFO_STR_REGISTER + SH4_FR14: sprintf(info->s, "FR14 :%08X %f", FP_RS(14),(double)FP_RFS(14)); break;
+ case CPUINFO_STR_REGISTER + SH4_FR15: sprintf(info->s, "FR15 :%08X %f", FP_RS(15),(double)FP_RFS(15)); break;
+ case CPUINFO_STR_REGISTER + SH4_XF0: sprintf(info->s, "XF0 :%08X %f", FP_XS( 0),(double)FP_XFS( 0)); break;
+ case CPUINFO_STR_REGISTER + SH4_XF1: sprintf(info->s, "XF1 :%08X %f", FP_XS( 1),(double)FP_XFS( 1)); break;
+ case CPUINFO_STR_REGISTER + SH4_XF2: sprintf(info->s, "XF2 :%08X %f", FP_XS( 2),(double)FP_XFS( 2)); break;
+ case CPUINFO_STR_REGISTER + SH4_XF3: sprintf(info->s, "XF3 :%08X %f", FP_XS( 3),(double)FP_XFS( 3)); break;
+ case CPUINFO_STR_REGISTER + SH4_XF4: sprintf(info->s, "XF4 :%08X %f", FP_XS( 4),(double)FP_XFS( 4)); break;
+ case CPUINFO_STR_REGISTER + SH4_XF5: sprintf(info->s, "XF5 :%08X %f", FP_XS( 5),(double)FP_XFS( 5)); break;
+ case CPUINFO_STR_REGISTER + SH4_XF6: sprintf(info->s, "XF6 :%08X %f", FP_XS( 6),(double)FP_XFS( 6)); break;
+ case CPUINFO_STR_REGISTER + SH4_XF7: sprintf(info->s, "XF7 :%08X %f", FP_XS( 7),(double)FP_XFS( 7)); break;
+ case CPUINFO_STR_REGISTER + SH4_XF8: sprintf(info->s, "XF8 :%08X %f", FP_XS( 8),(double)FP_XFS( 8)); break;
+ case CPUINFO_STR_REGISTER + SH4_XF9: sprintf(info->s, "XF9 :%08X %f", FP_XS( 9),(double)FP_XFS( 9)); break;
+ case CPUINFO_STR_REGISTER + SH4_XF10: sprintf(info->s, "XF10 :%08X %f", FP_XS(10),(double)FP_XFS(10)); break;
+ case CPUINFO_STR_REGISTER + SH4_XF11: sprintf(info->s, "XF11 :%08X %f", FP_XS(11),(double)FP_XFS(11)); break;
+ case CPUINFO_STR_REGISTER + SH4_XF12: sprintf(info->s, "XF12 :%08X %f", FP_XS(12),(double)FP_XFS(12)); break;
+ case CPUINFO_STR_REGISTER + SH4_XF13: sprintf(info->s, "XF13 :%08X %f", FP_XS(13),(double)FP_XFS(13)); break;
+ case CPUINFO_STR_REGISTER + SH4_XF14: sprintf(info->s, "XF14 :%08X %f", FP_XS(14),(double)FP_XFS(14)); break;
+ case CPUINFO_STR_REGISTER + SH4_XF15: sprintf(info->s, "XF15 :%08X %f", FP_XS(15),(double)FP_XFS(15)); break; //%01.2e
+#endif
+ }
+}
+
+CPU_GET_INFO( sh3 )
+{
+ switch (state)
+ {
+ /* --- the following bits of info are returned as pointers to data or functions --- */
+ case CPUINFO_FCT_RESET: info->reset = CPU_RESET_NAME(sh3); break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case DEVINFO_STR_NAME: strcpy(info->s, "SH-3"); break;
+ case DEVINFO_STR_FAMILY: strcpy(info->s, "Hitachi SH7700"); break;
+
+ default: CPU_GET_INFO_CALL(sh4); break;
+ }
+}
+
+CPU_GET_INFO( sh3be )
+{
+ switch (state)
+ {
+ /* --- the following bits of info are returned as pointers to data or functions --- */
+ case CPUINFO_FCT_RESET: info->reset = CPU_RESET_NAME(sh3); break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case DEVINFO_STR_NAME: strcpy(info->s, "SH-3"); break;
+ case DEVINFO_STR_FAMILY: strcpy(info->s, "Hitachi SH7700"); break;
+
+ case DEVINFO_INT_ENDIANNESS: info->i = ENDIANNESS_BIG; break;
+
+ default: CPU_GET_INFO_CALL(sh4); break;
+ }
+}
+
+CPU_GET_INFO( sh4be )
+{
+ switch (state)
+ {
+ case DEVINFO_INT_ENDIANNESS: info->i = ENDIANNESS_BIG; break;
+ default: CPU_GET_INFO_CALL(sh4); break;
+ }
+}
+
+DEFINE_LEGACY_CPU_DEVICE(SH3LE, sh3);
+DEFINE_LEGACY_CPU_DEVICE(SH3BE, sh3be);
+DEFINE_LEGACY_CPU_DEVICE(SH4LE, sh4);
+DEFINE_LEGACY_CPU_DEVICE(SH4BE, sh4be);
+
+#endif // USE_SH4DRC