3058 lines
77 KiB
C
3058 lines
77 KiB
C
/* 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 <20> doit <20>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;
|
||
}
|
||
|
||
//////////////////////////////////////////////////////////////////////////////
|