/* Copyright 2003-2005 Guillaume Duhamel Copyright 2004-2007 Theo Berkau Copyright 2005 Fabien Coulon This file is part of Yabause. Yabause is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. Yabause is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Yabause; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ // SH2 Interpreter Core #include "sh2core.h" #include "sh2int.h" #include "sh2idle.h" #include "cs0.h" #include "debug.h" #include "error.h" #include "memory.h" #include "bios.h" #include "yabause.h" // #define SH2_TRACE // Uncomment to enable tracing #ifdef SH2_TRACE # include "sh2trace.h" # define MappedMemoryWriteByte(a,v) do { \ uint32_t __a = (a), __v = (v); \ sh2_trace_writeb(__a, __v); \ MappedMemoryWriteByte(__a, __v); \ } while (0) # define MappedMemoryWriteWord(a,v) do { \ uint32_t __a = (a), __v = (v); \ sh2_trace_writew(__a, __v); \ MappedMemoryWriteWord(__a, __v); \ } while (0) # define MappedMemoryWriteLong(a,v) do { \ uint32_t __a = (a), __v = (v); \ sh2_trace_writel(__a, __v); \ MappedMemoryWriteLong(__a, __v); \ } while (0) #endif opcodefunc opcodes[0x10000]; SH2Interface_struct SH2Interpreter = { SH2CORE_INTERPRETER, "SH2 Interpreter", SH2InterpreterInit, SH2InterpreterDeInit, SH2InterpreterReset, SH2InterpreterExec, SH2InterpreterGetRegisters, SH2InterpreterGetGPR, SH2InterpreterGetSR, SH2InterpreterGetGBR, SH2InterpreterGetVBR, SH2InterpreterGetMACH, SH2InterpreterGetMACL, SH2InterpreterGetPR, SH2InterpreterGetPC, SH2InterpreterSetRegisters, SH2InterpreterSetGPR, SH2InterpreterSetSR, SH2InterpreterSetGBR, SH2InterpreterSetVBR, SH2InterpreterSetMACH, SH2InterpreterSetMACL, SH2InterpreterSetPR, SH2InterpreterSetPC, SH2InterpreterSendInterrupt, SH2InterpreterGetInterrupts, SH2InterpreterSetInterrupts, NULL // SH2WriteNotify not used }; SH2Interface_struct SH2DebugInterpreter = { SH2CORE_DEBUGINTERPRETER, "SH2 Debugger Interpreter", SH2DebugInterpreterInit, SH2InterpreterDeInit, SH2InterpreterReset, SH2DebugInterpreterExec, SH2InterpreterGetRegisters, SH2InterpreterGetGPR, SH2InterpreterGetSR, SH2InterpreterGetGBR, SH2InterpreterGetVBR, SH2InterpreterGetMACH, SH2InterpreterGetMACL, SH2InterpreterGetPR, SH2InterpreterGetPC, SH2InterpreterSetRegisters, SH2InterpreterSetGPR, SH2InterpreterSetSR, SH2InterpreterSetGBR, SH2InterpreterSetVBR, SH2InterpreterSetMACH, SH2InterpreterSetMACL, SH2InterpreterSetPR, SH2InterpreterSetPC, SH2InterpreterSendInterrupt, SH2InterpreterGetInterrupts, SH2InterpreterSetInterrupts, NULL // SH2WriteNotify not used }; fetchfunc fetchlist[0x100]; ////////////////////////////////////////////////////////////////////////////// static u32 FASTCALL FetchBios(u32 addr) { return T2ReadWord(BiosRom, addr & 0x7FFFF); } ////////////////////////////////////////////////////////////////////////////// static u32 FASTCALL FetchCs0(u32 addr) { return CartridgeArea->Cs0ReadWord(addr); } ////////////////////////////////////////////////////////////////////////////// static u32 FASTCALL FetchLWram(u32 addr) { return T2ReadWord(LowWram, addr & 0xFFFFF); } ////////////////////////////////////////////////////////////////////////////// static u32 FASTCALL FetchHWram(u32 addr) { return T2ReadWord(HighWram, addr & 0xFFFFF); } ////////////////////////////////////////////////////////////////////////////// static u32 FASTCALL FetchInvalid(UNUSED u32 addr) { return 0xFFFF; } ////////////////////////////////////////////////////////////////////////////// static void FASTCALL SH2delay(SH2_struct * sh, u32 addr) { #ifdef SH2_TRACE sh2_trace(sh, addr); #endif // Fetch Instruction #ifdef EXEC_FROM_CACHE if ((addr & 0xC0000000) == 0xC0000000) sh->instruction = DataArrayReadWord(addr); else #endif sh->instruction = fetchlist[(addr >> 20) & 0x0FF](addr); // Execute it opcodes[sh->instruction](sh); sh->regs.PC -= 2; } ////////////////////////////////////////////////////////////////////////////// static void FASTCALL SH2undecoded(SH2_struct * sh) { int vectnum; if (yabsys.emulatebios) { if (BiosHandleFunc(sh)) return; } YabSetError(YAB_ERR_SH2INVALIDOPCODE, sh); // Save regs.SR on stack sh->regs.R[15]-=4; MappedMemoryWriteLong(sh->regs.R[15],sh->regs.SR.all); // Save regs.PC on stack sh->regs.R[15]-=4; MappedMemoryWriteLong(sh->regs.R[15],sh->regs.PC + 2); // What caused the exception? The delay slot or a general instruction? // 4 for General Instructions, 6 for delay slot vectnum = 4; // Fix me // Jump to Exception service routine sh->regs.PC = MappedMemoryReadLong(sh->regs.VBR+(vectnum<<2)); sh->cycles++; } ////////////////////////////////////////////////////////////////////////////// static void FASTCALL SH2add(SH2_struct * sh) { sh->regs.R[INSTRUCTION_B(sh->instruction)] += sh->regs.R[INSTRUCTION_C(sh->instruction)]; sh->regs.PC += 2; sh->cycles++; } ////////////////////////////////////////////////////////////////////////////// static void FASTCALL SH2addi(SH2_struct * sh) { s32 cd = (s32)(s8)INSTRUCTION_CD(sh->instruction); s32 b = INSTRUCTION_B(sh->instruction); sh->regs.R[b] += cd; sh->regs.PC += 2; sh->cycles++; } ////////////////////////////////////////////////////////////////////////////// static void FASTCALL SH2addc(SH2_struct * sh) { u32 tmp0, tmp1; s32 source = INSTRUCTION_C(sh->instruction); s32 dest = INSTRUCTION_B(sh->instruction); tmp1 = sh->regs.R[source] + sh->regs.R[dest]; tmp0 = sh->regs.R[dest]; sh->regs.R[dest] = tmp1 + sh->regs.SR.part.T; if (tmp0 > tmp1) sh->regs.SR.part.T = 1; else sh->regs.SR.part.T = 0; if (tmp1 > sh->regs.R[dest]) sh->regs.SR.part.T = 1; sh->regs.PC += 2; sh->cycles++; } ////////////////////////////////////////////////////////////////////////////// static void FASTCALL SH2addv(SH2_struct * sh) { s32 dest,src,ans; s32 n = INSTRUCTION_B(sh->instruction); s32 m = INSTRUCTION_C(sh->instruction); if ((s32) sh->regs.R[n] >= 0) dest = 0; else dest = 1; if ((s32) sh->regs.R[m] >= 0) src = 0; else src = 1; src += dest; sh->regs.R[n] += sh->regs.R[m]; if ((s32) sh->regs.R[n] >= 0) ans = 0; else ans = 1; ans += dest; if (src == 0 || src == 2) if (ans == 1) sh->regs.SR.part.T = 1; else sh->regs.SR.part.T = 0; else sh->regs.SR.part.T = 0; sh->regs.PC += 2; sh->cycles++; } ////////////////////////////////////////////////////////////////////////////// static void FASTCALL SH2y_and(SH2_struct * sh) { sh->regs.R[INSTRUCTION_B(sh->instruction)] &= sh->regs.R[INSTRUCTION_C(sh->instruction)]; sh->regs.PC += 2; sh->cycles++; } ////////////////////////////////////////////////////////////////////////////// static void FASTCALL SH2andi(SH2_struct * sh) { sh->regs.R[0] &= INSTRUCTION_CD(sh->instruction); sh->regs.PC += 2; sh->cycles++; } ////////////////////////////////////////////////////////////////////////////// static void FASTCALL SH2andm(SH2_struct * sh) { s32 temp; s32 source = INSTRUCTION_CD(sh->instruction); temp = (s32) MappedMemoryReadByte(sh->regs.GBR + sh->regs.R[0]); temp &= source; MappedMemoryWriteByte((sh->regs.GBR + sh->regs.R[0]),temp); sh->regs.PC += 2; sh->cycles += 3; } ////////////////////////////////////////////////////////////////////////////// static void FASTCALL SH2bf(SH2_struct * sh) { if (sh->regs.SR.part.T == 0) { s32 disp = (s32)(s8)sh->instruction; sh->regs.PC = sh->regs.PC+(disp<<1)+4; sh->cycles += 3; } else { sh->regs.PC+=2; sh->cycles++; } } ////////////////////////////////////////////////////////////////////////////// static void FASTCALL SH2bfs(SH2_struct * sh) { if (sh->regs.SR.part.T == 0) { s32 disp = (s32)(s8)sh->instruction; u32 temp = sh->regs.PC; sh->regs.PC = sh->regs.PC + (disp << 1) + 4; sh->cycles += 2; SH2delay(sh, temp + 2); } else { sh->regs.PC += 2; sh->cycles++; } } ////////////////////////////////////////////////////////////////////////////// static void FASTCALL SH2bra(SH2_struct * sh) { s32 disp = INSTRUCTION_BCD(sh->instruction); u32 temp = sh->regs.PC; if ((disp&0x800) != 0) disp |= 0xFFFFF000; sh->regs.PC = sh->regs.PC + (disp<<1) + 4; sh->cycles += 2; SH2delay(sh, temp + 2); } ////////////////////////////////////////////////////////////////////////////// static void FASTCALL SH2braf(SH2_struct * sh) { u32 temp; s32 m = INSTRUCTION_B(sh->instruction); temp = sh->regs.PC; sh->regs.PC += sh->regs.R[m] + 4; sh->cycles += 2; SH2delay(sh, temp + 2); } ////////////////////////////////////////////////////////////////////////////// static void FASTCALL SH2bsr(SH2_struct * sh) { u32 temp; s32 disp = INSTRUCTION_BCD(sh->instruction); temp = sh->regs.PC; if ((disp&0x800) != 0) disp |= 0xFFFFF000; sh->regs.PR = sh->regs.PC + 4; sh->regs.PC = sh->regs.PC+(disp<<1) + 4; sh->cycles += 2; SH2delay(sh, temp + 2); } ////////////////////////////////////////////////////////////////////////////// static void FASTCALL SH2bsrf(SH2_struct * sh) { u32 temp = sh->regs.PC; sh->regs.PR = sh->regs.PC + 4; sh->regs.PC += sh->regs.R[INSTRUCTION_B(sh->instruction)] + 4; sh->cycles += 2; SH2delay(sh, temp + 2); } ////////////////////////////////////////////////////////////////////////////// static void FASTCALL SH2bt(SH2_struct * sh) { if (sh->regs.SR.part.T == 1) { s32 disp = (s32)(s8)sh->instruction; sh->regs.PC = sh->regs.PC+(disp<<1)+4; sh->cycles += 3; } else { sh->regs.PC += 2; sh->cycles++; } } ////////////////////////////////////////////////////////////////////////////// static void FASTCALL SH2bts(SH2_struct * sh) { if (sh->regs.SR.part.T) { s32 disp = (s32)(s8)sh->instruction; u32 temp = sh->regs.PC; sh->regs.PC += (disp << 1) + 4; sh->cycles += 2; SH2delay(sh, temp + 2); } else { sh->regs.PC+=2; sh->cycles++; } } ////////////////////////////////////////////////////////////////////////////// static void FASTCALL SH2clrmac(SH2_struct * sh) { sh->regs.MACH = 0; sh->regs.MACL = 0; sh->regs.PC += 2; sh->cycles++; } ////////////////////////////////////////////////////////////////////////////// static void FASTCALL SH2clrt(SH2_struct * sh) { sh->regs.SR.part.T = 0; sh->regs.PC += 2; sh->cycles++; } ////////////////////////////////////////////////////////////////////////////// static void FASTCALL SH2cmpeq(SH2_struct * sh) { if (sh->regs.R[INSTRUCTION_B(sh->instruction)] == sh->regs.R[INSTRUCTION_C(sh->instruction)]) sh->regs.SR.part.T = 1; else sh->regs.SR.part.T = 0; sh->regs.PC += 2; sh->cycles++; } ////////////////////////////////////////////////////////////////////////////// static void FASTCALL SH2cmpge(SH2_struct * sh) { if ((s32)sh->regs.R[INSTRUCTION_B(sh->instruction)] >= (s32)sh->regs.R[INSTRUCTION_C(sh->instruction)]) sh->regs.SR.part.T = 1; else sh->regs.SR.part.T = 0; sh->regs.PC += 2; sh->cycles++; } ////////////////////////////////////////////////////////////////////////////// static void FASTCALL SH2cmpgt(SH2_struct * sh) { if ((s32)sh->regs.R[INSTRUCTION_B(sh->instruction)]>(s32)sh->regs.R[INSTRUCTION_C(sh->instruction)]) sh->regs.SR.part.T = 1; else sh->regs.SR.part.T = 0; sh->regs.PC+=2; sh->cycles++; } ////////////////////////////////////////////////////////////////////////////// static void FASTCALL SH2cmphi(SH2_struct * sh) { if ((u32)sh->regs.R[INSTRUCTION_B(sh->instruction)] > (u32)sh->regs.R[INSTRUCTION_C(sh->instruction)]) sh->regs.SR.part.T = 1; else sh->regs.SR.part.T = 0; sh->regs.PC+=2; sh->cycles++; } ////////////////////////////////////////////////////////////////////////////// static void FASTCALL SH2cmphs(SH2_struct * sh) { if ((u32)sh->regs.R[INSTRUCTION_B(sh->instruction)] >= (u32)sh->regs.R[INSTRUCTION_C(sh->instruction)]) sh->regs.SR.part.T = 1; else sh->regs.SR.part.T = 0; sh->regs.PC+=2; sh->cycles++; } ////////////////////////////////////////////////////////////////////////////// static void FASTCALL SH2cmpim(SH2_struct * sh) { s32 imm; s32 i = INSTRUCTION_CD(sh->instruction); imm = (s32)(s8)i; if (sh->regs.R[0] == (u32) imm) // FIXME: ouais � doit �re bon... sh->regs.SR.part.T = 1; else sh->regs.SR.part.T = 0; sh->regs.PC+=2; sh->cycles++; } ////////////////////////////////////////////////////////////////////////////// static void FASTCALL SH2cmppl(SH2_struct * sh) { if ((s32)sh->regs.R[INSTRUCTION_B(sh->instruction)]>0) sh->regs.SR.part.T = 1; else sh->regs.SR.part.T = 0; sh->regs.PC+=2; sh->cycles++; } ////////////////////////////////////////////////////////////////////////////// static void FASTCALL SH2cmppz(SH2_struct * sh) { if ((s32)sh->regs.R[INSTRUCTION_B(sh->instruction)]>=0) sh->regs.SR.part.T = 1; else sh->regs.SR.part.T = 0; sh->regs.PC+=2; sh->cycles++; } ////////////////////////////////////////////////////////////////////////////// static void FASTCALL SH2cmpstr(SH2_struct * sh) { u32 temp; s32 HH,HL,LH,LL; s32 m = INSTRUCTION_C(sh->instruction); s32 n = INSTRUCTION_B(sh->instruction); temp=sh->regs.R[n]^sh->regs.R[m]; HH = (temp>>24) & 0x000000FF; HL = (temp>>16) & 0x000000FF; LH = (temp>>8) & 0x000000FF; LL = temp & 0x000000FF; HH = HH && HL && LH && LL; if (HH == 0) sh->regs.SR.part.T = 1; else sh->regs.SR.part.T = 0; sh->regs.PC+=2; sh->cycles++; } ////////////////////////////////////////////////////////////////////////////// static void FASTCALL SH2div0s(SH2_struct * sh) { s32 m = INSTRUCTION_C(sh->instruction); s32 n = INSTRUCTION_B(sh->instruction); if ((sh->regs.R[n]&0x80000000)==0) sh->regs.SR.part.Q = 0; else sh->regs.SR.part.Q = 1; if ((sh->regs.R[m]&0x80000000)==0) sh->regs.SR.part.M = 0; else sh->regs.SR.part.M = 1; sh->regs.SR.part.T = !(sh->regs.SR.part.M == sh->regs.SR.part.Q); sh->regs.PC += 2; sh->cycles++; } ////////////////////////////////////////////////////////////////////////////// static void FASTCALL SH2div0u(SH2_struct * sh) { sh->regs.SR.part.M = sh->regs.SR.part.Q = sh->regs.SR.part.T = 0; sh->regs.PC += 2; sh->cycles++; } ////////////////////////////////////////////////////////////////////////////// static void FASTCALL SH2div1(SH2_struct * sh) { u32 tmp0; u8 old_q, tmp1; s32 m = INSTRUCTION_C(sh->instruction); s32 n = INSTRUCTION_B(sh->instruction); old_q = sh->regs.SR.part.Q; sh->regs.SR.part.Q = (u8)((0x80000000 & sh->regs.R[n])!=0); sh->regs.R[n] <<= 1; sh->regs.R[n]|=(u32) sh->regs.SR.part.T; switch(old_q) { case 0: switch(sh->regs.SR.part.M) { case 0: tmp0 = sh->regs.R[n]; sh->regs.R[n] -= sh->regs.R[m]; tmp1 = (sh->regs.R[n] > tmp0); switch(sh->regs.SR.part.Q) { case 0: sh->regs.SR.part.Q = tmp1; break; case 1: sh->regs.SR.part.Q = (u8) (tmp1 == 0); break; } break; case 1: tmp0 = sh->regs.R[n]; sh->regs.R[n] += sh->regs.R[m]; tmp1 = (sh->regs.R[n] < tmp0); switch(sh->regs.SR.part.Q) { case 0: sh->regs.SR.part.Q = (u8) (tmp1 == 0); break; case 1: sh->regs.SR.part.Q = tmp1; break; } break; } break; case 1: switch(sh->regs.SR.part.M) { case 0: tmp0 = sh->regs.R[n]; sh->regs.R[n] += sh->regs.R[m]; tmp1 = (sh->regs.R[n] < tmp0); switch(sh->regs.SR.part.Q) { case 0: sh->regs.SR.part.Q = tmp1; break; case 1: sh->regs.SR.part.Q = (u8) (tmp1 == 0); break; } break; case 1: tmp0 = sh->regs.R[n]; sh->regs.R[n] -= sh->regs.R[m]; tmp1 = (sh->regs.R[n] > tmp0); switch(sh->regs.SR.part.Q) { case 0: sh->regs.SR.part.Q = (u8) (tmp1 == 0); break; case 1: sh->regs.SR.part.Q = tmp1; break; } break; } break; } sh->regs.SR.part.T = (sh->regs.SR.part.Q == sh->regs.SR.part.M); sh->regs.PC += 2; sh->cycles++; } ////////////////////////////////////////////////////////////////////////////// static void FASTCALL SH2dmuls(SH2_struct * sh) { u32 RnL,RnH,RmL,RmH,Res0,Res1,Res2; u32 temp0,temp1,temp2,temp3; s32 tempm,tempn,fnLmL; s32 m = INSTRUCTION_C(sh->instruction); s32 n = INSTRUCTION_B(sh->instruction); tempn = (s32)sh->regs.R[n]; tempm = (s32)sh->regs.R[m]; if (tempn < 0) tempn = 0 - tempn; if (tempm < 0) tempm = 0 - tempm; if ((s32) (sh->regs.R[n] ^ sh->regs.R[m]) < 0) fnLmL = -1; else fnLmL = 0; temp1 = (u32) tempn; temp2 = (u32) 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; } sh->regs.MACH = Res2; sh->regs.MACL = Res0; sh->regs.PC += 2; sh->cycles += 2; } ////////////////////////////////////////////////////////////////////////////// static void FASTCALL SH2dmulu(SH2_struct * sh) { u32 RnL,RnH,RmL,RmH,Res0,Res1,Res2; u32 temp0,temp1,temp2,temp3; s32 m = INSTRUCTION_C(sh->instruction); s32 n = INSTRUCTION_B(sh->instruction); RnL = sh->regs.R[n] & 0x0000FFFF; RnH = (sh->regs.R[n] >> 16) & 0x0000FFFF; RmL = sh->regs.R[m] & 0x0000FFFF; RmH = (sh->regs.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; sh->regs.MACH = Res2; sh->regs.MACL = Res0; sh->regs.PC += 2; sh->cycles += 2; } ////////////////////////////////////////////////////////////////////////////// static void FASTCALL SH2dt(SH2_struct * sh) { s32 n = INSTRUCTION_B(sh->instruction); sh->regs.R[n]--; if (sh->regs.R[n] == 0) sh->regs.SR.part.T = 1; else sh->regs.SR.part.T = 0; sh->regs.PC += 2; sh->cycles++; } ////////////////////////////////////////////////////////////////////////////// static void FASTCALL SH2extsb(SH2_struct * sh) { s32 m = INSTRUCTION_C(sh->instruction); s32 n = INSTRUCTION_B(sh->instruction); sh->regs.R[n] = (u32)(s8)sh->regs.R[m]; sh->regs.PC += 2; sh->cycles++; } ////////////////////////////////////////////////////////////////////////////// static void FASTCALL SH2extsw(SH2_struct * sh) { s32 m = INSTRUCTION_C(sh->instruction); s32 n = INSTRUCTION_B(sh->instruction); sh->regs.R[n] = (u32)(s16)sh->regs.R[m]; sh->regs.PC += 2; sh->cycles++; } ////////////////////////////////////////////////////////////////////////////// static void FASTCALL SH2extub(SH2_struct * sh) { s32 m = INSTRUCTION_C(sh->instruction); s32 n = INSTRUCTION_B(sh->instruction); sh->regs.R[n] = (u32)(u8)sh->regs.R[m]; sh->regs.PC += 2; sh->cycles++; } ////////////////////////////////////////////////////////////////////////////// static void FASTCALL SH2extuw(SH2_struct * sh) { s32 m = INSTRUCTION_C(sh->instruction); s32 n = INSTRUCTION_B(sh->instruction); sh->regs.R[n] = (u32)(u16)sh->regs.R[m]; sh->regs.PC += 2; sh->cycles++; } ////////////////////////////////////////////////////////////////////////////// static void FASTCALL SH2jmp(SH2_struct * sh) { u32 temp; s32 m = INSTRUCTION_B(sh->instruction); temp=sh->regs.PC; sh->regs.PC = sh->regs.R[m]; sh->cycles += 2; SH2delay(sh, temp + 2); } ////////////////////////////////////////////////////////////////////////////// static void FASTCALL SH2jsr(SH2_struct * sh) { u32 temp; s32 m = INSTRUCTION_B(sh->instruction); temp = sh->regs.PC; sh->regs.PR = sh->regs.PC + 4; sh->regs.PC = sh->regs.R[m]; sh->cycles += 2; SH2delay(sh, temp + 2); } ////////////////////////////////////////////////////////////////////////////// static void FASTCALL SH2ldcgbr(SH2_struct * sh) { sh->regs.GBR = sh->regs.R[INSTRUCTION_B(sh->instruction)]; sh->regs.PC += 2; sh->cycles++; } ////////////////////////////////////////////////////////////////////////////// static void FASTCALL SH2ldcmgbr(SH2_struct * sh) { s32 m = INSTRUCTION_B(sh->instruction); sh->regs.GBR = MappedMemoryReadLong(sh->regs.R[m]); sh->regs.R[m] += 4; sh->regs.PC += 2; sh->cycles += 3; } ////////////////////////////////////////////////////////////////////////////// static void FASTCALL SH2ldcmsr(SH2_struct * sh) { s32 m = INSTRUCTION_B(sh->instruction); sh->regs.SR.all = MappedMemoryReadLong(sh->regs.R[m]) & 0x000003F3; sh->regs.R[m] += 4; sh->regs.PC += 2; sh->cycles += 3; } ////////////////////////////////////////////////////////////////////////////// static void FASTCALL SH2ldcmvbr(SH2_struct * sh) { s32 m = INSTRUCTION_B(sh->instruction); sh->regs.VBR = MappedMemoryReadLong(sh->regs.R[m]); sh->regs.R[m] += 4; sh->regs.PC += 2; sh->cycles += 3; } ////////////////////////////////////////////////////////////////////////////// static void FASTCALL SH2ldcsr(SH2_struct * sh) { sh->regs.SR.all = sh->regs.R[INSTRUCTION_B(sh->instruction)]&0x000003F3; sh->regs.PC += 2; sh->cycles++; } ////////////////////////////////////////////////////////////////////////////// static void FASTCALL SH2ldcvbr(SH2_struct * sh) { s32 m = INSTRUCTION_B(sh->instruction); sh->regs.VBR = sh->regs.R[m]; sh->regs.PC += 2; sh->cycles++; } ////////////////////////////////////////////////////////////////////////////// static void FASTCALL SH2ldsmach(SH2_struct * sh) { sh->regs.MACH = sh->regs.R[INSTRUCTION_B(sh->instruction)]; sh->regs.PC+=2; sh->cycles++; } ////////////////////////////////////////////////////////////////////////////// static void FASTCALL SH2ldsmacl(SH2_struct * sh) { sh->regs.MACL = sh->regs.R[INSTRUCTION_B(sh->instruction)]; sh->regs.PC += 2; sh->cycles++; } ////////////////////////////////////////////////////////////////////////////// static void FASTCALL SH2ldsmmach(SH2_struct * sh) { s32 m = INSTRUCTION_B(sh->instruction); sh->regs.MACH = MappedMemoryReadLong(sh->regs.R[m]); sh->regs.R[m] += 4; sh->regs.PC += 2; sh->cycles++; } ////////////////////////////////////////////////////////////////////////////// static void FASTCALL SH2ldsmmacl(SH2_struct * sh) { s32 m = INSTRUCTION_B(sh->instruction); sh->regs.MACL = MappedMemoryReadLong(sh->regs.R[m]); sh->regs.R[m] += 4; sh->regs.PC += 2; sh->cycles++; } ////////////////////////////////////////////////////////////////////////////// static void FASTCALL SH2ldsmpr(SH2_struct * sh) { s32 m = INSTRUCTION_B(sh->instruction); sh->regs.PR = MappedMemoryReadLong(sh->regs.R[m]); sh->regs.R[m] += 4; sh->regs.PC += 2; sh->cycles++; } ////////////////////////////////////////////////////////////////////////////// static void FASTCALL SH2ldspr(SH2_struct * sh) { sh->regs.PR = sh->regs.R[INSTRUCTION_B(sh->instruction)]; sh->regs.PC += 2; sh->cycles++; } ////////////////////////////////////////////////////////////////////////////// static void FASTCALL SH2macl(SH2_struct * sh) { u32 RnL,RnH,RmL,RmH,Res0,Res1,Res2; u32 temp0,temp1,temp2,temp3; s32 tempm,tempn,fnLmL; s32 m = INSTRUCTION_C(sh->instruction); s32 n = INSTRUCTION_B(sh->instruction); tempn = (s32) MappedMemoryReadLong(sh->regs.R[n]); sh->regs.R[n] += 4; tempm = (s32) MappedMemoryReadLong(sh->regs.R[m]); sh->regs.R[m] += 4; if ((s32) (tempn^tempm) < 0) fnLmL = -1; else fnLmL = 0; if (tempn < 0) tempn = 0 - tempn; if (tempm < 0) tempm = 0 - tempm; temp1 = (u32) tempn; temp2 = (u32) 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(sh->regs.SR.part.S == 1) { Res0=sh->regs.MACL+Res0; if (sh->regs.MACL>Res0) Res2++; if (sh->regs.MACH & 0x00008000); else Res2 += sh->regs.MACH | 0xFFFF0000; Res2+=(sh->regs.MACH&0x0000FFFF); if(((s32)Res2<0)&&(Res2<0xFFFF8000)) { Res2=0x00008000; Res0=0x00000000; } if(((s32)Res2>0)&&(Res2>0x00007FFF)) { Res2=0x00007FFF; Res0=0xFFFFFFFF; }; sh->regs.MACH=Res2; sh->regs.MACL=Res0; } else { Res0=sh->regs.MACL+Res0; if (sh->regs.MACL>Res0) Res2++; Res2+=sh->regs.MACH; sh->regs.MACH=Res2; sh->regs.MACL=Res0; } sh->regs.PC+=2; sh->cycles += 3; } ////////////////////////////////////////////////////////////////////////////// static void FASTCALL SH2macw(SH2_struct * sh) { s32 tempm,tempn,dest,src,ans; u32 templ; s32 m = INSTRUCTION_C(sh->instruction); s32 n = INSTRUCTION_B(sh->instruction); tempn=(s32) MappedMemoryReadWord(sh->regs.R[n]); sh->regs.R[n]+=2; tempm=(s32) MappedMemoryReadWord(sh->regs.R[m]); sh->regs.R[m]+=2; templ=sh->regs.MACL; tempm=((s32)(s16)tempn*(s32)(s16)tempm); if ((s32)sh->regs.MACL>=0) dest=0; else dest=1; if ((s32)tempm>=0) { src=0; tempn=0; } else { src=1; tempn=0xFFFFFFFF; } src+=dest; sh->regs.MACL+=tempm; if ((s32)sh->regs.MACL>=0) ans=0; else ans=1; ans+=dest; if (sh->regs.SR.part.S == 1) { if (ans==1) { if (src==0) sh->regs.MACL=0x7FFFFFFF; if (src==2) sh->regs.MACL=0x80000000; } } else { sh->regs.MACH+=tempn; if (templ>sh->regs.MACL) sh->regs.MACH+=1; } sh->regs.PC+=2; sh->cycles += 3; } ////////////////////////////////////////////////////////////////////////////// static void FASTCALL SH2mov(SH2_struct * sh) { sh->regs.R[INSTRUCTION_B(sh->instruction)]=sh->regs.R[INSTRUCTION_C(sh->instruction)]; sh->regs.PC+=2; sh->cycles++; } ////////////////////////////////////////////////////////////////////////////// static void FASTCALL SH2mova(SH2_struct * sh) { s32 disp = INSTRUCTION_CD(sh->instruction); sh->regs.R[0]=((sh->regs.PC+4)&0xFFFFFFFC)+(disp<<2); sh->regs.PC+=2; sh->cycles++; } ////////////////////////////////////////////////////////////////////////////// static void FASTCALL SH2movbl(SH2_struct * sh) { s32 m = INSTRUCTION_C(sh->instruction); s32 n = INSTRUCTION_B(sh->instruction); sh->regs.R[n] = (s32)(s8)MappedMemoryReadByte(sh->regs.R[m]); sh->regs.PC += 2; sh->cycles++; } ////////////////////////////////////////////////////////////////////////////// static void FASTCALL SH2movbl0(SH2_struct * sh) { s32 m = INSTRUCTION_C(sh->instruction); s32 n = INSTRUCTION_B(sh->instruction); sh->regs.R[n] = (s32)(s8)MappedMemoryReadByte(sh->regs.R[m] + sh->regs.R[0]); sh->regs.PC += 2; sh->cycles++; } ////////////////////////////////////////////////////////////////////////////// static void FASTCALL SH2movbl4(SH2_struct * sh) { s32 m = INSTRUCTION_C(sh->instruction); s32 disp = INSTRUCTION_D(sh->instruction); sh->regs.R[0] = (s32)(s8)MappedMemoryReadByte(sh->regs.R[m] + disp); sh->regs.PC+=2; sh->cycles++; } ////////////////////////////////////////////////////////////////////////////// static void FASTCALL SH2movblg(SH2_struct * sh) { s32 disp = INSTRUCTION_CD(sh->instruction); sh->regs.R[0] = (s32)(s8)MappedMemoryReadByte(sh->regs.GBR + disp); sh->regs.PC+=2; sh->cycles++; } ////////////////////////////////////////////////////////////////////////////// static void FASTCALL SH2movbm(SH2_struct * sh) { s32 m = INSTRUCTION_C(sh->instruction); s32 n = INSTRUCTION_B(sh->instruction); MappedMemoryWriteByte((sh->regs.R[n] - 1),sh->regs.R[m]); sh->regs.R[n] -= 1; sh->regs.PC += 2; sh->cycles++; } ////////////////////////////////////////////////////////////////////////////// static void FASTCALL SH2movbp(SH2_struct * sh) { s32 m = INSTRUCTION_C(sh->instruction); s32 n = INSTRUCTION_B(sh->instruction); sh->regs.R[n] = (s32)(s8)MappedMemoryReadByte(sh->regs.R[m]); if (n != m) sh->regs.R[m] += 1; sh->regs.PC += 2; sh->cycles++; } ////////////////////////////////////////////////////////////////////////////// static void FASTCALL SH2movbs(SH2_struct * sh) { int b = INSTRUCTION_B(sh->instruction); int c = INSTRUCTION_C(sh->instruction); MappedMemoryWriteByte(sh->regs.R[b], sh->regs.R[c]); sh->regs.PC += 2; sh->cycles++; } ////////////////////////////////////////////////////////////////////////////// static void FASTCALL SH2movbs0(SH2_struct * sh) { MappedMemoryWriteByte(sh->regs.R[INSTRUCTION_B(sh->instruction)] + sh->regs.R[0], sh->regs.R[INSTRUCTION_C(sh->instruction)]); sh->regs.PC += 2; sh->cycles++; } ////////////////////////////////////////////////////////////////////////////// static void FASTCALL SH2movbs4(SH2_struct * sh) { s32 disp = INSTRUCTION_D(sh->instruction); s32 n = INSTRUCTION_C(sh->instruction); MappedMemoryWriteByte(sh->regs.R[n]+disp,sh->regs.R[0]); sh->regs.PC+=2; sh->cycles++; } ////////////////////////////////////////////////////////////////////////////// static void FASTCALL SH2movbsg(SH2_struct * sh) { s32 disp = INSTRUCTION_CD(sh->instruction); MappedMemoryWriteByte(sh->regs.GBR + disp,sh->regs.R[0]); sh->regs.PC += 2; sh->cycles++; } ////////////////////////////////////////////////////////////////////////////// static void FASTCALL SH2movi(SH2_struct * sh) { s32 i = INSTRUCTION_CD(sh->instruction); s32 n = INSTRUCTION_B(sh->instruction); sh->regs.R[n] = (s32)(s8)i; sh->regs.PC += 2; sh->cycles++; } ////////////////////////////////////////////////////////////////////////////// static void FASTCALL SH2movli(SH2_struct * sh) { s32 disp = INSTRUCTION_CD(sh->instruction); s32 n = INSTRUCTION_B(sh->instruction); sh->regs.R[n] = MappedMemoryReadLong(((sh->regs.PC + 4) & 0xFFFFFFFC) + (disp << 2)); sh->regs.PC += 2; sh->cycles++; } ////////////////////////////////////////////////////////////////////////////// static void FASTCALL SH2movll(SH2_struct * sh) { sh->regs.R[INSTRUCTION_B(sh->instruction)] = MappedMemoryReadLong(sh->regs.R[INSTRUCTION_C(sh->instruction)]); sh->regs.PC += 2; sh->cycles++; } ////////////////////////////////////////////////////////////////////////////// static void FASTCALL SH2movll0(SH2_struct * sh) { sh->regs.R[INSTRUCTION_B(sh->instruction)] = MappedMemoryReadLong(sh->regs.R[INSTRUCTION_C(sh->instruction)] + sh->regs.R[0]); sh->regs.PC += 2; sh->cycles++; } ////////////////////////////////////////////////////////////////////////////// static void FASTCALL SH2movll4(SH2_struct * sh) { s32 m = INSTRUCTION_C(sh->instruction); s32 disp = INSTRUCTION_D(sh->instruction); s32 n = INSTRUCTION_B(sh->instruction); sh->regs.R[n] = MappedMemoryReadLong(sh->regs.R[m] + (disp << 2)); sh->regs.PC += 2; sh->cycles++; } ////////////////////////////////////////////////////////////////////////////// static void FASTCALL SH2movllg(SH2_struct * sh) { s32 disp = INSTRUCTION_CD(sh->instruction); sh->regs.R[0] = MappedMemoryReadLong(sh->regs.GBR + (disp << 2)); sh->regs.PC+=2; sh->cycles++; } ////////////////////////////////////////////////////////////////////////////// static void FASTCALL SH2movlm(SH2_struct * sh) { s32 m = INSTRUCTION_C(sh->instruction); s32 n = INSTRUCTION_B(sh->instruction); MappedMemoryWriteLong(sh->regs.R[n] - 4,sh->regs.R[m]); sh->regs.R[n] -= 4; sh->regs.PC += 2; sh->cycles++; } ////////////////////////////////////////////////////////////////////////////// static void FASTCALL SH2movlp(SH2_struct * sh) { s32 m = INSTRUCTION_C(sh->instruction); s32 n = INSTRUCTION_B(sh->instruction); sh->regs.R[n] = MappedMemoryReadLong(sh->regs.R[m]); if (n != m) sh->regs.R[m] += 4; sh->regs.PC += 2; sh->cycles++; } ////////////////////////////////////////////////////////////////////////////// static void FASTCALL SH2movls(SH2_struct * sh) { int b = INSTRUCTION_B(sh->instruction); int c = INSTRUCTION_C(sh->instruction); MappedMemoryWriteLong(sh->regs.R[b], sh->regs.R[c]); sh->regs.PC += 2; sh->cycles++; } ////////////////////////////////////////////////////////////////////////////// static void FASTCALL SH2movls0(SH2_struct * sh) { MappedMemoryWriteLong(sh->regs.R[INSTRUCTION_B(sh->instruction)] + sh->regs.R[0], sh->regs.R[INSTRUCTION_C(sh->instruction)]); sh->regs.PC += 2; sh->cycles++; } ////////////////////////////////////////////////////////////////////////////// static void FASTCALL SH2movls4(SH2_struct * sh) { s32 m = INSTRUCTION_C(sh->instruction); s32 disp = INSTRUCTION_D(sh->instruction); s32 n = INSTRUCTION_B(sh->instruction); MappedMemoryWriteLong(sh->regs.R[n]+(disp<<2),sh->regs.R[m]); sh->regs.PC += 2; sh->cycles++; } ////////////////////////////////////////////////////////////////////////////// static void FASTCALL SH2movlsg(SH2_struct * sh) { s32 disp = INSTRUCTION_CD(sh->instruction); MappedMemoryWriteLong(sh->regs.GBR+(disp<<2),sh->regs.R[0]); sh->regs.PC+=2; sh->cycles++; } ////////////////////////////////////////////////////////////////////////////// static void FASTCALL SH2movt(SH2_struct * sh) { sh->regs.R[INSTRUCTION_B(sh->instruction)] = (0x00000001 & sh->regs.SR.all); sh->regs.PC += 2; sh->cycles++; } ////////////////////////////////////////////////////////////////////////////// static void FASTCALL SH2movwi(SH2_struct * sh) { s32 disp = INSTRUCTION_CD(sh->instruction); s32 n = INSTRUCTION_B(sh->instruction); sh->regs.R[n] = (s32)(s16)MappedMemoryReadWord(sh->regs.PC + (disp<<1) + 4); sh->regs.PC+=2; sh->cycles++; } ////////////////////////////////////////////////////////////////////////////// static void FASTCALL SH2movwl(SH2_struct * sh) { s32 m = INSTRUCTION_C(sh->instruction); s32 n = INSTRUCTION_B(sh->instruction); sh->regs.R[n] = (s32)(s16)MappedMemoryReadWord(sh->regs.R[m]); sh->regs.PC += 2; sh->cycles++; } ////////////////////////////////////////////////////////////////////////////// static void FASTCALL SH2movwl0(SH2_struct * sh) { s32 m = INSTRUCTION_C(sh->instruction); s32 n = INSTRUCTION_B(sh->instruction); sh->regs.R[n] = (s32)(s16)MappedMemoryReadWord(sh->regs.R[m]+sh->regs.R[0]); sh->regs.PC+=2; sh->cycles++; } ////////////////////////////////////////////////////////////////////////////// static void FASTCALL SH2movwl4(SH2_struct * sh) { s32 m = INSTRUCTION_C(sh->instruction); s32 disp = INSTRUCTION_D(sh->instruction); sh->regs.R[0] = (s32)(s16)MappedMemoryReadWord(sh->regs.R[m]+(disp<<1)); sh->regs.PC+=2; sh->cycles++; } ////////////////////////////////////////////////////////////////////////////// static void FASTCALL SH2movwlg(SH2_struct * sh) { s32 disp = INSTRUCTION_CD(sh->instruction); sh->regs.R[0] = (s32)(s16)MappedMemoryReadWord(sh->regs.GBR+(disp<<1)); sh->regs.PC += 2; sh->cycles++; } ////////////////////////////////////////////////////////////////////////////// static void FASTCALL SH2movwm(SH2_struct * sh) { s32 m = INSTRUCTION_C(sh->instruction); s32 n = INSTRUCTION_B(sh->instruction); MappedMemoryWriteWord(sh->regs.R[n] - 2,sh->regs.R[m]); sh->regs.R[n] -= 2; sh->regs.PC += 2; sh->cycles++; } ////////////////////////////////////////////////////////////////////////////// static void FASTCALL SH2movwp(SH2_struct * sh) { s32 m = INSTRUCTION_C(sh->instruction); s32 n = INSTRUCTION_B(sh->instruction); sh->regs.R[n] = (s32)(s16)MappedMemoryReadWord(sh->regs.R[m]); if (n != m) sh->regs.R[m] += 2; sh->regs.PC += 2; sh->cycles++; } ////////////////////////////////////////////////////////////////////////////// static void FASTCALL SH2movws(SH2_struct * sh) { s32 m = INSTRUCTION_C(sh->instruction); s32 n = INSTRUCTION_B(sh->instruction); MappedMemoryWriteWord(sh->regs.R[n],sh->regs.R[m]); sh->regs.PC += 2; sh->cycles++; } ////////////////////////////////////////////////////////////////////////////// static void FASTCALL SH2movws0(SH2_struct * sh) { MappedMemoryWriteWord(sh->regs.R[INSTRUCTION_B(sh->instruction)] + sh->regs.R[0], sh->regs.R[INSTRUCTION_C(sh->instruction)]); sh->regs.PC+=2; sh->cycles++; } ////////////////////////////////////////////////////////////////////////////// static void FASTCALL SH2movws4(SH2_struct * sh) { s32 disp = INSTRUCTION_D(sh->instruction); s32 n = INSTRUCTION_C(sh->instruction); MappedMemoryWriteWord(sh->regs.R[n]+(disp<<1),sh->regs.R[0]); sh->regs.PC+=2; sh->cycles++; } ////////////////////////////////////////////////////////////////////////////// static void FASTCALL SH2movwsg(SH2_struct * sh) { s32 disp = INSTRUCTION_CD(sh->instruction); MappedMemoryWriteWord(sh->regs.GBR+(disp<<1),sh->regs.R[0]); sh->regs.PC+=2; sh->cycles++; } ////////////////////////////////////////////////////////////////////////////// static void FASTCALL SH2mull(SH2_struct * sh) { s32 m = INSTRUCTION_C(sh->instruction); s32 n = INSTRUCTION_B(sh->instruction); sh->regs.MACL = sh->regs.R[n] * sh->regs.R[m]; sh->regs.PC+=2; sh->cycles += 2; } ////////////////////////////////////////////////////////////////////////////// static void FASTCALL SH2muls(SH2_struct * sh) { s32 m = INSTRUCTION_C(sh->instruction); s32 n = INSTRUCTION_B(sh->instruction); sh->regs.MACL = ((s32)(s16)sh->regs.R[n]*(s32)(s16)sh->regs.R[m]); sh->regs.PC += 2; sh->cycles++; } ////////////////////////////////////////////////////////////////////////////// static void FASTCALL SH2mulu(SH2_struct * sh) { s32 m = INSTRUCTION_C(sh->instruction); s32 n = INSTRUCTION_B(sh->instruction); sh->regs.MACL = ((u32)(u16)sh->regs.R[n] * (u32)(u16)sh->regs.R[m]); sh->regs.PC+=2; sh->cycles++; } ////////////////////////////////////////////////////////////////////////////// static void FASTCALL SH2neg(SH2_struct * sh) { sh->regs.R[INSTRUCTION_B(sh->instruction)]=0-sh->regs.R[INSTRUCTION_C(sh->instruction)]; sh->regs.PC+=2; sh->cycles++; } ////////////////////////////////////////////////////////////////////////////// static void FASTCALL SH2negc(SH2_struct * sh) { u32 temp; s32 m = INSTRUCTION_C(sh->instruction); s32 n = INSTRUCTION_B(sh->instruction); temp=0-sh->regs.R[m]; sh->regs.R[n] = temp - sh->regs.SR.part.T; if (0 < temp) sh->regs.SR.part.T=1; else sh->regs.SR.part.T=0; if (temp < sh->regs.R[n]) sh->regs.SR.part.T=1; sh->regs.PC+=2; sh->cycles++; } ////////////////////////////////////////////////////////////////////////////// static void FASTCALL SH2nop(SH2_struct * sh) { sh->regs.PC += 2; sh->cycles++; } ////////////////////////////////////////////////////////////////////////////// static void FASTCALL SH2y_not(SH2_struct * sh) { sh->regs.R[INSTRUCTION_B(sh->instruction)] = ~sh->regs.R[INSTRUCTION_C(sh->instruction)]; sh->regs.PC += 2; sh->cycles++; } ////////////////////////////////////////////////////////////////////////////// static void FASTCALL SH2y_or(SH2_struct * sh) { sh->regs.R[INSTRUCTION_B(sh->instruction)] |= sh->regs.R[INSTRUCTION_C(sh->instruction)]; sh->regs.PC += 2; sh->cycles++; } ////////////////////////////////////////////////////////////////////////////// static void FASTCALL SH2ori(SH2_struct * sh) { sh->regs.R[0] |= INSTRUCTION_CD(sh->instruction); sh->regs.PC += 2; sh->cycles++; } ////////////////////////////////////////////////////////////////////////////// static void FASTCALL SH2orm(SH2_struct * sh) { s32 temp; s32 source = INSTRUCTION_CD(sh->instruction); temp = (s32) MappedMemoryReadByte(sh->regs.GBR + sh->regs.R[0]); temp |= source; MappedMemoryWriteByte(sh->regs.GBR + sh->regs.R[0],temp); sh->regs.PC += 2; sh->cycles += 3; } ////////////////////////////////////////////////////////////////////////////// static void FASTCALL SH2rotcl(SH2_struct * sh) { s32 temp; s32 n = INSTRUCTION_B(sh->instruction); if ((sh->regs.R[n]&0x80000000)==0) temp=0; else temp=1; sh->regs.R[n]<<=1; if (sh->regs.SR.part.T == 1) sh->regs.R[n]|=0x00000001; else sh->regs.R[n]&=0xFFFFFFFE; if (temp==1) sh->regs.SR.part.T=1; else sh->regs.SR.part.T=0; sh->regs.PC+=2; sh->cycles++; } ////////////////////////////////////////////////////////////////////////////// static void FASTCALL SH2rotcr(SH2_struct * sh) { s32 temp; s32 n = INSTRUCTION_B(sh->instruction); if ((sh->regs.R[n]&0x00000001)==0) temp=0; else temp=1; sh->regs.R[n]>>=1; if (sh->regs.SR.part.T == 1) sh->regs.R[n]|=0x80000000; else sh->regs.R[n]&=0x7FFFFFFF; if (temp==1) sh->regs.SR.part.T=1; else sh->regs.SR.part.T=0; sh->regs.PC+=2; sh->cycles++; } ////////////////////////////////////////////////////////////////////////////// static void FASTCALL SH2rotl(SH2_struct * sh) { s32 n = INSTRUCTION_B(sh->instruction); if ((sh->regs.R[n]&0x80000000)==0) sh->regs.SR.part.T=0; else sh->regs.SR.part.T=1; sh->regs.R[n]<<=1; if (sh->regs.SR.part.T==1) sh->regs.R[n]|=0x00000001; else sh->regs.R[n]&=0xFFFFFFFE; sh->regs.PC+=2; sh->cycles++; } ////////////////////////////////////////////////////////////////////////////// static void FASTCALL SH2rotr(SH2_struct * sh) { s32 n = INSTRUCTION_B(sh->instruction); if ((sh->regs.R[n]&0x00000001)==0) sh->regs.SR.part.T = 0; else sh->regs.SR.part.T = 1; sh->regs.R[n]>>=1; if (sh->regs.SR.part.T == 1) sh->regs.R[n]|=0x80000000; else sh->regs.R[n]&=0x7FFFFFFF; sh->regs.PC+=2; sh->cycles++; } ////////////////////////////////////////////////////////////////////////////// static void FASTCALL SH2rte(SH2_struct * sh) { u32 temp; temp=sh->regs.PC; sh->regs.PC = MappedMemoryReadLong(sh->regs.R[15]); sh->regs.R[15] += 4; sh->regs.SR.all = MappedMemoryReadLong(sh->regs.R[15]) & 0x000003F3; sh->regs.R[15] += 4; sh->cycles += 4; SH2delay(sh, temp + 2); } ////////////////////////////////////////////////////////////////////////////// static void FASTCALL SH2rts(SH2_struct * sh) { u32 temp; temp = sh->regs.PC; sh->regs.PC = sh->regs.PR; sh->cycles += 2; SH2delay(sh, temp + 2); } ////////////////////////////////////////////////////////////////////////////// static void FASTCALL SH2sett(SH2_struct * sh) { sh->regs.SR.part.T = 1; sh->regs.PC += 2; sh->cycles++; } ////////////////////////////////////////////////////////////////////////////// static void FASTCALL SH2shal(SH2_struct * sh) { s32 n = INSTRUCTION_B(sh->instruction); if ((sh->regs.R[n] & 0x80000000) == 0) sh->regs.SR.part.T = 0; else sh->regs.SR.part.T = 1; sh->regs.R[n] <<= 1; sh->regs.PC += 2; sh->cycles++; } ////////////////////////////////////////////////////////////////////////////// static void FASTCALL SH2shar(SH2_struct * sh) { s32 temp; s32 n = INSTRUCTION_B(sh->instruction); if ((sh->regs.R[n]&0x00000001)==0) sh->regs.SR.part.T = 0; else sh->regs.SR.part.T = 1; if ((sh->regs.R[n]&0x80000000)==0) temp = 0; else temp = 1; sh->regs.R[n] >>= 1; if (temp == 1) sh->regs.R[n] |= 0x80000000; else sh->regs.R[n] &= 0x7FFFFFFF; sh->regs.PC += 2; sh->cycles++; } ////////////////////////////////////////////////////////////////////////////// static void FASTCALL SH2shll(SH2_struct * sh) { s32 n = INSTRUCTION_B(sh->instruction); if ((sh->regs.R[n]&0x80000000)==0) sh->regs.SR.part.T=0; else sh->regs.SR.part.T=1; sh->regs.R[n]<<=1; sh->regs.PC+=2; sh->cycles++; } ////////////////////////////////////////////////////////////////////////////// static void FASTCALL SH2shll2(SH2_struct * sh) { sh->regs.R[INSTRUCTION_B(sh->instruction)] <<= 2; sh->regs.PC+=2; sh->cycles++; } ////////////////////////////////////////////////////////////////////////////// static void FASTCALL SH2shll8(SH2_struct * sh) { sh->regs.R[INSTRUCTION_B(sh->instruction)]<<=8; sh->regs.PC+=2; sh->cycles++; } ////////////////////////////////////////////////////////////////////////////// static void FASTCALL SH2shll16(SH2_struct * sh) { sh->regs.R[INSTRUCTION_B(sh->instruction)]<<=16; sh->regs.PC+=2; sh->cycles++; } ////////////////////////////////////////////////////////////////////////////// static void FASTCALL SH2shlr(SH2_struct * sh) { s32 n = INSTRUCTION_B(sh->instruction); if ((sh->regs.R[n]&0x00000001)==0) sh->regs.SR.part.T=0; else sh->regs.SR.part.T=1; sh->regs.R[n]>>=1; sh->regs.PC+=2; sh->cycles++; } ////////////////////////////////////////////////////////////////////////////// static void FASTCALL SH2shlr2(SH2_struct * sh) { s32 n = INSTRUCTION_B(sh->instruction); sh->regs.R[n]>>=2; sh->regs.PC+=2; sh->cycles++; } ////////////////////////////////////////////////////////////////////////////// static void FASTCALL SH2shlr8(SH2_struct * sh) { s32 n = INSTRUCTION_B(sh->instruction); sh->regs.R[n]>>=8; sh->regs.PC+=2; sh->cycles++; } ////////////////////////////////////////////////////////////////////////////// static void FASTCALL SH2shlr16(SH2_struct * sh) { s32 n = INSTRUCTION_B(sh->instruction); sh->regs.R[n]>>=16; sh->regs.PC+=2; sh->cycles++; } ////////////////////////////////////////////////////////////////////////////// static void FASTCALL SH2stcgbr(SH2_struct * sh) { s32 n = INSTRUCTION_B(sh->instruction); sh->regs.R[n]=sh->regs.GBR; sh->regs.PC+=2; sh->cycles++; } ////////////////////////////////////////////////////////////////////////////// static void FASTCALL SH2stcmgbr(SH2_struct * sh) { s32 n = INSTRUCTION_B(sh->instruction); sh->regs.R[n]-=4; MappedMemoryWriteLong(sh->regs.R[n],sh->regs.GBR); sh->regs.PC+=2; sh->cycles += 2; } ////////////////////////////////////////////////////////////////////////////// static void FASTCALL SH2stcmsr(SH2_struct * sh) { s32 n = INSTRUCTION_B(sh->instruction); sh->regs.R[n]-=4; MappedMemoryWriteLong(sh->regs.R[n],sh->regs.SR.all); sh->regs.PC+=2; sh->cycles += 2; } ////////////////////////////////////////////////////////////////////////////// static void FASTCALL SH2stcmvbr(SH2_struct * sh) { s32 n = INSTRUCTION_B(sh->instruction); sh->regs.R[n]-=4; MappedMemoryWriteLong(sh->regs.R[n],sh->regs.VBR); sh->regs.PC+=2; sh->cycles += 2; } ////////////////////////////////////////////////////////////////////////////// static void FASTCALL SH2stcsr(SH2_struct * sh) { s32 n = INSTRUCTION_B(sh->instruction); sh->regs.R[n] = sh->regs.SR.all; sh->regs.PC+=2; sh->cycles++; } ////////////////////////////////////////////////////////////////////////////// static void FASTCALL SH2stcvbr(SH2_struct * sh) { s32 n = INSTRUCTION_B(sh->instruction); sh->regs.R[n]=sh->regs.VBR; sh->regs.PC+=2; sh->cycles++; } ////////////////////////////////////////////////////////////////////////////// static void FASTCALL SH2stsmach(SH2_struct * sh) { s32 n = INSTRUCTION_B(sh->instruction); sh->regs.R[n]=sh->regs.MACH; sh->regs.PC+=2; sh->cycles++; } ////////////////////////////////////////////////////////////////////////////// static void FASTCALL SH2stsmacl(SH2_struct * sh) { s32 n = INSTRUCTION_B(sh->instruction); sh->regs.R[n]=sh->regs.MACL; sh->regs.PC+=2; sh->cycles++; } ////////////////////////////////////////////////////////////////////////////// static void FASTCALL SH2stsmmach(SH2_struct * sh) { s32 n = INSTRUCTION_B(sh->instruction); sh->regs.R[n] -= 4; MappedMemoryWriteLong(sh->regs.R[n],sh->regs.MACH); sh->regs.PC+=2; sh->cycles++; } ////////////////////////////////////////////////////////////////////////////// static void FASTCALL SH2stsmmacl(SH2_struct * sh) { s32 n = INSTRUCTION_B(sh->instruction); sh->regs.R[n] -= 4; MappedMemoryWriteLong(sh->regs.R[n],sh->regs.MACL); sh->regs.PC+=2; sh->cycles++; } ////////////////////////////////////////////////////////////////////////////// static void FASTCALL SH2stsmpr(SH2_struct * sh) { s32 n = INSTRUCTION_B(sh->instruction); sh->regs.R[n] -= 4; MappedMemoryWriteLong(sh->regs.R[n],sh->regs.PR); sh->regs.PC+=2; sh->cycles++; } ////////////////////////////////////////////////////////////////////////////// static void FASTCALL SH2stspr(SH2_struct * sh) { s32 n = INSTRUCTION_B(sh->instruction); sh->regs.R[n] = sh->regs.PR; sh->regs.PC+=2; sh->cycles++; } ////////////////////////////////////////////////////////////////////////////// static void FASTCALL SH2sub(SH2_struct * sh) { s32 m = INSTRUCTION_C(sh->instruction); s32 n = INSTRUCTION_B(sh->instruction); sh->regs.R[n]-=sh->regs.R[m]; sh->regs.PC+=2; sh->cycles++; } ////////////////////////////////////////////////////////////////////////////// static void FASTCALL SH2subc(SH2_struct * sh) { s32 m = INSTRUCTION_C(sh->instruction); s32 n = INSTRUCTION_B(sh->instruction); u32 tmp0,tmp1; tmp1 = sh->regs.R[n] - sh->regs.R[m]; tmp0 = sh->regs.R[n]; sh->regs.R[n] = tmp1 - sh->regs.SR.part.T; if (tmp0 < tmp1) sh->regs.SR.part.T = 1; else sh->regs.SR.part.T = 0; if (tmp1 < sh->regs.R[n]) sh->regs.SR.part.T = 1; sh->regs.PC += 2; sh->cycles++; } ////////////////////////////////////////////////////////////////////////////// static void FASTCALL SH2subv(SH2_struct * sh) { s32 m = INSTRUCTION_C(sh->instruction); s32 n = INSTRUCTION_B(sh->instruction); s32 dest,src,ans; if ((s32)sh->regs.R[n]>=0) dest=0; else dest=1; if ((s32)sh->regs.R[m]>=0) src=0; else src=1; src+=dest; sh->regs.R[n]-=sh->regs.R[m]; if ((s32)sh->regs.R[n]>=0) ans=0; else ans=1; ans+=dest; if (src==1) { if (ans==1) sh->regs.SR.part.T=1; else sh->regs.SR.part.T=0; } else sh->regs.SR.part.T=0; sh->regs.PC+=2; sh->cycles++; } ////////////////////////////////////////////////////////////////////////////// static void FASTCALL SH2swapb(SH2_struct * sh) { u32 temp0,temp1; s32 m = INSTRUCTION_C(sh->instruction); s32 n = INSTRUCTION_B(sh->instruction); temp0=sh->regs.R[m]&0xffff0000; temp1=(sh->regs.R[m]&0x000000ff)<<8; sh->regs.R[n]=(sh->regs.R[m]>>8)&0x000000ff; sh->regs.R[n]=sh->regs.R[n]|temp1|temp0; sh->regs.PC+=2; sh->cycles++; } ////////////////////////////////////////////////////////////////////////////// static void FASTCALL SH2swapw(SH2_struct * sh) { u32 temp; s32 m = INSTRUCTION_C(sh->instruction); s32 n = INSTRUCTION_B(sh->instruction); temp=(sh->regs.R[m]>>16)&0x0000FFFF; sh->regs.R[n]=sh->regs.R[m]<<16; sh->regs.R[n]|=temp; sh->regs.PC+=2; sh->cycles++; } ////////////////////////////////////////////////////////////////////////////// static void FASTCALL SH2tas(SH2_struct * sh) { s32 temp; s32 n = INSTRUCTION_B(sh->instruction); temp=(s32) MappedMemoryReadByte(sh->regs.R[n]); if (temp==0) sh->regs.SR.part.T=1; else sh->regs.SR.part.T=0; temp|=0x00000080; MappedMemoryWriteByte(sh->regs.R[n],temp); sh->regs.PC+=2; sh->cycles += 4; } ////////////////////////////////////////////////////////////////////////////// static void FASTCALL SH2trapa(SH2_struct * sh) { s32 imm = INSTRUCTION_CD(sh->instruction); sh->regs.R[15]-=4; MappedMemoryWriteLong(sh->regs.R[15],sh->regs.SR.all); sh->regs.R[15]-=4; MappedMemoryWriteLong(sh->regs.R[15],sh->regs.PC + 2); sh->regs.PC = MappedMemoryReadLong(sh->regs.VBR+(imm<<2)); sh->cycles += 8; } ////////////////////////////////////////////////////////////////////////////// static void FASTCALL SH2tst(SH2_struct * sh) { s32 m = INSTRUCTION_C(sh->instruction); s32 n = INSTRUCTION_B(sh->instruction); if ((sh->regs.R[n]&sh->regs.R[m])==0) sh->regs.SR.part.T = 1; else sh->regs.SR.part.T = 0; sh->regs.PC += 2; sh->cycles++; } ////////////////////////////////////////////////////////////////////////////// static void FASTCALL SH2tsti(SH2_struct * sh) { s32 temp; s32 i = INSTRUCTION_CD(sh->instruction); temp=sh->regs.R[0]&i; if (temp==0) sh->regs.SR.part.T = 1; else sh->regs.SR.part.T = 0; sh->regs.PC+=2; sh->cycles++; } ////////////////////////////////////////////////////////////////////////////// static void FASTCALL SH2tstm(SH2_struct * sh) { s32 temp; s32 i = INSTRUCTION_CD(sh->instruction); temp=(s32) MappedMemoryReadByte(sh->regs.GBR+sh->regs.R[0]); temp&=i; if (temp==0) sh->regs.SR.part.T = 1; else sh->regs.SR.part.T = 0; sh->regs.PC+=2; sh->cycles += 3; } ////////////////////////////////////////////////////////////////////////////// static void FASTCALL SH2y_xor(SH2_struct * sh) { int b = INSTRUCTION_B(sh->instruction); int c = INSTRUCTION_C(sh->instruction); sh->regs.R[b] ^= sh->regs.R[c]; sh->regs.PC += 2; sh->cycles++; } ////////////////////////////////////////////////////////////////////////////// static void FASTCALL SH2xori(SH2_struct * sh) { s32 source = INSTRUCTION_CD(sh->instruction); sh->regs.R[0] ^= source; sh->regs.PC += 2; sh->cycles++; } ////////////////////////////////////////////////////////////////////////////// static void FASTCALL SH2xorm(SH2_struct * sh) { s32 source = INSTRUCTION_CD(sh->instruction); s32 temp; temp = (s32) MappedMemoryReadByte(sh->regs.GBR + sh->regs.R[0]); temp ^= source; MappedMemoryWriteByte(sh->regs.GBR + sh->regs.R[0],temp); sh->regs.PC += 2; sh->cycles += 3; } ////////////////////////////////////////////////////////////////////////////// static void FASTCALL SH2xtrct(SH2_struct * sh) { u32 temp; s32 m = INSTRUCTION_C(sh->instruction); s32 n = INSTRUCTION_B(sh->instruction); temp=(sh->regs.R[m]<<16)&0xFFFF0000; sh->regs.R[n]=(sh->regs.R[n]>>16)&0x0000FFFF; sh->regs.R[n]|=temp; sh->regs.PC+=2; sh->cycles++; } ////////////////////////////////////////////////////////////////////////////// static void FASTCALL SH2sleep(SH2_struct * sh) { sh->cycles += 3; } ////////////////////////////////////////////////////////////////////////////// static opcodefunc decode(u16 instruction) { switch (INSTRUCTION_A(instruction)) { case 0: switch (INSTRUCTION_D(instruction)) { case 2: switch (INSTRUCTION_C(instruction)) { case 0: return &SH2stcsr; case 1: return &SH2stcgbr; case 2: return &SH2stcvbr; default: return &SH2undecoded; } case 3: switch (INSTRUCTION_C(instruction)) { case 0: return &SH2bsrf; case 2: return &SH2braf; default: return &SH2undecoded; } case 4: return &SH2movbs0; case 5: return &SH2movws0; case 6: return &SH2movls0; case 7: return &SH2mull; case 8: switch (INSTRUCTION_C(instruction)) { case 0: return &SH2clrt; case 1: return &SH2sett; case 2: return &SH2clrmac; default: return &SH2undecoded; } case 9: switch (INSTRUCTION_C(instruction)) { case 0: return &SH2nop; case 1: return &SH2div0u; case 2: return &SH2movt; default: return &SH2undecoded; } case 10: switch (INSTRUCTION_C(instruction)) { case 0: return &SH2stsmach; case 1: return &SH2stsmacl; case 2: return &SH2stspr; default: return &SH2undecoded; } case 11: switch (INSTRUCTION_C(instruction)) { case 0: return &SH2rts; case 1: return &SH2sleep; case 2: return &SH2rte; default: return &SH2undecoded; } case 12: return &SH2movbl0; case 13: return &SH2movwl0; case 14: return &SH2movll0; case 15: return &SH2macl; default: return &SH2undecoded; } case 1: return &SH2movls4; case 2: switch (INSTRUCTION_D(instruction)) { case 0: return &SH2movbs; case 1: return &SH2movws; case 2: return &SH2movls; case 4: return &SH2movbm; case 5: return &SH2movwm; case 6: return &SH2movlm; case 7: return &SH2div0s; case 8: return &SH2tst; case 9: return &SH2y_and; case 10: return &SH2y_xor; case 11: return &SH2y_or; case 12: return &SH2cmpstr; case 13: return &SH2xtrct; case 14: return &SH2mulu; case 15: return &SH2muls; default: return &SH2undecoded; } case 3: switch(INSTRUCTION_D(instruction)) { case 0: return &SH2cmpeq; case 2: return &SH2cmphs; case 3: return &SH2cmpge; case 4: return &SH2div1; case 5: return &SH2dmulu; case 6: return &SH2cmphi; case 7: return &SH2cmpgt; case 8: return &SH2sub; case 10: return &SH2subc; case 11: return &SH2subv; case 12: return &SH2add; case 13: return &SH2dmuls; case 14: return &SH2addc; case 15: return &SH2addv; default: return &SH2undecoded; } case 4: switch(INSTRUCTION_D(instruction)) { case 0: switch(INSTRUCTION_C(instruction)) { case 0: return &SH2shll; case 1: return &SH2dt; case 2: return &SH2shal; default: return &SH2undecoded; } case 1: switch(INSTRUCTION_C(instruction)) { case 0: return &SH2shlr; case 1: return &SH2cmppz; case 2: return &SH2shar; default: return &SH2undecoded; } case 2: switch(INSTRUCTION_C(instruction)) { case 0: return &SH2stsmmach; case 1: return &SH2stsmmacl; case 2: return &SH2stsmpr; default: return &SH2undecoded; } case 3: switch(INSTRUCTION_C(instruction)) { case 0: return &SH2stcmsr; case 1: return &SH2stcmgbr; case 2: return &SH2stcmvbr; default: return &SH2undecoded; } case 4: switch(INSTRUCTION_C(instruction)) { case 0: return &SH2rotl; case 2: return &SH2rotcl; default: return &SH2undecoded; } case 5: switch(INSTRUCTION_C(instruction)) { case 0: return &SH2rotr; case 1: return &SH2cmppl; case 2: return &SH2rotcr; default: return &SH2undecoded; } case 6: switch(INSTRUCTION_C(instruction)) { case 0: return &SH2ldsmmach; case 1: return &SH2ldsmmacl; case 2: return &SH2ldsmpr; default: return &SH2undecoded; } case 7: switch(INSTRUCTION_C(instruction)) { case 0: return &SH2ldcmsr; case 1: return &SH2ldcmgbr; case 2: return &SH2ldcmvbr; default: return &SH2undecoded; } case 8: switch(INSTRUCTION_C(instruction)) { case 0: return &SH2shll2; case 1: return &SH2shll8; case 2: return &SH2shll16; default: return &SH2undecoded; } case 9: switch(INSTRUCTION_C(instruction)) { case 0: return &SH2shlr2; case 1: return &SH2shlr8; case 2: return &SH2shlr16; default: return &SH2undecoded; } case 10: switch(INSTRUCTION_C(instruction)) { case 0: return &SH2ldsmach; case 1: return &SH2ldsmacl; case 2: return &SH2ldspr; default: return &SH2undecoded; } case 11: switch(INSTRUCTION_C(instruction)) { case 0: return &SH2jsr; case 1: return &SH2tas; case 2: return &SH2jmp; default: return &SH2undecoded; } case 14: switch(INSTRUCTION_C(instruction)) { case 0: return &SH2ldcsr; case 1: return &SH2ldcgbr; case 2: return &SH2ldcvbr; default: return &SH2undecoded; } case 15: return &SH2macw; default: return &SH2undecoded; } case 5: return &SH2movll4; case 6: switch (INSTRUCTION_D(instruction)) { case 0: return &SH2movbl; case 1: return &SH2movwl; case 2: return &SH2movll; case 3: return &SH2mov; case 4: return &SH2movbp; case 5: return &SH2movwp; case 6: return &SH2movlp; case 7: return &SH2y_not; case 8: return &SH2swapb; case 9: return &SH2swapw; case 10: return &SH2negc; case 11: return &SH2neg; case 12: return &SH2extub; case 13: return &SH2extuw; case 14: return &SH2extsb; case 15: return &SH2extsw; } case 7: return &SH2addi; case 8: switch (INSTRUCTION_B(instruction)) { case 0: return &SH2movbs4; case 1: return &SH2movws4; case 4: return &SH2movbl4; case 5: return &SH2movwl4; case 8: return &SH2cmpim; case 9: return &SH2bt; case 11: return &SH2bf; case 13: return &SH2bts; case 15: return &SH2bfs; default: return &SH2undecoded; } case 9: return &SH2movwi; case 10: return &SH2bra; case 11: return &SH2bsr; case 12: switch(INSTRUCTION_B(instruction)) { case 0: return &SH2movbsg; case 1: return &SH2movwsg; case 2: return &SH2movlsg; case 3: return &SH2trapa; case 4: return &SH2movblg; case 5: return &SH2movwlg; case 6: return &SH2movllg; case 7: return &SH2mova; case 8: return &SH2tsti; case 9: return &SH2andi; case 10: return &SH2xori; case 11: return &SH2ori; case 12: return &SH2tstm; case 13: return &SH2andm; case 14: return &SH2xorm; case 15: return &SH2orm; } case 13: return &SH2movli; case 14: return &SH2movi; default: return &SH2undecoded; } } ////////////////////////////////////////////////////////////////////////////// int SH2InterpreterInit() { int i; // Initialize any internal variables for(i = 0;i < 0x10000;i++) opcodes[i] = decode(i); for (i = 0; i < 0x100; i++) { switch (i) { case 0x000: // Bios fetchlist[i] = FetchBios; break; case 0x002: // Low Work Ram fetchlist[i] = FetchLWram; break; case 0x020: // CS0 fetchlist[i] = FetchCs0; break; case 0x060: // High Work Ram case 0x061: case 0x062: case 0x063: case 0x064: case 0x065: case 0x066: case 0x067: case 0x068: case 0x069: case 0x06A: case 0x06B: case 0x06C: case 0x06D: case 0x06E: case 0x06F: fetchlist[i] = FetchHWram; break; default: fetchlist[i] = FetchInvalid; break; } } SH2ClearCodeBreakpoints(MSH2); SH2ClearCodeBreakpoints(SSH2); SH2ClearMemoryBreakpoints(MSH2); SH2ClearMemoryBreakpoints(SSH2); MSH2->breakpointEnabled = 0; SSH2->breakpointEnabled = 0; return 0; } int SH2DebugInterpreterInit() { SH2InterpreterInit(); MSH2->breakpointEnabled = 1; SSH2->breakpointEnabled = 1; return 0; } ////////////////////////////////////////////////////////////////////////////// void SH2InterpreterDeInit() { // DeInitialize any internal variables here } ////////////////////////////////////////////////////////////////////////////// void SH2InterpreterReset(UNUSED SH2_struct *context) { // Reset any internal variables here } ////////////////////////////////////////////////////////////////////////////// static INLINE void SH2UBCInterrupt(SH2_struct *context, u32 flag) { if (15 > context->regs.SR.part.I) // Since UBC's interrupt are always level 15 { context->regs.R[15] -= 4; MappedMemoryWriteLong(context->regs.R[15], context->regs.SR.all); context->regs.R[15] -= 4; MappedMemoryWriteLong(context->regs.R[15], context->regs.PC); context->regs.SR.part.I = 15; context->regs.PC = MappedMemoryReadLong(context->regs.VBR + (12 << 2)); LOG("interrupt successfully handled\n"); } context->onchip.BRCR |= flag; } ////////////////////////////////////////////////////////////////////////////// static INLINE void SH2HandleInterrupts(SH2_struct *context) { if (context->NumberOfInterrupts != 0) { if (context->interrupts[context->NumberOfInterrupts-1].level > context->regs.SR.part.I) { context->regs.R[15] -= 4; MappedMemoryWriteLong(context->regs.R[15], context->regs.SR.all); context->regs.R[15] -= 4; MappedMemoryWriteLong(context->regs.R[15], context->regs.PC); context->regs.SR.part.I = context->interrupts[context->NumberOfInterrupts-1].level; context->regs.PC = MappedMemoryReadLong(context->regs.VBR + (context->interrupts[context->NumberOfInterrupts-1].vector << 2)); context->NumberOfInterrupts--; context->isIdle = 0; context->isSleeping = 0; } } } ////////////////////////////////////////////////////////////////////////////// FASTCALL void SH2DebugInterpreterExec(SH2_struct *context, u32 cycles) { #ifdef SH2_TRACE /* Avoid accumulating leftover cycles multiple times, since the trace * code automatically adds state->cycles to the cycle accumulator when * printing a trace line */ sh2_trace_add_cycles(-(context->cycles)); #endif SH2HandleInterrupts(context); while(context->cycles < cycles) { #ifdef EMULATEUBC int ubcinterrupt=0, ubcflag=0; #endif SH2HandleBreakpoints(context); #ifdef SH2_TRACE sh2_trace(context, context->regs.PC); #endif #ifdef EMULATEUBC if (context->onchip.BBRA & (BBR_CPA_CPU | BBR_IDA_INST | BBR_RWA_READ)) // Break on cpu, instruction, read cycles { if (context->onchip.BARA.all == (context->regs.PC & (~context->onchip.BAMRA.all))) { LOG("Trigger UBC A interrupt: PC = %08X\n", context->regs.PC); if (!(context->onchip.BRCR & BRCR_PCBA)) { // Break before instruction fetch SH2UBCInterrupt(context, BRCR_CMFCA); } else { // Break after instruction fetch ubcinterrupt=1; ubcflag = BRCR_CMFCA; } } } else if(context->onchip.BBRB & (BBR_CPA_CPU | BBR_IDA_INST | BBR_RWA_READ)) // Break on cpu, instruction, read cycles { if (context->onchip.BARB.all == (context->regs.PC & (~context->onchip.BAMRB.all))) { LOG("Trigger UBC B interrupt: PC = %08X\n", context->regs.PC); if (!(context->onchip.BRCR & BRCR_PCBB)) { // Break before instruction fetch SH2UBCInterrupt(context, BRCR_CMFCB); } else { // Break after instruction fetch ubcinterrupt=1; ubcflag = BRCR_CMFCB; } } } #endif // Fetch Instruction #ifdef EXEC_FROM_CACHE if ((context->regs.PC & 0xC0000000) == 0xC0000000) context->instruction = DataArrayReadWord(context->regs.PC); else #endif context->instruction = fetchlist[(context->regs.PC >> 20) & 0x0FF](context->regs.PC); // Execute it opcodes[context->instruction](context); #ifdef EMULATEUBC if (ubcinterrupt) SH2UBCInterrupt(context, ubcflag); #endif } #ifdef SH2_TRACE sh2_trace_add_cycles(context->cycles); #endif } ////////////////////////////////////////////////////////////////////////////// FASTCALL void SH2InterpreterExec(SH2_struct *context, u32 cycles) { SH2HandleInterrupts(context); if (context->isIdle) SH2idleParse(context, cycles); else SH2idleCheck(context, cycles); while(context->cycles < cycles) { // Fetch Instruction context->instruction = fetchlist[(context->regs.PC >> 20) & 0x0FF](context->regs.PC); // Execute it opcodes[context->instruction](context); } } ////////////////////////////////////////////////////////////////////////////// void SH2InterpreterGetRegisters(SH2_struct *context, sh2regs_struct *regs) { memcpy(regs, &context->regs, sizeof(sh2regs_struct)); } ////////////////////////////////////////////////////////////////////////////// u32 SH2InterpreterGetGPR(SH2_struct *context, int num) { return context->regs.R[num]; } ////////////////////////////////////////////////////////////////////////////// u32 SH2InterpreterGetSR(SH2_struct *context) { return context->regs.SR.all; } ////////////////////////////////////////////////////////////////////////////// u32 SH2InterpreterGetGBR(SH2_struct *context) { return context->regs.GBR; } ////////////////////////////////////////////////////////////////////////////// u32 SH2InterpreterGetVBR(SH2_struct *context) { return context->regs.VBR; } ////////////////////////////////////////////////////////////////////////////// u32 SH2InterpreterGetMACH(SH2_struct *context) { return context->regs.MACH; } ////////////////////////////////////////////////////////////////////////////// u32 SH2InterpreterGetMACL(SH2_struct *context) { return context->regs.MACL; } ////////////////////////////////////////////////////////////////////////////// u32 SH2InterpreterGetPR(SH2_struct *context) { return context->regs.PR; } ////////////////////////////////////////////////////////////////////////////// u32 SH2InterpreterGetPC(SH2_struct *context) { return context->regs.PC; } ////////////////////////////////////////////////////////////////////////////// void SH2InterpreterSetRegisters(SH2_struct *context, const sh2regs_struct *regs) { memcpy(&context->regs, regs, sizeof(sh2regs_struct)); } ////////////////////////////////////////////////////////////////////////////// void SH2InterpreterSetGPR(SH2_struct *context, int num, u32 value) { context->regs.R[num] = value; } ////////////////////////////////////////////////////////////////////////////// void SH2InterpreterSetSR(SH2_struct *context, u32 value) { context->regs.SR.all = value; } ////////////////////////////////////////////////////////////////////////////// void SH2InterpreterSetGBR(SH2_struct *context, u32 value) { context->regs.GBR = value; } ////////////////////////////////////////////////////////////////////////////// void SH2InterpreterSetVBR(SH2_struct *context, u32 value) { context->regs.VBR = value; } ////////////////////////////////////////////////////////////////////////////// void SH2InterpreterSetMACH(SH2_struct *context, u32 value) { context->regs.MACH = value; } ////////////////////////////////////////////////////////////////////////////// void SH2InterpreterSetMACL(SH2_struct *context, u32 value) { context->regs.MACL = value; } ////////////////////////////////////////////////////////////////////////////// void SH2InterpreterSetPR(SH2_struct *context, u32 value) { context->regs.PR = value; } ////////////////////////////////////////////////////////////////////////////// void SH2InterpreterSetPC(SH2_struct *context, u32 value) { context->regs.PC = value; } ////////////////////////////////////////////////////////////////////////////// void SH2InterpreterSendInterrupt(SH2_struct *context, u8 vector, u8 level) { u32 i, i2; interrupt_struct tmp; // Make sure interrupt doesn't already exist for (i = 0; i < context->NumberOfInterrupts; i++) { if (context->interrupts[i].vector == vector) return; } context->interrupts[context->NumberOfInterrupts].level = level; context->interrupts[context->NumberOfInterrupts].vector = vector; context->NumberOfInterrupts++; // Sort interrupts for (i = 0; i < (context->NumberOfInterrupts-1); i++) { for (i2 = i+1; i2 < context->NumberOfInterrupts; i2++) { if (context->interrupts[i].level > context->interrupts[i2].level) { tmp.level = context->interrupts[i].level; tmp.vector = context->interrupts[i].vector; context->interrupts[i].level = context->interrupts[i2].level; context->interrupts[i].vector = context->interrupts[i2].vector; context->interrupts[i2].level = tmp.level; context->interrupts[i2].vector = tmp.vector; } } } } ////////////////////////////////////////////////////////////////////////////// int SH2InterpreterGetInterrupts(SH2_struct *context, interrupt_struct interrupts[MAX_INTERRUPTS]) { memcpy(interrupts, context->interrupts, sizeof(interrupt_struct) * MAX_INTERRUPTS); return context->NumberOfInterrupts; } ////////////////////////////////////////////////////////////////////////////// void SH2InterpreterSetInterrupts(SH2_struct *context, int num_interrupts, const interrupt_struct interrupts[MAX_INTERRUPTS]) { memcpy(context->interrupts, interrupts, sizeof(interrupt_struct) * MAX_INTERRUPTS); context->NumberOfInterrupts = num_interrupts; } //////////////////////////////////////////////////////////////////////////////