diff options
Diffstat (limited to 'trunk/src/emu/cpu/sh4/sh4.c')
-rw-r--r-- | trunk/src/emu/cpu/sh4/sh4.c | 3752 |
1 files changed, 3752 insertions, 0 deletions
diff --git a/trunk/src/emu/cpu/sh4/sh4.c b/trunk/src/emu/cpu/sh4/sh4.c new file mode 100644 index 00000000000..09d9efccafa --- /dev/null +++ b/trunk/src/emu/cpu/sh4/sh4.c @@ -0,0 +1,3752 @@ +/***************************************************************************** + * + * sh4.c + * Portable Hitachi SH-4 (SH7750 family) emulator + * + * By R. Belmont, based on sh2.c by Juergen Buchmueller, Mariusz Wojcieszek, + * Olivier Galibert, Sylvain Glaize, and James Forshaw. + * + * + * TODO: FPU + * DMA + * on-board peripherals + * + * DONE: boot/reset setup + * 64-bit data bus + * banked registers + * additional registers for supervisor mode + * FPU status and data registers + * state save for the new registers + * interrupts + * store queues + * + *****************************************************************************/ + +#include "emu.h" +#include "debugger.h" +#include "sh4.h" +#include "sh4regs.h" +#include "sh4comn.h" +#include "sh3comn.h" +#include "sh4tmu.h" + +#ifndef USE_SH4DRC + +CPU_DISASSEMBLE( sh4 ); +CPU_DISASSEMBLE( sh4be ); + +typedef const void (*sh4ophandler)(sh4_state*, const UINT16); + +sh4ophandler master_ophandler_table[0x10000]; +void sh4_build_optable(sh4_state* sh4); + + +/* Called for unimplemented opcodes */ +const void TODO(sh4_state *sh4, const UINT16 opcode) +{ +} + +#if 0 +int sign_of(int n) +{ + return(sh4->fr[n]>>31); +} + +void zero(int n,int sign) +{ +if (sign == 0) + sh4->fr[n] = 0x00000000; +else + sh4->fr[n] = 0x80000000; +if ((sh4->fpscr & PR) == 1) + sh4->fr[n+1] = 0x00000000; +} + +int data_type_of(int n) +{ +UINT32 abs; + + abs = sh4->fr[n] & 0x7fffffff; + if ((sh4->fpscr & PR) == 0) { /* Single-precision */ + if (abs < 0x00800000) { + if (((sh4->fpscr & DN) == 1) || (abs == 0x00000000)) { + if (sign_of(n) == 0) { + zero(n, 0); + return(SH4_FPU_PZERO); + } else { + zero(n, 1); + return(SH4_FPU_NZERO); + } + } else + return(SH4_FPU_DENORM); + } else + if (abs < 0x7f800000) + return(SH4_FPU_NORM); + else + if (abs == 0x7f800000) { + if (sign_of(n) == 0) + return(SH4_FPU_PINF); + else + return(SH4_FPU_NINF); + } else + if (abs < 0x7fc00000) + return(SH4_FPU_qNaN); + else + return(SH4_FPU_sNaN); + } else { /* Double-precision */ + if (abs < 0x00100000) { + if (((sh4->fpscr & DN) == 1) || ((abs == 0x00000000) && (sh4->fr[n+1] == 0x00000000))) { + if(sign_of(n) == 0) { + zero(n, 0); + return(SH4_FPU_PZERO); + } else { + zero(n, 1); + return(SH4_FPU_NZERO); + } + } else + return(SH4_FPU_DENORM); + } else + if (abs < 0x7ff00000) + return(SH4_FPU_NORM); + else + if ((abs == 0x7ff00000) && (sh4->fr[n+1] == 0x00000000)) { + if (sign_of(n) == 0) + return(SH4_FPU_PINF); + else + return(SH4_FPU_NINF); + } else + if (abs < 0x7ff80000) + return(SH4_FPU_qNaN); + else + return(SH4_FPU_sNaN); + } + return(SH4_FPU_NORM); +} +#endif + +const UINT8 RB(sh4_state *sh4, offs_t A) +{ + if (A >= 0xe0000000) + return sh4->program->read_byte(A); + + return sh4->program->read_byte(A & AM); +} + +const UINT16 RW(sh4_state *sh4, offs_t A) +{ + if (A >= 0xe0000000) + return sh4->program->read_word(A); + + return sh4->program->read_word(A & AM); +} + +const UINT32 RL(sh4_state *sh4, offs_t A) +{ + if (A >= 0xe0000000) + return sh4->program->read_dword(A); + + return sh4->program->read_dword(A & AM); +} + +const void WB(sh4_state *sh4, offs_t A, UINT8 V) +{ + if (A >= 0xe0000000) + { + sh4->program->write_byte(A,V); + return; + } + + sh4->program->write_byte(A & AM,V); +} + +const void WW(sh4_state *sh4, offs_t A, UINT16 V) +{ + if (A >= 0xe0000000) + { + sh4->program->write_word(A,V); + return; + } + + sh4->program->write_word(A & AM,V); +} + +const void WL(sh4_state *sh4, offs_t A, UINT32 V) +{ + if (A >= 0xe0000000) + { + sh4->program->write_dword(A,V); + return; + } + + sh4->program->write_dword(A & AM,V); +} + +/* code cycles t-bit + * 0011 nnnn mmmm 1100 1 - + * ADD Rm,Rn + */ +const void ADD(sh4_state *sh4, const UINT16 opcode) +{ + sh4->r[Rn] += sh4->r[Rm]; +} + +/* code cycles t-bit + * 0111 nnnn iiii iiii 1 - + * ADD #imm,Rn + */ +const void ADDI(sh4_state *sh4, const UINT16 opcode) +{ + sh4->r[Rn] += (INT32)(INT16)(INT8)(opcode&0xff); +} + +/* code cycles t-bit + * 0011 nnnn mmmm 1110 1 carry + * ADDC Rm,Rn + */ +const void ADDC(sh4_state *sh4, const UINT16 opcode) +{ + UINT32 m = Rm; UINT32 n = Rn; + 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 + */ +const void ADDV(sh4_state *sh4, const UINT16 opcode) +{ + UINT32 m = Rm; UINT32 n = Rn; + 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 + */ +const void AND(sh4_state *sh4, const UINT16 opcode) +{ + sh4->r[Rn] &= sh4->r[Rm]; +} + + +/* code cycles t-bit + * 1100 1001 iiii iiii 1 - + * AND #imm,R0 + */ +const void ANDI(sh4_state *sh4, const UINT16 opcode) +{ + sh4->r[0] &= (opcode&0xff); +} + +/* code cycles t-bit + * 1100 1101 iiii iiii 1 - + * AND.B #imm,@(R0,GBR) + */ +const void ANDM(sh4_state *sh4, const UINT16 opcode) +{ + UINT32 temp; + + sh4->ea = sh4->gbr + sh4->r[0]; + temp = (opcode&0xff) & RB(sh4, sh4->ea ); + WB(sh4, sh4->ea, temp ); + sh4->sh4_icount -= 2; +} + +/* code cycles t-bit + * 1000 1011 dddd dddd 3/1 - + * BF disp8 + */ +const void BF(sh4_state *sh4, const UINT16 opcode) +{ + if ((sh4->sr & T) == 0) + { + INT32 disp = ((INT32)(opcode&0xff) << 24) >> 24; + sh4->pc = sh4->ea = sh4->pc + disp * 2 + 2; + sh4->sh4_icount -= 2; + } +} + +/* code cycles t-bit + * 1000 1111 dddd dddd 3/1 - + * BFS disp8 + */ +const void BFS(sh4_state *sh4, const UINT16 opcode) +{ + if ((sh4->sr & T) == 0) + { + INT32 disp = ((INT32)(opcode&0xff) << 24) >> 24; + sh4->delay = sh4->pc; + sh4->pc = sh4->ea = sh4->pc + disp * 2 + 2; + sh4->sh4_icount--; + } +} + +/* code cycles t-bit + * 1010 dddd dddd dddd 2 - + * BRA disp12 + */ +const void BRA(sh4_state *sh4, const UINT16 opcode) +{ + INT32 disp = ((INT32)(opcode&0xfff) << 20) >> 20; + +#if BUSY_LOOP_HACKS + if (disp == -2) + { + UINT32 next_opcode = RW(sh4,sh4->ppc & AM); + /* BRA $ + * NOP + */ + if (next_opcode == 0x0009) + sh4->sh4_icount %= 3; /* cycles for BRA $ and NOP taken (3) */ + } +#endif + sh4->delay = sh4->pc; + sh4->pc = sh4->ea = sh4->pc + disp * 2 + 2; + sh4->sh4_icount--; +} + +/* code cycles t-bit + * 0000 mmmm 0010 0011 2 - + * BRAF Rm + */ +const void BRAF(sh4_state *sh4, const UINT16 opcode) +{ + sh4->delay = sh4->pc; + sh4->pc += sh4->r[Rn] + 2; + sh4->sh4_icount--; +} + +/* code cycles t-bit + * 1011 dddd dddd dddd 2 - + * BSR disp12 + */ +const void BSR(sh4_state *sh4, const UINT16 opcode) +{ + INT32 disp = ((INT32)(opcode&0xfff) << 20) >> 20; + + sh4->pr = sh4->pc + 2; + sh4->delay = sh4->pc; + sh4->pc = sh4->ea = sh4->pc + disp * 2 + 2; + sh4->sh4_icount--; +} + +/* code cycles t-bit + * 0000 mmmm 0000 0011 2 - + * BSRF Rm + */ +const void BSRF(sh4_state *sh4, const UINT16 opcode) +{ + sh4->pr = sh4->pc + 2; + sh4->delay = sh4->pc; + sh4->pc += sh4->r[Rn] + 2; + sh4->sh4_icount--; +} + +/* code cycles t-bit + * 1000 1001 dddd dddd 3/1 - + * BT disp8 + */ +const void BT(sh4_state *sh4, const UINT16 opcode) +{ + if ((sh4->sr & T) != 0) + { + INT32 disp = ((INT32)(opcode&0xff) << 24) >> 24; + sh4->pc = sh4->ea = sh4->pc + disp * 2 + 2; + sh4->sh4_icount -= 2; + } +} + +/* code cycles t-bit + * 1000 1101 dddd dddd 2/1 - + * BTS disp8 + */ +const void BTS(sh4_state *sh4, const UINT16 opcode) +{ + if ((sh4->sr & T) != 0) + { + INT32 disp = ((INT32)(opcode&0xff) << 24) >> 24; + sh4->delay = sh4->pc; + sh4->pc = sh4->ea = sh4->pc + disp * 2 + 2; + sh4->sh4_icount--; + } +} + +/* code cycles t-bit + * 0000 0000 0010 1000 1 - + * CLRMAC + */ +const void CLRMAC(sh4_state *sh4, const UINT16 opcode) +{ + sh4->mach = 0; + sh4->macl = 0; +} + +/* code cycles t-bit + * 0000 0000 0000 1000 1 - + * CLRT + */ +const void CLRT(sh4_state *sh4, const UINT16 opcode) +{ + sh4->sr &= ~T; +} + +/* code cycles t-bit + * 0011 nnnn mmmm 0000 1 comparison result + * CMP_EQ Rm,Rn + */ +const void CMPEQ(sh4_state *sh4, const UINT16 opcode) +{ + if (sh4->r[Rn] == sh4->r[Rm]) + sh4->sr |= T; + else + sh4->sr &= ~T; +} + +/* code cycles t-bit + * 0011 nnnn mmmm 0011 1 comparison result + * CMP_GE Rm,Rn + */ +const void CMPGE(sh4_state *sh4, const UINT16 opcode) +{ + if ((INT32) sh4->r[Rn] >= (INT32) sh4->r[Rm]) + sh4->sr |= T; + else + sh4->sr &= ~T; +} + +/* code cycles t-bit + * 0011 nnnn mmmm 0111 1 comparison result + * CMP_GT Rm,Rn + */ +const void CMPGT(sh4_state *sh4, const UINT16 opcode) +{ + if ((INT32) sh4->r[Rn] > (INT32) sh4->r[Rm]) + sh4->sr |= T; + else + sh4->sr &= ~T; +} + +/* code cycles t-bit + * 0011 nnnn mmmm 0110 1 comparison result + * CMP_HI Rm,Rn + */ +const void CMPHI(sh4_state *sh4, const UINT16 opcode) +{ + if ((UINT32) sh4->r[Rn] > (UINT32) sh4->r[Rm]) + sh4->sr |= T; + else + sh4->sr &= ~T; +} + +/* code cycles t-bit + * 0011 nnnn mmmm 0010 1 comparison result + * CMP_HS Rm,Rn + */ +const void CMPHS(sh4_state *sh4, const UINT16 opcode) +{ + if ((UINT32) sh4->r[Rn] >= (UINT32) sh4->r[Rm]) + sh4->sr |= T; + else + sh4->sr &= ~T; +} + + +/* code cycles t-bit + * 0100 nnnn 0001 0101 1 comparison result + * CMP_PL Rn + */ +const void CMPPL(sh4_state *sh4, const UINT16 opcode) +{ + if ((INT32) sh4->r[Rn] > 0) + sh4->sr |= T; + else + sh4->sr &= ~T; +} + +/* code cycles t-bit + * 0100 nnnn 0001 0001 1 comparison result + * CMP_PZ Rn + */ +const void CMPPZ(sh4_state *sh4, const UINT16 opcode) +{ + if ((INT32) sh4->r[Rn] >= 0) + sh4->sr |= T; + else + sh4->sr &= ~T; +} + +/* code cycles t-bit + * 0010 nnnn mmmm 1100 1 comparison result + * CMP_STR Rm,Rn + */ +const void CMPSTR(sh4_state *sh4, const UINT16 opcode) +{ + UINT32 temp; + INT32 HH, HL, LH, LL; + temp = sh4->r[Rn] ^ sh4->r[Rm]; + 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 + */ +const void CMPIM(sh4_state *sh4, const UINT16 opcode) +{ + UINT32 imm = (UINT32)(INT32)(INT16)(INT8)(opcode&0xff); + + 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 + */ +const void DIV0S(sh4_state *sh4, const UINT16 opcode) +{ + UINT32 m = Rm; UINT32 n = Rn; + + 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 + */ +const void DIV0U(sh4_state *sh4, const UINT16 opcode) +{ + sh4->sr &= ~(M | Q | T); +} + +/* code cycles t-bit + * 0011 nnnn mmmm 0100 1 calculation result + * DIV1 Rm,Rn + */ +const void DIV1(sh4_state *sh4, const UINT16 opcode) +{ + UINT32 m = Rm; UINT32 n = Rn; + + 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 */ +const void DMULS(sh4_state *sh4, const UINT16 opcode) +{ + UINT32 m = Rm; UINT32 n = Rn; + + UINT32 RnL, RnH, RmL, RmH, Res0, Res1, Res2; + UINT32 temp0, temp1, temp2, temp3; + INT32 tempm, tempn, fnLmL; + + tempn = (INT32) sh4->r[n]; + tempm = (INT32) sh4->r[m]; + if (tempn < 0) + tempn = 0 - tempn; + if (tempm < 0) + tempm = 0 - tempm; + if ((INT32) (sh4->r[n] ^ sh4->r[m]) < 0) + fnLmL = -1; + else + fnLmL = 0; + temp1 = (UINT32) tempn; + temp2 = (UINT32) tempm; + RnL = temp1 & 0x0000ffff; + RnH = (temp1 >> 16) & 0x0000ffff; + RmL = temp2 & 0x0000ffff; + RmH = (temp2 >> 16) & 0x0000ffff; + temp0 = RmL * RnL; + temp1 = RmH * RnL; + temp2 = RmL * RnH; + temp3 = RmH * RnH; + Res2 = 0; + Res1 = temp1 + temp2; + if (Res1 < temp1) + Res2 += 0x00010000; + temp1 = (Res1 << 16) & 0xffff0000; + Res0 = temp0 + temp1; + if (Res0 < temp0) + Res2++; + Res2 = Res2 + ((Res1 >> 16) & 0x0000ffff) + temp3; + if (fnLmL < 0) + { + Res2 = ~Res2; + if (Res0 == 0) + Res2++; + else + Res0 = (~Res0) + 1; + } + sh4->mach = Res2; + sh4->macl = Res0; + sh4->sh4_icount--; +} + +/* DMULU.L Rm,Rn */ +const void DMULU(sh4_state *sh4, const UINT16 opcode) +{ + UINT32 m = Rm; UINT32 n = Rn; + + UINT32 RnL, RnH, RmL, RmH, Res0, Res1, Res2; + UINT32 temp0, temp1, temp2, temp3; + + RnL = sh4->r[n] & 0x0000ffff; + RnH = (sh4->r[n] >> 16) & 0x0000ffff; + RmL = sh4->r[m] & 0x0000ffff; + RmH = (sh4->r[m] >> 16) & 0x0000ffff; + temp0 = RmL * RnL; + temp1 = RmH * RnL; + temp2 = RmL * RnH; + temp3 = RmH * RnH; + Res2 = 0; + Res1 = temp1 + temp2; + if (Res1 < temp1) + Res2 += 0x00010000; + temp1 = (Res1 << 16) & 0xffff0000; + Res0 = temp0 + temp1; + if (Res0 < temp0) + Res2++; + Res2 = Res2 + ((Res1 >> 16) & 0x0000ffff) + temp3; + sh4->mach = Res2; + sh4->macl = Res0; + sh4->sh4_icount--; +} + +/* DT Rn */ +const void DT(sh4_state *sh4, const UINT16 opcode) +{ + UINT32 n = Rn; + + sh4->r[n]--; + if (sh4->r[n] == 0) + sh4->sr |= T; + else + sh4->sr &= ~T; +#if BUSY_LOOP_HACKS + { + UINT32 next_opcode = RW(sh4,sh4->ppc & AM); + /* DT Rn + * BF $-2 + */ + if (next_opcode == 0x8bfd) + { + while (sh4->r[n] > 1 && sh4->sh4_icount > 4) + { + sh4->r[n]--; + sh4->sh4_icount -= 4; /* cycles for DT (1) and BF taken (3) */ + } + } + } +#endif +} + +/* EXTS.B Rm,Rn */ +const void EXTSB(sh4_state *sh4, const UINT16 opcode) +{ + sh4->r[Rn] = ((INT32)sh4->r[Rm] << 24) >> 24; +} + +/* EXTS.W Rm,Rn */ +const void EXTSW(sh4_state *sh4, const UINT16 opcode) +{ + sh4->r[Rn] = ((INT32)sh4->r[Rm] << 16) >> 16; +} + +/* EXTU.B Rm,Rn */ +const void EXTUB(sh4_state *sh4, const UINT16 opcode) +{ + sh4->r[Rn] = sh4->r[Rm] & 0x000000ff; +} + +/* EXTU.W Rm,Rn */ +const void EXTUW(sh4_state *sh4, const UINT16 opcode) +{ + sh4->r[Rn] = sh4->r[Rm] & 0x0000ffff; +} + +/* JMP @Rm */ +const void JMP(sh4_state *sh4, const UINT16 opcode) +{ + sh4->delay = sh4->pc; + sh4->pc = sh4->ea = sh4->r[Rn]; +} + +/* JSR @Rm */ +const void JSR(sh4_state *sh4, const UINT16 opcode) +{ + sh4->delay = sh4->pc; + sh4->pr = sh4->pc + 2; + sh4->pc = sh4->ea = sh4->r[Rn]; + sh4->sh4_icount--; +} + + +/* LDC Rm,SR */ +const void LDCSR(sh4_state *sh4, const UINT16 opcode) +{ + UINT32 reg; + + reg = sh4->r[Rn]; + if ((sh4->device->machine().debug_flags & DEBUG_FLAG_ENABLED) != 0) + sh4_syncronize_register_bank(sh4, (sh4->sr & sRB) >> 29); + if ((sh4->r[Rn] & sRB) != (sh4->sr & sRB)) + sh4_change_register_bank(sh4, sh4->r[Rn] & sRB ? 1 : 0); + sh4->sr = reg & FLAGS; + sh4_exception_recompute(sh4); +} + +/* LDC Rm,GBR */ +const void LDCGBR(sh4_state *sh4, const UINT16 opcode) +{ + sh4->gbr = sh4->r[Rn]; +} + +/* LDC Rm,VBR */ +const void LDCVBR(sh4_state *sh4, const UINT16 opcode) +{ + sh4->vbr = sh4->r[Rn]; +} + +/* LDC.L @Rm+,SR */ +const void LDCMSR(sh4_state *sh4, const UINT16 opcode) +{ + UINT32 old; + + old = sh4->sr; + sh4->ea = sh4->r[Rn]; + sh4->sr = RL(sh4, sh4->ea ) & FLAGS; + if ((sh4->device->machine().debug_flags & DEBUG_FLAG_ENABLED) != 0) + sh4_syncronize_register_bank(sh4, (old & sRB) >> 29); + if ((old & sRB) != (sh4->sr & sRB)) + sh4_change_register_bank(sh4, sh4->sr & sRB ? 1 : 0); + sh4->r[Rn] += 4; + sh4->sh4_icount -= 2; + sh4_exception_recompute(sh4); +} + +/* LDC.L @Rm+,GBR */ +const void LDCMGBR(sh4_state *sh4, const UINT16 opcode) +{ + sh4->ea = sh4->r[Rn]; + sh4->gbr = RL(sh4, sh4->ea ); + sh4->r[Rn] += 4; + sh4->sh4_icount -= 2; +} + +/* LDC.L @Rm+,VBR */ +const void LDCMVBR(sh4_state *sh4, const UINT16 opcode) +{ + sh4->ea = sh4->r[Rn]; + sh4->vbr = RL(sh4, sh4->ea ); + sh4->r[Rn] += 4; + sh4->sh4_icount -= 2; +} + +/* LDS Rm,MACH */ +const void LDSMACH(sh4_state *sh4, const UINT16 opcode) +{ + sh4->mach = sh4->r[Rn]; +} + +/* LDS Rm,MACL */ +const void LDSMACL(sh4_state *sh4, const UINT16 opcode) +{ + sh4->macl = sh4->r[Rn]; +} + +/* LDS Rm,PR */ +const void LDSPR(sh4_state *sh4, const UINT16 opcode) +{ + sh4->pr = sh4->r[Rn]; +} + +/* LDS.L @Rm+,MACH */ +const void LDSMMACH(sh4_state *sh4, const UINT16 opcode) +{ + sh4->ea = sh4->r[Rn]; + sh4->mach = RL(sh4, sh4->ea ); + sh4->r[Rn] += 4; +} + +/* LDS.L @Rm+,MACL */ +const void LDSMMACL(sh4_state *sh4, const UINT16 opcode) +{ + sh4->ea = sh4->r[Rn]; + sh4->macl = RL(sh4, sh4->ea ); + sh4->r[Rn] += 4; +} + +/* LDS.L @Rm+,PR */ +const void LDSMPR(sh4_state *sh4, const UINT16 opcode) +{ + sh4->ea = sh4->r[Rn]; + sh4->pr = RL(sh4, sh4->ea ); + sh4->r[Rn] += 4; +} + +/* MAC.L @Rm+,@Rn+ */ +const void MAC_L(sh4_state *sh4, const UINT16 opcode) +{ + UINT32 m = Rm; UINT32 n = Rn; + + UINT32 RnL, RnH, RmL, RmH, Res0, Res1, Res2; + UINT32 temp0, temp1, temp2, temp3; + INT32 tempm, tempn, fnLmL; + + tempn = (INT32) RL(sh4, sh4->r[n] ); + sh4->r[n] += 4; + tempm = (INT32) RL(sh4, sh4->r[m] ); + sh4->r[m] += 4; + if ((INT32) (tempn ^ tempm) < 0) + fnLmL = -1; + else + fnLmL = 0; + if (tempn < 0) + tempn = 0 - tempn; + if (tempm < 0) + tempm = 0 - tempm; + temp1 = (UINT32) tempn; + temp2 = (UINT32) tempm; + RnL = temp1 & 0x0000ffff; + RnH = (temp1 >> 16) & 0x0000ffff; + RmL = temp2 & 0x0000ffff; + RmH = (temp2 >> 16) & 0x0000ffff; + temp0 = RmL * RnL; + temp1 = RmH * RnL; + temp2 = RmL * RnH; + temp3 = RmH * RnH; + Res2 = 0; + Res1 = temp1 + temp2; + if (Res1 < temp1) + Res2 += 0x00010000; + temp1 = (Res1 << 16) & 0xffff0000; + Res0 = temp0 + temp1; + if (Res0 < temp0) + Res2++; + Res2 = Res2 + ((Res1 >> 16) & 0x0000ffff) + temp3; + if (fnLmL < 0) + { + Res2 = ~Res2; + if (Res0 == 0) + Res2++; + else + Res0 = (~Res0) + 1; + } + if (sh4->sr & S) + { + Res0 = sh4->macl + Res0; + if (sh4->macl > Res0) + Res2++; + Res2 += (sh4->mach & 0x0000ffff); + if (((INT32) Res2 < 0) && (Res2 < 0xffff8000)) + { + Res2 = 0x00008000; + Res0 = 0x00000000; + } + else if (((INT32) Res2 > 0) && (Res2 > 0x00007fff)) + { + Res2 = 0x00007fff; + Res0 = 0xffffffff; + } + sh4->mach = Res2; + sh4->macl = Res0; + } + else + { + Res0 = sh4->macl + Res0; + if (sh4->macl > Res0) + Res2++; + Res2 += sh4->mach; + sh4->mach = Res2; + sh4->macl = Res0; + } + sh4->sh4_icount -= 2; +} + +/* MAC.W @Rm+,@Rn+ */ +const void MAC_W(sh4_state *sh4, const UINT16 opcode) +{ + UINT32 m = Rm; UINT32 n = Rn; + + INT32 tempm, tempn, dest, src, ans; + UINT32 templ; + + tempn = (INT32) RW(sh4, sh4->r[n] ); + sh4->r[n] += 2; + tempm = (INT32) RW(sh4, sh4->r[m] ); + sh4->r[m] += 2; + templ = sh4->macl; + tempm = ((INT32) (short) tempn * (INT32) (short) tempm); + if ((INT32) sh4->macl >= 0) + dest = 0; + else + dest = 1; + if ((INT32) tempm >= 0) + { + src = 0; + tempn = 0; + } + else + { + src = 1; + tempn = 0xffffffff; + } + src += dest; + sh4->macl += tempm; + if ((INT32) sh4->macl >= 0) + ans = 0; + else + ans = 1; + ans += dest; + if (sh4->sr & S) + { + if (ans == 1) + { + if (src == 0) + sh4->macl = 0x7fffffff; + if (src == 2) + sh4->macl = 0x80000000; + } + } + else + { + sh4->mach += tempn; + if (templ > sh4->macl) + sh4->mach += 1; + } + sh4->sh4_icount -= 2; +} + +/* MOV Rm,Rn */ +const void MOV(sh4_state *sh4, const UINT16 opcode) +{ + sh4->r[Rn] = sh4->r[Rm]; +} + +/* MOV.B Rm,@Rn */ +const void MOVBS(sh4_state *sh4, const UINT16 opcode) +{ + sh4->ea = sh4->r[Rn]; + WB(sh4, sh4->ea, sh4->r[Rm] & 0x000000ff); +} + +/* MOV.W Rm,@Rn */ +const void MOVWS(sh4_state *sh4, const UINT16 opcode) +{ + sh4->ea = sh4->r[Rn]; + WW(sh4, sh4->ea, sh4->r[Rm] & 0x0000ffff); +} + +/* MOV.L Rm,@Rn */ +const void MOVLS(sh4_state *sh4, const UINT16 opcode) +{ + sh4->ea = sh4->r[Rn]; + WL(sh4, sh4->ea, sh4->r[Rm] ); +} + +/* MOV.B @Rm,Rn */ +const void MOVBL(sh4_state *sh4, const UINT16 opcode) +{ + sh4->ea = sh4->r[Rm]; + sh4->r[Rn] = (UINT32)(INT32)(INT16)(INT8) RB(sh4, sh4->ea ); +} + +/* MOV.W @Rm,Rn */ +const void MOVWL(sh4_state *sh4, const UINT16 opcode) +{ + sh4->ea = sh4->r[Rm]; + sh4->r[Rn] = (UINT32)(INT32)(INT16) RW(sh4, sh4->ea ); +} + +/* MOV.L @Rm,Rn */ +const void MOVLL(sh4_state *sh4, const UINT16 opcode) +{ + sh4->ea = sh4->r[Rm]; + sh4->r[Rn] = RL(sh4, sh4->ea ); +} + +/* MOV.B Rm,@-Rn */ +const void MOVBM(sh4_state *sh4, const UINT16 opcode) +{ + UINT32 data = sh4->r[Rm] & 0x000000ff; + + sh4->r[Rn] -= 1; + WB(sh4, sh4->r[Rn], data ); +} + +/* MOV.W Rm,@-Rn */ +const void MOVWM(sh4_state *sh4, const UINT16 opcode) +{ + UINT32 data = sh4->r[Rm] & 0x0000ffff; + + sh4->r[Rn] -= 2; + WW(sh4, sh4->r[Rn], data ); +} + +/* MOV.L Rm,@-Rn */ +const void MOVLM(sh4_state *sh4, const UINT16 opcode) +{ + UINT32 data = sh4->r[Rm]; + + sh4->r[Rn] -= 4; + WL(sh4, sh4->r[Rn], data ); +} + +/* MOV.B @Rm+,Rn */ +const void MOVBP(sh4_state *sh4, const UINT16 opcode) +{ + UINT32 m = Rm; UINT32 n = Rn; + + sh4->r[n] = (UINT32)(INT32)(INT16)(INT8) RB(sh4, sh4->r[m] ); + if (n != m) + sh4->r[m] += 1; +} + +/* MOV.W @Rm+,Rn */ +const void MOVWP(sh4_state *sh4, const UINT16 opcode) +{ + UINT32 m = Rm; UINT32 n = Rn; + + sh4->r[n] = (UINT32)(INT32)(INT16) RW(sh4, sh4->r[m] ); + if (n != m) + sh4->r[m] += 2; +} + +/* MOV.L @Rm+,Rn */ +const void MOVLP(sh4_state *sh4, const UINT16 opcode) +{ + UINT32 m = Rm; UINT32 n = Rn; + + sh4->r[n] = RL(sh4, sh4->r[m] ); + if (n != m) + sh4->r[m] += 4; +} + +/* MOV.B Rm,@(R0,Rn) */ +const void MOVBS0(sh4_state *sh4, const UINT16 opcode) +{ + sh4->ea = sh4->r[Rn] + sh4->r[0]; + WB(sh4, sh4->ea, sh4->r[Rm] & 0x000000ff ); +} + +/* MOV.W Rm,@(R0,Rn) */ +const void MOVWS0(sh4_state *sh4, const UINT16 opcode) +{ + sh4->ea = sh4->r[Rn] + sh4->r[0]; + WW(sh4, sh4->ea, sh4->r[Rm] & 0x0000ffff ); +} + +/* MOV.L Rm,@(R0,Rn) */ +const void MOVLS0(sh4_state *sh4, const UINT16 opcode) +{ + sh4->ea = sh4->r[Rn] + sh4->r[0]; + WL(sh4, sh4->ea, sh4->r[Rm] ); +} + +/* MOV.B @(R0,Rm),Rn */ +const void MOVBL0(sh4_state *sh4, const UINT16 opcode) +{ + sh4->ea = sh4->r[Rm] + sh4->r[0]; + sh4->r[Rn] = (UINT32)(INT32)(INT16)(INT8) RB(sh4, sh4->ea ); +} + +/* MOV.W @(R0,Rm),Rn */ +const void MOVWL0(sh4_state *sh4, const UINT16 opcode) +{ + sh4->ea = sh4->r[Rm] + sh4->r[0]; + sh4->r[Rn] = (UINT32)(INT32)(INT16) RW(sh4, sh4->ea ); +} + +/* MOV.L @(R0,Rm),Rn */ +const void MOVLL0(sh4_state *sh4, const UINT16 opcode) +{ + sh4->ea = sh4->r[Rm] + sh4->r[0]; + sh4->r[Rn] = RL(sh4, sh4->ea ); +} + +/* MOV #imm,Rn */ +const void MOVI(sh4_state *sh4, const UINT16 opcode) +{ + sh4->r[Rn] = (UINT32)(INT32)(INT16)(INT8)(opcode&0xff); +} + +/* MOV.W @(disp8,PC),Rn */ +const void MOVWI(sh4_state *sh4, const UINT16 opcode) +{ + UINT32 disp = opcode & 0xff; + sh4->ea = sh4->pc + disp * 2 + 2; + sh4->r[Rn] = (UINT32)(INT32)(INT16) RW(sh4, sh4->ea ); +} + +/* MOV.L @(disp8,PC),Rn */ +const void MOVLI(sh4_state *sh4, const UINT16 opcode) +{ + UINT32 disp = opcode & 0xff; + sh4->ea = ((sh4->pc + 2) & ~3) + disp * 4; + sh4->r[Rn] = RL(sh4, sh4->ea ); +} + +/* MOV.B @(disp8,GBR),R0 */ +const void MOVBLG(sh4_state *sh4, const UINT16 opcode) +{ + UINT32 disp = opcode & 0xff; + sh4->ea = sh4->gbr + disp; + sh4->r[0] = (UINT32)(INT32)(INT16)(INT8) RB(sh4, sh4->ea ); +} + +/* MOV.W @(disp8,GBR),R0 */ +const void MOVWLG(sh4_state *sh4, const UINT16 opcode) +{ + UINT32 disp = opcode & 0xff; + sh4->ea = sh4->gbr + disp * 2; + sh4->r[0] = (INT32)(INT16) RW(sh4, sh4->ea ); +} + +/* MOV.L @(disp8,GBR),R0 */ +const void MOVLLG(sh4_state *sh4, const UINT16 opcode) +{ + UINT32 disp = opcode & 0xff; + sh4->ea = sh4->gbr + disp * 4; + sh4->r[0] = RL(sh4, sh4->ea ); +} + +/* MOV.B R0,@(disp8,GBR) */ +const void MOVBSG(sh4_state *sh4, const UINT16 opcode) +{ + UINT32 disp = opcode & 0xff; + sh4->ea = sh4->gbr + disp; + WB(sh4, sh4->ea, sh4->r[0] & 0x000000ff ); +} + +/* MOV.W R0,@(disp8,GBR) */ +const void MOVWSG(sh4_state *sh4, const UINT16 opcode) +{ + UINT32 disp = opcode & 0xff; + sh4->ea = sh4->gbr + disp * 2; + WW(sh4, sh4->ea, sh4->r[0] & 0x0000ffff ); +} + +/* MOV.L R0,@(disp8,GBR) */ +const void MOVLSG(sh4_state *sh4, const UINT16 opcode) +{ + UINT32 disp = opcode & 0xff; + sh4->ea = sh4->gbr + disp * 4; + WL(sh4, sh4->ea, sh4->r[0] ); +} + +/* MOV.B R0,@(disp4,Rm) */ +const void MOVBS4(sh4_state *sh4, const UINT16 opcode) +{ + UINT32 disp = opcode & 0x0f; + sh4->ea = sh4->r[Rm] + disp; + WB(sh4, sh4->ea, sh4->r[0] & 0x000000ff ); +} + +/* MOV.W R0,@(disp4,Rm) */ +const void MOVWS4(sh4_state *sh4, const UINT16 opcode) +{ + UINT32 disp = opcode & 0x0f; + sh4->ea = sh4->r[Rm] + disp * 2; + WW(sh4, sh4->ea, sh4->r[0] & 0x0000ffff ); +} + +/* MOV.L Rm,@(disp4,Rn) */ +const void MOVLS4(sh4_state *sh4, const UINT16 opcode) +{ + UINT32 disp = opcode & 0x0f; + sh4->ea = sh4->r[Rn] + disp * 4; + WL(sh4, sh4->ea, sh4->r[Rm] ); +} + +/* MOV.B @(disp4,Rm),R0 */ +const void MOVBL4(sh4_state *sh4, const UINT16 opcode) +{ + UINT32 disp = opcode & 0x0f; + sh4->ea = sh4->r[Rm] + disp; + sh4->r[0] = (UINT32)(INT32)(INT16)(INT8) RB(sh4, sh4->ea ); +} + +/* MOV.W @(disp4,Rm),R0 */ +const void MOVWL4(sh4_state *sh4, const UINT16 opcode) +{ + UINT32 disp = opcode & 0x0f; + sh4->ea = sh4->r[Rm] + disp * 2; + sh4->r[0] = (UINT32)(INT32)(INT16) RW(sh4, sh4->ea ); +} + +/* MOV.L @(disp4,Rm),Rn */ +const void MOVLL4(sh4_state *sh4, const UINT16 opcode) +{ + UINT32 disp = opcode & 0x0f; + sh4->ea = sh4->r[Rm] + disp * 4; + sh4->r[Rn] = RL(sh4, sh4->ea ); +} + +/* MOVA @(disp8,PC),R0 */ +const void MOVA(sh4_state *sh4, const UINT16 opcode) +{ + UINT32 disp = opcode & 0xff; + sh4->ea = ((sh4->pc + 2) & ~3) + disp * 4; + sh4->r[0] = sh4->ea; +} + +/* MOVT Rn */ +const void MOVT(sh4_state *sh4, const UINT16 opcode) +{ + sh4->r[Rn] = sh4->sr & T; +} + +/* MUL.L Rm,Rn */ +const void MULL(sh4_state *sh4, const UINT16 opcode) +{ + sh4->macl = sh4->r[Rn] * sh4->r[Rm]; + sh4->sh4_icount--; +} + +/* MULS Rm,Rn */ +const void MULS(sh4_state *sh4, const UINT16 opcode) +{ + sh4->macl = (INT16) sh4->r[Rn] * (INT16) sh4->r[Rm]; +} + +/* MULU Rm,Rn */ +const void MULU(sh4_state *sh4, const UINT16 opcode) +{ + sh4->macl = (UINT16) sh4->r[Rn] * (UINT16) sh4->r[Rm]; +} + +/* NEG Rm,Rn */ +const void NEG(sh4_state *sh4, const UINT16 opcode) +{ + sh4->r[Rn] = 0 - sh4->r[Rm]; +} + +/* NEGC Rm,Rn */ +const void NEGC(sh4_state *sh4, const UINT16 opcode) +{ + UINT32 temp; + + temp = sh4->r[Rm]; + sh4->r[Rn] = -temp - (sh4->sr & T); + if (temp || (sh4->sr & T)) + sh4->sr |= T; + else + sh4->sr &= ~T; +} + +/* NOP */ +const void NOP(sh4_state *sh4, const UINT16 opcode) +{ +} + +/* NOT Rm,Rn */ +const void NOT(sh4_state *sh4, const UINT16 opcode) +{ + sh4->r[Rn] = ~sh4->r[Rm]; +} + +/* OR Rm,Rn */ +const void OR(sh4_state *sh4, const UINT16 opcode) +{ + sh4->r[Rn] |= sh4->r[Rm]; +} + +/* OR #imm,R0 */ +const void ORI(sh4_state *sh4, const UINT16 opcode) +{ + sh4->r[0] |= (opcode&0xff); + sh4->sh4_icount -= 2; +} + +/* OR.B #imm,@(R0,GBR) */ +const void ORM(sh4_state *sh4, const UINT16 opcode) +{ + UINT32 temp; + + sh4->ea = sh4->gbr + sh4->r[0]; + temp = RB(sh4, sh4->ea ); + temp |= (opcode&0xff); + WB(sh4, sh4->ea, temp ); +} + +/* ROTCL Rn */ +const void ROTCL(sh4_state *sh4, const UINT16 opcode) +{ + UINT32 n = Rn; + + 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 */ +const void ROTCR(sh4_state *sh4, const UINT16 opcode) +{ + UINT32 n = Rn; + + 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 */ +const void ROTL(sh4_state *sh4, const UINT16 opcode) +{ + UINT32 n = Rn; + + sh4->sr = (sh4->sr & ~T) | ((sh4->r[n] >> 31) & T); + sh4->r[n] = (sh4->r[n] << 1) | (sh4->r[n] >> 31); +} + +/* ROTR Rn */ +const void ROTR(sh4_state *sh4, const UINT16 opcode) +{ + UINT32 n = Rn; + + sh4->sr = (sh4->sr & ~T) | (sh4->r[n] & T); + sh4->r[n] = (sh4->r[n] >> 1) | (sh4->r[n] << 31); +} + +/* RTE */ +const void RTE(sh4_state *sh4, const UINT16 opcode) +{ + sh4->delay = sh4->pc; + sh4->pc = sh4->ea = sh4->spc; + if ((sh4->device->machine().debug_flags & DEBUG_FLAG_ENABLED) != 0) + sh4_syncronize_register_bank(sh4, (sh4->sr & sRB) >> 29); + if ((sh4->ssr & sRB) != (sh4->sr & sRB)) + sh4_change_register_bank(sh4, sh4->ssr & sRB ? 1 : 0); + sh4->sr = sh4->ssr; + sh4->sh4_icount--; + sh4_exception_recompute(sh4); +} + +/* RTS */ +const void RTS(sh4_state *sh4, const UINT16 opcode) +{ + sh4->delay = sh4->pc; + sh4->pc = sh4->ea = sh4->pr; + sh4->sh4_icount--; +} + +/* SETT */ +const void SETT(sh4_state *sh4, const UINT16 opcode) +{ + sh4->sr |= T; +} + +/* SHAL Rn (same as SHLL) */ +const void SHAL(sh4_state *sh4, const UINT16 opcode) +{ + UINT32 n = Rn; + + sh4->sr = (sh4->sr & ~T) | ((sh4->r[n] >> 31) & T); + sh4->r[n] <<= 1; +} + +/* SHAR Rn */ +const void SHAR(sh4_state *sh4, const UINT16 opcode) +{ + UINT32 n = Rn; + + sh4->sr = (sh4->sr & ~T) | (sh4->r[n] & T); + sh4->r[n] = (UINT32)((INT32)sh4->r[n] >> 1); +} + +/* SHLL Rn (same as SHAL) */ +const void SHLL(sh4_state *sh4, const UINT16 opcode) +{ + UINT32 n = Rn; + + sh4->sr = (sh4->sr & ~T) | ((sh4->r[n] >> 31) & T); + sh4->r[n] <<= 1; +} + +/* SHLL2 Rn */ +const void SHLL2(sh4_state *sh4, const UINT16 opcode) +{ + sh4->r[Rn] <<= 2; +} + +/* SHLL8 Rn */ +const void SHLL8(sh4_state *sh4, const UINT16 opcode) +{ + sh4->r[Rn] <<= 8; +} + +/* SHLL16 Rn */ +const void SHLL16(sh4_state *sh4, const UINT16 opcode) +{ + sh4->r[Rn] <<= 16; +} + +/* SHLR Rn */ +const void SHLR(sh4_state *sh4, const UINT16 opcode) +{ + UINT32 n = Rn; + + sh4->sr = (sh4->sr & ~T) | (sh4->r[n] & T); + sh4->r[n] >>= 1; +} + +/* SHLR2 Rn */ +const void SHLR2(sh4_state *sh4, const UINT16 opcode) +{ + sh4->r[Rn] >>= 2; +} + +/* SHLR8 Rn */ +const void SHLR8(sh4_state *sh4, const UINT16 opcode) +{ + sh4->r[Rn] >>= 8; +} + +/* SHLR16 Rn */ +const void SHLR16(sh4_state *sh4, const UINT16 opcode) +{ + sh4->r[Rn] >>= 16; +} + +/* SLEEP */ +const void SLEEP(sh4_state *sh4, const UINT16 opcode) +{ + /* 0 = normal mode */ + /* 1 = enters into power-down mode */ + /* 2 = go out the power-down mode after an exception */ + if(sh4->sleep_mode != 2) + sh4->pc -= 2; + sh4->sh4_icount -= 2; + /* Wait_for_exception; */ + if(sh4->sleep_mode == 0) + sh4->sleep_mode = 1; + else if(sh4->sleep_mode == 2) + sh4->sleep_mode = 0; +} + +/* STC SR,Rn */ +const void STCSR(sh4_state *sh4, const UINT16 opcode) +{ + sh4->r[Rn] = sh4->sr; +} + +/* STC GBR,Rn */ +const void STCGBR(sh4_state *sh4, const UINT16 opcode) +{ + sh4->r[Rn] = sh4->gbr; +} + +/* STC VBR,Rn */ +const void STCVBR(sh4_state *sh4, const UINT16 opcode) +{ + sh4->r[Rn] = sh4->vbr; +} + +/* STC.L SR,@-Rn */ +const void STCMSR(sh4_state *sh4, const UINT16 opcode) +{ + UINT32 n = Rn; + + sh4->r[n] -= 4; + sh4->ea = sh4->r[n]; + WL(sh4, sh4->ea, sh4->sr ); + sh4->sh4_icount--; +} + +/* STC.L GBR,@-Rn */ +const void STCMGBR(sh4_state *sh4, const UINT16 opcode) +{ + UINT32 n = Rn; + + sh4->r[n] -= 4; + sh4->ea = sh4->r[n]; + WL(sh4, sh4->ea, sh4->gbr ); + sh4->sh4_icount--; +} + +/* STC.L VBR,@-Rn */ +const void STCMVBR(sh4_state *sh4, const UINT16 opcode) +{ + UINT32 n = Rn; + + sh4->r[n] -= 4; + sh4->ea = sh4->r[n]; + WL(sh4, sh4->ea, sh4->vbr ); + sh4->sh4_icount--; +} + +/* STS MACH,Rn */ +const void STSMACH(sh4_state *sh4, const UINT16 opcode) +{ + sh4->r[Rn] = sh4->mach; +} + +/* STS MACL,Rn */ +const void STSMACL(sh4_state *sh4, const UINT16 opcode) +{ + sh4->r[Rn] = sh4->macl; +} + +/* STS PR,Rn */ +const void STSPR(sh4_state *sh4, const UINT16 opcode) +{ + sh4->r[Rn] = sh4->pr; +} + +/* STS.L MACH,@-Rn */ +const void STSMMACH(sh4_state *sh4, const UINT16 opcode) +{ + UINT32 n = Rn; + + sh4->r[n] -= 4; + sh4->ea = sh4->r[n]; + WL(sh4, sh4->ea, sh4->mach ); +} + +/* STS.L MACL,@-Rn */ +const void STSMMACL(sh4_state *sh4, const UINT16 opcode) +{ + UINT32 n = Rn; + + sh4->r[n] -= 4; + sh4->ea = sh4->r[n]; + WL(sh4, sh4->ea, sh4->macl ); +} + +/* STS.L PR,@-Rn */ +const void STSMPR(sh4_state *sh4, const UINT16 opcode) +{ + UINT32 n = Rn; + + sh4->r[n] -= 4; + sh4->ea = sh4->r[n]; + WL(sh4, sh4->ea, sh4->pr ); +} + +/* SUB Rm,Rn */ +const void SUB(sh4_state *sh4, const UINT16 opcode) +{ + sh4->r[Rn] -= sh4->r[Rm]; +} + +/* SUBC Rm,Rn */ +const void SUBC(sh4_state *sh4, const UINT16 opcode) +{ + UINT32 m = Rm; UINT32 n = Rn; + + 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 */ +const void SUBV(sh4_state *sh4, const UINT16 opcode) +{ + UINT32 m = Rm; UINT32 n = Rn; + + 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 */ +const void SWAPB(sh4_state *sh4, const UINT16 opcode) +{ + UINT32 m = Rm; UINT32 n = Rn; + + 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 */ +const void SWAPW(sh4_state *sh4, const UINT16 opcode) +{ + UINT32 m = Rm; UINT32 n = Rn; + + UINT32 temp; + + temp = (sh4->r[m] >> 16) & 0x0000ffff; + sh4->r[n] = (sh4->r[m] << 16) | temp; +} + +/* TAS.B @Rn */ +const void TAS(sh4_state *sh4, const UINT16 opcode) +{ + UINT32 n = Rn; + + UINT32 temp; + sh4->ea = sh4->r[n]; + /* Bus Lock enable */ + temp = RB(sh4, sh4->ea ); + if (temp == 0) + sh4->sr |= T; + else + sh4->sr &= ~T; + temp |= 0x80; + /* Bus Lock disable */ + WB(sh4, sh4->ea, temp ); + sh4->sh4_icount -= 3; +} + +/* TRAPA #imm */ +const void TRAPA(sh4_state *sh4, const UINT16 opcode) +{ + UINT32 imm = opcode & 0xff; + + if (sh4->cpu_type == CPU_TYPE_SH4) + { + sh4->m[TRA] = imm << 2; + } + else /* SH3 */ + { + sh4->m_sh3internal_upper[SH3_TRA_ADDR] = imm << 2; + } + + + sh4->ssr = sh4->sr; + sh4->spc = sh4->pc; + sh4->sgr = sh4->r[15]; + + sh4->sr |= MD; + if ((sh4->device->machine().debug_flags & DEBUG_FLAG_ENABLED) != 0) + sh4_syncronize_register_bank(sh4, (sh4->sr & sRB) >> 29); + if (!(sh4->sr & sRB)) + sh4_change_register_bank(sh4, 1); + sh4->sr |= sRB; + sh4->sr |= BL; + sh4_exception_recompute(sh4); + + if (sh4->cpu_type == CPU_TYPE_SH4) + { + sh4->m[EXPEVT] = 0x00000160; + } + else /* SH3 */ + { + sh4->m_sh3internal_upper[SH3_EXPEVT_ADDR] = 0x00000160; + } + + sh4->pc = sh4->vbr + 0x00000100; + + sh4->sh4_icount -= 7; +} + +/* TST Rm,Rn */ +const void TST(sh4_state *sh4, const UINT16 opcode) +{ + if ((sh4->r[Rn] & sh4->r[Rm]) == 0) + sh4->sr |= T; + else + sh4->sr &= ~T; +} + +/* TST #imm,R0 */ +const void TSTI(sh4_state *sh4, const UINT16 opcode) +{ + UINT32 imm = opcode & 0xff; + + if ((imm & sh4->r[0]) == 0) + sh4->sr |= T; + else + sh4->sr &= ~T; +} + +/* TST.B #imm,@(R0,GBR) */ +const void TSTM(sh4_state *sh4, const UINT16 opcode) +{ + UINT32 imm = opcode & 0xff; + + sh4->ea = sh4->gbr + sh4->r[0]; + if ((imm & RB(sh4, sh4->ea )) == 0) + sh4->sr |= T; + else + sh4->sr &= ~T; + sh4->sh4_icount -= 2; +} + +/* XOR Rm,Rn */ +const void XOR(sh4_state *sh4, const UINT16 opcode) +{ + sh4->r[Rn] ^= sh4->r[Rm]; +} + +/* XOR #imm,R0 */ +const void XORI(sh4_state *sh4, const UINT16 opcode) +{ + UINT32 imm = opcode & 0xff; + sh4->r[0] ^= imm; +} + +/* XOR.B #imm,@(R0,GBR) */ +const void XORM(sh4_state *sh4, const UINT16 opcode) +{ + UINT32 imm = opcode & 0xff; + UINT32 temp; + + sh4->ea = sh4->gbr + sh4->r[0]; + temp = RB(sh4, sh4->ea ); + temp ^= imm; + WB(sh4, sh4->ea, temp ); + sh4->sh4_icount -= 2; +} + +/* XTRCT Rm,Rn */ +const void XTRCT(sh4_state *sh4, const UINT16 opcode) +{ + UINT32 m = Rm; UINT32 n = Rn; + + UINT32 temp; + + temp = (sh4->r[m] << 16) & 0xffff0000; + sh4->r[n] = (sh4->r[n] >> 16) & 0x0000ffff; + sh4->r[n] |= temp; +} + +/* STC SSR,Rn */ +const void STCSSR(sh4_state *sh4, const UINT16 opcode) +{ + sh4->r[Rn] = sh4->ssr; +} + +/* STC SPC,Rn */ +const void STCSPC(sh4_state *sh4, const UINT16 opcode) +{ + sh4->r[Rn] = sh4->spc; +} + +/* STC SGR,Rn */ +const void STCSGR(sh4_state *sh4, const UINT16 opcode) +{ + sh4->r[Rn] = sh4->sgr; +} + +/* STS FPUL,Rn */ +const void STSFPUL(sh4_state *sh4, const UINT16 opcode) +{ + sh4->r[Rn] = sh4->fpul; +} + +/* STS FPSCR,Rn */ +const void STSFPSCR(sh4_state *sh4, const UINT16 opcode) +{ + sh4->r[Rn] = sh4->fpscr & 0x003FFFFF; +} + +/* STC DBR,Rn */ +const void STCDBR(sh4_state *sh4, const UINT16 opcode) +{ + sh4->r[Rn] = sh4->dbr; +} + +/* STCRBANK Rm_BANK,Rn */ +const void STCRBANK(sh4_state *sh4, const UINT16 opcode) +{ + UINT32 m = Rm; + + sh4->r[Rn] = sh4->rbnk[sh4->sr&sRB ? 0 : 1][m & 7]; +} + +/* STCMRBANK Rm_BANK,@-Rn */ +const void STCMRBANK(sh4_state *sh4, const UINT16 opcode) +{ + UINT32 m = Rm; UINT32 n = Rn; + + sh4->r[n] -= 4; + sh4->ea = sh4->r[n]; + WL(sh4, sh4->ea, sh4->rbnk[sh4->sr&sRB ? 0 : 1][m & 7]); + sh4->sh4_icount--; +} + +/* MOVCA.L R0,@Rn */ +const void MOVCAL(sh4_state *sh4, const UINT16 opcode) +{ + sh4->ea = sh4->r[Rn]; + WL(sh4, sh4->ea, sh4->r[0] ); +} + +const void CLRS(sh4_state *sh4, const UINT16 opcode) +{ + sh4->sr &= ~S; +} + +const void SETS(sh4_state *sh4, const UINT16 opcode) +{ + sh4->sr |= S; +} + +/* STS.L SGR,@-Rn */ +const void STCMSGR(sh4_state *sh4, const UINT16 opcode) +{ + UINT32 n = Rn; + + sh4->r[n] -= 4; + sh4->ea = sh4->r[n]; + WL(sh4, sh4->ea, sh4->sgr ); +} + +/* STS.L FPUL,@-Rn */ +const void STSMFPUL(sh4_state *sh4, const UINT16 opcode) +{ + UINT32 n = Rn; + + sh4->r[n] -= 4; + sh4->ea = sh4->r[n]; + WL(sh4, sh4->ea, sh4->fpul ); +} + +/* STS.L FPSCR,@-Rn */ +const void STSMFPSCR(sh4_state *sh4, const UINT16 opcode) +{ + UINT32 n = Rn; + + sh4->r[n] -= 4; + sh4->ea = sh4->r[n]; + WL(sh4, sh4->ea, sh4->fpscr & 0x003FFFFF); +} + +/* STC.L DBR,@-Rn */ +const void STCMDBR(sh4_state *sh4, const UINT16 opcode) +{ + UINT32 n = Rn; + + sh4->r[n] -= 4; + sh4->ea = sh4->r[n]; + WL(sh4, sh4->ea, sh4->dbr ); +} + +/* STC.L SSR,@-Rn */ +const void STCMSSR(sh4_state *sh4, const UINT16 opcode) +{ + UINT32 n = Rn; + + sh4->r[n] -= 4; + sh4->ea = sh4->r[n]; + WL(sh4, sh4->ea, sh4->ssr ); +} + +/* STC.L SPC,@-Rn */ +const void STCMSPC(sh4_state *sh4, const UINT16 opcode) +{ + UINT32 n = Rn; + + sh4->r[n] -= 4; + sh4->ea = sh4->r[n]; + WL(sh4, sh4->ea, sh4->spc ); +} + +/* LDS.L @Rm+,FPUL */ +const void LDSMFPUL(sh4_state *sh4, const UINT16 opcode) +{ + sh4->ea = sh4->r[Rn]; + sh4->fpul = RL(sh4, sh4->ea ); + sh4->r[Rn] += 4; +} + +/* LDS.L @Rm+,FPSCR */ +const void LDSMFPSCR(sh4_state *sh4, const UINT16 opcode) +{ + UINT32 s; + + s = sh4->fpscr; + sh4->ea = sh4->r[Rn]; + sh4->fpscr = RL(sh4, sh4->ea ); + sh4->fpscr &= 0x003FFFFF; + sh4->r[Rn] += 4; + if ((s & FR) != (sh4->fpscr & FR)) + sh4_swap_fp_registers(sh4); +#ifdef LSB_FIRST + if ((s & PR) != (sh4->fpscr & PR)) + sh4_swap_fp_couples(sh4); +#endif + sh4->fpu_sz = (sh4->fpscr & SZ) ? 1 : 0; + sh4->fpu_pr = (sh4->fpscr & PR) ? 1 : 0; +} + +/* LDC.L @Rm+,DBR */ +const void LDCMDBR(sh4_state *sh4, const UINT16 opcode) +{ + sh4->ea = sh4->r[Rn]; + sh4->dbr = RL(sh4, sh4->ea ); + sh4->r[Rn] += 4; +} + +/* LDC.L @Rn+,Rm_BANK */ +const void LDCMRBANK(sh4_state *sh4, const UINT16 opcode) +{ + UINT32 m = Rm; UINT32 n = Rn; + + sh4->ea = sh4->r[n]; + sh4->rbnk[sh4->sr&sRB ? 0 : 1][m & 7] = RL(sh4, sh4->ea ); + sh4->r[n] += 4; +} + +/* LDC.L @Rm+,SSR */ +const void LDCMSSR(sh4_state *sh4, const UINT16 opcode) +{ + sh4->ea = sh4->r[Rn]; + sh4->ssr = RL(sh4, sh4->ea ); + sh4->r[Rn] += 4; +} + +/* LDC.L @Rm+,SPC */ +const void LDCMSPC(sh4_state *sh4, const UINT16 opcode) +{ + sh4->ea = sh4->r[Rn]; + sh4->spc = RL(sh4, sh4->ea ); + sh4->r[Rn] += 4; +} + +/* LDS Rm,FPUL */ +const void LDSFPUL(sh4_state *sh4, const UINT16 opcode) +{ + sh4->fpul = sh4->r[Rn]; +} + +/* LDS Rm,FPSCR */ +const void LDSFPSCR(sh4_state *sh4, const UINT16 opcode) +{ + UINT32 s; + + s = sh4->fpscr; + sh4->fpscr = sh4->r[Rn] & 0x003FFFFF; + if ((s & FR) != (sh4->fpscr & FR)) + sh4_swap_fp_registers(sh4); +#ifdef LSB_FIRST + if ((s & PR) != (sh4->fpscr & PR)) + sh4_swap_fp_couples(sh4); +#endif + sh4->fpu_sz = (sh4->fpscr & SZ) ? 1 : 0; + sh4->fpu_pr = (sh4->fpscr & PR) ? 1 : 0; +} + +/* LDC Rm,DBR */ +const void LDCDBR(sh4_state *sh4, const UINT16 opcode) +{ + sh4->dbr = sh4->r[Rn]; +} + +/* SHAD Rm,Rn */ +const void SHAD(sh4_state *sh4, const UINT16 opcode) +{ + UINT32 m = Rm; UINT32 n = Rn; + + 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 */ +const void SHLD(sh4_state *sh4, const UINT16 opcode) +{ + UINT32 m = Rm; UINT32 n = Rn; + + 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 */ +const void LDCRBANK(sh4_state *sh4, const UINT16 opcode) +{ + UINT32 m = Rm; + + sh4->rbnk[sh4->sr&sRB ? 0 : 1][m & 7] = sh4->r[Rn]; +} + +/* LDC Rm,SSR */ +const void LDCSSR(sh4_state *sh4, const UINT16 opcode) +{ + sh4->ssr = sh4->r[Rn]; +} + +/* LDC Rm,SPC */ +const void LDCSPC(sh4_state *sh4, const UINT16 opcode) +{ + sh4->spc = sh4->r[Rn]; +} + +/* PREF @Rn */ +const void PREFM(sh4_state *sh4, const UINT16 opcode) +{ + int a; + UINT32 addr,dest,sq; + + addr = sh4->r[Rn]; // address + if ((addr >= 0xE0000000) && (addr <= 0xE3FFFFFF)) + { + if (sh4->sh4_mmu_enabled) + { + addr = addr & 0xFFFFFFE0; + dest = sh4_getsqremap(sh4, addr); // good enough for naomi-gd rom, probably not much else + + } + else + { + sq = (addr & 0x20) >> 5; + dest = addr & 0x03FFFFE0; + if (sq == 0) + { + if (sh4->cpu_type == CPU_TYPE_SH4) + { + dest |= (sh4->m[QACR0] & 0x1C) << 24; + } + else + { + fatalerror("sh4->cpu_type != CPU_TYPE_SH4 but access internal regs\n"); + } + } + else + { + if (sh4->cpu_type == CPU_TYPE_SH4) + { + dest |= (sh4->m[QACR1] & 0x1C) << 24; + } + else + { + fatalerror("sh4->cpu_type != CPU_TYPE_SH4 but access internal regs\n"); + } + + } + addr = addr & 0xFFFFFFE0; + } + + for (a = 0;a < 4;a++) + { + // shouldn't be causing a memory read, should store sq writes in registers. + sh4->program->write_qword(dest, sh4->program->read_qword(addr)); + addr += 8; + dest += 8; + } + } +} + +/***************************************************************************** + * OPCODE DISPATCHERS + *****************************************************************************/ + + + + + + + + + + + + + + + + + +/* FMOV.S @Rm+,FRn PR=0 SZ=0 1111nnnnmmmm1001 */ +/* FMOV @Rm+,DRn PR=0 SZ=1 1111nnn0mmmm1001 */ +/* FMOV @Rm+,XDn PR=0 SZ=1 1111nnn1mmmm1001 */ +/* FMOV @Rm+,XDn PR=1 1111nnn1mmmm1001 */ +const void FMOVMRIFR(sh4_state *sh4, const UINT16 opcode) +{ + UINT32 m = Rm; UINT32 n = Rn; + + if (sh4->fpu_pr) { /* PR = 1 */ + n = n & 14; + sh4->ea = sh4->r[m]; + sh4->r[m] += 8; + sh4->xf[n+NATIVE_ENDIAN_VALUE_LE_BE(1,0)] = RL(sh4, sh4->ea ); + sh4->xf[n+NATIVE_ENDIAN_VALUE_LE_BE(0,1)] = RL(sh4, sh4->ea+4 ); + } else { /* PR = 0 */ + if (sh4->fpu_sz) { /* SZ = 1 */ + if (n & 1) { + n = n & 14; + sh4->ea = sh4->r[m]; + sh4->xf[n] = RL(sh4, sh4->ea ); + sh4->r[m] += 4; + sh4->xf[n+1] = RL(sh4, sh4->ea+4 ); + sh4->r[m] += 4; + } else { + sh4->ea = sh4->r[m]; + sh4->fr[n] = RL(sh4, sh4->ea ); + sh4->r[m] += 4; + sh4->fr[n+1] = RL(sh4, sh4->ea+4 ); + sh4->r[m] += 4; + } + } else { /* SZ = 0 */ + sh4->ea = sh4->r[m]; + sh4->fr[n] = RL(sh4, sh4->ea ); + sh4->r[m] += 4; + } + } +} + +/* FMOV.S FRm,@Rn PR=0 SZ=0 1111nnnnmmmm1010 */ +/* FMOV DRm,@Rn PR=0 SZ=1 1111nnnnmmm01010 */ +/* FMOV XDm,@Rn PR=0 SZ=1 1111nnnnmmm11010 */ +/* FMOV XDm,@Rn PR=1 1111nnnnmmm11010 */ +const void FMOVFRMR(sh4_state *sh4, const UINT16 opcode) +{ + UINT32 m = Rm; UINT32 n = Rn; + + if (sh4->fpu_pr) { /* PR = 1 */ + m= m & 14; + sh4->ea = sh4->r[n]; + WL(sh4, sh4->ea,sh4->xf[m+NATIVE_ENDIAN_VALUE_LE_BE(1,0)] ); + WL(sh4, sh4->ea+4,sh4->xf[m+NATIVE_ENDIAN_VALUE_LE_BE(0,1)] ); + } else { /* PR = 0 */ + if (sh4->fpu_sz) { /* SZ = 1 */ + if (m & 1) { + m= m & 14; + sh4->ea = sh4->r[n]; + WL(sh4, sh4->ea,sh4->xf[m] ); + WL(sh4, sh4->ea+4,sh4->xf[m+1] ); + } else { + sh4->ea = sh4->r[n]; + WL(sh4, sh4->ea,sh4->fr[m] ); + WL(sh4, sh4->ea+4,sh4->fr[m+1] ); + } + } else { /* SZ = 0 */ + sh4->ea = sh4->r[n]; + WL(sh4, sh4->ea,sh4->fr[m] ); + } + } +} + +/* FMOV.S FRm,@-Rn PR=0 SZ=0 1111nnnnmmmm1011 */ +/* FMOV DRm,@-Rn PR=0 SZ=1 1111nnnnmmm01011 */ +/* FMOV XDm,@-Rn PR=0 SZ=1 1111nnnnmmm11011 */ +/* FMOV XDm,@-Rn PR=1 1111nnnnmmm11011 */ +const void FMOVFRMDR(sh4_state *sh4, const UINT16 opcode) +{ + UINT32 m = Rm; UINT32 n = Rn; + + if (sh4->fpu_pr) { /* PR = 1 */ + m= m & 14; + sh4->r[n] -= 8; + sh4->ea = sh4->r[n]; + WL(sh4, sh4->ea,sh4->xf[m+NATIVE_ENDIAN_VALUE_LE_BE(1,0)] ); + WL(sh4, sh4->ea+4,sh4->xf[m+NATIVE_ENDIAN_VALUE_LE_BE(0,1)] ); + } else { /* PR = 0 */ + if (sh4->fpu_sz) { /* SZ = 1 */ + if (m & 1) { + m= m & 14; + sh4->r[n] -= 8; + sh4->ea = sh4->r[n]; + WL(sh4, sh4->ea,sh4->xf[m] ); + WL(sh4, sh4->ea+4,sh4->xf[m+1] ); + } else { + sh4->r[n] -= 8; + sh4->ea = sh4->r[n]; + WL(sh4, sh4->ea,sh4->fr[m] ); + WL(sh4, sh4->ea+4,sh4->fr[m+1] ); + } + } else { /* SZ = 0 */ + sh4->r[n] -= 4; + sh4->ea = sh4->r[n]; + WL(sh4, sh4->ea,sh4->fr[m] ); + } + } +} + +/* FMOV.S FRm,@(R0,Rn) PR=0 SZ=0 1111nnnnmmmm0111 */ +/* FMOV DRm,@(R0,Rn) PR=0 SZ=1 1111nnnnmmm00111 */ +/* FMOV XDm,@(R0,Rn) PR=0 SZ=1 1111nnnnmmm10111 */ +/* FMOV XDm,@(R0,Rn) PR=1 1111nnnnmmm10111 */ +const void FMOVFRS0(sh4_state *sh4, const UINT16 opcode) +{ + UINT32 m = Rm; UINT32 n = Rn; + + if (sh4->fpu_pr) { /* PR = 1 */ + m= m & 14; + sh4->ea = sh4->r[0] + sh4->r[n]; + WL(sh4, sh4->ea,sh4->xf[m+NATIVE_ENDIAN_VALUE_LE_BE(1,0)] ); + WL(sh4, sh4->ea+4,sh4->xf[m+NATIVE_ENDIAN_VALUE_LE_BE(0,1)] ); + } else { /* PR = 0 */ + if (sh4->fpu_sz) { /* SZ = 1 */ + if (m & 1) { + m= m & 14; + sh4->ea = sh4->r[0] + sh4->r[n]; + WL(sh4, sh4->ea,sh4->xf[m] ); + WL(sh4, sh4->ea+4,sh4->xf[m+1] ); + } else { + sh4->ea = sh4->r[0] + sh4->r[n]; + WL(sh4, sh4->ea,sh4->fr[m] ); + WL(sh4, sh4->ea+4,sh4->fr[m+1] ); + } + } else { /* SZ = 0 */ + sh4->ea = sh4->r[0] + sh4->r[n]; + WL(sh4, sh4->ea,sh4->fr[m] ); + } + } +} + +/* FMOV.S @(R0,Rm),FRn PR=0 SZ=0 1111nnnnmmmm0110 */ +/* FMOV @(R0,Rm),DRn PR=0 SZ=1 1111nnn0mmmm0110 */ +/* FMOV @(R0,Rm),XDn PR=0 SZ=1 1111nnn1mmmm0110 */ +/* FMOV @(R0,Rm),XDn PR=1 1111nnn1mmmm0110 */ +const void FMOVS0FR(sh4_state *sh4, const UINT16 opcode) +{ + UINT32 m = Rm; UINT32 n = Rn; + + if (sh4->fpu_pr) { /* PR = 1 */ + n= n & 14; + sh4->ea = sh4->r[0] + sh4->r[m]; + sh4->xf[n+NATIVE_ENDIAN_VALUE_LE_BE(1,0)] = RL(sh4, sh4->ea ); + sh4->xf[n+NATIVE_ENDIAN_VALUE_LE_BE(0,1)] = RL(sh4, sh4->ea+4 ); + } else { /* PR = 0 */ + if (sh4->fpu_sz) { /* SZ = 1 */ + if (n & 1) { + n= n & 14; + sh4->ea = sh4->r[0] + sh4->r[m]; + sh4->xf[n] = RL(sh4, sh4->ea ); + sh4->xf[n+1] = RL(sh4, sh4->ea+4 ); + } else { + sh4->ea = sh4->r[0] + sh4->r[m]; + sh4->fr[n] = RL(sh4, sh4->ea ); + sh4->fr[n+1] = RL(sh4, sh4->ea+4 ); + } + } else { /* SZ = 0 */ + sh4->ea = sh4->r[0] + sh4->r[m]; + sh4->fr[n] = RL(sh4, sh4->ea ); + } + } +} + +/* FMOV.S @Rm,FRn PR=0 SZ=0 1111nnnnmmmm1000 */ +/* FMOV @Rm,DRn PR=0 SZ=1 1111nnn0mmmm1000 */ +/* FMOV @Rm,XDn PR=0 SZ=1 1111nnn1mmmm1000 */ +/* FMOV @Rm,XDn PR=1 1111nnn1mmmm1000 */ +/* FMOV @Rm,DRn PR=1 1111nnn0mmmm1000 */ +const void FMOVMRFR(sh4_state *sh4, const UINT16 opcode) +{ + UINT32 m = Rm; UINT32 n = Rn; + + if (sh4->fpu_pr) { /* PR = 1 */ + if (n & 1) { + n= n & 14; + sh4->ea = sh4->r[m]; + sh4->xf[n+NATIVE_ENDIAN_VALUE_LE_BE(1,0)] = RL(sh4, sh4->ea ); + sh4->xf[n+NATIVE_ENDIAN_VALUE_LE_BE(0,1)] = RL(sh4, sh4->ea+4 ); + } else { + n= n & 14; + sh4->ea = sh4->r[m]; + sh4->fr[n+NATIVE_ENDIAN_VALUE_LE_BE(1,0)] = RL(sh4, sh4->ea ); + sh4->fr[n+NATIVE_ENDIAN_VALUE_LE_BE(0,1)] = RL(sh4, sh4->ea+4 ); + } + } else { /* PR = 0 */ + if (sh4->fpu_sz) { /* SZ = 1 */ + if (n & 1) { + n= n & 14; + sh4->ea = sh4->r[m]; + sh4->xf[n] = RL(sh4, sh4->ea ); + sh4->xf[n+1] = RL(sh4, sh4->ea+4 ); + } else { + n= n & 14; + sh4->ea = sh4->r[m]; + sh4->fr[n] = RL(sh4, sh4->ea ); + sh4->fr[n+1] = RL(sh4, sh4->ea+4 ); + } + } else { /* SZ = 0 */ + sh4->ea = sh4->r[m]; + sh4->fr[n] = RL(sh4, sh4->ea ); + } + } +} + +/* FMOV FRm,FRn PR=0 SZ=0 FRm -> FRn 1111nnnnmmmm1100 */ +/* FMOV DRm,DRn PR=0 SZ=1 DRm -> DRn 1111nnn0mmm01100 */ +/* FMOV XDm,DRn PR=1 XDm -> DRn 1111nnn0mmm11100 */ +/* FMOV DRm,XDn PR=1 DRm -> XDn 1111nnn1mmm01100 */ +/* FMOV XDm,XDn PR=1 XDm -> XDn 1111nnn1mmm11100 */ +const void FMOVFR(sh4_state *sh4, const UINT16 opcode) +{ + UINT32 m = Rm; UINT32 n = Rn; + + if ((sh4->fpu_sz == 0) && (sh4->fpu_pr == 0)) /* SZ = 0 */ + sh4->fr[n] = sh4->fr[m]; + else { /* SZ = 1 or PR = 1 */ + if (m & 1) { + if (n & 1) { + sh4->xf[n & 14] = sh4->xf[m & 14]; + sh4->xf[n | 1] = sh4->xf[m | 1]; + } else { + sh4->fr[n] = sh4->xf[m & 14]; + sh4->fr[n | 1] = sh4->xf[m | 1]; + } + } else { + if (n & 1) { + sh4->xf[n & 14] = sh4->fr[m]; + sh4->xf[n | 1] = sh4->fr[m | 1]; // (a&14)+1 -> a|1 + } else { + sh4->fr[n] = sh4->fr[m]; + sh4->fr[n | 1] = sh4->fr[m | 1]; + } + } + } +} + +/* FLDI1 FRn 1111nnnn10011101 */ +const void FLDI1(sh4_state *sh4, const UINT16 opcode) +{ + sh4->fr[Rn] = 0x3F800000; +} + +/* FLDI0 FRn 1111nnnn10001101 */ +const void FLDI0(sh4_state *sh4, const UINT16 opcode) +{ + sh4->fr[Rn] = 0; +} + +/* FLDS FRm,FPUL 1111mmmm00011101 */ +const void FLDS(sh4_state *sh4, const UINT16 opcode) +{ + sh4->fpul = sh4->fr[Rn]; +} + +/* FSTS FPUL,FRn 1111nnnn00001101 */ +const void FSTS(sh4_state *sh4, const UINT16 opcode) +{ + sh4->fr[Rn] = sh4->fpul; +} + +/* FRCHG 1111101111111101 */ +const void FRCHG(sh4_state *sh4) +{ + sh4->fpscr ^= FR; + sh4_swap_fp_registers(sh4); +} + +/* FSCHG 1111001111111101 */ +const void FSCHG(sh4_state *sh4) +{ + sh4->fpscr ^= SZ; + sh4->fpu_sz = (sh4->fpscr & SZ) ? 1 : 0; +} + +/* FTRC FRm,FPUL PR=0 1111mmmm00111101 */ +/* FTRC DRm,FPUL PR=1 1111mmm000111101 */ +const void FTRC(sh4_state *sh4, const UINT16 opcode) +{ + UINT32 n = Rn; + + if (sh4->fpu_pr) { /* PR = 1 */ + n = n & 14; + *((INT32 *)&sh4->fpul) = (INT32)FP_RFD(n); + } else { /* PR = 0 */ + /* read sh4->fr[n] as float -> truncate -> fpul(32) */ + *((INT32 *)&sh4->fpul) = (INT32)FP_RFS(n); + } +} + +/* FLOAT FPUL,FRn PR=0 1111nnnn00101101 */ +/* FLOAT FPUL,DRn PR=1 1111nnn000101101 */ +const void FLOAT(sh4_state *sh4, const UINT16 opcode) +{ + UINT32 n = Rn; + + if (sh4->fpu_pr) { /* PR = 1 */ + n = n & 14; + FP_RFD(n) = (double)*((INT32 *)&sh4->fpul); + } else { /* PR = 0 */ + FP_RFS(n) = (float)*((INT32 *)&sh4->fpul); + } +} + +/* FNEG FRn PR=0 1111nnnn01001101 */ +/* FNEG DRn PR=1 1111nnn001001101 */ +const void FNEG(sh4_state *sh4, const UINT16 opcode) +{ + UINT32 n = Rn; + + if (sh4->fpu_pr) { /* PR = 1 */ + FP_RFD(n) = -FP_RFD(n); + } else { /* PR = 0 */ + FP_RFS(n) = -FP_RFS(n); + } +} + +/* FABS FRn PR=0 1111nnnn01011101 */ +/* FABS DRn PR=1 1111nnn001011101 */ +const void FABS(sh4_state *sh4, const UINT16 opcode) +{ + UINT32 n = Rn; + + if (sh4->fpu_pr) { /* PR = 1 */ +#ifdef LSB_FIRST + n = n | 1; // n & 14 + 1 + sh4->fr[n] = sh4->fr[n] & 0x7fffffff; +#else + n = n & 14; + sh4->fr[n] = sh4->fr[n] & 0x7fffffff; +#endif + } else { /* PR = 0 */ + sh4->fr[n] = sh4->fr[n] & 0x7fffffff; + } +} + +/* FCMP/EQ FRm,FRn PR=0 1111nnnnmmmm0100 */ +/* FCMP/EQ DRm,DRn PR=1 1111nnn0mmm00100 */ +const void FCMP_EQ(sh4_state *sh4, const UINT16 opcode) +{ + UINT32 m = Rm; UINT32 n = Rn; + + if (sh4->fpu_pr) { /* PR = 1 */ + n = n & 14; + m = m & 14; + if (FP_RFD(n) == FP_RFD(m)) + sh4->sr |= T; + else + sh4->sr &= ~T; + } else { /* PR = 0 */ + if (FP_RFS(n) == FP_RFS(m)) + sh4->sr |= T; + else + sh4->sr &= ~T; + } +} + +/* FCMP/GT FRm,FRn PR=0 1111nnnnmmmm0101 */ +/* FCMP/GT DRm,DRn PR=1 1111nnn0mmm00101 */ +const void FCMP_GT(sh4_state *sh4, const UINT16 opcode) +{ + UINT32 m = Rm; UINT32 n = Rn; + + if (sh4->fpu_pr) { /* PR = 1 */ + n = n & 14; + m = m & 14; + if (FP_RFD(n) > FP_RFD(m)) + sh4->sr |= T; + else + sh4->sr &= ~T; + } else { /* PR = 0 */ + if (FP_RFS(n) > FP_RFS(m)) + sh4->sr |= T; + else + sh4->sr &= ~T; + } +} + +/* FCNVDS DRm,FPUL PR=1 1111mmm010111101 */ +const void FCNVDS(sh4_state *sh4, const UINT16 opcode) +{ + UINT32 n = Rn; + + if (sh4->fpu_pr) { /* PR = 1 */ + n = n & 14; + if (sh4->fpscr & RM) + sh4->fr[n | NATIVE_ENDIAN_VALUE_LE_BE(0,1)] &= 0xe0000000; /* round toward zero*/ + *((float *)&sh4->fpul) = (float)FP_RFD(n); + } +} + +/* FCNVSD FPUL, DRn PR=1 1111nnn010101101 */ +const void FCNVSD(sh4_state *sh4, const UINT16 opcode) +{ + UINT32 n = Rn; + + if (sh4->fpu_pr) { /* PR = 1 */ + n = n & 14; + FP_RFD(n) = (double)*((float *)&sh4->fpul); + } +} + +/* FADD FRm,FRn PR=0 1111nnnnmmmm0000 */ +/* FADD DRm,DRn PR=1 1111nnn0mmm00000 */ +const void FADD(sh4_state *sh4, const UINT16 opcode) +{ + UINT32 m = Rm; UINT32 n = Rn; + + if (sh4->fpu_pr) { /* PR = 1 */ + n = n & 14; + m = m & 14; + FP_RFD(n) = FP_RFD(n) + FP_RFD(m); + } else { /* PR = 0 */ + FP_RFS(n) = FP_RFS(n) + FP_RFS(m); + } +} + +/* FSUB FRm,FRn PR=0 1111nnnnmmmm0001 */ +/* FSUB DRm,DRn PR=1 1111nnn0mmm00001 */ +const void FSUB(sh4_state *sh4, const UINT16 opcode) +{ + UINT32 m = Rm; UINT32 n = Rn; + + if (sh4->fpu_pr) { /* PR = 1 */ + n = n & 14; + m = m & 14; + FP_RFD(n) = FP_RFD(n) - FP_RFD(m); + } else { /* PR = 0 */ + FP_RFS(n) = FP_RFS(n) - FP_RFS(m); + } +} + + +/* FMUL FRm,FRn PR=0 1111nnnnmmmm0010 */ +/* FMUL DRm,DRn PR=1 1111nnn0mmm00010 */ +const void FMUL(sh4_state *sh4, const UINT16 opcode) +{ + UINT32 m = Rm; UINT32 n = Rn; + + if (sh4->fpu_pr) { /* PR = 1 */ + n = n & 14; + m = m & 14; + FP_RFD(n) = FP_RFD(n) * FP_RFD(m); + } else { /* PR = 0 */ + FP_RFS(n) = FP_RFS(n) * FP_RFS(m); + } +} + +/* FDIV FRm,FRn PR=0 1111nnnnmmmm0011 */ +/* FDIV DRm,DRn PR=1 1111nnn0mmm00011 */ +const void FDIV(sh4_state *sh4, const UINT16 opcode) +{ + UINT32 m = Rm; UINT32 n = Rn; + + if (sh4->fpu_pr) { /* PR = 1 */ + n = n & 14; + m = m & 14; + if (FP_RFD(m) == 0) + return; + FP_RFD(n) = FP_RFD(n) / FP_RFD(m); + } else { /* PR = 0 */ + if (FP_RFS(m) == 0) + return; + FP_RFS(n) = FP_RFS(n) / FP_RFS(m); + } +} + +/* FMAC FR0,FRm,FRn PR=0 1111nnnnmmmm1110 */ +const void FMAC(sh4_state *sh4, const UINT16 opcode) +{ + UINT32 m = Rm; UINT32 n = Rn; + + if (sh4->fpu_pr == 0) { /* PR = 0 */ + FP_RFS(n) = (FP_RFS(0) * FP_RFS(m)) + FP_RFS(n); + } +} + +/* FSQRT FRn PR=0 1111nnnn01101101 */ +/* FSQRT DRn PR=1 1111nnnn01101101 */ +const void FSQRT(sh4_state *sh4, const UINT16 opcode) +{ + UINT32 n = Rn; + + if (sh4->fpu_pr) { /* PR = 1 */ + n = n & 14; + if (FP_RFD(n) < 0) + return; + FP_RFD(n) = sqrtf(FP_RFD(n)); + } else { /* PR = 0 */ + if (FP_RFS(n) < 0) + return; + FP_RFS(n) = sqrtf(FP_RFS(n)); + } +} + +/* FSRRA FRn PR=0 1111nnnn01111101 */ +const void FSRRA(sh4_state *sh4, const UINT16 opcode) +{ + UINT32 n = Rn; + + if (FP_RFS(n) < 0) + return; + FP_RFS(n) = 1.0 / sqrtf(FP_RFS(n)); +} + +/* FSSCA FPUL,FRn PR=0 1111nnn011111101 */ +const void FSSCA(sh4_state *sh4, const UINT16 opcode) +{ + UINT32 n = Rn; + +float angle; + + angle = (((float)(sh4->fpul & 0xFFFF)) / 65536.0) * 2.0 * M_PI; + FP_RFS(n) = sinf(angle); + FP_RFS(n+1) = cosf(angle); +} + +/* FIPR FVm,FVn PR=0 1111nnmm11101101 */ +const void FIPR(sh4_state *sh4, const UINT16 opcode) +{ + UINT32 n = Rn; + +UINT32 m; +float ml[4]; +int a; + + m = (n & 3) << 2; + n = n & 12; + for (a = 0;a < 4;a++) + ml[a] = FP_RFS(n+a) * FP_RFS(m+a); + FP_RFS(n+3) = ml[0] + ml[1] + ml[2] + ml[3]; +} + +/* FTRV XMTRX,FVn PR=0 1111nn0111111101 */ +const void FTRV(sh4_state *sh4, const UINT16 opcode) +{ + UINT32 n = Rn; + +int i,j; +float sum[4]; + + n = n & 12; + for (i = 0;i < 4;i++) { + sum[i] = 0; + for (j=0;j < 4;j++) + sum[i] += FP_XFS((j << 2) + i)*FP_RFS(n + j); + } + for (i = 0;i < 4;i++) + FP_RFS(n + i) = sum[i]; +} + +const void op1111_0xf13(sh4_state *sh4, const UINT16 opcode) +{ + if (opcode & 0x100) { + if (opcode & 0x200) { + switch (opcode & 0xC00) + { + case 0x000: + FSCHG(sh4); + break; + case 0x800: + FRCHG(sh4); + break; + default: + debugger_break(sh4->device->machine()); + break; + } + } else { + FTRV(sh4, opcode); + } + } else { + FSSCA(sh4, opcode); + } +} + +const void dbreak(sh4_state *sh4, const UINT16 opcode) +{ + debugger_break(sh4->device->machine()); +} + + +sh4ophandler op1111_0x13_handlers[] = +{ + FSTS, FLDS, FLOAT, FTRC, FNEG, FABS, FSQRT, FSRRA, FLDI0, FLDI1, FCNVSD, FCNVDS, dbreak, dbreak, FIPR, op1111_0xf13 +}; + +const void op1111_0x13(sh4_state *sh4, UINT16 opcode) +{ + op1111_0x13_handlers[(opcode&0xf0)>>4](sh4, opcode); +} + + +/***************************************************************************** + * MAME CPU INTERFACE + *****************************************************************************/ + +static CPU_RESET( common_sh4_reset ) +{ + sh4_state *sh4 = get_safe_token(device); + emu_timer *tsaved[4]; + emu_timer *tsave[5]; + UINT32 *m; + int save_is_slave; + int savecpu_clock, savebus_clock, savepm_clock; + + void (*f)(UINT32 data); + device_irq_acknowledge_callback save_irqcallback; + + m = sh4->m; + tsaved[0] = sh4->dma_timer[0]; + tsaved[1] = sh4->dma_timer[1]; + tsaved[2] = sh4->dma_timer[2]; + tsaved[3] = sh4->dma_timer[3]; + tsave[0] = sh4->refresh_timer; + tsave[1] = sh4->rtc_timer; + tsave[2] = sh4->timer[0]; + tsave[3] = sh4->timer[1]; + tsave[4] = sh4->timer[2]; + + f = sh4->ftcsr_read_callback; + save_irqcallback = sh4->irq_callback; + save_is_slave = sh4->is_slave; + savecpu_clock = sh4->cpu_clock; + savebus_clock = sh4->bus_clock; + savepm_clock = sh4->pm_clock; + memset(sh4, 0, sizeof(*sh4)); + sh4->is_slave = save_is_slave; + sh4->cpu_clock = savecpu_clock; + sh4->bus_clock = savebus_clock; + sh4->pm_clock = savepm_clock; + sh4->ftcsr_read_callback = f; + sh4->irq_callback = save_irqcallback; + sh4->device = device; + sh4->internal = device->space(AS_PROGRAM); + sh4->program = device->space(AS_PROGRAM); + sh4->direct = &sh4->program->direct(); + sh4->io = device->space(AS_IO); + + sh4->dma_timer[0] = tsaved[0]; + sh4->dma_timer[1] = tsaved[1]; + sh4->dma_timer[2] = tsaved[2]; + sh4->dma_timer[3] = tsaved[3]; + sh4->refresh_timer = tsave[0]; + sh4->rtc_timer = tsave[1]; + sh4->timer[0] = tsave[2]; + sh4->timer[1] = tsave[3]; + sh4->timer[2] = tsave[4]; + sh4->m = m; + memset(sh4->m, 0, 16384*4); + sh4_default_exception_priorities(sh4); + memset(sh4->exception_requesting, 0, sizeof(sh4->exception_requesting)); + + sh4->rtc_timer->adjust(attotime::from_hz(128)); + + + sh4->pc = 0xa0000000; + sh4->r[15] = RL(sh4,4); + sh4->sr = 0x700000f0; + sh4->fpscr = 0x00040001; + sh4->fpu_sz = (sh4->fpscr & SZ) ? 1 : 0; + sh4->fpu_pr = (sh4->fpscr & PR) ? 1 : 0; + sh4->fpul = 0; + sh4->dbr = 0; + + sh4->internal_irq_level = -1; + sh4->irln = 15; + sh4->sleep_mode = 0; + + sh4->sh4_mmu_enabled = 0; + + sh4_build_optable(sh4); +} + +/*------------------------------------------------- + sh3_reset - reset the processor +-------------------------------------------------*/ + +static CPU_RESET( sh3 ) +{ + sh4_state *sh4 = get_safe_token(device); + + CPU_RESET_CALL(common_sh4_reset); + + sh4->cpu_type = CPU_TYPE_SH3; + + sh4->SH4_TCOR0 = 0xffffffff; + sh4->SH4_TCNT0 = 0xffffffff; + sh4->SH4_TCOR1 = 0xffffffff; + sh4->SH4_TCNT1 = 0xffffffff; + sh4->SH4_TCOR2 = 0xffffffff; + sh4->SH4_TCNT2 = 0xffffffff; + +} + +static CPU_RESET( sh4 ) +{ + sh4_state *sh4 = get_safe_token(device); + + CPU_RESET_CALL(common_sh4_reset); + + sh4->cpu_type = CPU_TYPE_SH4; + + sh4->m[RCR2] = 0x09; + sh4->SH4_TCOR0 = 0xffffffff; + sh4->SH4_TCNT0 = 0xffffffff; + sh4->SH4_TCOR1 = 0xffffffff; + sh4->SH4_TCNT1 = 0xffffffff; + sh4->SH4_TCOR2 = 0xffffffff; + sh4->SH4_TCNT2 = 0xffffffff; +} + +/* These tables are combined into our main opcode jump table, master_ophandler_table in the RESET function */ + +sh4ophandler op1000_handler[] = +{ + MOVBS4, MOVWS4, NOP, NOP, MOVBL4, MOVWL4, NOP, NOP, CMPIM, BT, NOP, BF, NOP, BTS, NOP, BFS +}; + +sh4ophandler op1100_handler[] = +{ + MOVBSG, MOVWSG, MOVLSG, TRAPA, MOVBLG, MOVWLG, MOVLLG, MOVA, TSTI, ANDI, XORI, ORI, TSTM, ANDM, XORM, ORM +}; + +sh4ophandler op0000_handlers[] = +{ + NOP, NOP, NOP, NOP, NOP, NOP, NOP, NOP, NOP, NOP, NOP, NOP, NOP, NOP, NOP, NOP, + NOP, NOP, NOP, NOP, NOP, NOP, NOP, NOP, NOP, NOP, NOP, NOP, NOP, NOP, NOP, NOP, + STCSR, STCGBR, STCVBR, STCSSR, STCSPC, NOP, NOP, NOP, STCRBANK, STCRBANK, STCRBANK, STCRBANK, STCRBANK, STCRBANK, STCRBANK, STCRBANK, + BSRF, NOP, BRAF, NOP, NOP, NOP, NOP, NOP, PREFM, TODO, TODO, TODO, MOVCAL, NOP, NOP, NOP, + MOVBS0, MOVBS0, MOVBS0, MOVBS0, MOVBS0, MOVBS0, MOVBS0, MOVBS0, MOVBS0, MOVBS0, MOVBS0, MOVBS0, MOVBS0, MOVBS0, MOVBS0, MOVBS0, + MOVWS0, MOVWS0, MOVWS0, MOVWS0, MOVWS0, MOVWS0, MOVWS0, MOVWS0, MOVWS0, MOVWS0, MOVWS0, MOVWS0, MOVWS0, MOVWS0, MOVWS0, MOVWS0, + MOVLS0, MOVLS0, MOVLS0, MOVLS0, MOVLS0, MOVLS0, MOVLS0, MOVLS0, MOVLS0, MOVLS0, MOVLS0, MOVLS0, MOVLS0, MOVLS0, MOVLS0, MOVLS0, + MULL, MULL, MULL, MULL, MULL, MULL, MULL, MULL, MULL, MULL, MULL, MULL, MULL, MULL, MULL, MULL, + CLRT, SETT, CLRMAC, TODO, CLRS, SETS, NOP, NOP, CLRT, SETT, CLRMAC, TODO, CLRS, SETS, NOP, NOP, + NOP, DIV0U, MOVT, NOP, NOP, DIV0U, MOVT, NOP, NOP, DIV0U, MOVT, NOP, NOP, DIV0U, MOVT, NOP, + STSMACH, STSMACL, STSPR, STCSGR, NOP, STSFPUL, STSFPSCR, STCDBR, STSMACH, STSMACL, STSPR, STCSGR, NOP, STSFPUL, STSFPSCR, STCDBR, + RTS, SLEEP, RTE, NOP, RTS, SLEEP, RTE, NOP, RTS, SLEEP, RTE, NOP, RTS, SLEEP, RTE, NOP, + MOVBL0, MOVBL0, MOVBL0, MOVBL0, MOVBL0, MOVBL0, MOVBL0, MOVBL0, MOVBL0, MOVBL0, MOVBL0, MOVBL0, MOVBL0, MOVBL0, MOVBL0, MOVBL0, + MOVWL0, MOVWL0, MOVWL0, MOVWL0, MOVWL0, MOVWL0, MOVWL0, MOVWL0, MOVWL0, MOVWL0, MOVWL0, MOVWL0, MOVWL0, MOVWL0, MOVWL0, MOVWL0, + MOVLL0, MOVLL0, MOVLL0, MOVLL0, MOVLL0, MOVLL0, MOVLL0, MOVLL0, MOVLL0, MOVLL0, MOVLL0, MOVLL0, MOVLL0, MOVLL0, MOVLL0, MOVLL0, + MAC_L, MAC_L, MAC_L, MAC_L, MAC_L, MAC_L, MAC_L, MAC_L, MAC_L, MAC_L, MAC_L, MAC_L, MAC_L, MAC_L, MAC_L, MAC_L, +}; + +sh4ophandler op0100_handlers[] = +{ + SHLL, DT, SHAL, NOP, SHLL, DT, SHAL, NOP, SHLL, DT, SHAL, NOP, SHLL, DT, SHAL, NOP, + SHLR, CMPPZ, SHAR, NOP, SHLR, CMPPZ, SHAR, NOP, SHLR, CMPPZ, SHAR, NOP, SHLR, CMPPZ, SHAR, NOP, + STSMMACH, STSMMACL, STSMPR, STCMSGR, NOP, STSMFPUL, STSMFPSCR, NOP, NOP, NOP, NOP, NOP, NOP, NOP, NOP, STCMDBR, + STCMSR, STCMGBR, STCMVBR, STCMSSR, STCMSPC, NOP, NOP, NOP, STCMRBANK, STCMRBANK, STCMRBANK, STCMRBANK, STCMRBANK, STCMRBANK, STCMRBANK, STCMRBANK, + ROTL, NOP, ROTCL, NOP, ROTL, NOP, ROTCL, NOP, ROTL, NOP, ROTCL, NOP, ROTL, NOP, ROTCL, NOP, + ROTR, CMPPL, ROTCR, NOP, ROTR, CMPPL, ROTCR, NOP, ROTR, CMPPL, ROTCR, NOP, ROTR, CMPPL, ROTCR, NOP, + LDSMMACH, LDSMMACL, LDSMPR, NOP, NOP, LDSMFPUL, LDSMFPSCR, NOP, NOP, NOP, NOP, NOP, NOP, NOP, NOP, LDCMDBR, + LDCMSR, LDCMGBR, LDCMVBR, LDCMSSR, LDCMSPC, NOP, NOP, NOP, LDCMRBANK, LDCMRBANK, LDCMRBANK, LDCMRBANK, LDCMRBANK, LDCMRBANK, LDCMRBANK, LDCMRBANK, + SHLL2, SHLL8, SHLL16, NOP, SHLL2, SHLL8, SHLL16, NOP, SHLL2, SHLL8, SHLL16, NOP, SHLL2, SHLL8, SHLL16, NOP, + SHLR2, SHLR8, SHLR16, NOP, SHLR2, SHLR8, SHLR16, NOP, SHLR2, SHLR8, SHLR16, NOP, SHLR2, SHLR8, SHLR16, NOP, + LDSMACH, LDSMACL, LDSPR, NOP, NOP, LDSFPUL, LDSFPSCR, NOP, NOP, NOP, NOP, NOP, NOP, NOP, NOP, LDCDBR, + JSR, TAS, JMP, NOP, JSR, TAS, JMP, NOP, JSR, TAS, JMP, NOP, JSR, TAS, JMP, NOP, + SHAD, SHAD, SHAD, SHAD, SHAD, SHAD, SHAD, SHAD, SHAD, SHAD, SHAD, SHAD, SHAD, SHAD, SHAD, SHAD, + SHLD, SHLD, SHLD, SHLD, SHLD, SHLD, SHLD, SHLD, SHLD, SHLD, SHLD, SHLD, SHLD, SHLD, SHLD, SHLD, + LDCSR, LDCGBR, LDCVBR, LDCSSR, LDCSPC, NOP, NOP, NOP, LDCRBANK, LDCRBANK, LDCRBANK, LDCRBANK, LDCRBANK, LDCRBANK, LDCRBANK, LDCRBANK, + MAC_W, MAC_W, MAC_W, MAC_W, MAC_W, MAC_W, MAC_W, MAC_W, MAC_W, MAC_W, MAC_W, MAC_W, MAC_W, MAC_W, MAC_W, MAC_W, +}; + + +sh4ophandler upper4bits[] = +{ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* j = 0x0000 - uses op0000_handlers*/ + MOVLS4, MOVLS4, MOVLS4, MOVLS4, MOVLS4, MOVLS4, MOVLS4, MOVLS4, MOVLS4, MOVLS4, MOVLS4, MOVLS4, MOVLS4, MOVLS4, MOVLS4, MOVLS4, /* j = 0x1000 */ + MOVBS, MOVWS, MOVLS, NOP, MOVBM, MOVWM, MOVLM, DIV0S, TST, AND, XOR, OR, CMPSTR, XTRCT, MULU, MULS, /* j = 0x2000 */ + CMPEQ, NOP, CMPHS, CMPGE, DIV1, DMULU, CMPHI, CMPGT, SUB, NOP, SUBC, SUBV, ADD, DMULS, ADDC, ADDV, /* j = 0x3000 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* j = 0x4000 - uses op0100_handlers*/ + MOVLL4, MOVLL4, MOVLL4, MOVLL4, MOVLL4, MOVLL4, MOVLL4, MOVLL4, MOVLL4, MOVLL4, MOVLL4, MOVLL4, MOVLL4, MOVLL4, MOVLL4, MOVLL4, /* j = 0x5000 */ + MOVBL, MOVWL, MOVLL, MOV, MOVBP, MOVWP, MOVLP, NOT, SWAPB, SWAPW, NEGC, NEG, EXTUB, EXTUW, EXTSB, EXTSW, /* j = 0x6000 */ + ADDI, ADDI, ADDI, ADDI, ADDI, ADDI, ADDI, ADDI, ADDI, ADDI, ADDI, ADDI, ADDI, ADDI, ADDI, ADDI, /* j = 0x7000 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* j = 0x8000 - uses op1000_handlers */ + MOVWI, MOVWI, MOVWI, MOVWI, MOVWI, MOVWI, MOVWI, MOVWI, MOVWI, MOVWI, MOVWI, MOVWI, MOVWI, MOVWI, MOVWI, MOVWI, /* j = 0x9000 */ + BRA, BRA, BRA, BRA, BRA, BRA, BRA, BRA, BRA, BRA, BRA, BRA, BRA, BRA, BRA, BRA, /* j = 0xa000 */ + BSR, BSR, BSR, BSR, BSR, BSR, BSR, BSR, BSR, BSR, BSR, BSR, BSR, BSR, BSR, BSR, /* j = 0xb000 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* j = 0xc000 - uses op1100_handlers */ + MOVLI, MOVLI, MOVLI, MOVLI, MOVLI, MOVLI, MOVLI, MOVLI, MOVLI, MOVLI, MOVLI, MOVLI, MOVLI, MOVLI, MOVLI, MOVLI, /* j = 0xd000 */ + MOVI, MOVI, MOVI, MOVI, MOVI, MOVI, MOVI, MOVI, MOVI, MOVI, MOVI, MOVI, MOVI, MOVI, MOVI, MOVI, /* j = 0xe000 */ + FADD, FSUB, FMUL, FDIV, FCMP_EQ, FCMP_GT, FMOVS0FR, FMOVFRS0, FMOVMRFR, FMOVMRIFR, FMOVFRMR, FMOVFRMDR, FMOVFR, op1111_0x13,FMAC, dbreak /* j = 0xf000 */ +}; + +void sh4_build_optable(sh4_state *sh4) +{ + int j,y,x,z; + + // combine our opcode handler tables into one larger table thus reducing level of indirection on all opcode handlers + for (j = 0; j<0x10000;j+=0x1000) + { + for (y = 0; y<0x1000;y+=0x100) + { + for (x=0; x<0x100;x+=0x10) + { + for (z=0;z<0x10;z++) + { + master_ophandler_table[j+y+x+z] = upper4bits[(((j+z)&0xf000)>>8) + (z & 0xf)]; + } + } + } + } + + j = 0x0000; + //for (j = 0; j<0x10000;j+=0x1000) + { + for (y = 0; y<0x1000;y+=0x100) + { + for (x=0; x<0x100;x+=0x10) + { + for (z=0;z<0x10;z++) + { + master_ophandler_table[j+y+x+z] = op0000_handlers[((((j+y+x+z)&0xf0)>>4)) | ((((j+y+x+z)&0xf)<<4))]; + } + } + } + } + + j = 0x4000; + //for (j = 0; j<0x10000;j+=0x1000) + { + for (y = 0; y<0x1000;y+=0x100) + { + for (x=0; x<0x100;x+=0x10) + { + for (z=0;z<0x10;z++) + { + master_ophandler_table[j+y+x+z] = op0100_handlers[((((j+y+x+z)&0xf0)>>4)) | ((((j+y+x+z)&0xf)<<4))]; + } + } + } + } + + + j = 0x8000; + //for (j = 0; j<0x10000;j+=0x1000) + { + for (y = 0; y<0x1000;y+=0x100) + { + for (x=0; x<0x100;x+=0x10) + { + for (z=0;z<0x10;z++) + { + master_ophandler_table[j+y+x+z] = op1000_handler[((((j+y+x+z)&0xf00)>>8))]; + } + } + } + } + + j = 0xc000; + //for (j = 0; j<0x10000;j+=0x1000) + { + for (y = 0; y<0x1000;y+=0x100) + { + for (x=0; x<0x100;x+=0x10) + { + for (z=0;z<0x10;z++) + { + master_ophandler_table[j+y+x+z] = op1100_handler[((((j+y+x+z)&0xf00)>>8))]; + } + } + } + } + + +} + + +/* Execute cycles - returns number of cycles actually run */ +static CPU_EXECUTE( sh4 ) +{ + sh4_state *sh4 = get_safe_token(device); + + if (sh4->cpu_off) + { + sh4->sh4_icount = 0; + return; + } + + do + { + if (sh4->delay) + { + const UINT16 opcode = sh4->direct->read_decrypted_word((UINT32)(sh4->delay & AM), WORD2_XOR_LE(0)); + + debugger_instruction_hook(device, (sh4->pc-2) & AM); + + sh4->delay = 0; + sh4->ppc = sh4->pc; + + master_ophandler_table[opcode](sh4, opcode); + + if (sh4->test_irq && !sh4->delay) + { + sh4_check_pending_irq(sh4, "mame_sh4_execute"); + } + } + else + { + const UINT16 opcode = sh4->direct->read_decrypted_word((UINT32)(sh4->pc & AM), WORD2_XOR_LE(0)); + + debugger_instruction_hook(device, sh4->pc & AM); + + sh4->pc += 2; + sh4->ppc = sh4->pc; + + master_ophandler_table[opcode](sh4, opcode); + + if (sh4->test_irq && !sh4->delay) + { + sh4_check_pending_irq(sh4, "mame_sh4_execute"); + } + } + + sh4->sh4_icount--; + } while( sh4->sh4_icount > 0 ); +} + +static CPU_EXECUTE( sh4be ) +{ + sh4_state *sh4 = get_safe_token(device); + + if (sh4->cpu_off) + { + sh4->sh4_icount = 0; + return; + } + + do + { + if (sh4->delay) + { + const UINT16 opcode = sh4->direct->read_decrypted_word((UINT32)(sh4->delay & AM), WORD_XOR_LE(6)); + + debugger_instruction_hook(device, sh4->delay & AM); + + sh4->delay = 0; + sh4->ppc = sh4->pc; + + master_ophandler_table[opcode](sh4, opcode); + + + if (sh4->test_irq && !sh4->delay) + { + sh4_check_pending_irq(sh4, "mame_sh4_execute"); + } + + + } + else + { + const UINT16 opcode = sh4->direct->read_decrypted_word((UINT32)(sh4->pc & AM), WORD_XOR_LE(6)); + + debugger_instruction_hook(device, sh4->pc & AM); + + sh4->pc += 2; + sh4->ppc = sh4->pc; + + master_ophandler_table[opcode](sh4, opcode); + + if (sh4->test_irq && !sh4->delay) + { + sh4_check_pending_irq(sh4, "mame_sh4_execute"); + } + } + + sh4->sh4_icount--; + } while( sh4->sh4_icount > 0 ); +} + +static CPU_INIT( sh4 ) +{ + const struct sh4_config *conf = (const struct sh4_config *)device->static_config(); + sh4_state *sh4 = get_safe_token(device); + + sh4_common_init(device); + + sh4_parse_configuration(sh4, conf); + + sh4->irq_callback = irqcallback; + sh4->device = device; + sh4->internal = device->space(AS_PROGRAM); + sh4->program = device->space(AS_PROGRAM); + sh4->io = device->space(AS_IO); + sh4_default_exception_priorities(sh4); + sh4->irln = 15; + sh4->test_irq = 0; + + device->save_item(NAME(sh4->pc)); + device->save_item(NAME(sh4->r[15])); + device->save_item(NAME(sh4->sr)); + device->save_item(NAME(sh4->pr)); + device->save_item(NAME(sh4->gbr)); + device->save_item(NAME(sh4->vbr)); + device->save_item(NAME(sh4->mach)); + device->save_item(NAME(sh4->macl)); + device->save_item(NAME(sh4->spc)); + device->save_item(NAME(sh4->ssr)); + device->save_item(NAME(sh4->sgr)); + device->save_item(NAME(sh4->fpscr)); + device->save_item(NAME(sh4->r[ 0])); + device->save_item(NAME(sh4->r[ 1])); + device->save_item(NAME(sh4->r[ 2])); + device->save_item(NAME(sh4->r[ 3])); + device->save_item(NAME(sh4->r[ 4])); + device->save_item(NAME(sh4->r[ 5])); + device->save_item(NAME(sh4->r[ 6])); + device->save_item(NAME(sh4->r[ 7])); + device->save_item(NAME(sh4->r[ 8])); + device->save_item(NAME(sh4->r[ 9])); + device->save_item(NAME(sh4->r[10])); + device->save_item(NAME(sh4->r[11])); + device->save_item(NAME(sh4->r[12])); + device->save_item(NAME(sh4->r[13])); + device->save_item(NAME(sh4->r[14])); + device->save_item(NAME(sh4->fr[ 0])); + device->save_item(NAME(sh4->fr[ 1])); + device->save_item(NAME(sh4->fr[ 2])); + device->save_item(NAME(sh4->fr[ 3])); + device->save_item(NAME(sh4->fr[ 4])); + device->save_item(NAME(sh4->fr[ 5])); + device->save_item(NAME(sh4->fr[ 6])); + device->save_item(NAME(sh4->fr[ 7])); + device->save_item(NAME(sh4->fr[ 8])); + device->save_item(NAME(sh4->fr[ 9])); + device->save_item(NAME(sh4->fr[10])); + device->save_item(NAME(sh4->fr[11])); + device->save_item(NAME(sh4->fr[12])); + device->save_item(NAME(sh4->fr[13])); + device->save_item(NAME(sh4->fr[14])); + device->save_item(NAME(sh4->fr[15])); + device->save_item(NAME(sh4->xf[ 0])); + device->save_item(NAME(sh4->xf[ 1])); + device->save_item(NAME(sh4->xf[ 2])); + device->save_item(NAME(sh4->xf[ 3])); + device->save_item(NAME(sh4->xf[ 4])); + device->save_item(NAME(sh4->xf[ 5])); + device->save_item(NAME(sh4->xf[ 6])); + device->save_item(NAME(sh4->xf[ 7])); + device->save_item(NAME(sh4->xf[ 8])); + device->save_item(NAME(sh4->xf[ 9])); + device->save_item(NAME(sh4->xf[10])); + device->save_item(NAME(sh4->xf[11])); + device->save_item(NAME(sh4->xf[12])); + device->save_item(NAME(sh4->xf[13])); + device->save_item(NAME(sh4->xf[14])); + device->save_item(NAME(sh4->xf[15])); + device->save_item(NAME(sh4->ea)); + device->save_item(NAME(sh4->fpul)); + device->save_item(NAME(sh4->dbr)); + device->save_item(NAME(sh4->exception_priority)); + device->save_item(NAME(sh4->exception_requesting)); + + device->save_item(NAME(sh4->SH4_TSTR)); + device->save_item(NAME(sh4->SH4_TCNT0)); + device->save_item(NAME(sh4->SH4_TCNT1)); + device->save_item(NAME(sh4->SH4_TCNT2)); + device->save_item(NAME(sh4->SH4_TCR0)); + device->save_item(NAME(sh4->SH4_TCR1)); + device->save_item(NAME(sh4->SH4_TCR2)); + device->save_item(NAME(sh4->SH4_TCOR0)); + device->save_item(NAME(sh4->SH4_TCOR1)); + device->save_item(NAME(sh4->SH4_TCOR2)); + device->save_item(NAME(sh4->SH4_TOCR)); + device->save_item(NAME(sh4->SH4_TCPR2)); + + device->save_item(NAME(sh4->SH4_IPRA)); + + device->save_item(NAME(sh4->SH4_IPRC)); + + + +} + +/************************************************************************** + * Generic set_info + **************************************************************************/ + +static CPU_SET_INFO( sh4 ) +{ + sh4_state *sh4 = get_safe_token(device); + + switch (state) + { + /* --- the following bits of info are set as 64-bit signed integers --- */ + case CPUINFO_INT_INPUT_STATE + SH4_IRL0: sh4_set_irq_line(sh4, SH4_IRL0, info->i); break; + case CPUINFO_INT_INPUT_STATE + SH4_IRL1: sh4_set_irq_line(sh4, SH4_IRL1, info->i); break; + case CPUINFO_INT_INPUT_STATE + SH4_IRL2: sh4_set_irq_line(sh4, SH4_IRL2, info->i); break; + case CPUINFO_INT_INPUT_STATE + SH4_IRL3: sh4_set_irq_line(sh4, SH4_IRL3, info->i); break; + case CPUINFO_INT_INPUT_STATE + SH4_IRLn: sh4_set_irq_line(sh4, SH4_IRLn, info->i); break; + case CPUINFO_INT_INPUT_STATE + INPUT_LINE_NMI: sh4_set_irq_line(sh4, INPUT_LINE_NMI, info->i); break; + + case CPUINFO_INT_REGISTER + SH4_PC: + case CPUINFO_INT_PC: sh4->pc = info->i; sh4->delay = 0; break; + case CPUINFO_INT_SP: sh4->r[15] = info->i; break; + case CPUINFO_INT_REGISTER + SH4_PR: sh4->pr = info->i; break; + case CPUINFO_INT_REGISTER + SH4_SR: + sh4->sr = info->i; + sh4_exception_recompute(sh4); + sh4_check_pending_irq(sh4, "sh4_set_info"); + break; + case CPUINFO_INT_REGISTER + SH4_GBR: sh4->gbr = info->i; break; + case CPUINFO_INT_REGISTER + SH4_VBR: sh4->vbr = info->i; break; + case CPUINFO_INT_REGISTER + SH4_DBR: sh4->dbr = info->i; break; + case CPUINFO_INT_REGISTER + SH4_MACH: sh4->mach = info->i; break; + case CPUINFO_INT_REGISTER + SH4_MACL: sh4->macl = info->i; break; + case CPUINFO_INT_REGISTER + SH4_R0: sh4->r[ 0] = info->i; break; + case CPUINFO_INT_REGISTER + SH4_R1: sh4->r[ 1] = info->i; break; + case CPUINFO_INT_REGISTER + SH4_R2: sh4->r[ 2] = info->i; break; + case CPUINFO_INT_REGISTER + SH4_R3: sh4->r[ 3] = info->i; break; + case CPUINFO_INT_REGISTER + SH4_R4: sh4->r[ 4] = info->i; break; + case CPUINFO_INT_REGISTER + SH4_R5: sh4->r[ 5] = info->i; break; + case CPUINFO_INT_REGISTER + SH4_R6: sh4->r[ 6] = info->i; break; + case CPUINFO_INT_REGISTER + SH4_R7: sh4->r[ 7] = info->i; break; + case CPUINFO_INT_REGISTER + SH4_R8: sh4->r[ 8] = info->i; break; + case CPUINFO_INT_REGISTER + SH4_R9: sh4->r[ 9] = info->i; break; + case CPUINFO_INT_REGISTER + SH4_R10: sh4->r[10] = info->i; break; + case CPUINFO_INT_REGISTER + SH4_R11: sh4->r[11] = info->i; break; + case CPUINFO_INT_REGISTER + SH4_R12: sh4->r[12] = info->i; break; + case CPUINFO_INT_REGISTER + SH4_R13: sh4->r[13] = info->i; break; + case CPUINFO_INT_REGISTER + SH4_R14: sh4->r[14] = info->i; break; + case CPUINFO_INT_REGISTER + SH4_R15: sh4->r[15] = info->i; break; + case CPUINFO_INT_REGISTER + SH4_EA: sh4->ea = info->i; break; + case CPUINFO_STR_REGISTER + SH4_R0_BK0: sh4->rbnk[0][0] = info->i; break; + case CPUINFO_STR_REGISTER + SH4_R1_BK0: sh4->rbnk[0][1] = info->i; break; + case CPUINFO_STR_REGISTER + SH4_R2_BK0: sh4->rbnk[0][2] = info->i; break; + case CPUINFO_STR_REGISTER + SH4_R3_BK0: sh4->rbnk[0][3] = info->i; break; + case CPUINFO_STR_REGISTER + SH4_R4_BK0: sh4->rbnk[0][4] = info->i; break; + case CPUINFO_STR_REGISTER + SH4_R5_BK0: sh4->rbnk[0][5] = info->i; break; + case CPUINFO_STR_REGISTER + SH4_R6_BK0: sh4->rbnk[0][6] = info->i; break; + case CPUINFO_STR_REGISTER + SH4_R7_BK0: sh4->rbnk[0][7] = info->i; break; + case CPUINFO_STR_REGISTER + SH4_R0_BK1: sh4->rbnk[1][0] = info->i; break; + case CPUINFO_STR_REGISTER + SH4_R1_BK1: sh4->rbnk[1][1] = info->i; break; + case CPUINFO_STR_REGISTER + SH4_R2_BK1: sh4->rbnk[1][2] = info->i; break; + case CPUINFO_STR_REGISTER + SH4_R3_BK1: sh4->rbnk[1][3] = info->i; break; + case CPUINFO_STR_REGISTER + SH4_R4_BK1: sh4->rbnk[1][4] = info->i; break; + case CPUINFO_STR_REGISTER + SH4_R5_BK1: sh4->rbnk[1][5] = info->i; break; + case CPUINFO_STR_REGISTER + SH4_R6_BK1: sh4->rbnk[1][6] = info->i; break; + case CPUINFO_STR_REGISTER + SH4_R7_BK1: sh4->rbnk[1][7] = info->i; break; + case CPUINFO_STR_REGISTER + SH4_SPC: sh4->spc = info->i; break; + case CPUINFO_STR_REGISTER + SH4_SSR: sh4->ssr = info->i; break; + case CPUINFO_STR_REGISTER + SH4_SGR: sh4->sgr = info->i; break; + case CPUINFO_STR_REGISTER + SH4_FPSCR: sh4->fpscr = info->i; break; + case CPUINFO_STR_REGISTER + SH4_FPUL: sh4->fpul = info->i; break; +#ifdef LSB_FIRST + case CPUINFO_STR_REGISTER + SH4_FR0: sh4->fr[ 0 ^ sh4->fpu_pr] = info->i; break; + case CPUINFO_STR_REGISTER + SH4_FR1: sh4->fr[ 1 ^ sh4->fpu_pr] = info->i; break; + case CPUINFO_STR_REGISTER + SH4_FR2: sh4->fr[ 2 ^ sh4->fpu_pr] = info->i; break; + case CPUINFO_STR_REGISTER + SH4_FR3: sh4->fr[ 3 ^ sh4->fpu_pr] = info->i; break; + case CPUINFO_STR_REGISTER + SH4_FR4: sh4->fr[ 4 ^ sh4->fpu_pr] = info->i; break; + case CPUINFO_STR_REGISTER + SH4_FR5: sh4->fr[ 5 ^ sh4->fpu_pr] = info->i; break; + case CPUINFO_STR_REGISTER + SH4_FR6: sh4->fr[ 6 ^ sh4->fpu_pr] = info->i; break; + case CPUINFO_STR_REGISTER + SH4_FR7: sh4->fr[ 7 ^ sh4->fpu_pr] = info->i; break; + case CPUINFO_STR_REGISTER + SH4_FR8: sh4->fr[ 8 ^ sh4->fpu_pr] = info->i; break; + case CPUINFO_STR_REGISTER + SH4_FR9: sh4->fr[ 9 ^ sh4->fpu_pr] = info->i; break; + case CPUINFO_STR_REGISTER + SH4_FR10: sh4->fr[10 ^ sh4->fpu_pr] = info->i; break; + case CPUINFO_STR_REGISTER + SH4_FR11: sh4->fr[11 ^ sh4->fpu_pr] = info->i; break; + case CPUINFO_STR_REGISTER + SH4_FR12: sh4->fr[12 ^ sh4->fpu_pr] = info->i; break; + case CPUINFO_STR_REGISTER + SH4_FR13: sh4->fr[13 ^ sh4->fpu_pr] = info->i; break; + case CPUINFO_STR_REGISTER + SH4_FR14: sh4->fr[14 ^ sh4->fpu_pr] = info->i; break; + case CPUINFO_STR_REGISTER + SH4_FR15: sh4->fr[15 ^ sh4->fpu_pr] = info->i; break; + case CPUINFO_STR_REGISTER + SH4_XF0: sh4->xf[ 0 ^ sh4->fpu_pr] = info->i; break; + case CPUINFO_STR_REGISTER + SH4_XF1: sh4->xf[ 1 ^ sh4->fpu_pr] = info->i; break; + case CPUINFO_STR_REGISTER + SH4_XF2: sh4->xf[ 2 ^ sh4->fpu_pr] = info->i; break; + case CPUINFO_STR_REGISTER + SH4_XF3: sh4->xf[ 3 ^ sh4->fpu_pr] = info->i; break; + case CPUINFO_STR_REGISTER + SH4_XF4: sh4->xf[ 4 ^ sh4->fpu_pr] = info->i; break; + case CPUINFO_STR_REGISTER + SH4_XF5: sh4->xf[ 5 ^ sh4->fpu_pr] = info->i; break; + case CPUINFO_STR_REGISTER + SH4_XF6: sh4->xf[ 6 ^ sh4->fpu_pr] = info->i; break; + case CPUINFO_STR_REGISTER + SH4_XF7: sh4->xf[ 7 ^ sh4->fpu_pr] = info->i; break; + case CPUINFO_STR_REGISTER + SH4_XF8: sh4->xf[ 8 ^ sh4->fpu_pr] = info->i; break; + case CPUINFO_STR_REGISTER + SH4_XF9: sh4->xf[ 9 ^ sh4->fpu_pr] = info->i; break; + case CPUINFO_STR_REGISTER + SH4_XF10: sh4->xf[10 ^ sh4->fpu_pr] = info->i; break; + case CPUINFO_STR_REGISTER + SH4_XF11: sh4->xf[11 ^ sh4->fpu_pr] = info->i; break; + case CPUINFO_STR_REGISTER + SH4_XF12: sh4->xf[12 ^ sh4->fpu_pr] = info->i; break; + case CPUINFO_STR_REGISTER + SH4_XF13: sh4->xf[13 ^ sh4->fpu_pr] = info->i; break; + case CPUINFO_STR_REGISTER + SH4_XF14: sh4->xf[14 ^ sh4->fpu_pr] = info->i; break; + case CPUINFO_STR_REGISTER + SH4_XF15: sh4->xf[15 ^ sh4->fpu_pr] = info->i; break; +#else + case CPUINFO_STR_REGISTER + SH4_FR0: sh4->fr[ 0] = info->i; break; + case CPUINFO_STR_REGISTER + SH4_FR1: sh4->fr[ 1] = info->i; break; + case CPUINFO_STR_REGISTER + SH4_FR2: sh4->fr[ 2] = info->i; break; + case CPUINFO_STR_REGISTER + SH4_FR3: sh4->fr[ 3] = info->i; break; + case CPUINFO_STR_REGISTER + SH4_FR4: sh4->fr[ 4] = info->i; break; + case CPUINFO_STR_REGISTER + SH4_FR5: sh4->fr[ 5] = info->i; break; + case CPUINFO_STR_REGISTER + SH4_FR6: sh4->fr[ 6] = info->i; break; + case CPUINFO_STR_REGISTER + SH4_FR7: sh4->fr[ 7] = info->i; break; + case CPUINFO_STR_REGISTER + SH4_FR8: sh4->fr[ 8] = info->i; break; + case CPUINFO_STR_REGISTER + SH4_FR9: sh4->fr[ 9] = info->i; break; + case CPUINFO_STR_REGISTER + SH4_FR10: sh4->fr[10] = info->i; break; + case CPUINFO_STR_REGISTER + SH4_FR11: sh4->fr[11] = info->i; break; + case CPUINFO_STR_REGISTER + SH4_FR12: sh4->fr[12] = info->i; break; + case CPUINFO_STR_REGISTER + SH4_FR13: sh4->fr[13] = info->i; break; + case CPUINFO_STR_REGISTER + SH4_FR14: sh4->fr[14] = info->i; break; + case CPUINFO_STR_REGISTER + SH4_FR15: sh4->fr[15] = info->i; break; + case CPUINFO_STR_REGISTER + SH4_XF0: sh4->xf[ 0] = info->i; break; + case CPUINFO_STR_REGISTER + SH4_XF1: sh4->xf[ 1] = info->i; break; + case CPUINFO_STR_REGISTER + SH4_XF2: sh4->xf[ 2] = info->i; break; + case CPUINFO_STR_REGISTER + SH4_XF3: sh4->xf[ 3] = info->i; break; + case CPUINFO_STR_REGISTER + SH4_XF4: sh4->xf[ 4] = info->i; break; + case CPUINFO_STR_REGISTER + SH4_XF5: sh4->xf[ 5] = info->i; break; + case CPUINFO_STR_REGISTER + SH4_XF6: sh4->xf[ 6] = info->i; break; + case CPUINFO_STR_REGISTER + SH4_XF7: sh4->xf[ 7] = info->i; break; + case CPUINFO_STR_REGISTER + SH4_XF8: sh4->xf[ 8] = info->i; break; + case CPUINFO_STR_REGISTER + SH4_XF9: sh4->xf[ 9] = info->i; break; + case CPUINFO_STR_REGISTER + SH4_XF10: sh4->xf[10] = info->i; break; + case CPUINFO_STR_REGISTER + SH4_XF11: sh4->xf[11] = info->i; break; + case CPUINFO_STR_REGISTER + SH4_XF12: sh4->xf[12] = info->i; break; + case CPUINFO_STR_REGISTER + SH4_XF13: sh4->xf[13] = info->i; break; + case CPUINFO_STR_REGISTER + SH4_XF14: sh4->xf[14] = info->i; break; + case CPUINFO_STR_REGISTER + SH4_XF15: sh4->xf[15] = info->i; break; +#endif + } +} + +void sh4_set_ftcsr_callback(device_t *device, sh4_ftcsr_callback callback) +{ + sh4_state *sh4 = get_safe_token(device); + sh4->ftcsr_read_callback = callback; +} + + +#if 0 +/*When OC index mode is off (CCR.OIX = 0)*/ +static ADDRESS_MAP_START( sh4_internal_map, AS_PROGRAM, 64, legacy_cpu_device ) + AM_RANGE(0x1C000000, 0x1C000FFF) AM_RAM AM_MIRROR(0x03FFD000) + AM_RANGE(0x1C002000, 0x1C002FFF) AM_RAM AM_MIRROR(0x03FFD000) + AM_RANGE(0xE0000000, 0xE000003F) AM_RAM AM_MIRROR(0x03FFFFC0) +ADDRESS_MAP_END +#endif + +/*When OC index mode is on (CCR.OIX = 1)*/ +static ADDRESS_MAP_START( sh4_internal_map, AS_PROGRAM, 64, legacy_cpu_device ) + AM_RANGE(0x1C000000, 0x1C000FFF) AM_RAM AM_MIRROR(0x01FFF000) + AM_RANGE(0x1E000000, 0x1E000FFF) AM_RAM AM_MIRROR(0x01FFF000) + AM_RANGE(0xE0000000, 0xE000003F) AM_RAM AM_MIRROR(0x03FFFFC0) // todo: store queues should be write only on DC's SH4, executing PREFM shouldn't cause an actual memory read access! + AM_RANGE(0xF6000000, 0xF7FFFFFF) AM_READWRITE_LEGACY(sh4_tlb_r,sh4_tlb_w) + AM_RANGE(0xFE000000, 0xFFFFFFFF) AM_READWRITE32_LEGACY(sh4_internal_r, sh4_internal_w, U64(0xffffffffffffffff)) +ADDRESS_MAP_END + +static ADDRESS_MAP_START( sh3_internal_map, AS_PROGRAM, 64, legacy_cpu_device ) + AM_RANGE(SH3_LOWER_REGBASE, SH3_LOWER_REGEND) AM_READWRITE32_LEGACY(sh3_internal_r, sh3_internal_w, U64(0xffffffffffffffff)) + AM_RANGE(SH3_UPPER_REGBASE, SH3_UPPER_REGEND) AM_READWRITE32_LEGACY(sh3_internal_high_r, sh3_internal_high_w, U64(0xffffffffffffffff)) +ADDRESS_MAP_END + + +/************************************************************************** + * Generic get_info + **************************************************************************/ + +CPU_GET_INFO( sh4 ) +{ + sh4_state *sh4 = (device != NULL && device->token() != NULL) ? get_safe_token(device) : NULL; + + switch (state) + { + /* --- the following bits of info are returned as 64-bit signed integers --- */ + case CPUINFO_INT_CONTEXT_SIZE: info->i = sizeof(sh4_state); break; + case CPUINFO_INT_INPUT_LINES: info->i = 5; break; + case CPUINFO_INT_DEFAULT_IRQ_VECTOR: info->i = 0; break; + case DEVINFO_INT_ENDIANNESS: info->i = ENDIANNESS_LITTLE; break; + case CPUINFO_INT_CLOCK_MULTIPLIER: info->i = 1; break; + case CPUINFO_INT_CLOCK_DIVIDER: info->i = 1; break; + case CPUINFO_INT_MIN_INSTRUCTION_BYTES: info->i = 2; break; + case CPUINFO_INT_MAX_INSTRUCTION_BYTES: info->i = 2; break; + case CPUINFO_INT_MIN_CYCLES: info->i = 1; break; + case CPUINFO_INT_MAX_CYCLES: info->i = 4; break; + + case DEVINFO_INT_DATABUS_WIDTH + AS_PROGRAM: info->i = 64; break; + case DEVINFO_INT_ADDRBUS_WIDTH + AS_PROGRAM: info->i = 32; break; + case DEVINFO_INT_ADDRBUS_SHIFT + AS_PROGRAM: info->i = 0; break; + case DEVINFO_INT_DATABUS_WIDTH + AS_DATA: info->i = 0; break; + case DEVINFO_INT_ADDRBUS_WIDTH + AS_DATA: info->i = 0; break; + case DEVINFO_INT_ADDRBUS_SHIFT + AS_DATA: info->i = 0; break; + case DEVINFO_INT_DATABUS_WIDTH + AS_IO: info->i = 64; break; + case DEVINFO_INT_ADDRBUS_WIDTH + AS_IO: info->i = 8; break; + case DEVINFO_INT_ADDRBUS_SHIFT + AS_IO: info->i = 0; break; + + case DEVINFO_PTR_INTERNAL_MEMORY_MAP + AS_PROGRAM: info->internal_map64 = ADDRESS_MAP_NAME(sh4_internal_map); break; + + case CPUINFO_INT_INPUT_STATE + SH4_IRL0: info->i = sh4->irq_line_state[SH4_IRL0]; break; + case CPUINFO_INT_INPUT_STATE + SH4_IRL1: info->i = sh4->irq_line_state[SH4_IRL1]; break; + case CPUINFO_INT_INPUT_STATE + SH4_IRL2: info->i = sh4->irq_line_state[SH4_IRL2]; break; + case CPUINFO_INT_INPUT_STATE + SH4_IRL3: info->i = sh4->irq_line_state[SH4_IRL3]; break; + case CPUINFO_INT_INPUT_STATE + INPUT_LINE_NMI: info->i = sh4->nmi_line_state; break; + + case CPUINFO_INT_PREVIOUSPC: info->i = sh4->ppc; break; + + case CPUINFO_INT_PC: + case CPUINFO_INT_REGISTER + SH4_PC: info->i = (sh4->delay) ? (sh4->delay & AM) : (sh4->pc & AM); break; + case CPUINFO_INT_SP: info->i = sh4->r[15]; break; + case CPUINFO_INT_REGISTER + SH4_PR: info->i = sh4->pr; break; + case CPUINFO_INT_REGISTER + SH4_SR: info->i = sh4->sr; break; + case CPUINFO_INT_REGISTER + SH4_GBR: info->i = sh4->gbr; break; + case CPUINFO_INT_REGISTER + SH4_VBR: info->i = sh4->vbr; break; + case CPUINFO_INT_REGISTER + SH4_DBR: info->i = sh4->dbr; break; + case CPUINFO_INT_REGISTER + SH4_MACH: info->i = sh4->mach; break; + case CPUINFO_INT_REGISTER + SH4_MACL: info->i = sh4->macl; break; + case CPUINFO_INT_REGISTER + SH4_R0: info->i = sh4->r[ 0]; break; + case CPUINFO_INT_REGISTER + SH4_R1: info->i = sh4->r[ 1]; break; + case CPUINFO_INT_REGISTER + SH4_R2: info->i = sh4->r[ 2]; break; + case CPUINFO_INT_REGISTER + SH4_R3: info->i = sh4->r[ 3]; break; + case CPUINFO_INT_REGISTER + SH4_R4: info->i = sh4->r[ 4]; break; + case CPUINFO_INT_REGISTER + SH4_R5: info->i = sh4->r[ 5]; break; + case CPUINFO_INT_REGISTER + SH4_R6: info->i = sh4->r[ 6]; break; + case CPUINFO_INT_REGISTER + SH4_R7: info->i = sh4->r[ 7]; break; + case CPUINFO_INT_REGISTER + SH4_R8: info->i = sh4->r[ 8]; break; + case CPUINFO_INT_REGISTER + SH4_R9: info->i = sh4->r[ 9]; break; + case CPUINFO_INT_REGISTER + SH4_R10: info->i = sh4->r[10]; break; + case CPUINFO_INT_REGISTER + SH4_R11: info->i = sh4->r[11]; break; + case CPUINFO_INT_REGISTER + SH4_R12: info->i = sh4->r[12]; break; + case CPUINFO_INT_REGISTER + SH4_R13: info->i = sh4->r[13]; break; + case CPUINFO_INT_REGISTER + SH4_R14: info->i = sh4->r[14]; break; + case CPUINFO_INT_REGISTER + SH4_R15: info->i = sh4->r[15]; break; + case CPUINFO_INT_REGISTER + SH4_EA: info->i = sh4->ea; break; + + /* --- the following bits of info are returned as pointers to data or functions --- */ + case CPUINFO_FCT_SET_INFO: info->setinfo = CPU_SET_INFO_NAME(sh4); break; + case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME(sh4); break; + case CPUINFO_FCT_RESET: info->reset = CPU_RESET_NAME(sh4); break; + case CPUINFO_FCT_EXECUTE: info->execute = CPU_EXECUTE_NAME(sh4); break; + case CPUINFO_FCT_BURN: info->burn = NULL; break; + case CPUINFO_FCT_DISASSEMBLE: info->disassemble = CPU_DISASSEMBLE_NAME(sh4); break; + case CPUINFO_PTR_INSTRUCTION_COUNTER: info->icount = &sh4->sh4_icount; break; + + /* --- the following bits of info are returned as NULL-terminated strings --- */ + case DEVINFO_STR_NAME: strcpy(info->s, "SH-4"); break; + case DEVINFO_STR_FAMILY: strcpy(info->s, "Hitachi SH7750"); break; + case DEVINFO_STR_VERSION: strcpy(info->s, "1.0"); break; + case DEVINFO_STR_SOURCE_FILE: strcpy(info->s, __FILE__); break; + case DEVINFO_STR_CREDITS: strcpy(info->s, "Copyright R. Belmont"); break; + + case CPUINFO_STR_FLAGS: + sprintf(info->s, "%s%s%s%s%c%c%d%c%c", + sh4->sr & MD ? "MD ":" ", + sh4->sr & sRB ? "RB ":" ", + sh4->sr & BL ? "BL ":" ", + sh4->sr & FD ? "FD ":" ", + sh4->sr & M ? 'M':'.', + sh4->sr & Q ? 'Q':'.', + (sh4->sr & I) >> 4, + sh4->sr & S ? 'S':'.', + sh4->sr & T ? 'T':'.'); + break; + + case CPUINFO_STR_REGISTER + SH4_PC: sprintf(info->s, "PC :%08X", sh4->pc); break; + case CPUINFO_STR_REGISTER + SH4_SR: sprintf(info->s, "SR :%08X", sh4->sr); break; + case CPUINFO_STR_REGISTER + SH4_PR: sprintf(info->s, "PR :%08X", sh4->pr); break; + case CPUINFO_STR_REGISTER + SH4_GBR: sprintf(info->s, "GBR :%08X", sh4->gbr); break; + case CPUINFO_STR_REGISTER + SH4_VBR: sprintf(info->s, "VBR :%08X", sh4->vbr); break; + case CPUINFO_STR_REGISTER + SH4_DBR: sprintf(info->s, "DBR :%08X", sh4->dbr); break; + case CPUINFO_STR_REGISTER + SH4_MACH: sprintf(info->s, "MACH:%08X", sh4->mach); break; + case CPUINFO_STR_REGISTER + SH4_MACL: sprintf(info->s, "MACL:%08X", sh4->macl); break; + case CPUINFO_STR_REGISTER + SH4_R0: sprintf(info->s, "R0 :%08X", sh4->r[ 0]); break; + case CPUINFO_STR_REGISTER + SH4_R1: sprintf(info->s, "R1 :%08X", sh4->r[ 1]); break; + case CPUINFO_STR_REGISTER + SH4_R2: sprintf(info->s, "R2 :%08X", sh4->r[ 2]); break; + case CPUINFO_STR_REGISTER + SH4_R3: sprintf(info->s, "R3 :%08X", sh4->r[ 3]); break; + case CPUINFO_STR_REGISTER + SH4_R4: sprintf(info->s, "R4 :%08X", sh4->r[ 4]); break; + case CPUINFO_STR_REGISTER + SH4_R5: sprintf(info->s, "R5 :%08X", sh4->r[ 5]); break; + case CPUINFO_STR_REGISTER + SH4_R6: sprintf(info->s, "R6 :%08X", sh4->r[ 6]); break; + case CPUINFO_STR_REGISTER + SH4_R7: sprintf(info->s, "R7 :%08X", sh4->r[ 7]); break; + case CPUINFO_STR_REGISTER + SH4_R8: sprintf(info->s, "R8 :%08X", sh4->r[ 8]); break; + case CPUINFO_STR_REGISTER + SH4_R9: sprintf(info->s, "R9 :%08X", sh4->r[ 9]); break; + case CPUINFO_STR_REGISTER + SH4_R10: sprintf(info->s, "R10 :%08X", sh4->r[10]); break; + case CPUINFO_STR_REGISTER + SH4_R11: sprintf(info->s, "R11 :%08X", sh4->r[11]); break; + case CPUINFO_STR_REGISTER + SH4_R12: sprintf(info->s, "R12 :%08X", sh4->r[12]); break; + case CPUINFO_STR_REGISTER + SH4_R13: sprintf(info->s, "R13 :%08X", sh4->r[13]); break; + case CPUINFO_STR_REGISTER + SH4_R14: sprintf(info->s, "R14 :%08X", sh4->r[14]); break; + case CPUINFO_STR_REGISTER + SH4_R15: sprintf(info->s, "R15 :%08X", sh4->r[15]); break; + case CPUINFO_STR_REGISTER + SH4_EA: sprintf(info->s, "EA :%08X", sh4->ea); break; + case CPUINFO_STR_REGISTER + SH4_R0_BK0: sprintf(info->s, "R0 BK 0 :%08X", sh4->rbnk[0][0]); break; + case CPUINFO_STR_REGISTER + SH4_R1_BK0: sprintf(info->s, "R1 BK 0 :%08X", sh4->rbnk[0][1]); break; + case CPUINFO_STR_REGISTER + SH4_R2_BK0: sprintf(info->s, "R2 BK 0 :%08X", sh4->rbnk[0][2]); break; + case CPUINFO_STR_REGISTER + SH4_R3_BK0: sprintf(info->s, "R3 BK 0 :%08X", sh4->rbnk[0][3]); break; + case CPUINFO_STR_REGISTER + SH4_R4_BK0: sprintf(info->s, "R4 BK 0 :%08X", sh4->rbnk[0][4]); break; + case CPUINFO_STR_REGISTER + SH4_R5_BK0: sprintf(info->s, "R5 BK 0 :%08X", sh4->rbnk[0][5]); break; + case CPUINFO_STR_REGISTER + SH4_R6_BK0: sprintf(info->s, "R6 BK 0 :%08X", sh4->rbnk[0][6]); break; + case CPUINFO_STR_REGISTER + SH4_R7_BK0: sprintf(info->s, "R7 BK 0 :%08X", sh4->rbnk[0][7]); break; + case CPUINFO_STR_REGISTER + SH4_R0_BK1: sprintf(info->s, "R0 BK 1 :%08X", sh4->rbnk[1][0]); break; + case CPUINFO_STR_REGISTER + SH4_R1_BK1: sprintf(info->s, "R1 BK 1 :%08X", sh4->rbnk[1][1]); break; + case CPUINFO_STR_REGISTER + SH4_R2_BK1: sprintf(info->s, "R2 BK 1 :%08X", sh4->rbnk[1][2]); break; + case CPUINFO_STR_REGISTER + SH4_R3_BK1: sprintf(info->s, "R3 BK 1 :%08X", sh4->rbnk[1][3]); break; + case CPUINFO_STR_REGISTER + SH4_R4_BK1: sprintf(info->s, "R4 BK 1 :%08X", sh4->rbnk[1][4]); break; + case CPUINFO_STR_REGISTER + SH4_R5_BK1: sprintf(info->s, "R5 BK 1 :%08X", sh4->rbnk[1][5]); break; + case CPUINFO_STR_REGISTER + SH4_R6_BK1: sprintf(info->s, "R6 BK 1 :%08X", sh4->rbnk[1][6]); break; + case CPUINFO_STR_REGISTER + SH4_R7_BK1: sprintf(info->s, "R7 BK 1 :%08X", sh4->rbnk[1][7]); break; + case CPUINFO_STR_REGISTER + SH4_SPC: sprintf(info->s, "SPC :%08X", sh4->spc); break; + case CPUINFO_STR_REGISTER + SH4_SSR: sprintf(info->s, "SSR :%08X", sh4->ssr); break; + case CPUINFO_STR_REGISTER + SH4_SGR: sprintf(info->s, "SGR :%08X", sh4->sgr); break; + case CPUINFO_STR_REGISTER + SH4_FPSCR: sprintf(info->s, "FPSCR :%08X", sh4->fpscr); break; + case CPUINFO_STR_REGISTER + SH4_FPUL: sprintf(info->s, "FPUL :%08X", sh4->fpul); break; +#ifdef LSB_FIRST + case CPUINFO_STR_REGISTER + SH4_FR0: sprintf(info->s, "FR0 :%08X %f", FP_RS2( 0),(double)FP_RFS2( 0)); break; + case CPUINFO_STR_REGISTER + SH4_FR1: sprintf(info->s, "FR1 :%08X %f", FP_RS2( 1),(double)FP_RFS2( 1)); break; + case CPUINFO_STR_REGISTER + SH4_FR2: sprintf(info->s, "FR2 :%08X %f", FP_RS2( 2),(double)FP_RFS2( 2)); break; + case CPUINFO_STR_REGISTER + SH4_FR3: sprintf(info->s, "FR3 :%08X %f", FP_RS2( 3),(double)FP_RFS2( 3)); break; + case CPUINFO_STR_REGISTER + SH4_FR4: sprintf(info->s, "FR4 :%08X %f", FP_RS2( 4),(double)FP_RFS2( 4)); break; + case CPUINFO_STR_REGISTER + SH4_FR5: sprintf(info->s, "FR5 :%08X %f", FP_RS2( 5),(double)FP_RFS2( 5)); break; + case CPUINFO_STR_REGISTER + SH4_FR6: sprintf(info->s, "FR6 :%08X %f", FP_RS2( 6),(double)FP_RFS2( 6)); break; + case CPUINFO_STR_REGISTER + SH4_FR7: sprintf(info->s, "FR7 :%08X %f", FP_RS2( 7),(double)FP_RFS2( 7)); break; + case CPUINFO_STR_REGISTER + SH4_FR8: sprintf(info->s, "FR8 :%08X %f", FP_RS2( 8),(double)FP_RFS2( 8)); break; + case CPUINFO_STR_REGISTER + SH4_FR9: sprintf(info->s, "FR9 :%08X %f", FP_RS2( 9),(double)FP_RFS2( 9)); break; + case CPUINFO_STR_REGISTER + SH4_FR10: sprintf(info->s, "FR10 :%08X %f", FP_RS2(10),(double)FP_RFS2(10)); break; + case CPUINFO_STR_REGISTER + SH4_FR11: sprintf(info->s, "FR11 :%08X %f", FP_RS2(11),(double)FP_RFS2(11)); break; + case CPUINFO_STR_REGISTER + SH4_FR12: sprintf(info->s, "FR12 :%08X %f", FP_RS2(12),(double)FP_RFS2(12)); break; + case CPUINFO_STR_REGISTER + SH4_FR13: sprintf(info->s, "FR13 :%08X %f", FP_RS2(13),(double)FP_RFS2(13)); break; + case CPUINFO_STR_REGISTER + SH4_FR14: sprintf(info->s, "FR14 :%08X %f", FP_RS2(14),(double)FP_RFS2(14)); break; + case CPUINFO_STR_REGISTER + SH4_FR15: sprintf(info->s, "FR15 :%08X %f", FP_RS2(15),(double)FP_RFS2(15)); break; + case CPUINFO_STR_REGISTER + SH4_XF0: sprintf(info->s, "XF0 :%08X %f", FP_XS2( 0),(double)FP_XFS2( 0)); break; + case CPUINFO_STR_REGISTER + SH4_XF1: sprintf(info->s, "XF1 :%08X %f", FP_XS2( 1),(double)FP_XFS2( 1)); break; + case CPUINFO_STR_REGISTER + SH4_XF2: sprintf(info->s, "XF2 :%08X %f", FP_XS2( 2),(double)FP_XFS2( 2)); break; + case CPUINFO_STR_REGISTER + SH4_XF3: sprintf(info->s, "XF3 :%08X %f", FP_XS2( 3),(double)FP_XFS2( 3)); break; + case CPUINFO_STR_REGISTER + SH4_XF4: sprintf(info->s, "XF4 :%08X %f", FP_XS2( 4),(double)FP_XFS2( 4)); break; + case CPUINFO_STR_REGISTER + SH4_XF5: sprintf(info->s, "XF5 :%08X %f", FP_XS2( 5),(double)FP_XFS2( 5)); break; + case CPUINFO_STR_REGISTER + SH4_XF6: sprintf(info->s, "XF6 :%08X %f", FP_XS2( 6),(double)FP_XFS2( 6)); break; + case CPUINFO_STR_REGISTER + SH4_XF7: sprintf(info->s, "XF7 :%08X %f", FP_XS2( 7),(double)FP_XFS2( 7)); break; + case CPUINFO_STR_REGISTER + SH4_XF8: sprintf(info->s, "XF8 :%08X %f", FP_XS2( 8),(double)FP_XFS2( 8)); break; + case CPUINFO_STR_REGISTER + SH4_XF9: sprintf(info->s, "XF9 :%08X %f", FP_XS2( 9),(double)FP_XFS2( 9)); break; + case CPUINFO_STR_REGISTER + SH4_XF10: sprintf(info->s, "XF10 :%08X %f", FP_XS2(10),(double)FP_XFS2(10)); break; + case CPUINFO_STR_REGISTER + SH4_XF11: sprintf(info->s, "XF11 :%08X %f", FP_XS2(11),(double)FP_XFS2(11)); break; + case CPUINFO_STR_REGISTER + SH4_XF12: sprintf(info->s, "XF12 :%08X %f", FP_XS2(12),(double)FP_XFS2(12)); break; + case CPUINFO_STR_REGISTER + SH4_XF13: sprintf(info->s, "XF13 :%08X %f", FP_XS2(13),(double)FP_XFS2(13)); break; + case CPUINFO_STR_REGISTER + SH4_XF14: sprintf(info->s, "XF14 :%08X %f", FP_XS2(14),(double)FP_XFS2(14)); break; + case CPUINFO_STR_REGISTER + SH4_XF15: sprintf(info->s, "XF15 :%08X %f", FP_XS2(15),(double)FP_XFS2(15)); break; +#else + case CPUINFO_STR_REGISTER + SH4_FR0: sprintf(info->s, "FR0 :%08X %f", FP_RS( 0),(double)FP_RFS( 0)); break; + case CPUINFO_STR_REGISTER + SH4_FR1: sprintf(info->s, "FR1 :%08X %f", FP_RS( 1),(double)FP_RFS( 1)); break; + case CPUINFO_STR_REGISTER + SH4_FR2: sprintf(info->s, "FR2 :%08X %f", FP_RS( 2),(double)FP_RFS( 2)); break; + case CPUINFO_STR_REGISTER + SH4_FR3: sprintf(info->s, "FR3 :%08X %f", FP_RS( 3),(double)FP_RFS( 3)); break; + case CPUINFO_STR_REGISTER + SH4_FR4: sprintf(info->s, "FR4 :%08X %f", FP_RS( 4),(double)FP_RFS( 4)); break; + case CPUINFO_STR_REGISTER + SH4_FR5: sprintf(info->s, "FR5 :%08X %f", FP_RS( 5),(double)FP_RFS( 5)); break; + case CPUINFO_STR_REGISTER + SH4_FR6: sprintf(info->s, "FR6 :%08X %f", FP_RS( 6),(double)FP_RFS( 6)); break; + case CPUINFO_STR_REGISTER + SH4_FR7: sprintf(info->s, "FR7 :%08X %f", FP_RS( 7),(double)FP_RFS( 7)); break; + case CPUINFO_STR_REGISTER + SH4_FR8: sprintf(info->s, "FR8 :%08X %f", FP_RS( 8),(double)FP_RFS( 8)); break; + case CPUINFO_STR_REGISTER + SH4_FR9: sprintf(info->s, "FR9 :%08X %f", FP_RS( 9),(double)FP_RFS( 9)); break; + case CPUINFO_STR_REGISTER + SH4_FR10: sprintf(info->s, "FR10 :%08X %f", FP_RS(10),(double)FP_RFS(10)); break; + case CPUINFO_STR_REGISTER + SH4_FR11: sprintf(info->s, "FR11 :%08X %f", FP_RS(11),(double)FP_RFS(11)); break; + case CPUINFO_STR_REGISTER + SH4_FR12: sprintf(info->s, "FR12 :%08X %f", FP_RS(12),(double)FP_RFS(12)); break; + case CPUINFO_STR_REGISTER + SH4_FR13: sprintf(info->s, "FR13 :%08X %f", FP_RS(13),(double)FP_RFS(13)); break; + case CPUINFO_STR_REGISTER + SH4_FR14: sprintf(info->s, "FR14 :%08X %f", FP_RS(14),(double)FP_RFS(14)); break; + case CPUINFO_STR_REGISTER + SH4_FR15: sprintf(info->s, "FR15 :%08X %f", FP_RS(15),(double)FP_RFS(15)); break; + case CPUINFO_STR_REGISTER + SH4_XF0: sprintf(info->s, "XF0 :%08X %f", FP_XS( 0),(double)FP_XFS( 0)); break; + case CPUINFO_STR_REGISTER + SH4_XF1: sprintf(info->s, "XF1 :%08X %f", FP_XS( 1),(double)FP_XFS( 1)); break; + case CPUINFO_STR_REGISTER + SH4_XF2: sprintf(info->s, "XF2 :%08X %f", FP_XS( 2),(double)FP_XFS( 2)); break; + case CPUINFO_STR_REGISTER + SH4_XF3: sprintf(info->s, "XF3 :%08X %f", FP_XS( 3),(double)FP_XFS( 3)); break; + case CPUINFO_STR_REGISTER + SH4_XF4: sprintf(info->s, "XF4 :%08X %f", FP_XS( 4),(double)FP_XFS( 4)); break; + case CPUINFO_STR_REGISTER + SH4_XF5: sprintf(info->s, "XF5 :%08X %f", FP_XS( 5),(double)FP_XFS( 5)); break; + case CPUINFO_STR_REGISTER + SH4_XF6: sprintf(info->s, "XF6 :%08X %f", FP_XS( 6),(double)FP_XFS( 6)); break; + case CPUINFO_STR_REGISTER + SH4_XF7: sprintf(info->s, "XF7 :%08X %f", FP_XS( 7),(double)FP_XFS( 7)); break; + case CPUINFO_STR_REGISTER + SH4_XF8: sprintf(info->s, "XF8 :%08X %f", FP_XS( 8),(double)FP_XFS( 8)); break; + case CPUINFO_STR_REGISTER + SH4_XF9: sprintf(info->s, "XF9 :%08X %f", FP_XS( 9),(double)FP_XFS( 9)); break; + case CPUINFO_STR_REGISTER + SH4_XF10: sprintf(info->s, "XF10 :%08X %f", FP_XS(10),(double)FP_XFS(10)); break; + case CPUINFO_STR_REGISTER + SH4_XF11: sprintf(info->s, "XF11 :%08X %f", FP_XS(11),(double)FP_XFS(11)); break; + case CPUINFO_STR_REGISTER + SH4_XF12: sprintf(info->s, "XF12 :%08X %f", FP_XS(12),(double)FP_XFS(12)); break; + case CPUINFO_STR_REGISTER + SH4_XF13: sprintf(info->s, "XF13 :%08X %f", FP_XS(13),(double)FP_XFS(13)); break; + case CPUINFO_STR_REGISTER + SH4_XF14: sprintf(info->s, "XF14 :%08X %f", FP_XS(14),(double)FP_XFS(14)); break; + case CPUINFO_STR_REGISTER + SH4_XF15: sprintf(info->s, "XF15 :%08X %f", FP_XS(15),(double)FP_XFS(15)); break; //%01.2e +#endif + } +} + +CPU_GET_INFO( sh3 ) +{ + switch (state) + { + /* --- the following bits of info are returned as pointers to data or functions --- */ + case CPUINFO_FCT_RESET: info->reset = CPU_RESET_NAME(sh3); break; + + /* --- the following bits of info are returned as NULL-terminated strings --- */ + case DEVINFO_STR_NAME: strcpy(info->s, "SH-3"); break; + case DEVINFO_STR_FAMILY: strcpy(info->s, "Hitachi SH7700"); break; + + case DEVINFO_PTR_INTERNAL_MEMORY_MAP + AS_PROGRAM: info->internal_map64 = ADDRESS_MAP_NAME(sh3_internal_map); break; + + default: CPU_GET_INFO_CALL(sh4); break; + } +} + +CPU_GET_INFO( sh3be ) +{ + switch (state) + { + /* --- the following bits of info are returned as pointers to data or functions --- */ + case CPUINFO_FCT_RESET: info->reset = CPU_RESET_NAME(sh3); break; + case CPUINFO_FCT_EXECUTE: info->execute = CPU_EXECUTE_NAME(sh4be); break; + case CPUINFO_FCT_DISASSEMBLE: info->disassemble = CPU_DISASSEMBLE_NAME(sh4be); break; + + /* --- the following bits of info are returned as NULL-terminated strings --- */ + case DEVINFO_STR_NAME: strcpy(info->s, "SH-3"); break; + case DEVINFO_STR_FAMILY: strcpy(info->s, "Hitachi SH7700"); break; + + case DEVINFO_PTR_INTERNAL_MEMORY_MAP + AS_PROGRAM: info->internal_map64 = ADDRESS_MAP_NAME(sh3_internal_map); break; + + case DEVINFO_INT_ENDIANNESS: info->i = ENDIANNESS_BIG; break; + + default: CPU_GET_INFO_CALL(sh4); break; + } +} + +CPU_GET_INFO( sh4be ) +{ + switch (state) + { + case CPUINFO_FCT_EXECUTE: info->execute = CPU_EXECUTE_NAME(sh4be); break; + case CPUINFO_FCT_DISASSEMBLE: info->disassemble = CPU_DISASSEMBLE_NAME(sh4be); break; + case DEVINFO_INT_ENDIANNESS: info->i = ENDIANNESS_BIG; break; + default: CPU_GET_INFO_CALL(sh4); break; + } +} + +DEFINE_LEGACY_CPU_DEVICE(SH3LE, sh3); +DEFINE_LEGACY_CPU_DEVICE(SH3BE, sh3be); +DEFINE_LEGACY_CPU_DEVICE(SH4LE, sh4); +DEFINE_LEGACY_CPU_DEVICE(SH4BE, sh4be); + +#endif // USE_SH4DRC |