summaryrefslogtreecommitdiffstatshomepage
path: root/src/emu/cpu/sh4/sh4.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/emu/cpu/sh4/sh4.c')
-rw-r--r--src/emu/cpu/sh4/sh4.c4637
1 files changed, 4637 insertions, 0 deletions
diff --git a/src/emu/cpu/sh4/sh4.c b/src/emu/cpu/sh4/sh4.c
new file mode 100644
index 00000000000..75967883d3d
--- /dev/null
+++ b/src/emu/cpu/sh4/sh4.c
@@ -0,0 +1,4637 @@
+/*****************************************************************************
+ *
+ * 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 "debugger.h"
+#include "sh4.h"
+#include "sh4regs.h"
+
+/* speed up delay loops, bail out of tight loops */
+#define BUSY_LOOP_HACKS 0
+
+#define VERBOSE 0
+
+#if VERBOSE
+#define LOG(x) logerror x
+#else
+#define LOG(x)
+#endif
+
+#define EXPPRI(pl,po,p,n) (((4-(pl)) << 24) | ((15-(po)) << 16) | ((p) << 8) | (255-(n)))
+#define NMIPRI() EXPPRI(3,0,16,SH4_INTC_NMI)
+#define INTPRI(p,n) EXPPRI(4,2,p,n)
+
+typedef struct
+{
+ UINT32 ppc;
+ UINT32 pc, spc;
+ UINT32 pr;
+ UINT32 sr, ssr;
+ UINT32 gbr, vbr;
+ UINT32 mach, macl;
+ UINT32 r[16], rbnk[2][8], sgr;
+ UINT32 fr[16], xf[16];
+ UINT32 ea;
+ UINT32 delay;
+ UINT32 cpu_off;
+ UINT32 pending_irq;
+ UINT32 test_irq;
+ UINT32 fpscr;
+ UINT32 fpul;
+ UINT32 dbr;
+
+ UINT32 exception_priority[128];
+ int exception_requesting[128];
+
+ INT8 irq_line_state[17];
+ int (*irq_callback)(int irqline);
+ UINT32 *m;
+ INT8 nmi_line_state;
+
+ int frt_input;
+ int irln;
+ int internal_irq_level;
+ int internal_irq_vector;
+
+ emu_timer *dma_timer[4];
+ emu_timer *refresh_timer;
+ emu_timer *rtc_timer;
+ emu_timer *timer0;
+ emu_timer *timer1;
+ emu_timer *timer2;
+ UINT32 refresh_timer_base;
+ int dma_timer_active[2];
+
+ int is_slave, cpu_number;
+ int cpu_clock, bus_clock, pm_clock;
+
+ void (*ftcsr_read_callback)(UINT32 data);
+} SH4;
+
+static int sh4_icount;
+static SH4 sh4;
+
+static const int tcnt_div[8] = { 4, 16, 64, 256, 1024, 1, 1, 1 };
+static const int rtcnt_div[8] = { 0, 4, 16, 64, 256, 1024, 2048, 4096 };
+static const int daysmonth[12] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
+static const int dmasize[8] = { 8, 1, 2, 4, 32, 0, 0, 0 };
+static const UINT32 exception_priority_default[] = { EXPPRI(1,1,0,0), EXPPRI(1,2,0,1), EXPPRI(1,1,0,2), EXPPRI(1,3,0,3), EXPPRI(1,4,0,4),
+ EXPPRI(2,0,0,5), EXPPRI(2,1,0,6), EXPPRI(2,2,0,7), EXPPRI(2,3,0,8), EXPPRI(2,4,0,9), EXPPRI(2,4,0,10), EXPPRI(2,4,0,11), EXPPRI(2,4,0,12),
+ EXPPRI(2,5,0,13), EXPPRI(2,5,0,14), EXPPRI(2,6,0,15), EXPPRI(2,6,0,16), EXPPRI(2,7,0,17), EXPPRI(2,7,0,18), EXPPRI(2,8,0,19),
+ EXPPRI(2,9,0,20), EXPPRI(2,4,0,21), EXPPRI(2,10,0,22), EXPPRI(3,0,16,SH4_INTC_NMI) };
+static const int exception_codes[] = { 0x000, 0x020, 0x000, 0x140, 0x140, 0x1E0, 0x0E0, 0x040, 0x0A0, 0x180, 0x1A0, 0x800, 0x820, 0x0E0,
+ 0x100, 0x040, 0x060, 0x0A0, 0x0C0, 0x120, 0x080, 0x160, 0x1E0, 0x1C0, 0x200, 0x220, 0x240, 0x260, 0x280, 0x2A0, 0x2C0, 0x2E0, 0x300,
+ 0x320, 0x340, 0x360, 0x380, 0x3A0, 0x3C0, 0x240, 0x2A0, 0x300, 0x360, 0x600, 0x620, 0x640, 0x660, 0x680, 0x6A0, 0x780, 0x7A0, 0x7C0,
+ 0x7E0, 0x6C0, 0xB00, 0xB80, 0x400, 0x420, 0x440, 0x460, 0x480, 0x4A0, 0x4C0, 0x4E0, 0x500, 0x520, 0x540, 0x700, 0x720, 0x740, 0x760,
+ 0x560, 0x580, 0x5A0 };
+
+enum {
+ ICF = 0x00800000,
+ OCFA = 0x00080000,
+ OCFB = 0x00040000,
+ OVF = 0x00020000
+};
+
+static void set_irq_line(int irqline, int state);
+
+/* Bits in SR */
+#define T 0x00000001
+#define S 0x00000002
+#define I 0x000000f0
+#define Q 0x00000100
+#define M 0x00000200
+#define FD 0x00008000
+#define BL 0x10000000
+#define sRB 0x20000000
+#define MD 0x40000000
+
+/* 29 bits */
+#define AM 0x1fffffff
+
+#define FLAGS (MD|sRB|BL|FD|M|Q|I|S|T)
+
+/* Bits in FPSCR */
+#define RM 0x00000003
+#define DN 0x00040000
+#define PR 0x00080000
+#define SZ 0x00100000
+#define FR 0x00200000
+
+#define Rn ((opcode>>8)&15)
+#define Rm ((opcode>>4)&15)
+
+/* Called for unimplemented opcodes */
+static void TODO(void)
+{
+}
+
+INLINE UINT8 RB(offs_t A)
+{
+ if (A >= 0xfe000000)
+ return sh4_internal_r(((A & 0x0fc) >> 2) | ((A & 0x1fe0000) >> 11), ~(0xff << ((A & 3)*8))) >> ((A & 3)*8);
+
+ if (A >= 0xe0000000)
+ return program_read_byte_64le(A);
+
+/* if (A >= 0x40000000)
+ return 0xa5;*/
+
+ return program_read_byte_64le(A & AM);
+}
+
+INLINE UINT16 RW(offs_t A)
+{
+ if (A >= 0xfe000000)
+ return sh4_internal_r(((A & 0x0fc) >> 2) | ((A & 0x1fe0000) >> 11), ~(0xffff << ((A & 2)*8))) >> ((A & 2)*8);
+
+ if (A >= 0xe0000000)
+ return program_read_word_64le(A);
+
+/* if (A >= 0x40000000)
+ return 0xa5a5;*/
+
+ return program_read_word_64le(A & AM);
+}
+
+INLINE UINT32 RL(offs_t A)
+{
+ if (A >= 0xfe000000)
+ return sh4_internal_r(((A & 0x0fc) >> 2) | ((A & 0x1fe0000) >> 11), 0);
+
+ if (A >= 0xe0000000)
+ return program_read_dword_64le(A);
+
+/* if (A >= 0x40000000)
+ return 0xa5a5a5a5;*/
+
+ return program_read_dword_64le(A & AM);
+}
+
+INLINE void WB(offs_t A, UINT8 V)
+{
+
+ if (A >= 0xfe000000)
+ {
+ sh4_internal_w(((A & 0x0fc) >> 2) | ((A & 0x1fe0000) >> 11), V << ((A & 3)*8), ~(0xff << ((A & 3)*8)));
+ return;
+ }
+
+ if (A >= 0xe0000000)
+ {
+ program_write_byte_64le(A,V);
+ return;
+ }
+
+/* if (A >= 0x40000000)
+ return;*/
+
+ program_write_byte_64le(A & AM,V);
+}
+
+INLINE void WW(offs_t A, UINT16 V)
+{
+ if (A >= 0xfe000000)
+ {
+ sh4_internal_w(((A & 0x0fc) >> 2) | ((A & 0x1fe0000) >> 11), V << ((A & 2)*8), ~(0xffff << ((A & 2)*8)));
+ return;
+ }
+
+ if (A >= 0xe0000000)
+ {
+ program_write_word_64le(A,V);
+ return;
+ }
+
+/* if (A >= 0x40000000)
+ return;*/
+
+ program_write_word_64le(A & AM,V);
+}
+
+INLINE void WL(offs_t A, UINT32 V)
+{
+ if (A >= 0xfe000000)
+ {
+ sh4_internal_w(((A & 0x0fc) >> 2) | ((A & 0x1fe0000) >> 11), V, 0);
+ return;
+ }
+
+ if (A >= 0xe0000000)
+ {
+ program_write_dword_64le(A,V);
+ return;
+ }
+
+/* if (A >= 0x40000000)
+ return;*/
+
+ program_write_dword_64le(A & AM,V);
+}
+
+static void sh4_change_register_bank(int to)
+{
+int s;
+
+ if (to) // 0 -> 1
+ {
+ for (s = 0;s < 8;s++)
+ {
+ sh4.rbnk[0][s] = sh4.r[s];
+ sh4.r[s] = sh4.rbnk[1][s];
+ }
+ }
+ else // 1 -> 0
+ {
+ for (s = 0;s < 8;s++)
+ {
+ sh4.rbnk[1][s] = sh4.r[s];
+ sh4.r[s] = sh4.rbnk[0][s];
+ }
+ }
+}
+
+#ifdef MAME_DEBUG
+static void sh4_syncronize_register_bank(int to)
+{
+int s;
+
+ for (s = 0;s < 8;s++)
+ {
+ sh4.rbnk[to][s] = sh4.r[s];
+ }
+}
+#endif
+
+static void sh4_default_exception_priorities(void) // setup default priorities for exceptions
+{
+int a;
+
+ for (a=0;a <= SH4_INTC_NMI;a++)
+ sh4.exception_priority[a] = exception_priority_default[a];
+ for (a=SH4_INTC_IRLn0;a <= SH4_INTC_IRLnE;a++)
+ sh4.exception_priority[a] = INTPRI(15-(a-SH4_INTC_IRLn0), a);
+ sh4.exception_priority[SH4_INTC_IRL0] = INTPRI(13, SH4_INTC_IRL0);
+ sh4.exception_priority[SH4_INTC_IRL1] = INTPRI(10, SH4_INTC_IRL1);
+ sh4.exception_priority[SH4_INTC_IRL2] = INTPRI(7, SH4_INTC_IRL2);
+ sh4.exception_priority[SH4_INTC_IRL3] = INTPRI(4, SH4_INTC_IRL3);
+ for (a=SH4_INTC_HUDI;a <= SH4_INTC_ROVI;a++)
+ sh4.exception_priority[a] = INTPRI(0, a);
+}
+
+static void sh4_exception_recompute(void) // checks if there is any interrupt with high enough priority
+{
+int a,z;
+
+ sh4.test_irq = 0;
+ if ((!sh4.pending_irq) || ((sh4.sr & BL) && (sh4.exception_requesting[SH4_INTC_NMI] == 0)))
+ return;
+ z = (sh4.sr >> 4) & 15;
+ for (a=0;a <= SH4_INTC_ROVI;a++)
+ {
+ if (sh4.exception_requesting[a])
+ if ((((int)sh4.exception_priority[a] >> 8) & 255) > z)
+ {
+ sh4.test_irq = 1; // will check for exception at end of instructions
+ break;
+ }
+ }
+}
+
+INLINE void sh4_exception_request(int exception) // start requesting an exception
+{
+ if (!sh4.exception_requesting[exception])
+ {
+ sh4.exception_requesting[exception] = 1;
+ sh4.pending_irq++;
+ sh4_exception_recompute();
+ }
+}
+
+INLINE void sh4_exception_unrequest(int exception) // stop requesting an exception
+{
+ if (sh4.exception_requesting[exception])
+ {
+ sh4.exception_requesting[exception] = 0;
+ sh4.pending_irq--;
+ sh4_exception_recompute();
+ }
+}
+
+INLINE void sh4_exception_checkunrequest(int exception)
+{
+ if (exception == SH4_INTC_NMI)
+ sh4_exception_unrequest(exception);
+ if ((exception == SH4_INTC_DMTE0) || (exception == SH4_INTC_DMTE1) ||
+ (exception == SH4_INTC_DMTE2) || (exception == SH4_INTC_DMTE3))
+ sh4_exception_unrequest(exception);
+}
+
+INLINE void sh4_exception(const char *message, int exception) // handle exception
+{
+ UINT32 vector;
+
+ if (exception < SH4_INTC_NMI)
+ return; // Not yet supported
+ if (exception == SH4_INTC_NMI) {
+ if ((sh4.sr & BL) && (!(sh4.m[ICR] & 0x200)))
+ return;
+ sh4.m[ICR] &= ~0x200;
+ sh4.m[INTEVT] = 0x1c0;
+ vector = 0x600;
+ sh4.irq_callback(INPUT_LINE_NMI);
+ LOG(("SH-4 #%d nmi exception after [%s]\n", cpu_getactivecpu(), message));
+ } else {
+// if ((sh4.m[ICR] & 0x4000) && (sh4.nmi_line_state == ASSERT_LINE))
+// return;
+ if (sh4.sr & BL)
+ return;
+ if (((sh4.exception_priority[exception] >> 8) & 255) <= ((sh4.sr >> 4) & 15))
+ return;
+ sh4.m[INTEVT] = exception_codes[exception];
+ vector = 0x600;
+ if ((exception >= SH4_INTC_IRL0) && (exception <= SH4_INTC_IRL3))
+ sh4.irq_callback(SH4_INTC_IRL0-exception+SH4_IRL0);
+ else
+ sh4.irq_callback(SH4_IRL3+1);
+ LOG(("SH-4 #%d interrupt exception #%d after [%s]\n", cpu_getactivecpu(), exception, message));
+ }
+ sh4_exception_checkunrequest(exception);
+
+ sh4.spc = sh4.pc;
+ sh4.ssr = sh4.sr;
+ sh4.sgr = sh4.r[15];
+
+ sh4.sr |= MD;
+#ifdef MAME_DEBUG
+ sh4_syncronize_register_bank((sh4.sr & sRB) >> 29);
+#endif
+ if (!(sh4.sr & sRB))
+ sh4_change_register_bank(1);
+ sh4.sr |= sRB;
+ sh4.sr |= BL;
+ sh4_exception_recompute();
+
+ /* fetch PC */
+ sh4.pc = sh4.vbr + vector;
+ change_pc(sh4.pc & AM);
+}
+
+INLINE void sh4_check_pending_irq(const char *message) // look for highest priority active exception and handle it
+{
+int a,irq,z;
+
+ irq = 0;
+ z = -1;
+ for (a=0;a <= SH4_INTC_ROVI;a++)
+ {
+ if (sh4.exception_requesting[a])
+ if ((int)sh4.exception_priority[a] > z)
+ {
+ z = sh4.exception_priority[a];
+ irq = a;
+ }
+ }
+ if (z >= 0)
+ sh4_exception(message, irq);
+}
+
+static void sh4_swap_fp_registers(void)
+{
+int s;
+UINT32 z;
+
+ for (s = 0;s <= 15;s++)
+ {
+ z = sh4.fr[s];
+ sh4.fr[s] = sh4.xf[s];
+ sh4.xf[s] = z;
+ }
+}
+
+/* code cycles t-bit
+ * 0011 nnnn mmmm 1100 1 -
+ * ADD Rm,Rn
+ */
+INLINE void ADD(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(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(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(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(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(UINT32 i)
+{
+ sh4.r[0] &= i;
+}
+
+/* code cycles t-bit
+ * 1100 1101 iiii iiii 1 -
+ * AND.B #imm,@(R0,GBR)
+ */
+INLINE void ANDM(UINT32 i)
+{
+ UINT32 temp;
+
+ sh4.ea = sh4.gbr + sh4.r[0];
+ temp = i & RB( sh4.ea );
+ WB( sh4.ea, temp );
+ sh4_icount -= 2;
+}
+
+/* code cycles t-bit
+ * 1000 1011 dddd dddd 3/1 -
+ * BF disp8
+ */
+INLINE void BF(UINT32 d)
+{
+ if ((sh4.sr & T) == 0)
+ {
+ INT32 disp = ((INT32)d << 24) >> 24;
+ sh4.pc = sh4.ea = sh4.pc + disp * 2 + 2;
+ change_pc(sh4.pc & AM);
+ sh4_icount -= 2;
+ }
+}
+
+/* code cycles t-bit
+ * 1000 1111 dddd dddd 3/1 -
+ * BFS disp8
+ */
+INLINE void BFS(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_icount--;
+ }
+}
+
+/* code cycles t-bit
+ * 1010 dddd dddd dddd 2 -
+ * BRA disp12
+ */
+INLINE void BRA(UINT32 d)
+{
+ INT32 disp = ((INT32)d << 20) >> 20;
+
+#if BUSY_LOOP_HACKS
+ if (disp == -2)
+ {
+ UINT32 next_opcode = RW(sh4.ppc & AM);
+ /* BRA $
+ * NOP
+ */
+ if (next_opcode == 0x0009)
+ 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_icount--;
+}
+
+/* code cycles t-bit
+ * 0000 mmmm 0010 0011 2 -
+ * BRAF Rm
+ */
+INLINE void BRAF(UINT32 m)
+{
+ sh4.delay = sh4.pc;
+ sh4.pc += sh4.r[m] + 2;
+ sh4_icount--;
+}
+
+/* code cycles t-bit
+ * 1011 dddd dddd dddd 2 -
+ * BSR disp12
+ */
+INLINE void BSR(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_icount--;
+}
+
+/* code cycles t-bit
+ * 0000 mmmm 0000 0011 2 -
+ * BSRF Rm
+ */
+INLINE void BSRF(UINT32 m)
+{
+ sh4.pr = sh4.pc + 2;
+ sh4.delay = sh4.pc;
+ sh4.pc += sh4.r[m] + 2;
+ sh4_icount--;
+}
+
+/* code cycles t-bit
+ * 1000 1001 dddd dddd 3/1 -
+ * BT disp8
+ */
+INLINE void BT(UINT32 d)
+{
+ if ((sh4.sr & T) != 0)
+ {
+ INT32 disp = ((INT32)d << 24) >> 24;
+ sh4.pc = sh4.ea = sh4.pc + disp * 2 + 2;
+ change_pc(sh4.pc & AM);
+ sh4_icount -= 2;
+ }
+}
+
+/* code cycles t-bit
+ * 1000 1101 dddd dddd 2/1 -
+ * BTS disp8
+ */
+INLINE void BTS(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_icount--;
+ }
+}
+
+/* code cycles t-bit
+ * 0000 0000 0010 1000 1 -
+ * CLRMAC
+ */
+INLINE void CLRMAC(void)
+{
+ sh4.mach = 0;
+ sh4.macl = 0;
+}
+
+/* code cycles t-bit
+ * 0000 0000 0000 1000 1 -
+ * CLRT
+ */
+INLINE void CLRT(void)
+{
+ sh4.sr &= ~T;
+}
+
+/* code cycles t-bit
+ * 0011 nnnn mmmm 0000 1 comparison result
+ * CMP_EQ Rm,Rn
+ */
+INLINE void CMPEQ(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(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(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(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(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(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(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(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(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(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(void)
+{
+ sh4.sr &= ~(M | Q | T);
+}
+
+/* code cycles t-bit
+ * 0011 nnnn mmmm 0100 1 calculation result
+ * DIV1 Rm,Rn
+ */
+INLINE void DIV1(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(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_icount--;
+}
+
+/* DMULU.L Rm,Rn */
+INLINE void DMULU(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_icount--;
+}
+
+/* DT Rn */
+INLINE void DT(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.ppc & AM);
+ /* DT Rn
+ * BF $-2
+ */
+ if (next_opcode == 0x8bfd)
+ {
+ while (sh4.r[n] > 1 && sh4_icount > 4)
+ {
+ sh4.r[n]--;
+ sh4_icount -= 4; /* cycles for DT (1) and BF taken (3) */
+ }
+ }
+ }
+#endif
+}
+
+/* EXTS.B Rm,Rn */
+INLINE void EXTSB(UINT32 m, UINT32 n)
+{
+ sh4.r[n] = ((INT32)sh4.r[m] << 24) >> 24;
+}
+
+/* EXTS.W Rm,Rn */
+INLINE void EXTSW(UINT32 m, UINT32 n)
+{
+ sh4.r[n] = ((INT32)sh4.r[m] << 16) >> 16;
+}
+
+/* EXTU.B Rm,Rn */
+INLINE void EXTUB(UINT32 m, UINT32 n)
+{
+ sh4.r[n] = sh4.r[m] & 0x000000ff;
+}
+
+/* EXTU.W Rm,Rn */
+INLINE void EXTUW(UINT32 m, UINT32 n)
+{
+ sh4.r[n] = sh4.r[m] & 0x0000ffff;
+}
+
+/* JMP @Rm */
+INLINE void JMP(UINT32 m)
+{
+ sh4.delay = sh4.pc;
+ sh4.pc = sh4.ea = sh4.r[m];
+}
+
+/* JSR @Rm */
+INLINE void JSR(UINT32 m)
+{
+ sh4.delay = sh4.pc;
+ sh4.pr = sh4.pc + 2;
+ sh4.pc = sh4.ea = sh4.r[m];
+ sh4_icount--;
+}
+
+
+/* LDC Rm,SR */
+INLINE void LDCSR(UINT32 m)
+{
+#ifdef MAME_DEBUG
+ sh4_syncronize_register_bank((sh4.sr & sRB) >> 29);
+#endif
+ if ((sh4.r[m] & sRB) != (sh4.sr & sRB))
+ sh4_change_register_bank(sh4.r[m] & sRB ? 1 : 0);
+ sh4.sr = sh4.r[m] & FLAGS;
+ sh4_exception_recompute();
+}
+
+/* LDC Rm,GBR */
+INLINE void LDCGBR(UINT32 m)
+{
+ sh4.gbr = sh4.r[m];
+}
+
+/* LDC Rm,VBR */
+INLINE void LDCVBR(UINT32 m)
+{
+ sh4.vbr = sh4.r[m];
+}
+
+/* LDC.L @Rm+,SR */
+INLINE void LDCMSR(UINT32 m)
+{
+UINT32 old;
+
+ old = sh4.sr;
+ sh4.ea = sh4.r[m];
+ sh4.sr = RL( sh4.ea ) & FLAGS;
+#ifdef MAME_DEBUG
+ sh4_syncronize_register_bank((old & sRB) >> 29);
+#endif
+ if ((old & sRB) != (sh4.sr & sRB))
+ sh4_change_register_bank(sh4.sr & sRB ? 1 : 0);
+ sh4.r[m] += 4;
+ sh4_icount -= 2;
+ sh4_exception_recompute();
+}
+
+/* LDC.L @Rm+,GBR */
+INLINE void LDCMGBR(UINT32 m)
+{
+ sh4.ea = sh4.r[m];
+ sh4.gbr = RL( sh4.ea );
+ sh4.r[m] += 4;
+ sh4_icount -= 2;
+}
+
+/* LDC.L @Rm+,VBR */
+INLINE void LDCMVBR(UINT32 m)
+{
+ sh4.ea = sh4.r[m];
+ sh4.vbr = RL( sh4.ea );
+ sh4.r[m] += 4;
+ sh4_icount -= 2;
+}
+
+/* LDS Rm,MACH */
+INLINE void LDSMACH(UINT32 m)
+{
+ sh4.mach = sh4.r[m];
+}
+
+/* LDS Rm,MACL */
+INLINE void LDSMACL(UINT32 m)
+{
+ sh4.macl = sh4.r[m];
+}
+
+/* LDS Rm,PR */
+INLINE void LDSPR(UINT32 m)
+{
+ sh4.pr = sh4.r[m];
+}
+
+/* LDS.L @Rm+,MACH */
+INLINE void LDSMMACH(UINT32 m)
+{
+ sh4.ea = sh4.r[m];
+ sh4.mach = RL( sh4.ea );
+ sh4.r[m] += 4;
+}
+
+/* LDS.L @Rm+,MACL */
+INLINE void LDSMMACL(UINT32 m)
+{
+ sh4.ea = sh4.r[m];
+ sh4.macl = RL( sh4.ea );
+ sh4.r[m] += 4;
+}
+
+/* LDS.L @Rm+,PR */
+INLINE void LDSMPR(UINT32 m)
+{
+ sh4.ea = sh4.r[m];
+ sh4.pr = RL( sh4.ea );
+ sh4.r[m] += 4;
+}
+
+/* MAC.L @Rm+,@Rn+ */
+INLINE void MAC_L(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.r[n] );
+ sh4.r[n] += 4;
+ tempm = (INT32) RL( 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_icount -= 2;
+}
+
+/* MAC.W @Rm+,@Rn+ */
+INLINE void MAC_W(UINT32 m, UINT32 n)
+{
+ INT32 tempm, tempn, dest, src, ans;
+ UINT32 templ;
+
+ tempn = (INT32) RW( sh4.r[n] );
+ sh4.r[n] += 2;
+ tempm = (INT32) RW( 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_icount -= 2;
+}
+
+/* MOV Rm,Rn */
+INLINE void MOV(UINT32 m, UINT32 n)
+{
+ sh4.r[n] = sh4.r[m];
+}
+
+/* MOV.B Rm,@Rn */
+INLINE void MOVBS(UINT32 m, UINT32 n)
+{
+ sh4.ea = sh4.r[n];
+ WB( sh4.ea, sh4.r[m] & 0x000000ff);
+}
+
+/* MOV.W Rm,@Rn */
+INLINE void MOVWS(UINT32 m, UINT32 n)
+{
+ sh4.ea = sh4.r[n];
+ WW( sh4.ea, sh4.r[m] & 0x0000ffff);
+}
+
+/* MOV.L Rm,@Rn */
+INLINE void MOVLS(UINT32 m, UINT32 n)
+{
+ sh4.ea = sh4.r[n];
+ WL( sh4.ea, sh4.r[m] );
+}
+
+/* MOV.B @Rm,Rn */
+INLINE void MOVBL(UINT32 m, UINT32 n)
+{
+ sh4.ea = sh4.r[m];
+ sh4.r[n] = (UINT32)(INT32)(INT16)(INT8) RB( sh4.ea );
+}
+
+/* MOV.W @Rm,Rn */
+INLINE void MOVWL(UINT32 m, UINT32 n)
+{
+ sh4.ea = sh4.r[m];
+ sh4.r[n] = (UINT32)(INT32)(INT16) RW( sh4.ea );
+}
+
+/* MOV.L @Rm,Rn */
+INLINE void MOVLL(UINT32 m, UINT32 n)
+{
+ sh4.ea = sh4.r[m];
+ sh4.r[n] = RL( sh4.ea );
+}
+
+/* MOV.B Rm,@-Rn */
+INLINE void MOVBM(UINT32 m, UINT32 n)
+{
+ /* SMG : bug fix, was reading sh4.r[n] */
+ UINT32 data = sh4.r[m] & 0x000000ff;
+
+ sh4.r[n] -= 1;
+ WB( sh4.r[n], data );
+}
+
+/* MOV.W Rm,@-Rn */
+INLINE void MOVWM(UINT32 m, UINT32 n)
+{
+ UINT32 data = sh4.r[m] & 0x0000ffff;
+
+ sh4.r[n] -= 2;
+ WW( sh4.r[n], data );
+}
+
+/* MOV.L Rm,@-Rn */
+INLINE void MOVLM(UINT32 m, UINT32 n)
+{
+ UINT32 data = sh4.r[m];
+
+ sh4.r[n] -= 4;
+ WL( sh4.r[n], data );
+}
+
+/* MOV.B @Rm+,Rn */
+INLINE void MOVBP(UINT32 m, UINT32 n)
+{
+ sh4.r[n] = (UINT32)(INT32)(INT16)(INT8) RB( sh4.r[m] );
+ if (n != m)
+ sh4.r[m] += 1;
+}
+
+/* MOV.W @Rm+,Rn */
+INLINE void MOVWP(UINT32 m, UINT32 n)
+{
+ sh4.r[n] = (UINT32)(INT32)(INT16) RW( sh4.r[m] );
+ if (n != m)
+ sh4.r[m] += 2;
+}
+
+/* MOV.L @Rm+,Rn */
+INLINE void MOVLP(UINT32 m, UINT32 n)
+{
+ sh4.r[n] = RL( sh4.r[m] );
+ if (n != m)
+ sh4.r[m] += 4;
+}
+
+/* MOV.B Rm,@(R0,Rn) */
+INLINE void MOVBS0(UINT32 m, UINT32 n)
+{
+ sh4.ea = sh4.r[n] + sh4.r[0];
+ WB( sh4.ea, sh4.r[m] & 0x000000ff );
+}
+
+/* MOV.W Rm,@(R0,Rn) */
+INLINE void MOVWS0(UINT32 m, UINT32 n)
+{
+ sh4.ea = sh4.r[n] + sh4.r[0];
+ WW( sh4.ea, sh4.r[m] & 0x0000ffff );
+}
+
+/* MOV.L Rm,@(R0,Rn) */
+INLINE void MOVLS0(UINT32 m, UINT32 n)
+{
+ sh4.ea = sh4.r[n] + sh4.r[0];
+ WL( sh4.ea, sh4.r[m] );
+}
+
+/* MOV.B @(R0,Rm),Rn */
+INLINE void MOVBL0(UINT32 m, UINT32 n)
+{
+ sh4.ea = sh4.r[m] + sh4.r[0];
+ sh4.r[n] = (UINT32)(INT32)(INT16)(INT8) RB( sh4.ea );
+}
+
+/* MOV.W @(R0,Rm),Rn */
+INLINE void MOVWL0(UINT32 m, UINT32 n)
+{
+ sh4.ea = sh4.r[m] + sh4.r[0];
+ sh4.r[n] = (UINT32)(INT32)(INT16) RW( sh4.ea );
+}
+
+/* MOV.L @(R0,Rm),Rn */
+INLINE void MOVLL0(UINT32 m, UINT32 n)
+{
+ sh4.ea = sh4.r[m] + sh4.r[0];
+ sh4.r[n] = RL( sh4.ea );
+}
+
+/* MOV #imm,Rn */
+INLINE void MOVI(UINT32 i, UINT32 n)
+{
+ sh4.r[n] = (UINT32)(INT32)(INT16)(INT8) i;
+}
+
+/* MOV.W @(disp8,PC),Rn */
+INLINE void MOVWI(UINT32 d, UINT32 n)
+{
+ UINT32 disp = d & 0xff;
+ sh4.ea = sh4.pc + disp * 2 + 2;
+ sh4.r[n] = (UINT32)(INT32)(INT16) RW( sh4.ea );
+}
+
+/* MOV.L @(disp8,PC),Rn */
+INLINE void MOVLI(UINT32 d, UINT32 n)
+{
+ UINT32 disp = d & 0xff;
+ sh4.ea = ((sh4.pc + 2) & ~3) + disp * 4;
+ sh4.r[n] = RL( sh4.ea );
+}
+
+/* MOV.B @(disp8,GBR),R0 */
+INLINE void MOVBLG(UINT32 d)
+{
+ UINT32 disp = d & 0xff;
+ sh4.ea = sh4.gbr + disp;
+ sh4.r[0] = (UINT32)(INT32)(INT16)(INT8) RB( sh4.ea );
+}
+
+/* MOV.W @(disp8,GBR),R0 */
+INLINE void MOVWLG(UINT32 d)
+{
+ UINT32 disp = d & 0xff;
+ sh4.ea = sh4.gbr + disp * 2;
+ sh4.r[0] = (INT32)(INT16) RW( sh4.ea );
+}
+
+/* MOV.L @(disp8,GBR),R0 */
+INLINE void MOVLLG(UINT32 d)
+{
+ UINT32 disp = d & 0xff;
+ sh4.ea = sh4.gbr + disp * 4;
+ sh4.r[0] = RL( sh4.ea );
+}
+
+/* MOV.B R0,@(disp8,GBR) */
+INLINE void MOVBSG(UINT32 d)
+{
+ UINT32 disp = d & 0xff;
+ sh4.ea = sh4.gbr + disp;
+ WB( sh4.ea, sh4.r[0] & 0x000000ff );
+}
+
+/* MOV.W R0,@(disp8,GBR) */
+INLINE void MOVWSG(UINT32 d)
+{
+ UINT32 disp = d & 0xff;
+ sh4.ea = sh4.gbr + disp * 2;
+ WW( sh4.ea, sh4.r[0] & 0x0000ffff );
+}
+
+/* MOV.L R0,@(disp8,GBR) */
+INLINE void MOVLSG(UINT32 d)
+{
+ UINT32 disp = d & 0xff;
+ sh4.ea = sh4.gbr + disp * 4;
+ WL( sh4.ea, sh4.r[0] );
+}
+
+/* MOV.B R0,@(disp4,Rn) */
+INLINE void MOVBS4(UINT32 d, UINT32 n)
+{
+ UINT32 disp = d & 0x0f;
+ sh4.ea = sh4.r[n] + disp;
+ WB( sh4.ea, sh4.r[0] & 0x000000ff );
+}
+
+/* MOV.W R0,@(disp4,Rn) */
+INLINE void MOVWS4(UINT32 d, UINT32 n)
+{
+ UINT32 disp = d & 0x0f;
+ sh4.ea = sh4.r[n] + disp * 2;
+ WW( sh4.ea, sh4.r[0] & 0x0000ffff );
+}
+
+/* MOV.L Rm,@(disp4,Rn) */
+INLINE void MOVLS4(UINT32 m, UINT32 d, UINT32 n)
+{
+ UINT32 disp = d & 0x0f;
+ sh4.ea = sh4.r[n] + disp * 4;
+ WL( sh4.ea, sh4.r[m] );
+}
+
+/* MOV.B @(disp4,Rm),R0 */
+INLINE void MOVBL4(UINT32 m, UINT32 d)
+{
+ UINT32 disp = d & 0x0f;
+ sh4.ea = sh4.r[m] + disp;
+ sh4.r[0] = (UINT32)(INT32)(INT16)(INT8) RB( sh4.ea );
+}
+
+/* MOV.W @(disp4,Rm),R0 */
+INLINE void MOVWL4(UINT32 m, UINT32 d)
+{
+ UINT32 disp = d & 0x0f;
+ sh4.ea = sh4.r[m] + disp * 2;
+ sh4.r[0] = (UINT32)(INT32)(INT16) RW( sh4.ea );
+}
+
+/* MOV.L @(disp4,Rm),Rn */
+INLINE void MOVLL4(UINT32 m, UINT32 d, UINT32 n)
+{
+ UINT32 disp = d & 0x0f;
+ sh4.ea = sh4.r[m] + disp * 4;
+ sh4.r[n] = RL( sh4.ea );
+}
+
+/* MOVA @(disp8,PC),R0 */
+INLINE void MOVA(UINT32 d)
+{
+ UINT32 disp = d & 0xff;
+ sh4.ea = ((sh4.pc + 2) & ~3) + disp * 4;
+ sh4.r[0] = sh4.ea;
+}
+
+/* MOVT Rn */
+INLINE void MOVT(UINT32 n)
+{
+ sh4.r[n] = sh4.sr & T;
+}
+
+/* MUL.L Rm,Rn */
+INLINE void MULL(UINT32 m, UINT32 n)
+{
+ sh4.macl = sh4.r[n] * sh4.r[m];
+ sh4_icount--;
+}
+
+/* MULS Rm,Rn */
+INLINE void MULS(UINT32 m, UINT32 n)
+{
+ sh4.macl = (INT16) sh4.r[n] * (INT16) sh4.r[m];
+}
+
+/* MULU Rm,Rn */
+INLINE void MULU(UINT32 m, UINT32 n)
+{
+ sh4.macl = (UINT16) sh4.r[n] * (UINT16) sh4.r[m];
+}
+
+/* NEG Rm,Rn */
+INLINE void NEG(UINT32 m, UINT32 n)
+{
+ sh4.r[n] = 0 - sh4.r[m];
+}
+
+/* NEGC Rm,Rn */
+INLINE void NEGC(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(void)
+{
+}
+
+/* NOT Rm,Rn */
+INLINE void NOT(UINT32 m, UINT32 n)
+{
+ sh4.r[n] = ~sh4.r[m];
+}
+
+/* OR Rm,Rn */
+INLINE void OR(UINT32 m, UINT32 n)
+{
+ sh4.r[n] |= sh4.r[m];
+}
+
+/* OR #imm,R0 */
+INLINE void ORI(UINT32 i)
+{
+ sh4.r[0] |= i;
+ sh4_icount -= 2;
+}
+
+/* OR.B #imm,@(R0,GBR) */
+INLINE void ORM(UINT32 i)
+{
+ UINT32 temp;
+
+ sh4.ea = sh4.gbr + sh4.r[0];
+ temp = RB( sh4.ea );
+ temp |= i;
+ WB( sh4.ea, temp );
+}
+
+/* ROTCL Rn */
+INLINE void ROTCL(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(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(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(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(void)
+{
+ sh4.delay = sh4.pc;
+ sh4.pc = sh4.ea = sh4.spc;
+#ifdef MAME_DEBUG
+ sh4_syncronize_register_bank((sh4.sr & sRB) >> 29);
+#endif
+ if ((sh4.ssr & sRB) != (sh4.sr & sRB))
+ sh4_change_register_bank(sh4.ssr & sRB ? 1 : 0);
+ sh4.sr = sh4.ssr;
+ sh4_icount--;
+ sh4_exception_recompute();
+}
+
+/* RTS */
+INLINE void RTS(void)
+{
+ sh4.delay = sh4.pc;
+ sh4.pc = sh4.ea = sh4.pr;
+ sh4_icount--;
+}
+
+/* SETT */
+INLINE void SETT(void)
+{
+ sh4.sr |= T;
+}
+
+/* SHAL Rn (same as SHLL) */
+INLINE void SHAL(UINT32 n)
+{
+ sh4.sr = (sh4.sr & ~T) | ((sh4.r[n] >> 31) & T);
+ sh4.r[n] <<= 1;
+}
+
+/* SHAR Rn */
+INLINE void SHAR(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(UINT32 n)
+{
+ sh4.sr = (sh4.sr & ~T) | ((sh4.r[n] >> 31) & T);
+ sh4.r[n] <<= 1;
+}
+
+/* SHLL2 Rn */
+INLINE void SHLL2(UINT32 n)
+{
+ sh4.r[n] <<= 2;
+}
+
+/* SHLL8 Rn */
+INLINE void SHLL8(UINT32 n)
+{
+ sh4.r[n] <<= 8;
+}
+
+/* SHLL16 Rn */
+INLINE void SHLL16(UINT32 n)
+{
+ sh4.r[n] <<= 16;
+}
+
+/* SHLR Rn */
+INLINE void SHLR(UINT32 n)
+{
+ sh4.sr = (sh4.sr & ~T) | (sh4.r[n] & T);
+ sh4.r[n] >>= 1;
+}
+
+/* SHLR2 Rn */
+INLINE void SHLR2(UINT32 n)
+{
+ sh4.r[n] >>= 2;
+}
+
+/* SHLR8 Rn */
+INLINE void SHLR8(UINT32 n)
+{
+ sh4.r[n] >>= 8;
+}
+
+/* SHLR16 Rn */
+INLINE void SHLR16(UINT32 n)
+{
+ sh4.r[n] >>= 16;
+}
+
+/* SLEEP */
+INLINE void SLEEP(void)
+{
+ sh4.pc -= 2;
+ sh4_icount -= 2;
+ /* Wait_for_exception; */
+}
+
+/* STC SR,Rn */
+INLINE void STCSR(UINT32 n)
+{
+ sh4.r[n] = sh4.sr;
+}
+
+/* STC GBR,Rn */
+INLINE void STCGBR(UINT32 n)
+{
+ sh4.r[n] = sh4.gbr;
+}
+
+/* STC VBR,Rn */
+INLINE void STCVBR(UINT32 n)
+{
+ sh4.r[n] = sh4.vbr;
+}
+
+/* STC.L SR,@-Rn */
+INLINE void STCMSR(UINT32 n)
+{
+ sh4.r[n] -= 4;
+ sh4.ea = sh4.r[n];
+ WL( sh4.ea, sh4.sr );
+ sh4_icount--;
+}
+
+/* STC.L GBR,@-Rn */
+INLINE void STCMGBR(UINT32 n)
+{
+ sh4.r[n] -= 4;
+ sh4.ea = sh4.r[n];
+ WL( sh4.ea, sh4.gbr );
+ sh4_icount--;
+}
+
+/* STC.L VBR,@-Rn */
+INLINE void STCMVBR(UINT32 n)
+{
+ sh4.r[n] -= 4;
+ sh4.ea = sh4.r[n];
+ WL( sh4.ea, sh4.vbr );
+ sh4_icount--;
+}
+
+/* STS MACH,Rn */
+INLINE void STSMACH(UINT32 n)
+{
+ sh4.r[n] = sh4.mach;
+}
+
+/* STS MACL,Rn */
+INLINE void STSMACL(UINT32 n)
+{
+ sh4.r[n] = sh4.macl;
+}
+
+/* STS PR,Rn */
+INLINE void STSPR(UINT32 n)
+{
+ sh4.r[n] = sh4.pr;
+}
+
+/* STS.L MACH,@-Rn */
+INLINE void STSMMACH(UINT32 n)
+{
+ sh4.r[n] -= 4;
+ sh4.ea = sh4.r[n];
+ WL( sh4.ea, sh4.mach );
+}
+
+/* STS.L MACL,@-Rn */
+INLINE void STSMMACL(UINT32 n)
+{
+ sh4.r[n] -= 4;
+ sh4.ea = sh4.r[n];
+ WL( sh4.ea, sh4.macl );
+}
+
+/* STS.L PR,@-Rn */
+INLINE void STSMPR(UINT32 n)
+{
+ sh4.r[n] -= 4;
+ sh4.ea = sh4.r[n];
+ WL( sh4.ea, sh4.pr );
+}
+
+/* SUB Rm,Rn */
+INLINE void SUB(UINT32 m, UINT32 n)
+{
+ sh4.r[n] -= sh4.r[m];
+}
+
+/* SUBC Rm,Rn */
+INLINE void SUBC(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(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(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(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(UINT32 n)
+{
+ UINT32 temp;
+ sh4.ea = sh4.r[n];
+ /* Bus Lock enable */
+ temp = RB( sh4.ea );
+ if (temp == 0)
+ sh4.sr |= T;
+ else
+ sh4.sr &= ~T;
+ temp |= 0x80;
+ /* Bus Lock disable */
+ WB( sh4.ea, temp );
+ sh4_icount -= 3;
+}
+
+/* TRAPA #imm */
+INLINE void TRAPA(UINT32 i)
+{
+ UINT32 imm = i & 0xff;
+
+ sh4.ea = sh4.vbr + imm * 4;
+
+ sh4.r[15] -= 4;
+ WL( sh4.r[15], sh4.sr );
+ sh4.r[15] -= 4;
+ WL( sh4.r[15], sh4.pc );
+
+ sh4.pc = RL( sh4.ea );
+ change_pc(sh4.pc & AM);
+
+ sh4_icount -= 7;
+}
+
+/* TST Rm,Rn */
+INLINE void TST(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(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(UINT32 i)
+{
+ UINT32 imm = i & 0xff;
+
+ sh4.ea = sh4.gbr + sh4.r[0];
+ if ((imm & RB( sh4.ea )) == 0)
+ sh4.sr |= T;
+ else
+ sh4.sr &= ~T;
+ sh4_icount -= 2;
+}
+
+/* XOR Rm,Rn */
+INLINE void XOR(UINT32 m, UINT32 n)
+{
+ sh4.r[n] ^= sh4.r[m];
+}
+
+/* XOR #imm,R0 */
+INLINE void XORI(UINT32 i)
+{
+ UINT32 imm = i & 0xff;
+ sh4.r[0] ^= imm;
+}
+
+/* XOR.B #imm,@(R0,GBR) */
+INLINE void XORM(UINT32 i)
+{
+ UINT32 imm = i & 0xff;
+ UINT32 temp;
+
+ sh4.ea = sh4.gbr + sh4.r[0];
+ temp = RB( sh4.ea );
+ temp ^= imm;
+ WB( sh4.ea, temp );
+ sh4_icount -= 2;
+}
+
+/* XTRCT Rm,Rn */
+INLINE void XTRCT(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(UINT32 n)
+{
+ sh4.r[n] = sh4.ssr;
+}
+
+/* STC SPC,Rn */
+INLINE void STCSPC(UINT32 n)
+{
+ sh4.r[n] = sh4.spc;
+}
+
+/* STC SGR,Rn */
+INLINE void STCSGR(UINT32 n)
+{
+ sh4.r[n] = sh4.sgr;
+}
+
+/* STS FPUL,Rn */
+INLINE void STSFPUL(UINT32 n)
+{
+ sh4.r[n] = sh4.fpul;
+}
+
+/* STS FPSCR,Rn */
+INLINE void STSFPSCR(UINT32 n)
+{
+ sh4.r[n] = sh4.fpscr & 0x003FFFFF;
+}
+
+/* STC DBR,Rn */
+INLINE void STCDBR(UINT32 n)
+{
+ sh4.r[n] = sh4.dbr;
+}
+
+/* STCRBANK Rm_BANK,Rn */
+INLINE void STCRBANK(UINT32 m, UINT32 n)
+{
+ sh4.r[n] = sh4.rbnk[sh4.sr&sRB ? 0 : 1][m & 7];
+}
+
+/* STCMRBANK Rm_BANK,@-Rn */
+INLINE void STCMRBANK(UINT32 m, UINT32 n)
+{
+ sh4.r[n] -= 4;
+ sh4.ea = sh4.r[n];
+ WL( sh4.ea, sh4.rbnk[sh4.sr&sRB ? 0 : 1][m & 7]);
+ sh4_icount--;
+}
+
+/* MOVCA.L R0,@Rn */
+INLINE void MOVCAL(UINT32 n)
+{
+ sh4.ea = sh4.r[n];
+ WL( sh4.ea, sh4.r[0] );
+}
+
+INLINE void CLRS(void)
+{
+ sh4.sr &= ~S;
+}
+
+INLINE void SETS(void)
+{
+ sh4.sr |= S;
+}
+
+/* STS.L SGR,@-Rn */
+INLINE void STCMSGR(UINT32 n)
+{
+ sh4.r[n] -= 4;
+ sh4.ea = sh4.r[n];
+ WL( sh4.ea, sh4.sgr );
+}
+
+/* STS.L FPUL,@-Rn */
+INLINE void STSMFPUL(UINT32 n)
+{
+ sh4.r[n] -= 4;
+ sh4.ea = sh4.r[n];
+ WL( sh4.ea, sh4.fpul );
+}
+
+/* STS.L FPSCR,@-Rn */
+INLINE void STSMFPSCR(UINT32 n)
+{
+ sh4.r[n] -= 4;
+ sh4.ea = sh4.r[n];
+ WL( sh4.ea, sh4.fpscr & 0x003FFFFF);
+}
+
+/* STC.L DBR,@-Rn */
+INLINE void STCMDBR(UINT32 n)
+{
+ sh4.r[n] -= 4;
+ sh4.ea = sh4.r[n];
+ WL( sh4.ea, sh4.dbr );
+}
+
+/* STC.L SSR,@-Rn */
+INLINE void STCMSSR(UINT32 n)
+{
+ sh4.r[n] -= 4;
+ sh4.ea = sh4.r[n];
+ WL( sh4.ea, sh4.ssr );
+}
+
+/* STC.L SPC,@-Rn */
+INLINE void STCMSPC(UINT32 n)
+{
+ sh4.r[n] -= 4;
+ sh4.ea = sh4.r[n];
+ WL( sh4.ea, sh4.spc );
+}
+
+/* LDS.L @Rm+,FPUL */
+INLINE void LDSMFPUL(UINT32 m)
+{
+ sh4.ea = sh4.r[m];
+ sh4.fpul = RL( sh4.ea );
+ sh4.r[m] += 4;
+}
+
+/* LDS.L @Rm+,FPSCR */
+INLINE void LDSMFPSCR(UINT32 m)
+{
+UINT32 s;
+
+ s = sh4.fpscr;
+ sh4.ea = sh4.r[m];
+ sh4.fpscr = RL( sh4.ea );
+ sh4.fpscr &= 0x003FFFFF;
+ sh4.r[m] += 4;
+ if ((s & FR) != (sh4.fpscr & FR))
+ sh4_swap_fp_registers();
+}
+
+/* LDC.L @Rm+,DBR */
+INLINE void LDCMDBR(UINT32 m)
+{
+ sh4.ea = sh4.r[m];
+ sh4.dbr = RL( sh4.ea );
+ sh4.r[m] += 4;
+}
+
+/* LDC.L @Rn+,Rm_BANK */
+INLINE void LDCMRBANK(UINT32 m, UINT32 n)
+{
+ sh4.ea = sh4.r[n];
+ sh4.rbnk[sh4.sr&sRB ? 0 : 1][m & 7] = RL( sh4.ea );
+ sh4.r[n] += 4;
+}
+
+/* LDC.L @Rm+,SSR */
+INLINE void LDCMSSR(UINT32 m)
+{
+ sh4.ea = sh4.r[m];
+ sh4.ssr = RL( sh4.ea );
+ sh4.r[m] += 4;
+}
+
+/* LDC.L @Rm+,SPC */
+INLINE void LDCMSPC(UINT32 m)
+{
+ sh4.ea = sh4.r[m];
+ sh4.spc = RL( sh4.ea );
+ sh4.r[m] += 4;
+}
+
+/* LDS Rm,FPUL */
+INLINE void LDSFPUL(UINT32 m)
+{
+ sh4.fpul = sh4.r[m];
+}
+
+/* LDS Rm,FPSCR */
+INLINE void LDSFPSCR(UINT32 m)
+{
+UINT32 s;
+
+ s = sh4.fpscr;
+ sh4.fpscr = sh4.r[m] & 0x003FFFFF;
+ if ((s & FR) != (sh4.fpscr & FR))
+ sh4_swap_fp_registers();
+}
+
+/* LDC Rm,DBR */
+INLINE void LDCDBR(UINT32 m)
+{
+ sh4.dbr = sh4.r[m];
+}
+
+/* SHAD Rm,Rn */
+INLINE void SHAD(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(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(UINT32 m, UINT32 n)
+{
+ sh4.rbnk[sh4.sr&sRB ? 0 : 1][m & 7] = sh4.r[n];
+}
+
+/* LDC Rm,SSR */
+INLINE void LDCSSR(UINT32 m)
+{
+ sh4.ssr = sh4.r[m];
+}
+
+/* LDC Rm,SPC */
+INLINE void LDCSPC(UINT32 m)
+{
+ sh4.spc = sh4.r[m];
+}
+
+/* PREF @Rn */
+INLINE void PREFM(UINT32 n)
+{
+int a;
+UINT32 addr,dest,sq;
+
+ addr = sh4.r[n]; // address
+ if ((addr >= 0xE0000000) && (addr <= 0xE3FFFFFF))
+ {
+ 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 < 8;a++)
+ {
+ program_write_dword_64le(dest, program_read_dword_64le(addr));
+ addr += 4;
+ dest += 4;
+ }
+ }
+}
+
+/*****************************************************************************
+ * OPCODE DISPATCHERS
+ *****************************************************************************/
+INLINE void op0000(UINT16 opcode)
+{
+ switch (opcode & 0xF)
+ {
+ case 0x0:
+ case 0x1:
+ break;
+ case 0x2:
+ if (opcode & 0x80) {
+ STCRBANK(Rm, Rn); return;
+ }
+ switch (opcode & 0x70)
+ {
+ case 0x00:
+ STCSR(Rn); break;
+ case 0x10:
+ STCGBR(Rn); break;
+ case 0x20:
+ STCVBR(Rn); break;
+ case 0x30:
+ STCSSR(Rn); break;
+ case 0x40:
+ STCSPC(Rn); break;
+ }
+ break;
+ case 0x3:
+ switch (opcode & 0xF0)
+ {
+ case 0x00:
+ BSRF(Rn); break;
+ case 0x20:
+ BRAF(Rn); break;
+ case 0x80:
+ PREFM(Rn); break;
+ case 0x90:
+ TODO(); break;
+ case 0xA0:
+ TODO(); break;
+ case 0xB0:
+ TODO(); break;
+ case 0xC0:
+ MOVCAL(Rn); break;
+ }
+ break;
+ case 0x4:
+ MOVBS0(Rm, Rn); break;
+ case 0x5:
+ MOVWS0(Rm, Rn); break;
+ case 0x6:
+ MOVLS0(Rm, Rn); break;
+ case 0x7:
+ MULL(Rm, Rn); break;
+ case 0x8:
+ switch (opcode & 0x70)
+ {
+ case 0x00:
+ CLRT(); break;
+ case 0x10:
+ SETT(); break;
+ case 0x20:
+ CLRMAC(); break;
+ case 0x30:
+ TODO(); break;
+ case 0x40:
+ CLRS(); break;
+ case 0x50:
+ SETS(); break;
+ }
+ break;
+ case 0x9:
+ switch (opcode & 0x30)
+ {
+ case 0x00:
+ NOP(); break;
+ case 0x10:
+ DIV0U(); break;
+ case 0x20:
+ MOVT(Rn); break;
+ }
+ break;
+ case 0xA:
+ switch (opcode & 0x70)
+ {
+ case 0x00:
+ STSMACH(Rn); break;
+ case 0x10:
+ STSMACL(Rn); break;
+ case 0x20:
+ STSPR(Rn); break;
+ case 0x30:
+ STCSGR(Rn); break;
+ case 0x50:
+ STSFPUL(Rn); break;
+ case 0x60:
+ STSFPSCR(Rn); break;
+ case 0x70:
+ STCDBR(Rn); break;
+ }
+ break;
+ case 0xB:
+ switch (opcode & 0x30)
+ {
+ case 0x00:
+ RTS(); break;
+ case 0x10:
+ SLEEP(); break;
+ case 0x20:
+ RTE(); break;
+ }
+ break;
+ case 0xC:
+ MOVBL0(Rm, Rn); break;
+ case 0xD:
+ MOVWL0(Rm, Rn); break;
+ case 0xE:
+ MOVLL0(Rm, Rn); break;
+ case 0xF:
+ MAC_L(Rm, Rn); break;
+ }
+}
+
+INLINE void op0001(UINT16 opcode)
+{
+ MOVLS4(Rm, opcode & 0x0f, Rn);
+}
+
+INLINE void op0010(UINT16 opcode)
+{
+ switch (opcode & 15)
+ {
+ case 0: MOVBS(Rm, Rn); break;
+ case 1: MOVWS(Rm, Rn); break;
+ case 2: MOVLS(Rm, Rn); break;
+ case 3: NOP(); break;
+ case 4: MOVBM(Rm, Rn); break;
+ case 5: MOVWM(Rm, Rn); break;
+ case 6: MOVLM(Rm, Rn); break;
+ case 7: DIV0S(Rm, Rn); break;
+ case 8: TST(Rm, Rn); break;
+ case 9: AND(Rm, Rn); break;
+ case 10: XOR(Rm, Rn); break;
+ case 11: OR(Rm, Rn); break;
+ case 12: CMPSTR(Rm, Rn); break;
+ case 13: XTRCT(Rm, Rn); break;
+ case 14: MULU(Rm, Rn); break;
+ case 15: MULS(Rm, Rn); break;
+ }
+}
+
+INLINE void op0011(UINT16 opcode)
+{
+ switch (opcode & 15)
+ {
+ case 0: CMPEQ(Rm, Rn); break;
+ case 1: NOP(); break;
+ case 2: CMPHS(Rm, Rn); break;
+ case 3: CMPGE(Rm, Rn); break;
+ case 4: DIV1(Rm, Rn); break;
+ case 5: DMULU(Rm, Rn); break;
+ case 6: CMPHI(Rm, Rn); break;
+ case 7: CMPGT(Rm, Rn); break;
+ case 8: SUB(Rm, Rn); break;
+ case 9: NOP(); break;
+ case 10: SUBC(Rm, Rn); break;
+ case 11: SUBV(Rm, Rn); break;
+ case 12: ADD(Rm, Rn); break;
+ case 13: DMULS(Rm, Rn); break;
+ case 14: ADDC(Rm, Rn); break;
+ case 15: ADDV(Rm, Rn); break;
+ }
+}
+
+INLINE void op0100(UINT16 opcode)
+{
+ switch (opcode & 0xF)
+ {
+ case 0x0:
+ switch (opcode & 0x30)
+ {
+ case 0x00:
+ SHLL(Rn); break;
+ case 0x10:
+ DT(Rn); break;
+ case 0x20:
+ SHAL(Rn); break;
+ }
+ break;
+ case 0x1:
+ switch (opcode & 0x30)
+ {
+ case 0x00:
+ SHLR(Rn); break;
+ case 0x10:
+ CMPPZ(Rn); break;
+ case 0x20:
+ SHAR(Rn); break;
+ }
+ break;
+ case 0x2:
+ switch (opcode & 0xF0)
+ {
+ case 0x00:
+ STSMMACH(Rn); break;
+ case 0x10:
+ STSMMACL(Rn); break;
+ case 0x20:
+ STSMPR(Rn); break;
+ case 0x30:
+ STCMSGR(Rn); break;
+ case 0x50:
+ STSMFPUL(Rn); break;
+ case 0x60:
+ STSMFPSCR(Rn); break;
+ case 0xF0:
+ STCMDBR(Rn); break;
+ }
+ break;
+ case 0x3:
+ if (opcode & 0x80) {
+ STCMRBANK(Rm, Rn); return;
+ }
+ switch (opcode & 0x70)
+ {
+ case 0x00:
+ STCMSR(Rn); break;
+ case 0x10:
+ STCMGBR(Rn); break;
+ case 0x20:
+ STCMVBR(Rn); break;
+ case 0x30:
+ STCMSSR(Rn); break;
+ case 0x40:
+ STCMSPC(Rn); break;
+ }
+ break;
+ case 0x4:
+ switch (opcode & 0x30)
+ {
+ case 0x00:
+ ROTL(Rn); break;
+ case 0x20:
+ ROTCL(Rn); break;
+ }
+ break;
+ case 0x5:
+ switch (opcode & 0x30)
+ {
+ case 0x00:
+ ROTR(Rn); break;
+ case 0x10:
+ CMPPL(Rn); break;
+ case 0x20:
+ ROTCR(Rn); break;
+ }
+ break;
+ case 0x6:
+ switch (opcode & 0xF0)
+ {
+ case 0x00:
+ LDSMMACH(Rn); break;
+ case 0x10:
+ LDSMMACL(Rn); break;
+ case 0x20:
+ LDSMPR(Rn); break;
+ case 0x50:
+ LDSMFPUL(Rn); break;
+ case 0x60:
+ LDSMFPSCR(Rn); break;
+ case 0xF0:
+ LDCMDBR(Rn); break;
+ }
+ break;
+ case 0x7:
+ if (opcode & 0x80) {
+ LDCMRBANK(Rm,Rn); return;
+ }
+ switch (opcode & 0x70)
+ {
+ case 0x00:
+ LDCMSR(Rn); break;
+ case 0x10:
+ LDCMGBR(Rn); break;
+ case 0x20:
+ LDCMVBR(Rn); break;
+ case 0x30:
+ LDCMSSR(Rn); break;
+ case 0x40:
+ LDCMSPC(Rn); break;
+ }
+ break;
+ case 0x8:
+ switch (opcode & 0x30)
+ {
+ case 0x00:
+ SHLL2(Rn); break;
+ case 0x10:
+ SHLL8(Rn); break;
+ case 0x20:
+ SHLL16(Rn); break;
+ }
+ break;
+ case 0x9:
+ switch (opcode & 0x30)
+ {
+ case 0x00:
+ SHLR2(Rn); break;
+ case 0x10:
+ SHLR8(Rn); break;
+ case 0x20:
+ SHLR16(Rn); break;
+ }
+ break;
+ case 0xA:
+ switch (opcode & 0xF0)
+ {
+ case 0x00:
+ LDSMACH(Rn); break;
+ case 0x10:
+ LDSMACL(Rn); break;
+ case 0x20:
+ LDSPR(Rn); break;
+ case 0x50:
+ LDSFPUL(Rn); break;
+ case 0x60:
+ LDSFPSCR(Rn); break;
+ case 0xF0:
+ LDCDBR(Rn); break;
+ }
+ break;
+ case 0xB:
+ switch (opcode & 0x30)
+ {
+ case 0x00:
+ JSR(Rn); break;
+ case 0x10:
+ TAS(Rn); break;
+ case 0x20:
+ JMP(Rn); break;
+ }
+ break;
+ case 0xC:
+ SHAD(Rm,Rn); break;
+ case 0xD:
+ SHLD(Rm,Rn); break;
+ case 0xE:
+ if (opcode & 0x80) {
+ LDCRBANK(Rm,Rn); return;
+ }
+ switch (opcode & 0x70)
+ {
+ case 0x00:
+ LDCSR(Rn); break;
+ case 0x10:
+ LDCGBR(Rn); break;
+ case 0x20:
+ LDCVBR(Rn); break;
+ case 0x30:
+ LDCSSR(Rn); break;
+ case 0x40:
+ LDCSPC(Rn); break;
+ }
+ break;
+ case 0xF:
+ MAC_W(Rm, Rn); break;
+ }
+}
+
+INLINE void op0101(UINT16 opcode)
+{
+ MOVLL4(Rm, opcode & 0x0f, Rn);
+}
+
+INLINE void op0110(UINT16 opcode)
+{
+ switch (opcode & 15)
+ {
+ case 0: MOVBL(Rm, Rn); break;
+ case 1: MOVWL(Rm, Rn); break;
+ case 2: MOVLL(Rm, Rn); break;
+ case 3: MOV(Rm, Rn); break;
+ case 4: MOVBP(Rm, Rn); break;
+ case 5: MOVWP(Rm, Rn); break;
+ case 6: MOVLP(Rm, Rn); break;
+ case 7: NOT(Rm, Rn); break;
+ case 8: SWAPB(Rm, Rn); break;
+ case 9: SWAPW(Rm, Rn); break;
+ case 10: NEGC(Rm, Rn); break;
+ case 11: NEG(Rm, Rn); break;
+ case 12: EXTUB(Rm, Rn); break;
+ case 13: EXTUW(Rm, Rn); break;
+ case 14: EXTSB(Rm, Rn); break;
+ case 15: EXTSW(Rm, Rn); break;
+ }
+}
+
+INLINE void op0111(UINT16 opcode)
+{
+ ADDI(opcode & 0xff, Rn);
+}
+
+INLINE void op1000(UINT16 opcode)
+{
+ switch ( opcode & (15<<8) )
+ {
+ case 0 << 8: MOVBS4(opcode & 0x0f, Rm); break;
+ case 1 << 8: MOVWS4(opcode & 0x0f, Rm); break;
+ case 2<< 8: NOP(); break;
+ case 3<< 8: NOP(); break;
+ case 4<< 8: MOVBL4(Rm, opcode & 0x0f); break;
+ case 5<< 8: MOVWL4(Rm, opcode & 0x0f); break;
+ case 6<< 8: NOP(); break;
+ case 7<< 8: NOP(); break;
+ case 8<< 8: CMPIM(opcode & 0xff); break;
+ case 9<< 8: BT(opcode & 0xff); break;
+ case 10<< 8: NOP(); break;
+ case 11<< 8: BF(opcode & 0xff); break;
+ case 12<< 8: NOP(); break;
+ case 13<< 8: BTS(opcode & 0xff); break;
+ case 14<< 8: NOP(); break;
+ case 15<< 8: BFS(opcode & 0xff); break;
+ }
+}
+
+
+INLINE void op1001(UINT16 opcode)
+{
+ MOVWI(opcode & 0xff, Rn);
+}
+
+INLINE void op1010(UINT16 opcode)
+{
+ BRA(opcode & 0xfff);
+}
+
+INLINE void op1011(UINT16 opcode)
+{
+ BSR(opcode & 0xfff);
+}
+
+INLINE void op1100(UINT16 opcode)
+{
+ switch (opcode & (15<<8))
+ {
+ case 0<<8: MOVBSG(opcode & 0xff); break;
+ case 1<<8: MOVWSG(opcode & 0xff); break;
+ case 2<<8: MOVLSG(opcode & 0xff); break;
+ case 3<<8: TRAPA(opcode & 0xff); break;
+ case 4<<8: MOVBLG(opcode & 0xff); break;
+ case 5<<8: MOVWLG(opcode & 0xff); break;
+ case 6<<8: MOVLLG(opcode & 0xff); break;
+ case 7<<8: MOVA(opcode & 0xff); break;
+ case 8<<8: TSTI(opcode & 0xff); break;
+ case 9<<8: ANDI(opcode & 0xff); break;
+ case 10<<8: XORI(opcode & 0xff); break;
+ case 11<<8: ORI(opcode & 0xff); break;
+ case 12<<8: TSTM(opcode & 0xff); break;
+ case 13<<8: ANDM(opcode & 0xff); break;
+ case 14<<8: XORM(opcode & 0xff); break;
+ case 15<<8: ORM(opcode & 0xff); break;
+ }
+}
+
+INLINE void op1101(UINT16 opcode)
+{
+ MOVLI(opcode & 0xff, Rn);
+}
+
+INLINE void op1110(UINT16 opcode)
+{
+ MOVI(opcode & 0xff, Rn);
+}
+
+/* FMOV @Rm+,DRn PR=0 SZ=1 1111nnn0mmmm1001 */
+/* FMOV @Rm+,XDn PR=1 1111nnn1mmmm1001 */
+/* FMOV.S @Rm+,FRn PR=0 SZ=0 1111nnnnmmmm1001 */
+INLINE void FMOVMRIFR(UINT32 m,UINT32 n)
+{
+ if (sh4.fpscr & PR) { /* PR = 1 */
+ n = n & 14;
+ sh4.ea = sh4.r[m];
+ sh4.xf[n] = RL( sh4.ea );
+ sh4.r[m] += 4;
+ sh4.xf[n+1] = RL( sh4.r[m] );
+ sh4.r[m] += 4;
+ } else { /* PR = 0 */
+ if (sh4.fpscr & SZ) { /* SZ = 1 */
+ n = n & 14;
+ sh4.ea = sh4.r[m];
+ sh4.fr[n] = RL( sh4.ea );
+ sh4.r[m] += 4;
+ sh4.fr[n+1] = RL( sh4.r[m] );
+ sh4.r[m] += 4;
+ } else { /* SZ = 0 */
+ sh4.ea = sh4.r[m];
+ sh4.fr[n] = RL( sh4.ea );
+ sh4.r[m] += 4;
+ }
+ }
+}
+
+/* FMOV XDm,@Rn PR=1 1111nnnnmmm11010 */
+/* FMOV.S FRm,@Rn PR=0 SZ=0 1111nnnnmmmm1010 */
+/* FMOV DRm,@Rn PR=0 SZ=1 1111nnnnmmm01010 */
+INLINE void FMOVFRMR(UINT32 m,UINT32 n)
+{
+ if (sh4.fpscr & PR) { /* PR = 1 */
+ m= m & 14;
+ sh4.ea = sh4.r[n];
+ WL( sh4.ea,sh4.xf[m] );
+ WL( sh4.ea+4,sh4.xf[m+1] );
+ } else { /* PR = 0 */
+ if (sh4.fpscr & SZ) { /* SZ = 1 */
+ m= m & 14;
+ sh4.ea = sh4.r[n];
+ WL( sh4.ea,sh4.fr[m] );
+ WL( sh4.ea+4,sh4.fr[m+1] );
+ } else { /* SZ = 0 */
+ sh4.ea = sh4.r[n];
+ WL( sh4.ea,sh4.fr[m] );
+ }
+ }
+}
+
+/* FMOV XDm,@-Rn PR=1 1111nnnnmmm11011 */
+/* FMOV.S FRm,@-Rn PR=0 SZ=0 1111nnnnmmmm1011 */
+/* FMOV DRm,@-Rn PR=0 SZ=1 1111nnnnmmm01011 */
+INLINE void FMOVFRMDR(UINT32 m,UINT32 n)
+{
+ if (sh4.fpscr & PR) { /* PR = 1 */
+ m= m & 14;
+ sh4.r[n] -= 8;
+ sh4.ea = sh4.r[n];
+ WL( sh4.ea,sh4.xf[m] );
+ WL( sh4.ea+4,sh4.xf[m+1] );
+ } else { /* PR = 0 */
+ if (sh4.fpscr & SZ) { /* SZ = 1 */
+ m= m & 14;
+ sh4.r[n] -= 8;
+ sh4.ea = sh4.r[n];
+ WL( sh4.ea,sh4.fr[m] );
+ WL( sh4.ea+4,sh4.fr[m+1] );
+ } else { /* SZ = 0 */
+ sh4.r[n] -= 4;
+ sh4.ea = sh4.r[n];
+ WL( sh4.ea,sh4.fr[m] );
+ }
+ }
+}
+
+/* FLDI1 FRn 1111nnnn10011101 */
+INLINE void FLDI1(UINT32 n)
+{
+ sh4.fr[n] = 0x3F800000;
+}
+
+/* FLDI0 FRn 1111nnnn10001101 */
+INLINE void FLDI0(UINT32 n)
+{
+ sh4.fr[n] = 0;
+}
+
+/* FMOV XDm,@(R0,Rn) PR=1 1111nnnnmmm10111 */
+/* FMOV.S FRm,@(R0,Rn) PR=0 SZ=0 1111nnnnmmmm0111 */
+/* FMOV DRm,@(R0,Rn) PR=0 SZ=1 1111nnnnmmm00111 */
+INLINE void FMOVFRS0(UINT32 m,UINT32 n)
+{
+ if (sh4.fpscr & PR) { /* PR = 1 */
+ m= m & 14;
+ sh4.ea = sh4.r[0] + sh4.r[n];
+ WL( sh4.ea,sh4.xf[m] );
+ WL( sh4.ea+4,sh4.xf[m+1] );
+ } else { /* PR = 0 */
+ if (sh4.fpscr & SZ) { /* SZ = 1 */
+ m= m & 14;
+ sh4.ea = sh4.r[0] + sh4.r[n];
+ WL( sh4.ea,sh4.fr[m] );
+ WL( sh4.ea+4,sh4.fr[m+1] );
+ } else { /* SZ = 0 */
+ sh4.ea = sh4.r[0] + sh4.r[n];
+ WL( sh4.ea,sh4.fr[m] );
+ }
+ }
+}
+
+/* FMOV @(R0,Rm),XDn PR=1 1111nnn1mmmm0110 */
+/* FMOV.S @(R0,Rm),FRn PR=0 SZ=0 1111nnnnmmmm0110 */
+/* FMOV @(R0,Rm),DRn PR=0 SZ=1 1111nnn0mmmm0110 */
+INLINE void FMOVS0FR(UINT32 m,UINT32 n)
+{
+ if (sh4.fpscr & PR) { /* PR = 1 */
+ n= n & 14;
+ sh4.ea = sh4.r[0] + sh4.r[m];
+ sh4.xf[n] = RL( sh4.ea );
+ sh4.xf[n+1] = RL( sh4.ea+4 );
+ } else { /* PR = 0 */
+ if (sh4.fpscr & SZ) { /* SZ = 1 */
+ n= n & 14;
+ sh4.ea = sh4.r[0] + sh4.r[m];
+ sh4.fr[n] = RL( sh4.ea );
+ sh4.fr[n+1] = RL( sh4.ea+4 );
+ } else { /* SZ = 0 */
+ sh4.ea = sh4.r[0] + sh4.r[m];
+ sh4.fr[n] = RL( sh4.ea );
+ }
+ }
+}
+
+/* FMOV @Rm,XDn PR=1 1111nnn1mmmm1000 */
+/* FMOV.S @Rm,FRn PR=0 SZ=0 1111nnnnmmmm1000 */
+/* FMOV @Rm,DRn PR=0 SZ=1 1111nnn0mmmm1000 */
+INLINE void FMOVMRFR(UINT32 m,UINT32 n)
+{
+ if (sh4.fpscr & PR) { /* PR = 1 */
+ n= n & 14;
+ sh4.ea = sh4.r[m];
+ sh4.xf[n] = RL( sh4.ea );
+ sh4.xf[n+1] = RL( sh4.ea+4 );
+ } else { /* PR = 0 */
+ if (sh4.fpscr & SZ) { /* SZ = 1 */
+ n= n & 14;
+ sh4.ea = sh4.r[m];
+ sh4.fr[n] = RL( sh4.ea );
+ sh4.fr[n+1] = RL( sh4.ea+4 );
+ } else { /* SZ = 0 */
+ sh4.ea = sh4.r[m];
+ sh4.fr[n] = RL( sh4.ea );
+ }
+ }
+}
+
+/* FRCHG 1111101111111101 */
+INLINE void FRCHG(void)
+{
+ sh4.fpscr ^= FR;
+ sh4_swap_fp_registers();
+}
+
+/* FSCHG 1111001111111101 */
+INLINE void FSCHG(void)
+{
+ sh4.fpscr ^= SZ;
+}
+
+INLINE void op1111(UINT16 opcode)
+{
+ switch (opcode & 0xf)
+ {
+ case 0:
+ TODO();
+ break;
+ case 1:
+ TODO();
+ break;
+ case 2:
+ TODO();
+ break;
+ case 3:
+ TODO();
+ break;
+ case 4:
+ TODO();
+ break;
+ case 5:
+ TODO();
+ break;
+ case 6:
+ FMOVS0FR(Rm,Rn);
+ break;
+ case 7:
+ FMOVFRS0(Rm,Rn);
+ break;
+ case 8:
+ FMOVMRFR(Rm,Rn);
+ break;
+ case 9:
+ FMOVMRIFR(Rm,Rn);
+ break;
+ case 10:
+ FMOVFRMR(Rm,Rn);
+ break;
+ case 11:
+ FMOVFRMDR(Rm,Rn);
+ break;
+ case 12:
+ TODO();
+ break;
+ case 13:
+ switch (opcode & 0xF0)
+ {
+ case 0x00:
+ TODO();
+ break;
+ case 0x10:
+ TODO();
+ break;
+ case 0x20:
+ TODO();
+ break;
+ case 0x30:
+ TODO();
+ break;
+ case 0x40:
+ TODO();
+ break;
+ case 0x50:
+ TODO();
+ break;
+ case 0x60:
+ TODO();
+ break;
+ case 0x80:
+ FLDI0(Rn);
+ break;
+ case 0x90:
+ FLDI1(Rn);
+ break;
+ case 0xA0:
+ TODO();
+ break;
+ case 0xB0:
+ TODO();
+ break;
+ case 0xE0:
+ TODO();
+ break;
+ case 0xF0:
+ if (opcode == 0xF3FD)
+ FSCHG();
+ else if (opcode == 0xFBFD)
+ FRCHG();
+ else if ((opcode & 0x300) == 0x100)
+ TODO();
+ break;
+ }
+ break;
+ case 14:
+ TODO();
+ break;
+ }
+}
+
+/*****************************************************************************
+ * MAME CPU INTERFACE
+ *****************************************************************************/
+
+static void sh4_reset(void)
+{
+ void *tsaved[4];
+ emu_timer *tsave[5];
+ UINT32 *m;
+ int cpunum;
+ int save_is_slave;
+ int savecpu_clock, savebus_clock, savepm_clock;
+
+ void (*f)(UINT32 data);
+ int (*save_irqcallback)(int);
+
+ cpunum = sh4.cpu_number;
+ 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.timer0;
+ tsave[3] = sh4.timer1;
+ tsave[4] = sh4.timer2;
+
+ 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.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.timer0 = tsave[2];
+ sh4.timer1 = tsave[3];
+ sh4.timer2 = tsave[4];
+ sh4.cpu_number = cpunum;
+ sh4.m = m;
+ memset(sh4.m, 0, 16384*4);
+ sh4_default_exception_priorities();
+ memset(sh4.exception_requesting, 0, sizeof(sh4.exception_requesting));
+
+ timer_adjust(sh4.rtc_timer, ATTOTIME_IN_HZ(128), cpunum, attotime_zero);
+ 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(4);
+ sh4.sr = 0x700000f0;
+ sh4.fpscr = 0x00040001;
+ sh4.fpul = 0;
+ sh4.dbr = 0;
+ change_pc(sh4.pc & AM);
+
+ sh4.internal_irq_level = -1;
+ sh4.irln = 15;
+}
+
+/* Execute cycles - returns number of cycles actually run */
+static int sh4_execute(int cycles)
+{
+ sh4_icount = cycles;
+
+ if (sh4.cpu_off)
+ return 0;
+
+ do
+ {
+ UINT32 opcode;
+
+ if (sh4.delay)
+ {
+ opcode = cpu_readop16(WORD2_XOR_LE((UINT32)(sh4.delay & AM)));
+ change_pc(sh4.pc & AM);
+ sh4.pc -= 2;
+ }
+ else
+ opcode = cpu_readop16(WORD2_XOR_LE((UINT32)(sh4.pc & AM)));
+
+ CALL_MAME_DEBUG;
+
+ sh4.delay = 0;
+ sh4.pc += 2;
+ sh4.ppc = sh4.pc;
+
+ switch (opcode & ( 15 << 12))
+ {
+ case 0<<12: op0000(opcode); break;
+ case 1<<12: op0001(opcode); break;
+ case 2<<12: op0010(opcode); break;
+ case 3<<12: op0011(opcode); break;
+ case 4<<12: op0100(opcode); break;
+ case 5<<12: op0101(opcode); break;
+ case 6<<12: op0110(opcode); break;
+ case 7<<12: op0111(opcode); break;
+ case 8<<12: op1000(opcode); break;
+ case 9<<12: op1001(opcode); break;
+ case 10<<12: op1010(opcode); break;
+ case 11<<12: op1011(opcode); break;
+ case 12<<12: op1100(opcode); break;
+ case 13<<12: op1101(opcode); break;
+ case 14<<12: op1110(opcode); break;
+ default: op1111(opcode); break;
+ }
+
+ if (sh4.test_irq && !sh4.delay)
+ {
+ sh4_check_pending_irq("mame_sh4_execute");
+ }
+ sh4_icount--;
+ } while( sh4_icount > 0 );
+
+ return cycles - sh4_icount;
+}
+
+/* Get registers, return context size */
+static void sh4_get_context(void *dst)
+{
+ if( dst )
+ memcpy(dst, &sh4, sizeof(SH4));
+}
+
+/* Set registers */
+static void sh4_set_context(void *src)
+{
+ if( src )
+ memcpy(&sh4, src, sizeof(SH4));
+}
+
+static UINT32 compute_ticks_refresh_timer(emu_timer *timer, int hertz, int base, int divisor)
+{
+ // elapsed:total = x : ticks
+ // x=elapsed*tics/total -> x=elapsed*(double)100000000/rtcnt_div[(sh4.m[RTCSR] >> 3) & 7]
+ // ticks/total=ticks / ((rtcnt_div[(sh4.m[RTCSR] >> 3) & 7] * ticks) / 100000000)=1/((rtcnt_div[(sh4.m[RTCSR] >> 3) & 7] / 100000000)=100000000/rtcnt_div[(sh4.m[RTCSR] >> 3) & 7]
+ return base + (UINT32)((attotime_to_double(timer_timeelapsed(timer)) * (double)hertz) / (double)divisor);
+}
+
+static void sh4_refresh_timer_recompute(void)
+{
+UINT32 ticks;
+
+ //if rtcnt < rtcor then rtcor-rtcnt
+ //if rtcnt >= rtcor then 256-rtcnt+rtcor=256+rtcor-rtcnt
+ ticks = sh4.m[RTCOR]-sh4.m[RTCNT];
+ if (ticks < 0)
+ ticks = 256 + ticks;
+ //((double)rtcnt_div[(sh4.m[RTCSR] >> 3) & 7] / (double)100000000)*ticks
+ timer_adjust(sh4.refresh_timer, attotime_mul(attotime_mul(ATTOTIME_IN_HZ(sh4.bus_clock), rtcnt_div[(sh4.m[RTCSR] >> 3) & 7]), ticks), sh4.cpu_number, attotime_zero);
+ sh4.refresh_timer_base = sh4.m[RTCNT];
+}
+
+/*-------------------------------------------------
+ sh4_scale_up_mame_time - multiply a attotime by
+ a (constant+1) where 0 <= constant < 2^32
+-------------------------------------------------*/
+
+INLINE attotime sh4_scale_up_mame_time(attotime _time1, UINT32 factor1)
+{
+ if (factor1 == 0)
+ return attotime_zero;
+ return attotime_mul(_time1, factor1 + 1);
+}
+
+static UINT32 compute_ticks_timer(emu_timer *timer, int hertz, int divisor)
+{
+ double ret;
+
+ ret=((attotime_to_double(timer_timeleft(timer)) * (double)hertz) / (double)divisor) - 1;
+ return (UINT32)ret;
+}
+
+static void sh4_timer0_recompute(void)
+{
+ double ticks;
+
+ ticks = sh4.m[TCNT0];
+ timer_adjust(sh4.timer0, sh4_scale_up_mame_time(attotime_mul(ATTOTIME_IN_HZ(sh4.pm_clock), tcnt_div[sh4.m[TCR0] & 7]), ticks), sh4.cpu_number, attotime_zero);
+}
+
+static void sh4_timer1_recompute(void)
+{
+ double ticks;
+
+ ticks = sh4.m[TCNT1];
+ timer_adjust(sh4.timer1, sh4_scale_up_mame_time(attotime_mul(ATTOTIME_IN_HZ(sh4.pm_clock), tcnt_div[sh4.m[TCR1] & 7]), ticks), sh4.cpu_number, attotime_zero);
+}
+
+static void sh4_timer2_recompute(void)
+{
+ double ticks;
+
+ ticks = sh4.m[TCNT2];
+ timer_adjust(sh4.timer2, sh4_scale_up_mame_time(attotime_mul(ATTOTIME_IN_HZ(sh4.pm_clock), tcnt_div[sh4.m[TCR2] & 7]), ticks), sh4.cpu_number, attotime_zero);
+}
+
+static TIMER_CALLBACK( sh4_refresh_timer_callback )
+{
+ int cpunum = param;
+
+ cpuintrf_push_context(cpunum);
+ sh4.m[RTCNT] = 0;
+ sh4_refresh_timer_recompute();
+ sh4.m[RTCSR] |= 128;
+ if ((sh4.m[MCR] & 4) && !(sh4.m[MCR] & 2))
+ {
+ sh4.m[RFCR] = (sh4.m[RFCR] + 1) & 1023;
+ if (((sh4.m[RTCSR] & 1) && (sh4.m[RFCR] == 512)) || (sh4.m[RFCR] == 0))
+ {
+ sh4.m[RFCR] = 0;
+ sh4.m[RTCSR] |= 4;
+ }
+ }
+ cpuintrf_pop_context();
+}
+
+static void increment_rtc_time(int mode)
+{
+ int carry, year, leap, days;
+
+ if (mode == 0)
+ {
+ carry = 0;
+ sh4.m[RSECCNT] = sh4.m[RSECCNT] + 1;
+ if ((sh4.m[RSECCNT] & 0xf) == 0xa)
+ sh4.m[RSECCNT] = sh4.m[RSECCNT] + 6;
+ if (sh4.m[RSECCNT] == 0x60)
+ {
+ sh4.m[RSECCNT] = 0;
+ carry=1;
+ }
+ else
+ return;
+ }
+ else
+ carry = 1;
+
+ sh4.m[RMINCNT] = sh4.m[RMINCNT] + carry;
+ if ((sh4.m[RMINCNT] & 0xf) == 0xa)
+ sh4.m[RMINCNT] = sh4.m[RMINCNT] + 6;
+ carry=0;
+ if (sh4.m[RMINCNT] == 0x60)
+ {
+ sh4.m[RMINCNT] = 0;
+ carry = 1;
+ }
+
+ sh4.m[RHRCNT] = sh4.m[RHRCNT] + carry;
+ if ((sh4.m[RHRCNT] & 0xf) == 0xa)
+ sh4.m[RHRCNT] = sh4.m[RHRCNT] + 6;
+ carry = 0;
+ if (sh4.m[RHRCNT] == 0x24)
+ {
+ sh4.m[RHRCNT] = 0;
+ carry = 1;
+ }
+
+ sh4.m[RWKCNT] = sh4.m[RWKCNT] + carry;
+ if (sh4.m[RWKCNT] == 0x7)
+ {
+ sh4.m[RWKCNT] = 0;
+ }
+
+ year = (sh4.m[RYRCNT] & 0xf) + ((sh4.m[RYRCNT] & 0xf0) >> 4)*10 + ((sh4.m[RYRCNT] & 0xf00) >> 8)*100 + ((sh4.m[RYRCNT] & 0xf000) >> 12)*1000;
+ leap = 0;
+ if (!(year%100))
+ {
+ if (!(year%400))
+ leap = 1;
+ }
+ else if (!(year%4))
+ leap = 1;
+ if (sh4.m[RMONCNT] != 2)
+ leap = 0;
+ days = daysmonth[(sh4.m[RMONCNT] & 0xf) + ((sh4.m[RMONCNT] & 0xf0) >> 4)*10 - 1];
+
+ sh4.m[RDAYCNT] = sh4.m[RDAYCNT] + carry;
+ if ((sh4.m[RDAYCNT] & 0xf) == 0xa)
+ sh4.m[RDAYCNT] = sh4.m[RDAYCNT] + 6;
+ carry = 0;
+ if (sh4.m[RDAYCNT] > (days+leap))
+ {
+ sh4.m[RDAYCNT] = 1;
+ carry = 1;
+ }
+
+ sh4.m[RMONCNT] = sh4.m[RMONCNT] + carry;
+ if ((sh4.m[RMONCNT] & 0xf) == 0xa)
+ sh4.m[RMONCNT] = sh4.m[RMONCNT] + 6;
+ carry=0;
+ if (sh4.m[RMONCNT] == 0x13)
+ {
+ sh4.m[RMONCNT] = 1;
+ carry = 1;
+ }
+
+ sh4.m[RYRCNT] = sh4.m[RYRCNT] + carry;
+ if ((sh4.m[RYRCNT] & 0xf) >= 0xa)
+ sh4.m[RYRCNT] = sh4.m[RYRCNT] + 6;
+ if ((sh4.m[RYRCNT] & 0xf0) >= 0xa0)
+ sh4.m[RYRCNT] = sh4.m[RYRCNT] + 0x60;
+ if ((sh4.m[RYRCNT] & 0xf00) >= 0xa00)
+ sh4.m[RYRCNT] = sh4.m[RYRCNT] + 0x600;
+ if ((sh4.m[RYRCNT] & 0xf000) >= 0xa000)
+ sh4.m[RYRCNT] = 0;
+}
+
+static TIMER_CALLBACK( sh4_rtc_timer_callback )
+{
+ int cpunum = param;
+
+ cpuintrf_push_context(cpunum);
+ timer_adjust(sh4.rtc_timer, ATTOTIME_IN_HZ(128), cpunum, attotime_zero);
+ sh4.m[R64CNT] = (sh4.m[R64CNT]+1) & 0x7f;
+ if (sh4.m[R64CNT] == 64)
+ {
+ sh4.m[RCR1] |= 0x80;
+ increment_rtc_time(0);
+ //sh4_exception_request(SH4_INTC_NMI); // TEST
+ }
+ cpuintrf_pop_context();
+}
+
+static TIMER_CALLBACK( sh4_timer0_callback )
+{
+ int cpunum = param;
+
+ cpuintrf_push_context(cpunum);
+ sh4.m[TCNT0] = sh4.m[TCOR0];
+ sh4_timer0_recompute();
+ sh4.m[TCR0] = sh4.m[TCR0] | 0x100;
+ if (sh4.m[TCR0] & 0x20)
+ sh4_exception_request(SH4_INTC_TUNI0);
+ cpuintrf_pop_context();
+}
+
+static TIMER_CALLBACK( sh4_timer1_callback )
+{
+ int cpunum = param;
+
+ cpuintrf_push_context(cpunum);
+ sh4.m[TCNT1] = sh4.m[TCOR1];
+ sh4_timer1_recompute();
+ sh4.m[TCR1] = sh4.m[TCR1] | 0x100;
+ if (sh4.m[TCR1] & 0x20)
+ sh4_exception_request(SH4_INTC_TUNI1);
+ cpuintrf_pop_context();
+}
+
+static TIMER_CALLBACK( sh4_timer2_callback )
+{
+ int cpunum = param;
+
+ cpuintrf_push_context(cpunum);
+ sh4.m[TCNT2] = sh4.m[TCOR2];
+ sh4_timer2_recompute();
+ sh4.m[TCR2] = sh4.m[TCR2] | 0x100;
+ if (sh4.m[TCR2] & 0x20)
+ sh4_exception_request(SH4_INTC_TUNI2);
+ cpuintrf_pop_context();
+}
+
+static TIMER_CALLBACK( sh4_dmac_callback )
+{
+ int cpunum = param >> 8;
+ int channel = param & 255;
+
+ cpuintrf_push_context(cpunum);
+ LOG(("SH4.%d: DMA %d complete\n", cpunum, channel));
+ sh4.dma_timer_active[channel] = 0;
+ switch (channel)
+ {
+ case 0:
+ sh4.m[DMATCR0] = 0;
+ sh4.m[CHCR0] |= 2;
+ if (sh4.m[CHCR0] & 4)
+ sh4_exception_request(SH4_INTC_DMTE0);
+ break;
+ case 1:
+ sh4.m[DMATCR1] = 0;
+ sh4.m[CHCR1] |= 2;
+ if (sh4.m[CHCR1] & 4)
+ sh4_exception_request(SH4_INTC_DMTE1);
+ break;
+ case 2:
+ sh4.m[DMATCR2] = 0;
+ sh4.m[CHCR2] |= 2;
+ if (sh4.m[CHCR2] & 4)
+ sh4_exception_request(SH4_INTC_DMTE2);
+ break;
+ case 3:
+ sh4.m[DMATCR3] = 0;
+ sh4.m[CHCR3] |= 2;
+ if (sh4.m[CHCR3] & 4)
+ sh4_exception_request(SH4_INTC_DMTE3);
+ break;
+ }
+ cpuintrf_pop_context();
+}
+
+static int sh4_dma_transfer(int channel, int timermode, UINT32 chcr, UINT32 *sar, UINT32 *dar, UINT32 *dmatcr)
+{
+ int incs, incd, size;
+ UINT32 src, dst, count;
+
+ incd = (chcr >> 14) & 3;
+ incs = (chcr >> 12) & 3;
+ size = dmasize[(chcr >> 4) & 7];
+ if(incd == 3 || incs == 3)
+ {
+ logerror("SH4: DMA: bad increment values (%d, %d, %d, %04x)\n", incd, incs, size, chcr);
+ return 0;
+ }
+ src = *sar;
+ dst = *dar;
+ count = *dmatcr;
+ if (!count)
+ count = 0x1000000;
+
+ LOG(("SH4: DMA %d start %x, %x, %x, %04x, %d, %d, %d\n", channel, src, dst, count, chcr, incs, incd, size));
+
+ if (timermode == 1)
+ {
+ sh4.dma_timer_active[channel] = 1;
+ timer_adjust(sh4.dma_timer[channel], ATTOTIME_IN_CYCLES(2*count+1, sh4.cpu_number), (sh4.cpu_number << 8) | channel, attotime_zero);
+ }
+ else if (timermode == 2)
+ {
+ sh4.dma_timer_active[channel] = 1;
+ timer_adjust(sh4.dma_timer[channel], attotime_zero, (sh4.cpu_number << 8) | channel, attotime_zero);
+ }
+
+ src &= AM;
+ dst &= AM;
+
+ switch(size)
+ {
+ case 1:
+ for(;count > 0; count --)
+ {
+ if(incs == 2)
+ src --;
+ if(incd == 2)
+ dst --;
+ program_write_byte_64le(dst, program_read_byte_64le(src));
+ if(incs == 1)
+ src ++;
+ if(incd == 1)
+ dst ++;
+ }
+ break;
+ case 2:
+ src &= ~1;
+ dst &= ~1;
+ for(;count > 0; count --)
+ {
+ if(incs == 2)
+ src -= 2;
+ if(incd == 2)
+ dst -= 2;
+ program_write_word_64le(dst, program_read_word_64le(src));
+ if(incs == 1)
+ src += 2;
+ if(incd == 1)
+ dst += 2;
+ }
+ break;
+ case 8:
+ src &= ~7;
+ dst &= ~7;
+ for(;count > 0; count --)
+ {
+ if(incs == 2)
+ src -= 8;
+ if(incd == 2)
+ dst -= 8;
+ program_write_qword_64le(dst, program_read_qword_64le(src));
+ if(incs == 1)
+ src += 8;
+ if(incd == 1)
+ dst += 8;
+
+ }
+ break;
+ case 4:
+ src &= ~3;
+ dst &= ~3;
+ for(;count > 0; count --)
+ {
+ if(incs == 2)
+ src -= 4;
+ if(incd == 2)
+ dst -= 4;
+ program_write_dword_64le(dst, program_read_dword_64le(src));
+ if(incs == 1)
+ src += 4;
+ if(incd == 1)
+ dst += 4;
+
+ }
+ break;
+ case 32:
+ src &= ~31;
+ dst &= ~31;
+ for(;count > 0; count --)
+ {
+ if(incs == 2)
+ src -= 32;
+ if(incd == 2)
+ dst -= 32;
+ program_write_qword_64le(dst, program_read_qword_64le(src));
+ program_write_qword_64le(dst+8, program_read_qword_64le(src+8));
+ program_write_qword_64le(dst+16, program_read_qword_64le(src+16));
+ program_write_qword_64le(dst+24, program_read_qword_64le(src+24));
+ if(incs == 1)
+ src += 32;
+ if(incd == 1)
+ dst += 32;
+ }
+ break;
+ }
+ *sar = (*sar & !AM) | src;
+ *dar = (*dar & !AM) | dst;
+ *dmatcr = count;
+ return 1;
+}
+
+static void sh4_dmac_check(int channel)
+{
+UINT32 dmatcr,chcr,sar,dar;
+
+ switch (channel)
+ {
+ case 0:
+ sar = sh4.m[SAR0];
+ dar = sh4.m[DAR0];
+ chcr = sh4.m[CHCR0];
+ dmatcr = sh4.m[DMATCR0];
+ break;
+ case 1:
+ sar = sh4.m[SAR1];
+ dar = sh4.m[DAR1];
+ chcr = sh4.m[CHCR1];
+ dmatcr = sh4.m[DMATCR1];
+ break;
+ case 2:
+ sar = sh4.m[SAR2];
+ dar = sh4.m[DAR2];
+ chcr = sh4.m[CHCR2];
+ dmatcr = sh4.m[DMATCR2];
+ break;
+ case 3:
+ sar = sh4.m[SAR3];
+ dar = sh4.m[DAR3];
+ chcr = sh4.m[CHCR3];
+ dmatcr = sh4.m[DMATCR3];
+ break;
+ default:
+ return;
+ }
+ if (chcr & sh4.m[DMAOR] & 1)
+ {
+ if ((((chcr >> 8) & 15) < 4) || (((chcr >> 8) & 15) > 6))
+ return;
+ if (!sh4.dma_timer_active[channel] && !(chcr & 2) && !(sh4.m[DMAOR] & 6))
+ sh4_dma_transfer(channel, 1, chcr, &sar, &dar, &dmatcr);
+ }
+ else
+ {
+ if (sh4.dma_timer_active[channel])
+ {
+ logerror("SH4: DMA %d cancelled in-flight but all data transferred", channel);
+ timer_adjust(sh4.dma_timer[channel], attotime_never, 0, attotime_zero);
+ sh4.dma_timer_active[channel] = 0;
+ }
+ }
+}
+
+static void sh4_dmac_nmi(void) // manage dma when nmi
+{
+int s;
+
+ sh4.m[DMAOR] |= 2; // nmif = 1
+ for (s = 0;s < 4;s++)
+ {
+ if (sh4.dma_timer_active[s])
+ {
+ logerror("SH4: DMA %d cancelled due to NMI but all data transferred", s);
+ timer_adjust(sh4.dma_timer[s], attotime_never, 0, attotime_zero);
+ sh4.dma_timer_active[s] = 0;
+ }
+ }
+}
+
+WRITE32_HANDLER( sh4_internal_w )
+{
+ UINT32 old = sh4.m[offset];
+ COMBINE_DATA(sh4.m+offset);
+
+ // logerror("sh4_internal_w: Write %08x (%x), %08x @ %08x\n", 0xfe000000+((offset & 0x3fc0) << 11)+((offset & 0x3f) << 2), offset, data, mem_mask);
+
+ switch( offset )
+ {
+ // Memory refresh
+ case RTCSR:
+ sh4.m[RTCSR] &= 255;
+ if ((old >> 3) & 7)
+ sh4.m[RTCNT] = compute_ticks_refresh_timer(sh4.refresh_timer, sh4.bus_clock, sh4.refresh_timer_base, rtcnt_div[(old >> 3) & 7]) & 0xff;
+ if ((sh4.m[RTCSR] >> 3) & 7)
+ { // activated
+ sh4_refresh_timer_recompute();
+ }
+ else
+ {
+ timer_adjust(sh4.refresh_timer, attotime_never, 0, attotime_zero);
+ }
+ break;
+
+ case RTCNT:
+ sh4.m[RTCNT] &= 255;
+ if ((sh4.m[RTCSR] >> 3) & 7)
+ { // active
+ sh4_refresh_timer_recompute();
+ }
+ break;
+
+ case RTCOR:
+ sh4.m[RTCOR] &= 255;
+ if ((sh4.m[RTCSR] >> 3) & 7)
+ { // active
+ sh4.m[RTCNT] = compute_ticks_refresh_timer(sh4.refresh_timer, sh4.bus_clock, sh4.refresh_timer_base, rtcnt_div[(sh4.m[RTCSR] >> 3) & 7]) & 0xff;
+ sh4_refresh_timer_recompute();
+ }
+ break;
+
+ case RFCR:
+ sh4.m[RFCR] &= 1023;
+ break;
+
+ // RTC
+ case RCR1:
+ if ((sh4.m[RCR1] & 8) && (~old & 8)) // 0 -> 1
+ sh4.m[RCR1] ^= 1;
+ break;
+
+ case RCR2:
+ if (sh4.m[RCR2] & 2)
+ {
+ sh4.m[R64CNT] = 0;
+ sh4.m[RCR2] ^= 2;
+ }
+ if (sh4.m[RCR2] & 4)
+ {
+ sh4.m[R64CNT] = 0;
+ if (sh4.m[RSECCNT] >= 30)
+ increment_rtc_time(1);
+ sh4.m[RSECCNT] = 0;
+ }
+ if ((sh4.m[RCR2] & 8) && (~old & 8))
+ { // 0 -> 1
+ timer_adjust(sh4.rtc_timer, ATTOTIME_IN_HZ(128), sh4.cpu_number, attotime_zero);
+ }
+ else if (~(sh4.m[RCR2]) & 8)
+ { // 0
+ timer_adjust(sh4.rtc_timer, attotime_never, 0, attotime_zero);
+ }
+ break;
+
+ // TMU
+ case TSTR:
+ if (old & 1)
+ sh4.m[TCNT0] = compute_ticks_timer(sh4.timer0, sh4.pm_clock, tcnt_div[sh4.m[TCR0] & 7]);
+ if ((sh4.m[TSTR] & 1) == 0) {
+ timer_adjust(sh4.timer0, attotime_never, 0, attotime_zero);
+ } else
+ sh4_timer0_recompute();
+
+ if (old & 2)
+ sh4.m[TCNT1] = compute_ticks_timer(sh4.timer1, sh4.pm_clock, tcnt_div[sh4.m[TCR1] & 7]);
+ if ((sh4.m[TSTR] & 2) == 0) {
+ timer_adjust(sh4.timer1, attotime_never, 0, attotime_zero);
+ } else
+ sh4_timer1_recompute();
+
+ if (old & 4)
+ sh4.m[TCNT2] = compute_ticks_timer(sh4.timer2, sh4.pm_clock, tcnt_div[sh4.m[TCR2] & 7]);
+ if ((sh4.m[TSTR] & 4) == 0) {
+ timer_adjust(sh4.timer2, attotime_never, 0, attotime_zero);
+ } else
+ sh4_timer2_recompute();
+ break;
+
+ case TCR0:
+ if (sh4.m[TSTR] & 1)
+ {
+ sh4.m[TCNT0] = compute_ticks_timer(sh4.timer0, sh4.pm_clock, tcnt_div[old & 7]);
+ sh4_timer0_recompute();
+ }
+ if (!(sh4.m[TCR0] & 0x20) || !(sh4.m[TCR0] & 0x100))
+ sh4_exception_unrequest(SH4_INTC_TUNI0);
+ break;
+ case TCR1:
+ if (sh4.m[TSTR] & 2)
+ {
+ sh4.m[TCNT1] = compute_ticks_timer(sh4.timer1, sh4.pm_clock, tcnt_div[old & 7]);
+ sh4_timer1_recompute();
+ }
+ if (!(sh4.m[TCR1] & 0x20) || !(sh4.m[TCR1] & 0x100))
+ sh4_exception_unrequest(SH4_INTC_TUNI1);
+ break;
+ case TCR2:
+ if (sh4.m[TSTR] & 4)
+ {
+ sh4.m[TCNT2] = compute_ticks_timer(sh4.timer2, sh4.pm_clock, tcnt_div[old & 7]);
+ sh4_timer2_recompute();
+ }
+ if (!(sh4.m[TCR2] & 0x20) || !(sh4.m[TCR2] & 0x100))
+ sh4_exception_unrequest(SH4_INTC_TUNI2);
+ break;
+
+ case TCOR0:
+ if (sh4.m[TSTR] & 1)
+ {
+ sh4.m[TCNT0] = compute_ticks_timer(sh4.timer0, sh4.pm_clock, tcnt_div[sh4.m[TCR0] & 7]);
+ sh4_timer0_recompute();
+ }
+ break;
+ case TCNT0:
+ if (sh4.m[TSTR] & 1)
+ sh4_timer0_recompute();
+ break;
+ case TCOR1:
+ if (sh4.m[TSTR] & 2)
+ {
+ sh4.m[TCNT1] = compute_ticks_timer(sh4.timer1, sh4.pm_clock, tcnt_div[sh4.m[TCR1] & 7]);
+ sh4_timer1_recompute();
+ }
+ break;
+ case TCNT1:
+ if (sh4.m[TSTR] & 2)
+ sh4_timer1_recompute();
+ break;
+ case TCOR2:
+ if (sh4.m[TSTR] & 4)
+ {
+ sh4.m[TCNT2] = compute_ticks_timer(sh4.timer2, sh4.pm_clock, tcnt_div[sh4.m[TCR2] & 7]);
+ sh4_timer2_recompute();
+ }
+ break;
+ case TCNT2:
+ if (sh4.m[TSTR] & 4)
+ sh4_timer2_recompute();
+ break;
+
+ // INTC
+ case ICR:
+ sh4.m[ICR] = (sh4.m[ICR] & 0x7fff) | (old & 0x8000);
+ break;
+ case IPRA:
+ sh4.exception_priority[SH4_INTC_ATI] = INTPRI(sh4.m[IPRA] & 0x000f, SH4_INTC_ATI);
+ sh4.exception_priority[SH4_INTC_PRI] = INTPRI(sh4.m[IPRA] & 0x000f, SH4_INTC_PRI);
+ sh4.exception_priority[SH4_INTC_CUI] = INTPRI(sh4.m[IPRA] & 0x000f, SH4_INTC_CUI);
+ sh4.exception_priority[SH4_INTC_TUNI2] = INTPRI((sh4.m[IPRA] & 0x00f0) >> 4, SH4_INTC_TUNI2);
+ sh4.exception_priority[SH4_INTC_TICPI2] = INTPRI((sh4.m[IPRA] & 0x00f0) >> 4, SH4_INTC_TICPI2);
+ sh4.exception_priority[SH4_INTC_TUNI1] = INTPRI((sh4.m[IPRA] & 0x0f00) >> 8, SH4_INTC_TUNI1);
+ sh4.exception_priority[SH4_INTC_TUNI0] = INTPRI((sh4.m[IPRA] & 0xf000) >> 12, SH4_INTC_TUNI0);
+ sh4_exception_recompute();
+ break;
+ case IPRB:
+ sh4.exception_priority[SH4_INTC_SCI1ERI] = INTPRI((sh4.m[IPRB] & 0x00f0) >> 4, SH4_INTC_SCI1ERI);
+ sh4.exception_priority[SH4_INTC_SCI1RXI] = INTPRI((sh4.m[IPRB] & 0x00f0) >> 4, SH4_INTC_SCI1RXI);
+ sh4.exception_priority[SH4_INTC_SCI1TXI] = INTPRI((sh4.m[IPRB] & 0x00f0) >> 4, SH4_INTC_SCI1TXI);
+ sh4.exception_priority[SH4_INTC_SCI1TEI] = INTPRI((sh4.m[IPRB] & 0x00f0) >> 4, SH4_INTC_SCI1TEI);
+ sh4.exception_priority[SH4_INTC_RCMI] = INTPRI((sh4.m[IPRB] & 0x0f00) >> 8, SH4_INTC_RCMI);
+ sh4.exception_priority[SH4_INTC_ROVI] = INTPRI((sh4.m[IPRB] & 0x0f00) >> 8, SH4_INTC_ROVI);
+ sh4.exception_priority[SH4_INTC_ITI] = INTPRI((sh4.m[IPRB] & 0xf000) >> 12, SH4_INTC_ITI);
+ sh4_exception_recompute();
+ break;
+ case IPRC:
+ sh4.exception_priority[SH4_INTC_HUDI] = INTPRI(sh4.m[IPRC] & 0x000f, SH4_INTC_HUDI);
+ sh4.exception_priority[SH4_INTC_SCIFERI] = INTPRI((sh4.m[IPRC] & 0x00f0) >> 4, SH4_INTC_SCIFERI);
+ sh4.exception_priority[SH4_INTC_SCIFRXI] = INTPRI((sh4.m[IPRC] & 0x00f0) >> 4, SH4_INTC_SCIFRXI);
+ sh4.exception_priority[SH4_INTC_SCIFBRI] = INTPRI((sh4.m[IPRC] & 0x00f0) >> 4, SH4_INTC_SCIFBRI);
+ sh4.exception_priority[SH4_INTC_SCIFTXI] = INTPRI((sh4.m[IPRC] & 0x00f0) >> 4, SH4_INTC_SCIFTXI);
+ sh4.exception_priority[SH4_INTC_DMTE0] = INTPRI((sh4.m[IPRC] & 0x0f00) >> 8, SH4_INTC_DMTE0);
+ sh4.exception_priority[SH4_INTC_DMTE1] = INTPRI((sh4.m[IPRC] & 0x0f00) >> 8, SH4_INTC_DMTE1);
+ sh4.exception_priority[SH4_INTC_DMTE2] = INTPRI((sh4.m[IPRC] & 0x0f00) >> 8, SH4_INTC_DMTE2);
+ sh4.exception_priority[SH4_INTC_DMTE3] = INTPRI((sh4.m[IPRC] & 0x0f00) >> 8, SH4_INTC_DMTE3);
+ sh4.exception_priority[SH4_INTC_DMAE] = INTPRI((sh4.m[IPRC] & 0x0f00) >> 8, SH4_INTC_DMAE);
+ sh4.exception_priority[SH4_INTC_GPOI] = INTPRI((sh4.m[IPRC] & 0xf000) >> 12, SH4_INTC_GPOI);
+ sh4_exception_recompute();
+ break;
+
+ // DMA
+ case SAR0:
+ case SAR1:
+ case SAR2:
+ case SAR3:
+ case DAR0:
+ case DAR1:
+ case DAR2:
+ case DAR3:
+ case DMATCR0:
+ case DMATCR1:
+ case DMATCR2:
+ case DMATCR3:
+ break;
+ case CHCR0:
+ sh4_dmac_check(0);
+ break;
+ case CHCR1:
+ sh4_dmac_check(1);
+ break;
+ case CHCR2:
+ sh4_dmac_check(2);
+ break;
+ case CHCR3:
+ sh4_dmac_check(3);
+ break;
+ case DMAOR:
+ if ((sh4.m[DMAOR] & 4) && (~old & 4))
+ sh4.m[DMAOR] &= ~4;
+ if ((sh4.m[DMAOR] & 2) && (~old & 2))
+ sh4.m[DMAOR] &= ~2;
+ sh4_dmac_check(0);
+ sh4_dmac_check(1);
+ sh4_dmac_check(2);
+ sh4_dmac_check(3);
+ break;
+
+ // Store Queues
+ case QACR0:
+ case QACR1:
+ break;
+
+ case SCBRR2:
+ break;
+
+ default:
+ logerror("sh4_internal_w: Unmapped write %08x, %08x @ %08x\n", 0xfe000000+((offset & 0x3fc0) << 11)+((offset & 0x3f) << 2), data, mem_mask);
+ break;
+ }
+}
+
+READ32_HANDLER( sh4_internal_r )
+{
+ // logerror("sh4_internal_r: Read %08x (%x) @ %08x\n", 0xfe000000+((offset & 0x3fc0) << 11)+((offset & 0x3f) << 2), offset, mem_mask);
+ switch( offset )
+ {
+ case RTCNT:
+ if ((sh4.m[RTCSR] >> 3) & 7)
+ { // activated
+ //((double)rtcnt_div[(sh4.m[RTCSR] >> 3) & 7] / (double)100000000)
+ //return (refresh_timer_base + (timer_timeelapsed(sh4.refresh_timer) * (double)100000000) / (double)rtcnt_div[(sh4.m[RTCSR] >> 3) & 7]) & 0xff;
+ return compute_ticks_refresh_timer(sh4.refresh_timer, sh4.bus_clock, sh4.refresh_timer_base, rtcnt_div[(sh4.m[RTCSR] >> 3) & 7]) & 0xff;
+ }
+ else
+ return sh4.m[RTCNT];
+ break;
+
+ case TCNT0:
+ if (sh4.m[TSTR] & 1)
+ return compute_ticks_timer(sh4.timer0, sh4.pm_clock, tcnt_div[sh4.m[TCR0] & 7]);
+ else
+ return sh4.m[TCNT0];
+ break;
+ case TCNT1:
+ if (sh4.m[TSTR] & 2)
+ return compute_ticks_timer(sh4.timer1, sh4.pm_clock, tcnt_div[sh4.m[TCR1] & 7]);
+ else
+ return sh4.m[TCNT1];
+ break;
+ case TCNT2:
+ if (sh4.m[TSTR] & 4)
+ return compute_ticks_timer(sh4.timer2, sh4.pm_clock, tcnt_div[sh4.m[TCR2] & 7]);
+ else
+ return sh4.m[TCNT2];
+ break;
+ }
+ return sh4.m[offset];
+}
+
+void sh4_set_frt_input(int cpunum, int state)
+{
+ if(state == PULSE_LINE)
+ {
+ sh4_set_frt_input(cpunum, ASSERT_LINE);
+ sh4_set_frt_input(cpunum, CLEAR_LINE);
+ return;
+ }
+
+ cpuintrf_push_context(cpunum);
+
+ if(sh4.frt_input == state) {
+ cpuintrf_pop_context();
+ return;
+ }
+
+ sh4.frt_input = state;
+
+ if(sh4.m[5] & 0x8000) {
+ if(state == CLEAR_LINE) {
+ cpuintrf_pop_context();
+ return;
+ }
+ } else {
+ if(state == ASSERT_LINE) {
+ cpuintrf_pop_context();
+ return;
+ }
+ }
+
+#if 0
+ sh4_timer_resync();
+ sh4.icr = sh4.frc;
+ sh4.m[4] |= ICF;
+ logerror("SH4.%d: ICF activated (%x)\n", sh4.cpu_number, sh4.pc & AM);
+ sh4_recalc_irq();
+#endif
+ cpuintrf_pop_context();
+}
+
+void sh4_set_irln_input(int cpunum, int value)
+{
+ if (sh4.irln == value)
+ return;
+ sh4.irln = value;
+ cpunum_set_input_line(cpunum, SH4_IRLn, PULSE_LINE);
+}
+
+static void set_irq_line(int irqline, int state) // set state of external interrupt line
+{
+int s;
+
+ if (irqline == INPUT_LINE_NMI)
+ {
+ if (sh4.nmi_line_state == state)
+ return;
+ if (sh4.m[ICR] & 0x100)
+ {
+ if ((state == CLEAR_LINE) && (sh4.nmi_line_state == ASSERT_LINE)) // rising
+ {
+ LOG(("SH-4 #%d assert nmi\n", cpu_getactivecpu()));
+ sh4_exception_request(SH4_INTC_NMI);
+ sh4_dmac_nmi();
+ }
+ }
+ else
+ {
+ if ((state == ASSERT_LINE) && (sh4.nmi_line_state == CLEAR_LINE)) // falling
+ {
+ LOG(("SH-4 #%d assert nmi\n", cpu_getactivecpu()));
+ sh4_exception_request(SH4_INTC_NMI);
+ sh4_dmac_nmi();
+ }
+ }
+ if (state == CLEAR_LINE)
+ sh4.m[ICR] ^= 0x8000;
+ else
+ sh4.m[ICR] |= 0x8000;
+ sh4.nmi_line_state = state;
+ }
+ else
+ {
+ if (sh4.m[ICR] & 0x80) // four independent external interrupt sources
+ {
+ if (irqline > SH4_IRL3)
+ return;
+ if (sh4.irq_line_state[irqline] == state)
+ return;
+ sh4.irq_line_state[irqline] = state;
+
+ if( state == CLEAR_LINE )
+ {
+ LOG(("SH-4 #%d cleared external irq IRL%d\n", cpu_getactivecpu(), irqline));
+ sh4_exception_unrequest(SH4_INTC_IRL0+irqline-SH4_IRL0);
+ }
+ else
+ {
+ LOG(("SH-4 #%d assert external irq IRL%d\n", cpu_getactivecpu(), irqline));
+ sh4_exception_request(SH4_INTC_IRL0+irqline-SH4_IRL0);
+ }
+ }
+ else // level-encoded interrupt
+ {
+ if (irqline != SH4_IRLn)
+ return;
+ if ((sh4.irln > 15) || (sh4.irln < 0))
+ return;
+ for (s = 0; s < 15; s++)
+ sh4_exception_unrequest(SH4_INTC_IRLn0+s);
+ if (sh4.irln < 15)
+ sh4_exception_request(SH4_INTC_IRLn0+sh4.irln);
+ LOG(("SH-4 #%d IRLn0-IRLn3 level #%d\n", cpu_getactivecpu(), sh4.irln));
+ }
+ }
+ if (sh4.test_irq && (!sh4.delay))
+ sh4_check_pending_irq("sh4_set_irq_line");
+}
+
+static void sh4_parse_configuration(const struct sh4_config *conf)
+{
+ if(conf)
+ {
+ switch((conf->md2 << 2) | (conf->md1 << 1) | (conf->md0))
+ {
+ case 0:
+ sh4.cpu_clock = conf->clock;
+ sh4.bus_clock = conf->clock / 4;
+ sh4.pm_clock = conf->clock / 4;
+ break;
+ case 1:
+ sh4.cpu_clock = conf->clock;
+ sh4.bus_clock = conf->clock / 6;
+ sh4.pm_clock = conf->clock / 6;
+ break;
+ case 2:
+ sh4.cpu_clock = conf->clock;
+ sh4.bus_clock = conf->clock / 3;
+ sh4.pm_clock = conf->clock / 6;
+ break;
+ case 3:
+ sh4.cpu_clock = conf->clock;
+ sh4.bus_clock = conf->clock / 3;
+ sh4.pm_clock = conf->clock / 6;
+ break;
+ case 4:
+ sh4.cpu_clock = conf->clock;
+ sh4.bus_clock = conf->clock / 2;
+ sh4.pm_clock = conf->clock / 4;
+ break;
+ case 5:
+ sh4.cpu_clock = conf->clock;
+ sh4.bus_clock = conf->clock / 2;
+ sh4.pm_clock = conf->clock / 4;
+ break;
+ }
+ sh4.is_slave = (~(conf->md7)) & 1;
+ }
+ else
+ {
+ sh4.cpu_clock = 200000000;
+ sh4.bus_clock = 100000000;
+ sh4.pm_clock = 50000000;
+ sh4.is_slave = 0;
+ }
+}
+
+#ifdef MAME_DEBUG
+static offs_t sh4_dasm(char *buffer, offs_t pc, const UINT8 *oprom, const UINT8 *opram)
+{
+ return DasmSH4( buffer, pc, (oprom[1] << 8) | oprom[0] );
+}
+#endif /* MAME_DEBUG */
+
+static void sh4_init(int index, int clock, const void *config, int (*irqcallback)(int))
+{
+ const struct sh4_config *conf = config;
+
+ sh4.timer0 = timer_alloc(sh4_timer0_callback);
+ timer_adjust(sh4.timer0, attotime_never, 0, attotime_zero);
+ sh4.timer1 = timer_alloc(sh4_timer1_callback);
+ timer_adjust(sh4.timer1, attotime_never, 0, attotime_zero);
+ sh4.timer2 = timer_alloc(sh4_timer2_callback);
+ timer_adjust(sh4.timer2, attotime_never, 0, attotime_zero);
+
+ sh4.dma_timer[0] = timer_alloc(sh4_dmac_callback);
+ timer_adjust(sh4.dma_timer[0], attotime_never, 0, attotime_zero);
+ sh4.dma_timer[1] = timer_alloc(sh4_dmac_callback);
+ timer_adjust(sh4.dma_timer[1], attotime_never, 0, attotime_zero);
+ sh4.dma_timer[2] = timer_alloc(sh4_dmac_callback);
+ timer_adjust(sh4.dma_timer[2], attotime_never, 0, attotime_zero);
+ sh4.dma_timer[3] = timer_alloc(sh4_dmac_callback);
+ timer_adjust(sh4.dma_timer[3], attotime_never, 0, attotime_zero);
+
+ sh4.refresh_timer = timer_alloc(sh4_refresh_timer_callback);
+ timer_adjust(sh4.refresh_timer, attotime_never, 0, attotime_zero);
+ sh4.refresh_timer_base = 0;
+
+ sh4.rtc_timer = timer_alloc(sh4_rtc_timer_callback);
+ timer_adjust(sh4.rtc_timer, attotime_never, 0, attotime_zero);
+
+ sh4.m = auto_malloc(16384*4);
+
+ sh4_parse_configuration(conf);
+
+ sh4.cpu_number = index;
+ sh4.irq_callback = irqcallback;
+ sh4_default_exception_priorities();
+ sh4.irln = 15;
+ sh4.test_irq = 0;
+
+ state_save_register_item("sh4", index, sh4.pc);
+ state_save_register_item("sh4", index, sh4.r[15]);
+ state_save_register_item("sh4", index, sh4.sr);
+ state_save_register_item("sh4", index, sh4.pr);
+ state_save_register_item("sh4", index, sh4.gbr);
+ state_save_register_item("sh4", index, sh4.vbr);
+ state_save_register_item("sh4", index, sh4.mach);
+ state_save_register_item("sh4", index, sh4.macl);
+ state_save_register_item("sh4", index, sh4.spc);
+ state_save_register_item("sh4", index, sh4.ssr);
+ state_save_register_item("sh4", index, sh4.sgr);
+ state_save_register_item("sh4", index, sh4.fpscr);
+ state_save_register_item("sh4", index, sh4.r[ 0]);
+ state_save_register_item("sh4", index, sh4.r[ 1]);
+ state_save_register_item("sh4", index, sh4.r[ 2]);
+ state_save_register_item("sh4", index, sh4.r[ 3]);
+ state_save_register_item("sh4", index, sh4.r[ 4]);
+ state_save_register_item("sh4", index, sh4.r[ 5]);
+ state_save_register_item("sh4", index, sh4.r[ 6]);
+ state_save_register_item("sh4", index, sh4.r[ 7]);
+ state_save_register_item("sh4", index, sh4.r[ 8]);
+ state_save_register_item("sh4", index, sh4.r[ 9]);
+ state_save_register_item("sh4", index, sh4.r[10]);
+ state_save_register_item("sh4", index, sh4.r[11]);
+ state_save_register_item("sh4", index, sh4.r[12]);
+ state_save_register_item("sh4", index, sh4.r[13]);
+ state_save_register_item("sh4", index, sh4.r[14]);
+ state_save_register_item("sh4", index, sh4.fr[ 0]);
+ state_save_register_item("sh4", index, sh4.fr[ 1]);
+ state_save_register_item("sh4", index, sh4.fr[ 2]);
+ state_save_register_item("sh4", index, sh4.fr[ 3]);
+ state_save_register_item("sh4", index, sh4.fr[ 4]);
+ state_save_register_item("sh4", index, sh4.fr[ 5]);
+ state_save_register_item("sh4", index, sh4.fr[ 6]);
+ state_save_register_item("sh4", index, sh4.fr[ 7]);
+ state_save_register_item("sh4", index, sh4.fr[ 8]);
+ state_save_register_item("sh4", index, sh4.fr[ 9]);
+ state_save_register_item("sh4", index, sh4.fr[10]);
+ state_save_register_item("sh4", index, sh4.fr[11]);
+ state_save_register_item("sh4", index, sh4.fr[12]);
+ state_save_register_item("sh4", index, sh4.fr[13]);
+ state_save_register_item("sh4", index, sh4.fr[14]);
+ state_save_register_item("sh4", index, sh4.fr[15]);
+ state_save_register_item("sh4", index, sh4.xf[ 0]);
+ state_save_register_item("sh4", index, sh4.xf[ 1]);
+ state_save_register_item("sh4", index, sh4.xf[ 2]);
+ state_save_register_item("sh4", index, sh4.xf[ 3]);
+ state_save_register_item("sh4", index, sh4.xf[ 4]);
+ state_save_register_item("sh4", index, sh4.xf[ 5]);
+ state_save_register_item("sh4", index, sh4.xf[ 6]);
+ state_save_register_item("sh4", index, sh4.xf[ 7]);
+ state_save_register_item("sh4", index, sh4.xf[ 8]);
+ state_save_register_item("sh4", index, sh4.xf[ 9]);
+ state_save_register_item("sh4", index, sh4.xf[10]);
+ state_save_register_item("sh4", index, sh4.xf[11]);
+ state_save_register_item("sh4", index, sh4.xf[12]);
+ state_save_register_item("sh4", index, sh4.xf[13]);
+ state_save_register_item("sh4", index, sh4.xf[14]);
+ state_save_register_item("sh4", index, sh4.xf[15]);
+ state_save_register_item("sh4", index, sh4.ea);
+ state_save_register_item("sh4", index, sh4.fpul);
+ state_save_register_item("sh4", index, sh4.dbr);
+ state_save_register_item_array("sh4", index, sh4.exception_priority);
+ state_save_register_item_array("sh4", index, sh4.exception_requesting);
+
+}
+
+void sh4_dma_ddt(struct sh4_ddt_dma *s)
+{
+UINT32 chcr;
+UINT32 *p32bits;
+UINT32 pos,len,siz;
+
+ if (sh4.dma_timer_active[s->channel])
+ return;
+ if (s->mode >= 0) {
+ switch (s->channel)
+ {
+ case 0:
+ if (s->mode & 1)
+ s->source = sh4.m[SAR0];
+ if (s->mode & 2)
+ sh4.m[SAR0] = s->source;
+ if (s->mode & 4)
+ s->destination = sh4.m[DAR0];
+ if (s->mode & 8)
+ sh4.m[DAR0] = s->destination;
+ break;
+ case 1:
+ if (s->mode & 1)
+ s->source = sh4.m[SAR1];
+ if (s->mode & 2)
+ sh4.m[SAR1] = s->source;
+ if (s->mode & 4)
+ s->destination = sh4.m[DAR1];
+ if (s->mode & 8)
+ sh4.m[DAR1] = s->destination;
+ break;
+ case 2:
+ if (s->mode & 1)
+ s->source = sh4.m[SAR2];
+ if (s->mode & 2)
+ sh4.m[SAR2] = s->source;
+ if (s->mode & 4)
+ s->destination = sh4.m[DAR2];
+ if (s->mode & 8)
+ sh4.m[DAR2] = s->destination;
+ break;
+ case 3:
+ default:
+ if (s->mode & 1)
+ s->source = sh4.m[SAR3];
+ if (s->mode & 2)
+ sh4.m[SAR3] = s->source;
+ if (s->mode & 4)
+ s->destination = sh4.m[DAR3];
+ if (s->mode & 8)
+ sh4.m[DAR3] = s->destination;
+ break;
+ }
+ switch (s->channel)
+ {
+ case 0:
+ chcr = sh4.m[CHCR0];
+ len = sh4.m[DMATCR0];
+ break;
+ case 1:
+ chcr = sh4.m[CHCR1];
+ len = sh4.m[DMATCR1];
+ break;
+ case 2:
+ chcr = sh4.m[CHCR2];
+ len = sh4.m[DMATCR2];
+ break;
+ case 3:
+ default:
+ chcr = sh4.m[CHCR3];
+ len = sh4.m[DMATCR3];
+ break;
+ }
+ if ((s->direction) == 0) {
+ chcr = (chcr & 0xffff3fff) | ((s->mode & 0x30) << 10);
+ } else {
+ chcr = (chcr & 0xffffcfff) | ((s->mode & 0x30) << 8);
+ }
+ siz = dmasize[(chcr >> 4) & 7];
+ if (siz && (s->size))
+ if ((len * siz) != (s->length * s->size))
+ return;
+ sh4_dma_transfer(s->channel, 0, chcr, &s->source, &s->destination, &len);
+ } else {
+ if ((s->direction) == 0) {
+ len = s->length;
+ p32bits = (UINT32 *)(s->buffer);
+ for (pos = 0;pos < len;pos++) {
+ *p32bits = program_read_dword_64le(s->source);
+ p32bits++;
+ s->source = s->source + 4;
+ }
+ } else {
+ len = s->length;
+ p32bits = (UINT32 *)(s->buffer);
+ for (pos = 0;pos < len;pos++) {
+ program_write_dword_64le(s->destination, *p32bits);
+ p32bits++;
+ s->destination = s->destination + 4;
+ }
+ }
+ }
+}
+
+
+/**************************************************************************
+ * Generic set_info
+ **************************************************************************/
+
+static void sh4_set_info(UINT32 state, cpuinfo *info)
+{
+ switch (state)
+ {
+ /* --- the following bits of info are set as 64-bit signed integers --- */
+ case CPUINFO_INT_INPUT_STATE + SH4_IRL0: set_irq_line(SH4_IRL0, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + SH4_IRL1: set_irq_line(SH4_IRL1, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + SH4_IRL2: set_irq_line(SH4_IRL2, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + SH4_IRL3: set_irq_line(SH4_IRL3, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + SH4_IRLn: set_irq_line(SH4_IRLn, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + INPUT_LINE_NMI: set_irq_line(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_check_pending_irq("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;
+ 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;
+
+ case CPUINFO_INT_SH4_IRLn_INPUT: sh4_set_irln_input(cpu_getactivecpu(), info->i); break;
+ case CPUINFO_INT_SH4_FRT_INPUT: sh4_set_frt_input(cpu_getactivecpu(), info->i); break;
+
+ /* --- the following bits of info are set as pointers to data or functions --- */
+ case CPUINFO_PTR_SH4_FTCSR_READ_CALLBACK: sh4.ftcsr_read_callback = (void (*) (UINT32 ))info->f; break;
+ case CPUINFO_PTR_SH4_EXTERNAL_DDT_DMA: sh4_dma_ddt((struct sh4_ddt_dma *)info->f); break;
+ }
+}
+
+#if 0
+/*When OC index mode is off (CCR.OIX = 0)*/
+static ADDRESS_MAP_START( sh4_internal_map, ADDRESS_SPACE_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, ADDRESS_SPACE_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)
+ADDRESS_MAP_END
+
+
+/**************************************************************************
+ * Generic get_info
+ **************************************************************************/
+
+void sh4_get_info(UINT32 state, cpuinfo *info)
+{
+ switch (state)
+ {
+ /* --- the following bits of info are returned as 64-bit signed integers --- */
+ case CPUINFO_INT_CONTEXT_SIZE: info->i = sizeof(sh4); break;
+ case CPUINFO_INT_INPUT_LINES: info->i = 5; break;
+ case CPUINFO_INT_DEFAULT_IRQ_VECTOR: info->i = 0; break;
+ case CPUINFO_INT_ENDIANNESS: info->i = CPU_IS_LE; 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 CPUINFO_INT_DATABUS_WIDTH + ADDRESS_SPACE_PROGRAM: info->i = 64; break;
+ case CPUINFO_INT_ADDRBUS_WIDTH + ADDRESS_SPACE_PROGRAM: info->i = 32; break;
+ case CPUINFO_INT_ADDRBUS_SHIFT + ADDRESS_SPACE_PROGRAM: info->i = 0; break;
+ case CPUINFO_INT_DATABUS_WIDTH + ADDRESS_SPACE_DATA: info->i = 0; break;
+ case CPUINFO_INT_ADDRBUS_WIDTH + ADDRESS_SPACE_DATA: info->i = 0; break;
+ case CPUINFO_INT_ADDRBUS_SHIFT + ADDRESS_SPACE_DATA: info->i = 0; break;
+ case CPUINFO_INT_DATABUS_WIDTH + ADDRESS_SPACE_IO: info->i = 0; break;
+ case CPUINFO_INT_ADDRBUS_WIDTH + ADDRESS_SPACE_IO: info->i = 0; break;
+ case CPUINFO_INT_ADDRBUS_SHIFT + ADDRESS_SPACE_IO: info->i = 0; break;
+
+ case CPUINFO_PTR_INTERNAL_MEMORY_MAP + ADDRESS_SPACE_PROGRAM: info->internal_map = construct_map_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_PTR_SET_INFO: info->setinfo = sh4_set_info; break;
+ case CPUINFO_PTR_GET_CONTEXT: info->getcontext = sh4_get_context; break;
+ case CPUINFO_PTR_SET_CONTEXT: info->setcontext = sh4_set_context; break;
+ case CPUINFO_PTR_INIT: info->init = sh4_init; break;
+ case CPUINFO_PTR_RESET: info->reset = sh4_reset; break;
+ case CPUINFO_PTR_EXECUTE: info->execute = sh4_execute; break;
+ case CPUINFO_PTR_BURN: info->burn = NULL; break;
+#ifdef MAME_DEBUG
+ case CPUINFO_PTR_DISASSEMBLE: info->disassemble = sh4_dasm; break;
+#endif /* MAME_DEBUG */
+ case CPUINFO_PTR_INSTRUCTION_COUNTER: info->icount = &sh4_icount; break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case CPUINFO_STR_NAME: strcpy(info->s, "SH-4"); break;
+ case CPUINFO_STR_CORE_FAMILY: strcpy(info->s, "Hitachi SH7750"); break;
+ case CPUINFO_STR_CORE_VERSION: strcpy(info->s, "1.0"); break;
+ case CPUINFO_STR_CORE_FILE: strcpy(info->s, __FILE__); break;
+ case CPUINFO_STR_CORE_CREDITS: strcpy(info->s, "Copyright (c) 2007 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;
+ case CPUINFO_STR_REGISTER + SH4_FR0: sprintf(info->s, "FR0 :%08X", sh4.fr[ 0]); break;
+ case CPUINFO_STR_REGISTER + SH4_FR1: sprintf(info->s, "FR1 :%08X", sh4.fr[ 1]); break;
+ case CPUINFO_STR_REGISTER + SH4_FR2: sprintf(info->s, "FR2 :%08X", sh4.fr[ 2]); break;
+ case CPUINFO_STR_REGISTER + SH4_FR3: sprintf(info->s, "FR3 :%08X", sh4.fr[ 3]); break;
+ case CPUINFO_STR_REGISTER + SH4_FR4: sprintf(info->s, "FR4 :%08X", sh4.fr[ 4]); break;
+ case CPUINFO_STR_REGISTER + SH4_FR5: sprintf(info->s, "FR5 :%08X", sh4.fr[ 5]); break;
+ case CPUINFO_STR_REGISTER + SH4_FR6: sprintf(info->s, "FR6 :%08X", sh4.fr[ 6]); break;
+ case CPUINFO_STR_REGISTER + SH4_FR7: sprintf(info->s, "FR7 :%08X", sh4.fr[ 7]); break;
+ case CPUINFO_STR_REGISTER + SH4_FR8: sprintf(info->s, "FR8 :%08X", sh4.fr[ 8]); break;
+ case CPUINFO_STR_REGISTER + SH4_FR9: sprintf(info->s, "FR9 :%08X", sh4.fr[ 9]); break;
+ case CPUINFO_STR_REGISTER + SH4_FR10: sprintf(info->s, "FR10 :%08X", sh4.fr[10]); break;
+ case CPUINFO_STR_REGISTER + SH4_FR11: sprintf(info->s, "FR11 :%08X", sh4.fr[11]); break;
+ case CPUINFO_STR_REGISTER + SH4_FR12: sprintf(info->s, "FR12 :%08X", sh4.fr[12]); break;
+ case CPUINFO_STR_REGISTER + SH4_FR13: sprintf(info->s, "FR13 :%08X", sh4.fr[13]); break;
+ case CPUINFO_STR_REGISTER + SH4_FR14: sprintf(info->s, "FR14 :%08X", sh4.fr[14]); break;
+ case CPUINFO_STR_REGISTER + SH4_FR15: sprintf(info->s, "FR15 :%08X", sh4.fr[15]); break;
+ case CPUINFO_STR_REGISTER + SH4_XF0: sprintf(info->s, "XF0 :%08X", sh4.xf[ 0]); break;
+ case CPUINFO_STR_REGISTER + SH4_XF1: sprintf(info->s, "XF1 :%08X", sh4.xf[ 1]); break;
+ case CPUINFO_STR_REGISTER + SH4_XF2: sprintf(info->s, "XF2 :%08X", sh4.xf[ 2]); break;
+ case CPUINFO_STR_REGISTER + SH4_XF3: sprintf(info->s, "XF3 :%08X", sh4.xf[ 3]); break;
+ case CPUINFO_STR_REGISTER + SH4_XF4: sprintf(info->s, "XF4 :%08X", sh4.xf[ 4]); break;
+ case CPUINFO_STR_REGISTER + SH4_XF5: sprintf(info->s, "XF5 :%08X", sh4.xf[ 5]); break;
+ case CPUINFO_STR_REGISTER + SH4_XF6: sprintf(info->s, "XF6 :%08X", sh4.xf[ 6]); break;
+ case CPUINFO_STR_REGISTER + SH4_XF7: sprintf(info->s, "XF7 :%08X", sh4.xf[ 7]); break;
+ case CPUINFO_STR_REGISTER + SH4_XF8: sprintf(info->s, "XF8 :%08X", sh4.xf[ 8]); break;
+ case CPUINFO_STR_REGISTER + SH4_XF9: sprintf(info->s, "XF9 :%08X", sh4.xf[ 9]); break;
+ case CPUINFO_STR_REGISTER + SH4_XF10: sprintf(info->s, "XF10 :%08X", sh4.xf[10]); break;
+ case CPUINFO_STR_REGISTER + SH4_XF11: sprintf(info->s, "XF11 :%08X", sh4.xf[11]); break;
+ case CPUINFO_STR_REGISTER + SH4_XF12: sprintf(info->s, "XF12 :%08X", sh4.xf[12]); break;
+ case CPUINFO_STR_REGISTER + SH4_XF13: sprintf(info->s, "XF13 :%08X", sh4.xf[13]); break;
+ case CPUINFO_STR_REGISTER + SH4_XF14: sprintf(info->s, "XF14 :%08X", sh4.xf[14]); break;
+ case CPUINFO_STR_REGISTER + SH4_XF15: sprintf(info->s, "XF15 :%08X", sh4.xf[15]); break;
+ case CPUINFO_PTR_SH4_FTCSR_READ_CALLBACK: info->f = (genf*)sh4.ftcsr_read_callback; break;
+
+ }
+}