project64/Source/Project64/N64 System/Recompiler/Recompiler Class.cpp

3967 lines
148 KiB
C++
Raw Normal View History

#include "..\..\N64 System.h"
#include "..\C Core\c core.h"
#include "..\C Core\Recompiler Ops.h"
#include "..\C Core\X86.h"
#include "..\C Core\CPU.h"
#undef PROGRAM_COUNTER
#undef RdramSize
#undef LookUpMode
#undef LinkBlocks
#undef CountPerOp
CRecompiler::CRecompiler(CMipsMemory * MMU, CProfiling & Profile, bool & EndEmulation, bool SyncSystem) :
_MMU(MMU),
_Reg(MMU->SystemRegisters()),
m_Profile(Profile),
PROGRAM_COUNTER(_Reg->PROGRAM_COUNTER),
m_EndEmulation(EndEmulation),
m_SyncSystem(SyncSystem),
m_Functions(),
m_FunctionsDelaySlot()
{
}
CRecompiler::~CRecompiler()
{
}
void CRecompiler::Run()
{
*g_MemoryStack = (DWORD)(N64MEM+(GPR[29].W[0] & 0x1FFFFFFF));
CoInitialize(NULL);
if (g_LogX86Code)
{
Start_x86_Log();
}
if (!g_MMU->AllocateRecompilerMemory(LookUpMode() != FuncFind_VirtualLookup && LookUpMode() != FuncFind_ChangeMemory))
{
return;
}
JumpTable = g_MMU->GetJumpTable();
RecompCode = g_MMU->GetRecompCode();
ResetRecompCode();
m_EndEmulation = false;
__try {
if (LookUpMode() == FuncFind_VirtualLookup)
{
if (bSMM_ValidFunc())
{
RecompilerMain_VirtualTable_validate();
} else {
RecompilerMain_VirtualTable();
}
}
else if (LookUpMode() == FuncFind_ChangeMemory)
{
RecompilerMain_ChangeMemory();
}
else
{
RecompilerMain_Lookup();
}
}
__except( _MMU->SystemMemoryFilter( GetExceptionCode(), GetExceptionInformation()) )
{
Notify().DisplayError(MSG_UNKNOWN_MEM_ACTION);
}
}
void CRecompiler::RecompilerMain_VirtualTable ( void )
{
CFunctionMap::PFUNCTION_INFO_TABLE * m_FunctionTable = m_Functions.GetFunctionTable();
while(!m_EndEmulation)
{
if (NextInstruction != DELAY_SLOT)
{
CFunctionMap::PFUNCTION_INFO_TABLE table = m_FunctionTable[PROGRAM_COUNTER >> 0xC];
if (table)
{
FUNCTION_INFO * info = table[(PROGRAM_COUNTER & 0xFFF) >> 2];
if (info != NULL)
{
const BYTE * Block = info->FunctionAddr();
_asm {
pushad
call Block
popad
}
continue;
}
}
if (!_MMU->ValidVaddr(PROGRAM_COUNTER))
{
DoTLBMiss(NextInstruction == DELAY_SLOT,PROGRAM_COUNTER);
NextInstruction = NORMAL;
if (!_MMU->ValidVaddr(PROGRAM_COUNTER))
{
DisplayError("Failed to tranlate PC to a PAddr: %X\n\nEmulation stopped",PROGRAM_COUNTER);
return;
}
}
FUNCTION_INFO * info = CompilerCode();
if (info == NULL || EndEmulation())
{
break;
}
} else {
FUNCTION_INFO * Info = m_FunctionsDelaySlot.FindFunction(PROGRAM_COUNTER);
//Find Block on hash table
if (Info == NULL)
{
if (!_MMU->ValidVaddr(PROGRAM_COUNTER))
{
DoTLBMiss(NextInstruction == DELAY_SLOT,PROGRAM_COUNTER);
NextInstruction = NORMAL;
if (!_MMU->ValidVaddr(PROGRAM_COUNTER))
{
DisplayError("Failed to tranlate PC to a PAddr: %X\n\nEmulation stopped",PROGRAM_COUNTER);
return;
}
continue;
}
//Find Block on hash table
Info = CompileDelaySlot(PROGRAM_COUNTER);
if (Info == NULL || EndEmulation())
{
break;
}
}
const BYTE * Block = Info->FunctionAddr();
_asm {
pushad
call Block
popad
}
continue;
}
}
}
void CRecompiler::RecompilerMain_VirtualTable_validate ( void )
{
CFunctionMap::PFUNCTION_INFO_TABLE * m_FunctionTable = m_Functions.GetFunctionTable();
while(!m_EndEmulation)
{
if (NextInstruction == DELAY_SLOT)
{
FUNCTION_INFO * Info = m_FunctionsDelaySlot.FindFunction(PROGRAM_COUNTER);
//Find Block on hash table
if (Info == NULL)
{
if (!_MMU->ValidVaddr(PROGRAM_COUNTER))
{
DoTLBMiss(NextInstruction == DELAY_SLOT,PROGRAM_COUNTER);
NextInstruction = NORMAL;
if (!_MMU->ValidVaddr(PROGRAM_COUNTER))
{
DisplayError("Failed to tranlate PC to a PAddr: %X\n\nEmulation stopped",PROGRAM_COUNTER);
return;
}
continue;
}
//Find Block on hash table
Info = CompileDelaySlot(PROGRAM_COUNTER);
if (Info == NULL || EndEmulation())
{
break;
}
}
const BYTE * Block = Info->FunctionAddr();
if ((*Info->MemLocation[0] != Info->MemContents[0]) ||
(*Info->MemLocation[1] != Info->MemContents[1]))
{
ClearRecompCode_Virt((Info->VStartPC() - 0x1000) & ~0xFFF,0x2000,Remove_ValidateFunc);
NextInstruction = DELAY_SLOT;
Info = NULL;
continue;
}
_asm {
pushad
call Block
popad
}
continue;
}
CFunctionMap::PFUNCTION_INFO_TABLE table = m_FunctionTable[PROGRAM_COUNTER >> 0xC];
if (table)
{
FUNCTION_INFO * info = table[(PROGRAM_COUNTER & 0xFFF) >> 2];
if (info != NULL)
{
if ((*info->MemLocation[0] != info->MemContents[0]) ||
(*info->MemLocation[1] != info->MemContents[1]))
{
ClearRecompCode_Virt((info->VStartPC() - 0x1000) & ~0xFFF,0x3000,Remove_ValidateFunc);
info = NULL;
continue;
}
const BYTE * Block = info->FunctionAddr();
_asm {
pushad
call Block
popad
}
continue;
}
}
if (!_MMU->ValidVaddr(PROGRAM_COUNTER))
{
DoTLBMiss(NextInstruction == DELAY_SLOT,PROGRAM_COUNTER);
NextInstruction = NORMAL;
if (!_MMU->ValidVaddr(PROGRAM_COUNTER))
{
DisplayError("Failed to tranlate PC to a PAddr: %X\n\nEmulation stopped",PROGRAM_COUNTER);
return;
}
}
FUNCTION_INFO * info = CompilerCode();
if (info == NULL || EndEmulation())
{
break;
}
}
/*
while(!m_EndEmulation)
{
if (!_MMU->ValidVaddr(PROGRAM_COUNTER))
{
DoTLBMiss(NextInstruction == DELAY_SLOT,PROGRAM_COUNTER);
NextInstruction = NORMAL;
if (!_MMU->ValidVaddr(PROGRAM_COUNTER))
{
DisplayError("Failed to tranlate PC to a PAddr: %X\n\nEmulation stopped",PROGRAM_COUNTER);
return;
}
}
if (NextInstruction == DELAY_SLOT)
{
FUNCTION_INFO * Info = m_FunctionsDelaySlot.FindFunction(PROGRAM_COUNTER);
//Find Block on hash table
if (Info == NULL)
{
Info = CompileDelaySlot(PROGRAM_COUNTER);
if (Info == NULL || EndEmulation())
{
break;
}
}
if (bSMM_ValidFunc())
{
if ((*Info->MemLocation[0] != Info->MemContents[0]) ||
(*Info->MemLocation[1] != Info->MemContents[1]))
{
ClearRecompCode_Virt((Info->StartPC() - 0x1000) & ~0xFFF,0x2000,Remove_ValidateFunc);
NextInstruction = DELAY_SLOT;
Info = NULL;
continue;
}
}
const BYTE * Block = Info->FunctionAddr();
_asm {
pushad
call Block
popad
}
continue;
}
FUNCTION_INFO * Info = m_Functions.FindFunction(PROGRAM_COUNTER);
//Find Block on hash table
if (Info == NULL)
{
Info = CompilerCode();
if (Info == NULL || EndEmulation())
{
break;
}
}
if (bSMM_ValidFunc())
{
if ((*Info->MemLocation[0] != Info->MemContents[0]) ||
(*Info->MemLocation[1] != Info->MemContents[1]))
{
ClearRecompCode_Virt((Info->StartPC() - 0x1000) & ~0xFFF,0x3000,Remove_ValidateFunc);
Info = NULL;
continue;
}
}
const BYTE * Block = Info->FunctionAddr();
_asm {
pushad
call Block
popad
}
}
*/
}
void CRecompiler::RecompilerMain_Lookup( void )
{
DWORD Addr;
FUNCTION_INFO * Info;
//const BYTE * Block;
while(!m_EndEmulation)
{
if (g_UseTlb)
{
if (!g_TLB->TranslateVaddr(PROGRAM_COUNTER, Addr))
{
DoTLBMiss(NextInstruction == DELAY_SLOT,PROGRAM_COUNTER);
NextInstruction = NORMAL;
if (!TranslateVaddr(PROGRAM_COUNTER, &Addr)) {
DisplayError("Failed to tranlate PC to a PAddr: %X\n\nEmulation stopped",PROGRAM_COUNTER);
return;
}
}
} else {
Addr = PROGRAM_COUNTER & 0x1FFFFFFF;
}
if (NextInstruction == DELAY_SLOT) {
FUNCTION_INFO * Info = m_FunctionsDelaySlot.FindFunction(PROGRAM_COUNTER);
//Find Block on hash table
if (Info == NULL)
{
Info = CompileDelaySlot(PROGRAM_COUNTER);
if (Info == NULL || EndEmulation())
{
break;
}
}
if (bSMM_ValidFunc())
{
if ((*Info->MemLocation[0] != Info->MemContents[0]) ||
(*Info->MemLocation[1] != Info->MemContents[1]))
{
ClearRecompCode_Virt((Info->VStartPC() - 0x1000) & ~0xFFF,0x2000,Remove_ValidateFunc);
NextInstruction = DELAY_SLOT;
Info = NULL;
continue;
}
}
const BYTE * Block = Info->FunctionAddr();
_asm {
pushad
call Block
popad
}
continue;
}
__try {
if (Addr > 0x10000000)
{
if (bRomInMemory())
{
if (Addr > 0x20000000)
{
WriteTraceF(TraceDebug,"Executing from non mapped space .1 PC: %X Addr: %X",PROGRAM_COUNTER, Addr);
DisplayError(GS(MSG_NONMAPPED_SPACE));
break;
}
Info = (FUNCTION_INFO *)*(JumpTable + (Addr >> 2));
} else {
if (PROGRAM_COUNTER >= 0xB0000000 && PROGRAM_COUNTER < (RomFileSize | 0xB0000000)) {
while (PROGRAM_COUNTER >= 0xB0000000 && PROGRAM_COUNTER < (RomFileSize | 0xB0000000)) {
ExecuteInterpreterOpCode();
}
continue;
} else {
WriteTraceF(TraceDebug,"Executing from non mapped space .1 PC: %X Addr: %X",PROGRAM_COUNTER, Addr);
DisplayError(GS(MSG_NONMAPPED_SPACE));
break;
}
}
} else {
Info = (FUNCTION_INFO *)*(JumpTable + (Addr >> 2));
}
} __except(EXCEPTION_EXECUTE_HANDLER) {
if (PROGRAM_COUNTER >= 0xB0000000 && PROGRAM_COUNTER < (RomFileSize | 0xB0000000)) {
while (PROGRAM_COUNTER >= 0xB0000000 && PROGRAM_COUNTER < (RomFileSize | 0xB0000000)) {
ExecuteInterpreterOpCode();
}
continue;
} else {
WriteTraceF(TraceDebug,"Executing from non mapped space .2 PC: %X Addr: %X",PROGRAM_COUNTER, Addr);
DisplayError(GS(MSG_NONMAPPED_SPACE));
return;
}
}
if (Info == NULL)
{
Info = CompilerCode();
if (Info == NULL || EndEmulation())
{
break;
}
*(JumpTable + (Addr >> 2)) = (void *)Info;
// if (SelfModCheck == ModCode_ProtectedMemory) {
// VirtualProtect(N64MEM + Addr, 4, PAGE_READONLY, &OldProtect);
// }
}
if (bSMM_ValidFunc())
{
if ((*Info->MemLocation[0] != Info->MemContents[0]) ||
(*Info->MemLocation[1] != Info->MemContents[1]))
{
ClearRecompCode_Virt((Info->VStartPC() - 0x1000) & ~0xFFF,0x3000,Remove_ValidateFunc);
Info = NULL;
continue;
}
}
#ifdef tofix
if (Profiling && IndvidualBlock) {
static DWORD ProfAddress = 0;
if ((PROGRAM_COUNTER & ~0xFFF) != ProfAddress) {
char Label[100];
ProfAddress = PROGRAM_COUNTER & ~0xFFF;
sprintf(Label,"PC: %X to %X",ProfAddress,ProfAddress+ 0xFFC);
// StartTimer(Label);
}
/*if (PROGRAM_COUNTER >= 0x800DD000 && PROGRAM_COUNTER <= 0x800DDFFC) {
char Label[100];
sprintf(Label,"PC: %X Block: %X",PROGRAM_COUNTER,Block);
StartTimer(Label);
}*/
// } else if ((Profiling || ShowCPUPer) && ProfilingLabel[0] == 0) {
// StartTimer("r4300i Running");
}
#endif
const BYTE * Block = Info->FunctionAddr();
_asm {
pushad
call Block
popad
}
}
}
void CRecompiler::ResetRecompCode()
{
RecompPos = RecompCode;
m_Functions.Reset();
m_FunctionsDelaySlot.Reset();
if (JumpTable)
{
memset(JumpTable,0,g_MMU->RdramSize());
memset(JumpTable + (0x04000000 >> 2),0,0x1000);
memset(JumpTable + (0x04001000 >> 2),0,0x1000);
if (bRomInMemory())
{
memset(JumpTable + (0x10000000 >> 2),0,RomFileSize);
}
}
#ifdef to_clean
DWORD count, OldProtect;
if (SelfModCheck == ModCode_ChangeMemory) {
DWORD count, PAddr, Value;
for (count = 0; count < TargetIndex; count++) {
PAddr = OrigMem[(WORD)(count)].PAddr;
Value = *(DWORD *)(N64MEM + PAddr);
if ( ((Value >> 16) == 0x7C7C) && ((Value & 0xFFFF) == count)) {
*(DWORD *)(N64MEM + PAddr) = OrigMem[(WORD)(count)].OriginalValue;
}
}
}
TargetIndex = 0;
//Jump Table
for (count = 0; count < (RdramSize >> 12); count ++ ) {
if (N64_Blocks.NoOfRDRamBlocks[count] > 0) {
N64_Blocks.NoOfRDRamBlocks[count] = 0;
memset(JumpTable + (count << 10),0,0x1000);
*(DelaySlotTable + count) = NULL;
if (VirtualProtect((N64MEM + (count << 12)), 4, PAGE_READWRITE, &OldProtect) == 0) {
DisplayError("Failed to unprotect %X\n1", (count << 12));
}
}
}
if (N64_Blocks.NoOfDMEMBlocks > 0) {
N64_Blocks.NoOfDMEMBlocks = 0;
memset(JumpTable + (0x04000000 >> 2),0,0x1000);
*(DelaySlotTable + (0x04000000 >> 12)) = NULL;
if (VirtualProtect((N64MEM + 0x04000000), 4, PAGE_READWRITE, &OldProtect) == 0) {
DisplayError("Failed to unprotect %X\n0", 0x04000000);
}
}
if (N64_Blocks.NoOfIMEMBlocks > 0) {
N64_Blocks.NoOfIMEMBlocks = 0;
memset(JumpTable + (0x04001000 >> 2),0,0x1000);
*(DelaySlotTable + (0x04001000 >> 12)) = NULL;
if (VirtualProtect((N64MEM + 0x04001000), 4, PAGE_READWRITE, &OldProtect) == 0) {
DisplayError("Failed to unprotect %X\n4", 0x04001000);
}
}
// if (N64_Blocks.NoOfPifRomBlocks > 0) {
// N64_Blocks.NoOfPifRomBlocks = 0;
// memset(JumpTable + (0x1FC00000 >> 2),0,0x1000);
// }
#endif
}
FUNCTION_INFO * CRecompiler::CompileDelaySlot(DWORD PC)
{
WriteTraceF(TraceRecompiler,"Compile Delay Slot: %X",PC);
if ((PC & 0xFFC) != 0) {
DisplayError("Why are you compiling the Delay Slot at %X",PC);
return NULL;
}
if (!r4300i_LW_VAddr(PC, &g_Opcode.Hex)) {
DisplayError("TLB Miss in delay slot\nEmulation will know stop");
return NULL;
}
FUNCTION_INFO * info = m_FunctionsDelaySlot.AddFunctionInfo(PC, _MMU->TranslateVaddr(PC));
CBlockInfo BlockInfo(PROGRAM_COUNTER, RecompPos);
CBlockSection * Section = &BlockInfo.ParentSection;
BYTE * Block = RecompPos;
DWORD StartAddress;
if (!TranslateVaddr(PC, &StartAddress))
{
return NULL;
}
if (StartAddress < RdramSize()) {
CPU_Message("====== RDRAM: Delay Slot ======");
} else if (StartAddress >= 0x04000000 && StartAddress <= 0x04000FFC) {
CPU_Message("====== DMEM: Delay Slot ======");
} else if (StartAddress >= 0x04001000 && StartAddress <= 0x04001FFC) {
CPU_Message("====== IMEM: Delay Slot ======");
} else if (StartAddress >= 0x1FC00000 && StartAddress <= 0x1FC00800) {
CPU_Message("====== PIF ROM: Delay Slot ======");
} else {
CPU_Message("====== Unknown: Delay Slot ======");
}
CPU_Message("x86 code at: %X",Block);
CPU_Message("Delay Slot location: %X",PROGRAM_COUNTER );
CPU_Message("====== recompiled code ======");
Section->AddParent(NULL);
Section->BlockCycleCount() += CountPerOp();
Section->BlockRandomModifier() += 1;
switch (Opcode.op) {
case R4300i_SPECIAL:
switch (Opcode.funct) {
case R4300i_SPECIAL_SLL: Compile_R4300i_SPECIAL_SLL(Section); break;
case R4300i_SPECIAL_SRL: Compile_R4300i_SPECIAL_SRL(Section); break;
case R4300i_SPECIAL_SRA: Compile_R4300i_SPECIAL_SRA(Section); break;
case R4300i_SPECIAL_SLLV: Compile_R4300i_SPECIAL_SLLV(Section); break;
case R4300i_SPECIAL_SRLV: Compile_R4300i_SPECIAL_SRLV(Section); break;
case R4300i_SPECIAL_SRAV: Compile_R4300i_SPECIAL_SRAV(Section); break;
case R4300i_SPECIAL_MFLO: Compile_R4300i_SPECIAL_MFLO(Section); break;
case R4300i_SPECIAL_MTLO: Compile_R4300i_SPECIAL_MTLO(Section); break;
case R4300i_SPECIAL_MFHI: Compile_R4300i_SPECIAL_MFHI(Section); break;
case R4300i_SPECIAL_MTHI: Compile_R4300i_SPECIAL_MTHI(Section); break;
case R4300i_SPECIAL_MULT: Compile_R4300i_SPECIAL_MULT(Section); break;
case R4300i_SPECIAL_DIV: Compile_R4300i_SPECIAL_DIV(Section); break;
case R4300i_SPECIAL_DIVU: Compile_R4300i_SPECIAL_DIVU(Section); break;
case R4300i_SPECIAL_MULTU: Compile_R4300i_SPECIAL_MULTU(Section); break;
case R4300i_SPECIAL_DMULTU: Compile_R4300i_SPECIAL_DMULTU(Section); break;
case R4300i_SPECIAL_DDIVU: Compile_R4300i_SPECIAL_DDIVU(Section); break;
case R4300i_SPECIAL_ADD: Compile_R4300i_SPECIAL_ADD(Section); break;
case R4300i_SPECIAL_ADDU: Compile_R4300i_SPECIAL_ADDU(Section); break;
case R4300i_SPECIAL_SUB: Compile_R4300i_SPECIAL_SUB(Section); break;
case R4300i_SPECIAL_SUBU: Compile_R4300i_SPECIAL_SUBU(Section); break;
case R4300i_SPECIAL_AND: Compile_R4300i_SPECIAL_AND(Section); break;
case R4300i_SPECIAL_OR: Compile_R4300i_SPECIAL_OR(Section); break;
case R4300i_SPECIAL_XOR: Compile_R4300i_SPECIAL_XOR(Section); break;
case R4300i_SPECIAL_SLT: Compile_R4300i_SPECIAL_SLT(Section); break;
case R4300i_SPECIAL_SLTU: Compile_R4300i_SPECIAL_SLTU(Section); break;
case R4300i_SPECIAL_DADD: Compile_R4300i_SPECIAL_DADD(Section); break;
case R4300i_SPECIAL_DADDU: Compile_R4300i_SPECIAL_DADDU(Section); break;
case R4300i_SPECIAL_DSLL32: Compile_R4300i_SPECIAL_DSLL32(Section); break;
case R4300i_SPECIAL_DSRA32: Compile_R4300i_SPECIAL_DSRA32(Section); break;
default:
Compile_R4300i_UnknownOpcode(Section); break;
}
break;
case R4300i_ADDI: Compile_R4300i_ADDI(Section); break;
case R4300i_ADDIU: Compile_R4300i_ADDIU(Section); break;
case R4300i_SLTI: Compile_R4300i_SLTI(Section); break;
case R4300i_SLTIU: Compile_R4300i_SLTIU(Section); break;
case R4300i_ANDI: Compile_R4300i_ANDI(Section); break;
case R4300i_ORI: Compile_R4300i_ORI(Section); break;
case R4300i_XORI: Compile_R4300i_XORI(Section); break;
case R4300i_LUI: Compile_R4300i_LUI(Section); break;
case R4300i_CP1:
switch (Opcode.rs) {
case R4300i_COP1_CF: Compile_R4300i_COP1_CF(Section); break;
case R4300i_COP1_MT: Compile_R4300i_COP1_MT(Section); break;
case R4300i_COP1_CT: Compile_R4300i_COP1_CT(Section); break;
case R4300i_COP1_MF: Compile_R4300i_COP1_MF(Section); break;
case R4300i_COP1_S:
switch (Opcode.funct) {
case R4300i_COP1_FUNCT_ADD: Compile_R4300i_COP1_S_ADD(Section); break;
case R4300i_COP1_FUNCT_SUB: Compile_R4300i_COP1_S_SUB(Section); break;
case R4300i_COP1_FUNCT_MUL: Compile_R4300i_COP1_S_MUL(Section); break;
case R4300i_COP1_FUNCT_DIV: Compile_R4300i_COP1_S_DIV(Section); break;
case R4300i_COP1_FUNCT_ABS: Compile_R4300i_COP1_S_ABS(Section); break;
case R4300i_COP1_FUNCT_NEG: Compile_R4300i_COP1_S_NEG(Section); break;
case R4300i_COP1_FUNCT_SQRT: Compile_R4300i_COP1_S_SQRT(Section); break;
case R4300i_COP1_FUNCT_MOV: Compile_R4300i_COP1_S_MOV(Section); break;
case R4300i_COP1_FUNCT_CVT_D: Compile_R4300i_COP1_S_CVT_D(Section); break;
case R4300i_COP1_FUNCT_ROUND_W: Compile_R4300i_COP1_S_ROUND_W(Section); break;
case R4300i_COP1_FUNCT_TRUNC_W: Compile_R4300i_COP1_S_TRUNC_W(Section); break;
case R4300i_COP1_FUNCT_FLOOR_W: Compile_R4300i_COP1_S_FLOOR_W(Section); break;
case R4300i_COP1_FUNCT_C_F: case R4300i_COP1_FUNCT_C_UN:
case R4300i_COP1_FUNCT_C_EQ: case R4300i_COP1_FUNCT_C_UEQ:
case R4300i_COP1_FUNCT_C_OLT: case R4300i_COP1_FUNCT_C_ULT:
case R4300i_COP1_FUNCT_C_OLE: case R4300i_COP1_FUNCT_C_ULE:
case R4300i_COP1_FUNCT_C_SF: case R4300i_COP1_FUNCT_C_NGLE:
case R4300i_COP1_FUNCT_C_SEQ: case R4300i_COP1_FUNCT_C_NGL:
case R4300i_COP1_FUNCT_C_LT: case R4300i_COP1_FUNCT_C_NGE:
case R4300i_COP1_FUNCT_C_LE: case R4300i_COP1_FUNCT_C_NGT:
Compile_R4300i_COP1_S_CMP(Section); break;
default:
Compile_R4300i_UnknownOpcode(Section); break;
}
break;
case R4300i_COP1_D:
switch (Opcode.funct) {
case R4300i_COP1_FUNCT_ADD: Compile_R4300i_COP1_D_ADD(Section); break;
case R4300i_COP1_FUNCT_SUB: Compile_R4300i_COP1_D_SUB(Section); break;
case R4300i_COP1_FUNCT_MUL: Compile_R4300i_COP1_D_MUL(Section); break;
case R4300i_COP1_FUNCT_DIV: Compile_R4300i_COP1_D_DIV(Section); break;
case R4300i_COP1_FUNCT_ABS: Compile_R4300i_COP1_D_ABS(Section); break;
case R4300i_COP1_FUNCT_NEG: Compile_R4300i_COP1_D_NEG(Section); break;
case R4300i_COP1_FUNCT_SQRT: Compile_R4300i_COP1_D_SQRT(Section); break;
case R4300i_COP1_FUNCT_MOV: Compile_R4300i_COP1_D_MOV(Section); break;
case R4300i_COP1_FUNCT_TRUNC_W: Compile_R4300i_COP1_D_TRUNC_W(Section); break;
case R4300i_COP1_FUNCT_CVT_S: Compile_R4300i_COP1_D_CVT_S(Section); break;
case R4300i_COP1_FUNCT_CVT_W: Compile_R4300i_COP1_D_CVT_W(Section); break;
case R4300i_COP1_FUNCT_C_F: case R4300i_COP1_FUNCT_C_UN:
case R4300i_COP1_FUNCT_C_EQ: case R4300i_COP1_FUNCT_C_UEQ:
case R4300i_COP1_FUNCT_C_OLT: case R4300i_COP1_FUNCT_C_ULT:
case R4300i_COP1_FUNCT_C_OLE: case R4300i_COP1_FUNCT_C_ULE:
case R4300i_COP1_FUNCT_C_SF: case R4300i_COP1_FUNCT_C_NGLE:
case R4300i_COP1_FUNCT_C_SEQ: case R4300i_COP1_FUNCT_C_NGL:
case R4300i_COP1_FUNCT_C_LT: case R4300i_COP1_FUNCT_C_NGE:
case R4300i_COP1_FUNCT_C_LE: case R4300i_COP1_FUNCT_C_NGT:
Compile_R4300i_COP1_D_CMP(Section); break;
default:
Compile_R4300i_UnknownOpcode(Section); break;
}
break;
case R4300i_COP1_W:
switch (Opcode.funct) {
case R4300i_COP1_FUNCT_CVT_S: Compile_R4300i_COP1_W_CVT_S(Section); break;
case R4300i_COP1_FUNCT_CVT_D: Compile_R4300i_COP1_W_CVT_D(Section); break;
default:
Compile_R4300i_UnknownOpcode(Section); break;
}
break;
default:
Compile_R4300i_UnknownOpcode(Section); break;
}
break;
case R4300i_LB: Compile_R4300i_LB(Section); break;
case R4300i_LH: Compile_R4300i_LH(Section); break;
case R4300i_LW: Compile_R4300i_LW(Section); break;
case R4300i_LBU: Compile_R4300i_LBU(Section); break;
case R4300i_LHU: Compile_R4300i_LHU(Section); break;
case R4300i_SB: Compile_R4300i_SB(Section); break;
case R4300i_SH: Compile_R4300i_SH(Section); break;
case R4300i_SW: Compile_R4300i_SW(Section); break;
case R4300i_SWR: Compile_R4300i_SWR(Section); break;
case R4300i_CACHE: Compile_R4300i_CACHE(Section); break;
case R4300i_LWC1: Compile_R4300i_LWC1(Section); break;
case R4300i_LDC1: Compile_R4300i_LDC1(Section); break;
case R4300i_LD: Compile_R4300i_LD(Section); break;
case R4300i_SWC1: Compile_R4300i_SWC1(Section); break;
case R4300i_SDC1: Compile_R4300i_SDC1(Section); break;
case R4300i_SD: Compile_R4300i_SD(Section); break;
default:
Compile_R4300i_UnknownOpcode(Section); break;
}
Section->ResetX86Protection();
WriteBackRegisters(Section);
UpdateCounters(&Section->BlockCycleCount(),&Section->BlockRandomModifier(), FALSE);
int x86Reg = Map_TempReg(Section,x86_Any,-1,FALSE);
MoveVariableToX86reg(&JumpToLocation,"JumpToLocation",x86Reg);
MoveX86regToVariable(x86Reg,&PROGRAM_COUNTER,"PROGRAM_COUNTER");
MoveConstToVariable(NORMAL,&NextInstruction,"NextInstruction");
if (CPU_Type == CPU_SyncCores) { Call_Direct(SyncToPC, "SyncToPC"); }
Ret();
CompileExitCode(BlockInfo);
CPU_Message("====== End of recompiled code ======");
info->SetVEndPC(BlockInfo.EndVAddr);
info->SetFunctionAddr(BlockInfo.CompiledLocation);
_MMU->VAddrToRealAddr(info->VStartPC(),*(reinterpret_cast<void **>(&info->MemLocation[0])));
info->MemLocation[1] = info->MemLocation[0] + 1;
info->MemContents[0] = *info->MemLocation[0];
info->MemContents[1] = *info->MemLocation[1];
NextInstruction = NORMAL;
return info;
}
bool CRecompiler::AnalyseBlock ( CBlockInfo & BlockInfo)
{
if (bLinkBlocks())
{
CBlockSection * Section = &BlockInfo.ParentSection;
if (!CreateSectionLinkage (Section)) { return false; }
DetermineLoop(Section,CBlockSection::GetNewTestValue(),CBlockSection::GetNewTestValue(), Section->SectionID);
while (FixConstants(Section,CBlockSection::GetNewTestValue())) {}
}
return true;
}
bool CRecompiler::FixConstants (CBlockSection * Section, DWORD Test)
{
if (Section == NULL) { return false; }
if (Section->Test == Test) { return false; }
Section->Test = Test;
InheritConstants(Section);
bool Changed = false;
/* BLOCK_SECTION * Parent;
int count, NoOfParents;
REG_INFO Original[2];
*/
CRegInfo Original[2] = { Section->Cont.RegSet, Section->Jump.RegSet };
if (!Section->ParentSection.empty()) {
for (SECTION_LIST::iterator iter = Section->ParentSection.begin(); iter != Section->ParentSection.end(); iter++)
{
CBlockSection * Parent = *iter;
if (Parent->ContinueSection == Section) {
for (int count = 0; count < 32; count++) {
if (Section->RegStart.MipsRegState(count) != Parent->Cont.RegSet.MipsRegState(count)) {
Section->RegStart.MipsRegState(count) = CRegInfo::STATE_UNKNOWN;
//*Changed = true;
}
Section->RegStart.MipsRegState(count) = CRegInfo::STATE_UNKNOWN;
}
}
if (Parent->JumpSection == Section) {
for (int count = 0; count < 32; count++) {
if (Section->RegStart.MipsRegState(count) != Parent->Jump.RegSet.MipsRegState(count)) {
Section->RegStart.MipsRegState(count) = CRegInfo::STATE_UNKNOWN;
//*Changed = true;
}
}
}
Section->RegWorking = Section->RegStart;
}
}
FillSectionInfo(Section, NORMAL);
if (Original[0] != Section->Cont.RegSet)
{
Changed = true;
}
if (Original[1] != Section->Jump.RegSet)
{
Changed = true;
}
if (Section->JumpSection && FixConstants(Section->JumpSection,Test)) { Changed = true; }
if (Section->ContinueSection && FixConstants(Section->ContinueSection,Test)) { Changed = true; }
return Changed;
}
void CRecompiler::InheritConstants(CBlockSection * Section)
{
if (Section->ParentSection.empty())
{
Section->RegStart.Initilize();
Section->RegWorking = Section->RegStart;
return;
}
CBlockSection * Parent = *(Section->ParentSection.begin());
CRegInfo * RegSet = (Section == Parent->ContinueSection?&Parent->Cont.RegSet:&Parent->Jump.RegSet);
Section->RegStart = *RegSet;
Section->RegWorking = *RegSet;
for (SECTION_LIST::iterator iter = Section->ParentSection.begin(); iter != Section->ParentSection.end(); iter++)
{
if (iter == Section->ParentSection.begin()) { continue; }
Parent = *iter;
RegSet = Section == Parent->ContinueSection?&Parent->Cont.RegSet:&Parent->Jump.RegSet;
for (int count = 0; count < 32; count++) {
if (Section->IsConst(count)) {
if (Section->MipsRegState(count) != RegSet->MipsRegState(count)) {
Section->MipsRegState(count) = CRegInfo::STATE_UNKNOWN;
} else if (Section->Is32Bit(count) && Section->MipsRegLo(count) != RegSet->MipsRegLo(count)) {
Section->MipsRegState(count) = CRegInfo::STATE_UNKNOWN;
} else if (Section->Is64Bit(count) && Section->MipsReg(count) != RegSet->MipsReg(count)) {
Section->MipsRegState(count) = CRegInfo::STATE_UNKNOWN;
}
}
}
}
Section->RegStart = Section->RegWorking;
}
CBlockSection * CRecompiler::ExistingSection(CBlockSection * StartSection, DWORD Addr, DWORD Test)
{
if (StartSection == NULL) { return NULL; }
if (StartSection->StartPC == Addr && StartSection->LinkAllowed)
{
return StartSection;
}
if (StartSection->Test == Test) { return NULL; }
StartSection->Test = Test;
CBlockSection * Section = ExistingSection(StartSection->JumpSection,Addr,Test);
if (Section != NULL) { return Section; }
Section = ExistingSection(StartSection->ContinueSection,Addr,Test);
if (Section != NULL) { return Section; }
return NULL;
}
bool CRecompiler::CreateSectionLinkage (CBlockSection * Section) {
InheritConstants(Section);
if (!FillSectionInfo(Section,NORMAL))
{
return false;
}
CBlockSection ** TargetSection[2];
CJumpInfo * JumpInfo[2];
if (Section->Jump.TargetPC < Section->Cont.TargetPC) {
TargetSection[0] = (CBlockSection **)&Section->JumpSection;
TargetSection[1] = (CBlockSection **)&Section->ContinueSection;
JumpInfo[0] = &Section->Jump;
JumpInfo[1] = &Section->Cont;
} else {
TargetSection[0] = (CBlockSection **)&Section->ContinueSection;
TargetSection[1] = (CBlockSection **)&Section->JumpSection;
JumpInfo[0] = &Section->Cont;
JumpInfo[1] = &Section->Jump;
}
CBlockInfo * BlockInfo = Section->BlockInfo;
for (int count = 0; count < 2; count ++)
{
if (JumpInfo[count]->TargetPC == (DWORD)-1 || *TargetSection[count] != NULL)
{
continue;
}
if (!JumpInfo[count]->DoneDelaySlot)
{
Section->Jump.RegSet = Section->RegWorking;
//this is a special delay slot section
BlockInfo->NoOfSections += 1;
*TargetSection[count] = new CBlockSection(BlockInfo,Section->CompilePC + 4,BlockInfo->NoOfSections);
(*TargetSection[count])->AddParent(Section);
(*TargetSection[count])->LinkAllowed = false;
InheritConstants((*TargetSection[count]));
if (!FillSectionInfo((*TargetSection[count]),END_BLOCK))
{
return false;
}
(*TargetSection[count])->Jump.TargetPC = -1;
(*TargetSection[count])->Cont.TargetPC = JumpInfo[count]->TargetPC;
(*TargetSection[count])->Cont.FallThrough = true;
(*TargetSection[count])->Cont.RegSet = (*TargetSection[count])->RegWorking;
JumpInfo[count]->TargetPC = Section->CompilePC + 4;
//Create the section that joins with that block
(*TargetSection[count])->ContinueSection = ExistingSection(&BlockInfo->ParentSection,(*TargetSection[count])->Cont.TargetPC,CBlockSection::GetNewTestValue());
if ((*TargetSection[count])->ContinueSection == NULL) {
BlockInfo->NoOfSections += 1;
(*TargetSection[count])->ContinueSection = new CBlockSection(BlockInfo,(*TargetSection[count])->Cont.TargetPC,BlockInfo->NoOfSections);
(*TargetSection[count])->ContinueSection->AddParent((*TargetSection[count]));
CreateSectionLinkage((*TargetSection[count])->ContinueSection);
} else {
(*TargetSection[count])->ContinueSection->AddParent((*TargetSection[count]));
}
} else {
*TargetSection[count] = ExistingSection(&BlockInfo->ParentSection,JumpInfo[count]->TargetPC,CBlockSection::GetNewTestValue());
if (*TargetSection[count] == NULL) {
BlockInfo->NoOfSections += 1;
*TargetSection[count] = new CBlockSection(BlockInfo,JumpInfo[count]->TargetPC,BlockInfo->NoOfSections);
(*TargetSection[count])->AddParent(Section);
CreateSectionLinkage(*TargetSection[count]);
} else {
(*TargetSection[count])->AddParent(Section);
}
}
}
return true;
}
bool CRecompiler::FillSectionInfo(CBlockSection * Section, STEP_TYPE StartStepType)
{
OPCODE Command;
if (Section->CompiledLocation != NULL) { return true; }
Section->CompilePC = Section->StartPC;
Section->RegWorking = Section->RegStart;
NextInstruction = StartStepType;
do {
if (!r4300i_LW_VAddr(Section->CompilePC, &Command.Hex)) {
DisplayError(GS(MSG_FAIL_LOAD_WORD));
return false;
}
switch (Command.op) {
case R4300i_SPECIAL:
switch (Command.funct) {
case R4300i_SPECIAL_SLL:
if (Command.rd == 0) { break; }
if (Section->InLoop && Command.rt == Command.rd) {
Section->MipsRegState(Command.rd) = CRegInfo::STATE_UNKNOWN;
}
if (Section->IsConst(Command.rt)) {
Section->MipsRegState(Command.rd) = CRegInfo::STATE_CONST_32;
Section->MipsRegLo(Command.rd) = Section->MipsRegLo(Command.rt) << Command.sa;
} else {
Section->MipsRegState(Command.rd) = CRegInfo::STATE_UNKNOWN;
}
break;
case R4300i_SPECIAL_SRL:
if (Command.rd == 0) { break; }
if (Section->InLoop && Command.rt == Command.rd) {
Section->MipsRegState(Command.rd) = CRegInfo::STATE_UNKNOWN;
}
if (Section->IsConst(Command.rt)) {
Section->MipsRegState(Command.rd) = CRegInfo::STATE_CONST_32;
Section->MipsRegLo(Command.rd) = Section->MipsRegLo(Command.rt) >> Command.sa;
} else {
Section->MipsRegState(Command.rd) = CRegInfo::STATE_UNKNOWN;
}
break;
case R4300i_SPECIAL_SRA:
if (Command.rd == 0) { break; }
if (Section->InLoop && Command.rt == Command.rd) {
Section->MipsRegState(Command.rd) = CRegInfo::STATE_UNKNOWN;
}
if (Section->IsConst(Command.rt)) {
Section->MipsRegState(Command.rd) = CRegInfo::STATE_CONST_32;
Section->MipsRegLo(Command.rd) = Section->MipsRegLo_S(Command.rt) >> Command.sa;
} else {
Section->MipsRegState(Command.rd) = CRegInfo::STATE_UNKNOWN;
}
break;
case R4300i_SPECIAL_SLLV:
if (Command.rd == 0) { break; }
if (Section->InLoop && (Command.rt == Command.rd || Command.rs == Command.rd)) {
Section->MipsRegState(Command.rd) = CRegInfo::STATE_UNKNOWN;
}
if (Section->IsConst(Command.rt) && Section->IsConst(Command.rs)) {
Section->MipsRegState(Command.rd) = CRegInfo::STATE_CONST_32;
Section->MipsRegLo(Command.rd) = Section->MipsRegLo(Command.rt) << (Section->MipsRegLo(Command.rs) & 0x1F);
} else {
Section->MipsRegState(Command.rd) = CRegInfo::STATE_UNKNOWN;
}
break;
case R4300i_SPECIAL_SRLV:
if (Command.rd == 0) { break; }
if (Section->InLoop && (Command.rt == Command.rd || Command.rs == Command.rd)) {
Section->MipsRegState(Command.rd) = CRegInfo::STATE_UNKNOWN;
}
if (Section->IsConst(Command.rt) && Section->IsConst(Command.rs)) {
Section->MipsRegState(Command.rd) = CRegInfo::STATE_CONST_32;
Section->MipsRegLo(Command.rd) = Section->MipsRegLo(Command.rt) >> (Section->MipsRegLo(Command.rs) & 0x1F);
} else {
Section->MipsRegState(Command.rd) = CRegInfo::STATE_UNKNOWN;
}
break;
case R4300i_SPECIAL_SRAV:
if (Command.rd == 0) { break; }
if (Section->InLoop && (Command.rt == Command.rd || Command.rs == Command.rd)) {
Section->MipsRegState(Command.rd) = CRegInfo::STATE_UNKNOWN;
}
if (Section->IsConst(Command.rt) && Section->IsConst(Command.rs)) {
Section->MipsRegState(Command.rd) = CRegInfo::STATE_CONST_32;
Section->MipsRegLo(Command.rd) = Section->MipsRegLo_S(Command.rt) >> (Section->MipsRegLo(Command.rs) & 0x1F);
} else {
Section->MipsRegState(Command.rd) = CRegInfo::STATE_UNKNOWN;
}
break;
case R4300i_SPECIAL_JR:
if (Section->IsConst(Command.rs)) {
Section->Jump.TargetPC = Section->MipsRegLo(Command.rs);
} else {
Section->Jump.TargetPC = (DWORD)-1;
}
NextInstruction = DELAY_SLOT;
break;
case R4300i_SPECIAL_JALR:
Section->MipsRegLo(Opcode.rd) = Section->CompilePC + 8;
Section->MipsRegState(Opcode.rd) = CRegInfo::STATE_CONST_32;
if (Section->IsConst(Command.rs)) {
Section->Jump.TargetPC = Section->MipsRegLo(Command.rs);
} else {
Section->Jump.TargetPC = (DWORD)-1;
}
NextInstruction = DELAY_SLOT;
break;
case R4300i_SPECIAL_SYSCALL:
case R4300i_SPECIAL_BREAK:
NextInstruction = END_BLOCK;
Section->CompilePC -= 4;
break;
case R4300i_SPECIAL_MFHI: Section->MipsRegState(Command.rd) = CRegInfo::STATE_UNKNOWN; break;
case R4300i_SPECIAL_MTHI: break;
case R4300i_SPECIAL_MFLO: Section->MipsRegState(Command.rd) = CRegInfo::STATE_UNKNOWN; break;
case R4300i_SPECIAL_MTLO: break;
case R4300i_SPECIAL_DSLLV:
if (Command.rd == 0) { break; }
if (Section->InLoop && (Command.rt == Command.rd || Command.rs == Command.rd)) {
Section->MipsRegState(Command.rd) = CRegInfo::STATE_UNKNOWN;
}
if (Section->IsConst(Command.rt) && Section->IsConst(Command.rs)) {
Section->MipsRegState(Command.rd) = CRegInfo::STATE_CONST_64;
Section->MipsReg(Command.rd) = Section->Is64Bit(Command.rt)?Section->MipsReg(Command.rt):(QWORD)Section->MipsRegLo_S(Command.rt) << (Section->MipsRegLo(Command.rs) & 0x3F);
} else {
Section->MipsRegState(Command.rd) = CRegInfo::STATE_UNKNOWN;
}
break;
case R4300i_SPECIAL_DSRLV:
if (Command.rd == 0) { break; }
if (Section->InLoop && (Command.rt == Command.rd || Command.rs == Command.rd)) {
Section->MipsRegState(Command.rd) = CRegInfo::STATE_UNKNOWN;
}
if (Section->IsConst(Command.rt) && Section->IsConst(Command.rs)) {
Section->MipsRegState(Command.rd) = CRegInfo::STATE_CONST_64;
Section->MipsReg(Command.rd) = Section->Is64Bit(Command.rt)?Section->MipsReg(Command.rt):(QWORD)Section->MipsRegLo_S(Command.rt) >> (Section->MipsRegLo(Command.rs) & 0x3F);
} else {
Section->MipsRegState(Command.rd) = CRegInfo::STATE_UNKNOWN;
}
break;
case R4300i_SPECIAL_DSRAV:
if (Command.rd == 0) { break; }
if (Section->InLoop && (Command.rt == Command.rd || Command.rs == Command.rd)) {
Section->MipsRegState(Command.rd) = CRegInfo::STATE_UNKNOWN;
}
if (Section->IsConst(Command.rt) && Section->IsConst(Command.rs)) {
Section->MipsRegState(Command.rd) = CRegInfo::STATE_CONST_64;
Section->MipsReg(Command.rd) = Section->Is64Bit(Command.rt)?Section->MipsReg_S(Command.rt):(_int64)Section->MipsRegLo_S(Command.rt) >> (Section->MipsRegLo(Command.rs) & 0x3F);
} else {
Section->MipsRegState(Command.rd) = CRegInfo::STATE_UNKNOWN;
}
break;
case R4300i_SPECIAL_MULT: break;
case R4300i_SPECIAL_MULTU: break;
case R4300i_SPECIAL_DIV: break;
case R4300i_SPECIAL_DIVU: break;
case R4300i_SPECIAL_DMULT: break;
case R4300i_SPECIAL_DMULTU: break;
case R4300i_SPECIAL_DDIV: break;
case R4300i_SPECIAL_DDIVU: break;
case R4300i_SPECIAL_ADD:
case R4300i_SPECIAL_ADDU:
if (Command.rd == 0) { break; }
if (Section->InLoop && (Command.rt == Command.rd || Command.rs == Command.rd)) {
Section->MipsRegState(Command.rd) = CRegInfo::STATE_UNKNOWN;
}
if (Section->IsConst(Command.rt) && Section->IsConst(Command.rs)) {
Section->MipsRegLo(Command.rd) = Section->MipsRegLo(Command.rs) + Section->MipsRegLo(Command.rt);
Section->MipsRegState(Command.rd) = CRegInfo::STATE_CONST_32;
} else {
Section->MipsRegState(Command.rd) = CRegInfo::STATE_UNKNOWN;
}
break;
case R4300i_SPECIAL_SUB:
case R4300i_SPECIAL_SUBU:
if (Command.rd == 0) { break; }
if (Section->InLoop && (Command.rt == Command.rd || Command.rs == Command.rd)) {
Section->MipsRegState(Command.rd) = CRegInfo::STATE_UNKNOWN;
}
if (Section->IsConst(Command.rt) && Section->IsConst(Command.rs)) {
Section->MipsRegLo(Command.rd) = Section->MipsRegLo(Command.rs) - Section->MipsRegLo(Command.rt);
Section->MipsRegState(Command.rd) = CRegInfo::STATE_CONST_32;
} else {
Section->MipsRegState(Command.rd) = CRegInfo::STATE_UNKNOWN;
}
break;
case R4300i_SPECIAL_AND:
if (Command.rd == 0) { break; }
if (Section->InLoop && (Command.rt == Command.rd || Command.rs == Command.rd)) {
Section->MipsRegState(Command.rd) = CRegInfo::STATE_UNKNOWN;
}
if (Section->IsConst(Command.rt) && Section->IsConst(Command.rs)) {
if (Section->Is64Bit(Command.rt) && Section->Is64Bit(Command.rs)) {
Section->MipsReg(Command.rd) = Section->MipsReg(Command.rt) & Section->MipsReg(Command.rs);
Section->MipsRegState(Command.rd) = CRegInfo::STATE_CONST_64;
} else if (Section->Is64Bit(Command.rt) || Section->Is64Bit(Command.rs)) {
if (Section->Is64Bit(Command.rt)) {
Section->MipsReg(Command.rd) = Section->MipsReg(Command.rt) & Section->MipsRegLo(Command.rs);
} else {
Section->MipsReg(Command.rd) = Section->MipsRegLo(Command.rt) & Section->MipsReg(Command.rs);
}
Section->MipsRegState(Command.rd) = CRegInfo::ConstantsType(Section->MipsReg(Command.rd));
} else {
Section->MipsRegLo(Command.rd) = Section->MipsRegLo(Command.rt) & Section->MipsRegLo(Command.rs);
Section->MipsRegState(Command.rd) = CRegInfo::STATE_CONST_32;
}
} else {
Section->MipsRegState(Command.rd) = CRegInfo::STATE_UNKNOWN;
}
break;
case R4300i_SPECIAL_OR:
if (Command.rd == 0) { break; }
if (Section->InLoop && (Command.rt == Command.rd || Command.rs == Command.rd)) {
Section->MipsRegState(Command.rd) = CRegInfo::STATE_UNKNOWN;
}
if (Section->IsConst(Command.rt) && Section->IsConst(Command.rs)) {
if (Section->Is64Bit(Command.rt) && Section->Is64Bit(Command.rs)) {
Section->MipsReg(Command.rd) = Section->MipsReg(Command.rt) | Section->MipsReg(Command.rs);
Section->MipsRegState(Command.rd) = CRegInfo::STATE_CONST_64;
} else if (Section->Is64Bit(Command.rt) || Section->Is64Bit(Command.rs)) {
if (Section->Is64Bit(Command.rt)) {
Section->MipsReg(Command.rd) = Section->MipsReg(Command.rt) | Section->MipsRegLo(Command.rs);
} else {
Section->MipsReg(Command.rd) = Section->MipsRegLo(Command.rt) | Section->MipsReg(Command.rs);
}
Section->MipsRegState(Command.rd) = CRegInfo::STATE_CONST_64;
} else {
Section->MipsRegLo(Command.rd) = Section->MipsRegLo(Command.rt) | Section->MipsRegLo(Command.rs);
Section->MipsRegState(Command.rd) = CRegInfo::STATE_CONST_32;
}
} else {
Section->MipsRegState(Command.rd) = CRegInfo::STATE_UNKNOWN;
}
break;
case R4300i_SPECIAL_XOR:
if (Command.rd == 0) { break; }
if (Section->InLoop && (Command.rt == Command.rd || Command.rs == Command.rd)) {
Section->MipsRegState(Command.rd) = CRegInfo::STATE_UNKNOWN;
}
if (Section->IsConst(Command.rt) && Section->IsConst(Command.rs)) {
if (Section->Is64Bit(Command.rt) && Section->Is64Bit(Command.rs)) {
Section->MipsReg(Command.rd) = Section->MipsReg(Command.rt) ^ Section->MipsReg(Command.rs);
Section->MipsRegState(Command.rd) = CRegInfo::STATE_CONST_64;
} else if (Section->Is64Bit(Command.rt) || Section->Is64Bit(Command.rs)) {
if (Section->Is64Bit(Command.rt)) {
Section->MipsReg(Command.rd) = Section->MipsReg(Command.rt) ^ Section->MipsRegLo(Command.rs);
} else {
Section->MipsReg(Command.rd) = Section->MipsRegLo(Command.rt) ^ Section->MipsReg(Command.rs);
}
Section->MipsRegState(Command.rd) = CRegInfo::STATE_CONST_64;
} else {
Section->MipsRegLo(Command.rd) = Section->MipsRegLo(Command.rt) ^ Section->MipsRegLo(Command.rs);
Section->MipsRegState(Command.rd) = CRegInfo::STATE_CONST_32;
}
} else {
Section->MipsRegState(Command.rd) = CRegInfo::STATE_UNKNOWN;
}
break;
case R4300i_SPECIAL_NOR:
if (Command.rd == 0) { break; }
if (Section->InLoop && (Command.rt == Command.rd || Command.rs == Command.rd)) {
Section->MipsRegState(Command.rd) = CRegInfo::STATE_UNKNOWN;
}
if (Section->IsConst(Command.rt) && Section->IsConst(Command.rs)) {
if (Section->Is64Bit(Command.rt) && Section->Is64Bit(Command.rs)) {
Section->MipsReg(Command.rd) = ~(Section->MipsReg(Command.rt) | Section->MipsReg(Command.rs));
Section->MipsRegState(Command.rd) = CRegInfo::STATE_CONST_64;
} else if (Section->Is64Bit(Command.rt) || Section->Is64Bit(Command.rs)) {
if (Section->Is64Bit(Command.rt)) {
Section->MipsReg(Command.rd) = ~(Section->MipsReg(Command.rt) | Section->MipsRegLo(Command.rs));
} else {
Section->MipsReg(Command.rd) = ~(Section->MipsRegLo(Command.rt) | Section->MipsReg(Command.rs));
}
Section->MipsRegState(Command.rd) = CRegInfo::STATE_CONST_64;
} else {
Section->MipsRegLo(Command.rd) = ~(Section->MipsRegLo(Command.rt) | Section->MipsRegLo(Command.rs));
Section->MipsRegState(Command.rd) = CRegInfo::STATE_CONST_32;
}
} else {
Section->MipsRegState(Command.rd) = CRegInfo::STATE_UNKNOWN;
}
break;
case R4300i_SPECIAL_SLT:
if (Command.rd == 0) { break; }
if (Section->IsConst(Command.rt) && Section->IsConst(Command.rs)) {
if (Section->Is64Bit(Command.rt) || Section->Is64Bit(Command.rs)) {
if (Section->Is64Bit(Command.rt)) {
Section->MipsRegLo(Command.rd) = (Section->MipsRegLo_S(Command.rs) < Section->MipsReg_S(Command.rt))?1:0;
} else {
Section->MipsRegLo(Command.rd) = (Section->MipsReg_S(Command.rs) < Section->MipsRegLo_S(Command.rt))?1:0;
}
} else {
Section->MipsRegLo(Command.rd) = (Section->MipsRegLo_S(Command.rs) < Section->MipsRegLo_S(Command.rt))?1:0;
}
Section->MipsRegState(Command.rd) = CRegInfo::STATE_CONST_32;
} else {
Section->MipsRegState(Command.rd) = CRegInfo::STATE_UNKNOWN;
}
break;
case R4300i_SPECIAL_SLTU:
if (Command.rd == 0) { break; }
if (Section->IsConst(Command.rt) && Section->IsConst(Command.rs)) {
if (Section->Is64Bit(Command.rt) || Section->Is64Bit(Command.rs)) {
if (Section->Is64Bit(Command.rt)) {
Section->MipsRegLo(Command.rd) = (Section->MipsRegLo(Command.rs) < Section->MipsReg(Command.rt))?1:0;
} else {
Section->MipsRegLo(Command.rd) = (Section->MipsReg(Command.rs) < Section->MipsRegLo(Command.rt))?1:0;
}
} else {
Section->MipsRegLo(Command.rd) = (Section->MipsRegLo(Command.rs) < Section->MipsRegLo(Command.rt))?1:0;
}
Section->MipsRegState(Command.rd) = CRegInfo::STATE_CONST_32;
} else {
Section->MipsRegState(Command.rd) = CRegInfo::STATE_UNKNOWN;
}
break;
case R4300i_SPECIAL_DADD:
case R4300i_SPECIAL_DADDU:
if (Command.rd == 0) { break; }
if (Section->InLoop && (Command.rt == Command.rd || Command.rs == Command.rd)) {
Section->MipsRegState(Command.rd) = CRegInfo::STATE_UNKNOWN;
}
if (Section->IsConst(Command.rt) && Section->IsConst(Command.rs)) {
Section->MipsReg(Command.rd) =
Section->Is64Bit(Command.rs)?Section->MipsReg(Command.rs):(_int64)Section->MipsRegLo_S(Command.rs) +
Section->Is64Bit(Command.rt)?Section->MipsReg(Command.rt):(_int64)Section->MipsRegLo_S(Command.rt);
Section->MipsRegState(Command.rd) = CRegInfo::STATE_CONST_64;
} else {
Section->MipsRegState(Command.rd) = CRegInfo::STATE_UNKNOWN;
}
break;
case R4300i_SPECIAL_DSUB:
case R4300i_SPECIAL_DSUBU:
if (Command.rd == 0) { break; }
if (Section->InLoop && (Command.rt == Command.rd || Command.rs == Command.rd)) {
Section->MipsRegState(Command.rd) = CRegInfo::STATE_UNKNOWN;
}
if (Section->IsConst(Command.rt) && Section->IsConst(Command.rs)) {
Section->MipsReg(Command.rd) =
Section->Is64Bit(Command.rs)?Section->MipsReg(Command.rs):(_int64)Section->MipsRegLo_S(Command.rs) -
Section->Is64Bit(Command.rt)?Section->MipsReg(Command.rt):(_int64)Section->MipsRegLo_S(Command.rt);
Section->MipsRegState(Command.rd) = CRegInfo::STATE_CONST_64;
} else {
Section->MipsRegState(Command.rd) = CRegInfo::STATE_UNKNOWN;
}
break;
case R4300i_SPECIAL_DSLL:
if (Command.rd == 0) { break; }
if (Section->InLoop && Command.rt == Command.rd) {
Section->MipsRegState(Command.rd) = CRegInfo::STATE_UNKNOWN;
}
if (Section->IsConst(Command.rt)) {
Section->MipsRegState(Command.rd) = CRegInfo::STATE_CONST_64;
Section->MipsReg(Command.rd) = Section->Is64Bit(Command.rt)?Section->MipsReg(Command.rt):(_int64)Section->MipsRegLo_S(Command.rt) << Command.sa;
} else {
Section->MipsRegState(Command.rd) = CRegInfo::STATE_UNKNOWN;
}
break;
case R4300i_SPECIAL_DSRL:
if (Command.rd == 0) { break; }
if (Section->InLoop && Command.rt == Command.rd) {
Section->MipsRegState(Command.rd) = CRegInfo::STATE_UNKNOWN;
}
if (Section->IsConst(Command.rt)) {
Section->MipsRegState(Command.rd) = CRegInfo::STATE_CONST_64;
Section->MipsReg(Command.rd) = Section->Is64Bit(Command.rt)?Section->MipsReg(Command.rt):(QWORD)Section->MipsRegLo_S(Command.rt) >> Command.sa;
} else {
Section->MipsRegState(Command.rd) = CRegInfo::STATE_UNKNOWN;
}
break;
case R4300i_SPECIAL_DSRA:
if (Command.rd == 0) { break; }
if (Section->InLoop && Command.rt == Command.rd) {
Section->MipsRegState(Command.rd) = CRegInfo::STATE_UNKNOWN;
}
if (Section->IsConst(Command.rt)) {
Section->MipsRegState(Command.rd) = CRegInfo::STATE_CONST_64;
Section->MipsReg_S(Command.rd) = Section->Is64Bit(Command.rt)?Section->MipsReg_S(Command.rt):(_int64)Section->MipsRegLo_S(Command.rt) >> Command.sa;
} else {
Section->MipsRegState(Command.rd) = CRegInfo::STATE_UNKNOWN;
}
break;
case R4300i_SPECIAL_DSLL32:
if (Command.rd == 0) { break; }
if (Section->InLoop && Command.rt == Command.rd) {
Section->MipsRegState(Command.rd) = CRegInfo::STATE_UNKNOWN;
}
if (Section->IsConst(Command.rt)) {
Section->MipsRegState(Command.rd) = CRegInfo::STATE_CONST_64;
Section->MipsReg(Command.rd) = Section->MipsRegLo(Command.rt) << (Command.sa + 32);
} else {
Section->MipsRegState(Command.rd) = CRegInfo::STATE_UNKNOWN;
}
break;
case R4300i_SPECIAL_DSRL32:
if (Command.rd == 0) { break; }
if (Section->InLoop && Command.rt == Command.rd) {
Section->MipsRegState(Command.rd) = CRegInfo::STATE_UNKNOWN;
}
if (Section->IsConst(Command.rt)) {
Section->MipsRegState(Command.rd) = CRegInfo::STATE_CONST_32;
Section->MipsRegLo(Command.rd) = (DWORD)(Section->MipsReg(Command.rt) >> (Command.sa + 32));
} else {
Section->MipsRegState(Command.rd) = CRegInfo::STATE_UNKNOWN;
}
break;
case R4300i_SPECIAL_DSRA32:
if (Command.rd == 0) { break; }
if (Section->InLoop && Command.rt == Command.rd) {
Section->MipsRegState(Command.rd) = CRegInfo::STATE_UNKNOWN;
}
if (Section->IsConst(Command.rt)) {
Section->MipsRegState(Command.rd) = CRegInfo::STATE_CONST_32;
Section->MipsRegLo(Command.rd) = (DWORD)(Section->MipsReg_S(Command.rt) >> (Command.sa + 32));
} else {
Section->MipsRegState(Command.rd) = CRegInfo::STATE_UNKNOWN;
}
break;
default:
#ifndef EXTERNAL_RELEASE
if (Command.Hex == 0x00000001) { break; }
DisplayError("Unhandled R4300i OpCode in FillSectionInfo 5\n%s",
R4300iOpcodeName(Command.Hex,Section->CompilePC));
#endif
NextInstruction = END_BLOCK;
Section->CompilePC -= 4;
}
break;
case R4300i_REGIMM:
switch (Command.rt) {
case R4300i_REGIMM_BLTZ:
case R4300i_REGIMM_BGEZ:
NextInstruction = DELAY_SLOT;
Section->Cont.TargetPC = Section->CompilePC + 8;
Section->Jump.TargetPC = Section->CompilePC + ((short)Command.offset << 2) + 4;
if (Section->CompilePC == Section->Jump.TargetPC) {
if (!DelaySlotEffectsCompare(Section->CompilePC,Command.rs,0)) {
Section->Jump.PermLoop = true;
}
}
break;
case R4300i_REGIMM_BLTZL:
case R4300i_REGIMM_BGEZL:
NextInstruction = LIKELY_DELAY_SLOT;
Section->Cont.TargetPC = Section->CompilePC + 8;
Section->Jump.TargetPC = Section->CompilePC + ((short)Command.offset << 2) + 4;
if (Section->CompilePC == Section->Jump.TargetPC) {
if (!DelaySlotEffectsCompare(Section->CompilePC,Command.rs,0)) {
Section->Jump.PermLoop = true;
}
}
break;
case R4300i_REGIMM_BLTZAL:
Section->MipsRegLo(31) = Section->CompilePC + 8;
Section->MipsRegState(31) = CRegInfo::STATE_CONST_32;
Section->Cont.TargetPC = Section->CompilePC + 8;
Section->Jump.TargetPC = Section->CompilePC + ((short)Command.offset << 2) + 4;
if (Section->CompilePC == Section->Jump.TargetPC) {
if (!DelaySlotEffectsCompare(Section->CompilePC,Command.rs,0)) {
Section->Jump.PermLoop = true;
}
}
break;
case R4300i_REGIMM_BGEZAL:
NextInstruction = DELAY_SLOT;
if (Section->IsConst(Command.rs))
{
__int64 Value;
if (Section->Is32Bit(Command.rs))
{
Value = Section->MipsRegLo_S(Command.rs);
} else {
Value = Section->MipsReg_S(Command.rs);
}
if (Value >= 0) {
Section->MipsRegLo(31) = Section->CompilePC + 8;
Section->MipsRegState(31) = CRegInfo::STATE_CONST_32;
Section->Jump.TargetPC = Section->CompilePC + ((short)Command.offset << 2) + 4;
if (Section->CompilePC == Section->Jump.TargetPC) {
if (!DelaySlotEffectsCompare(Section->CompilePC,31,0)) {
Section->Jump.PermLoop = true;
}
}
break;
}
}
Section->MipsRegLo(31) = Section->CompilePC + 8;
Section->MipsRegState(31) = CRegInfo::STATE_CONST_32;
Section->Cont.TargetPC = Section->CompilePC + 8;
Section->Jump.TargetPC = Section->CompilePC + ((short)Command.offset << 2) + 4;
if (Section->CompilePC == Section->Jump.TargetPC) {
if (!DelaySlotEffectsCompare(Section->CompilePC,Command.rs,0)) {
Section->Jump.PermLoop = true;
}
}
break;
default:
#ifndef EXTERNAL_RELEASE
if (Command.Hex == 0x0407000D) { break; }
DisplayError("Unhandled R4300i OpCode in FillSectionInfo 4\n%s",
R4300iOpcodeName(Command.Hex,Section->CompilePC));
#endif
NextInstruction = END_BLOCK;
Section->CompilePC -= 4;
}
break;
case R4300i_JAL:
NextInstruction = DELAY_SLOT;
Section->MipsRegLo(31) = Section->CompilePC + 8;
Section->MipsRegState(31) = CRegInfo::STATE_CONST_32;
Section->Jump.TargetPC = (Section->CompilePC & 0xF0000000) + (Command.target << 2);
if (Section->CompilePC == Section->Jump.TargetPC) {
if (!DelaySlotEffectsCompare(Section->CompilePC,31,0)) {
Section->Jump.PermLoop = true;
}
}
break;
case R4300i_J:
NextInstruction = DELAY_SLOT;
Section->Jump.TargetPC = (Section->CompilePC & 0xF0000000) + (Command.target << 2);
if (Section->CompilePC == Section->Jump.TargetPC) { Section->Jump.PermLoop = true; }
break;
case R4300i_BEQ:
NextInstruction = DELAY_SLOT;
Section->Cont.TargetPC = Section->CompilePC + 8;
Section->Jump.TargetPC = Section->CompilePC + ((short)Command.offset << 2) + 4;
if (Section->CompilePC == Section->Jump.TargetPC) {
if (!DelaySlotEffectsCompare(Section->CompilePC,Command.rs,Command.rt)) {
Section->Jump.PermLoop = true;
}
}
if (Section->IsConst(Command.rs) && Section->IsConst(Command.rt))
{
__int64 Value1, Value2;
if (Section->Is32Bit(Command.rs))
{
Value1 = Section->MipsRegLo_S(Command.rs);
} else {
Value1 = Section->MipsReg_S(Command.rs);
}
if (Section->Is32Bit(Command.rt))
{
Value2 = Section->MipsRegLo_S(Command.rt);
} else {
Value2 = Section->MipsReg_S(Command.rt);
}
if (Value1 == Value2)
{
Section->Cont.TargetPC = -1;
}
}
break;
case R4300i_BNE:
case R4300i_BLEZ:
case R4300i_BGTZ:
NextInstruction = DELAY_SLOT;
Section->Cont.TargetPC = Section->CompilePC + 8;
Section->Jump.TargetPC = Section->CompilePC + ((short)Command.offset << 2) + 4;
if (Section->CompilePC == Section->Jump.TargetPC) {
if (!DelaySlotEffectsCompare(Section->CompilePC,Command.rs,Command.rt)) {
Section->Jump.PermLoop = true;
}
}
break;
case R4300i_ADDI:
case R4300i_ADDIU:
if (Command.rt == 0) { break; }
if (Section->InLoop && Command.rs == Command.rt) {
Section->MipsRegState(Command.rt) = CRegInfo::STATE_UNKNOWN;
}
if (Section->IsConst(Command.rs)) {
Section->MipsRegLo(Command.rt) = Section->MipsRegLo(Command.rs) + (short)Command.immediate;
Section->MipsRegState(Command.rt) = CRegInfo::STATE_CONST_32;
} else {
Section->MipsRegState(Command.rt) = CRegInfo::STATE_UNKNOWN;
}
break;
case R4300i_SLTI:
if (Command.rt == 0) { break; }
if (Section->IsConst(Command.rs)) {
if (Section->Is64Bit(Command.rs)) {
Section->MipsRegLo(Command.rt) = (Section->MipsReg_S(Command.rs) < (_int64)((short)Command.immediate))?1:0;
} else {
Section->MipsRegLo(Command.rt) = (Section->MipsRegLo_S(Command.rs) < (int)((short)Command.immediate))?1:0;
}
Section->MipsRegState(Command.rt) = CRegInfo::STATE_CONST_32;
} else {
Section->MipsRegState(Command.rt) = CRegInfo::STATE_UNKNOWN;
}
break;
case R4300i_SLTIU:
if (Command.rt == 0) { break; }
if (Section->IsConst(Command.rs)) {
if (Section->Is64Bit(Command.rs)) {
Section->MipsRegLo(Command.rt) = (Section->MipsReg(Command.rs) < (unsigned _int64)((short)Command.immediate))?1:0;
} else {
Section->MipsRegLo(Command.rt) = (Section->MipsRegLo(Command.rs) < (DWORD)((short)Command.immediate))?1:0;
}
Section->MipsRegState(Command.rt) = CRegInfo::STATE_CONST_32;
} else {
Section->MipsRegState(Command.rt) = CRegInfo::STATE_UNKNOWN;
}
break;
case R4300i_LUI:
if (Command.rt == 0) { break; }
Section->MipsRegLo(Command.rt) = ((short)Command.offset << 16);
Section->MipsRegState(Command.rt) = CRegInfo::STATE_CONST_32;
break;
case R4300i_ANDI:
if (Command.rt == 0) { break; }
if (Section->InLoop && Command.rs == Command.rt) {
Section->MipsRegState(Command.rt) = CRegInfo::STATE_UNKNOWN;
}
if (Section->IsConst(Command.rs)) {
Section->MipsRegState(Command.rt) = CRegInfo::STATE_CONST_32;
Section->MipsRegLo(Command.rt) = Section->MipsRegLo(Command.rs) & Command.immediate;
} else {
Section->MipsRegState(Command.rt) = CRegInfo::STATE_UNKNOWN;
}
break;
case R4300i_ORI:
if (Command.rt == 0) { break; }
if (Section->InLoop && Command.rs == Command.rt) {
Section->MipsRegState(Command.rt) = CRegInfo::STATE_UNKNOWN;
}
if (Section->IsConst(Command.rs)) {
Section->MipsRegState(Command.rt) = CRegInfo::STATE_CONST_32;
Section->MipsRegLo(Command.rt) = Section->MipsRegLo(Command.rs) | Command.immediate;
} else {
Section->MipsRegState(Command.rt) = CRegInfo::STATE_UNKNOWN;
}
break;
case R4300i_XORI:
if (Command.rt == 0) { break; }
if (Section->InLoop && Command.rs == Command.rt) {
Section->MipsRegState(Command.rt) = CRegInfo::STATE_UNKNOWN;
}
if (Section->IsConst(Command.rs)) {
Section->MipsRegState(Command.rt) = CRegInfo::STATE_CONST_32;
Section->MipsRegLo(Command.rt) = Section->MipsRegLo(Command.rs) ^ Command.immediate;
} else {
Section->MipsRegState(Command.rt) = CRegInfo::STATE_UNKNOWN;
}
break;
case R4300i_CP0:
switch (Command.rs) {
case R4300i_COP0_MF:
if (Command.rt == 0) { break; }
Section->MipsRegState(Command.rt) = CRegInfo::STATE_UNKNOWN;
break;
case R4300i_COP0_MT: break;
default:
if ( (Command.rs & 0x10 ) != 0 ) {
switch( Command.funct ) {
case R4300i_COP0_CO_TLBR: break;
case R4300i_COP0_CO_TLBWI: break;
case R4300i_COP0_CO_TLBWR: break;
case R4300i_COP0_CO_TLBP: break;
case R4300i_COP0_CO_ERET: NextInstruction = END_BLOCK; break;
default:
#ifndef EXTERNAL_RELEASE
DisplayError("Unhandled R4300i OpCode in FillSectionInfo\n%s",
R4300iOpcodeName(Command.Hex,Section->CompilePC));
#endif
NextInstruction = END_BLOCK;
Section->CompilePC -= 4;
}
} else {
#ifndef EXTERNAL_RELEASE
DisplayError("Unhandled R4300i OpCode in FillSectionInfo 3\n%s",
R4300iOpcodeName(Command.Hex,Section->CompilePC));
#endif
NextInstruction = END_BLOCK;
Section->CompilePC -= 4;
}
}
break;
case R4300i_CP1:
switch (Command.fmt) {
case R4300i_COP1_CF:
case R4300i_COP1_MF:
case R4300i_COP1_DMF:
if (Command.rt == 0) { break; }
Section->MipsRegState(Command.rt) = CRegInfo::STATE_UNKNOWN;
break;
case R4300i_COP1_BC:
switch (Command.ft) {
case R4300i_COP1_BC_BCFL:
case R4300i_COP1_BC_BCTL:
NextInstruction = LIKELY_DELAY_SLOT;
Section->Cont.TargetPC = Section->CompilePC + 8;
Section->Jump.TargetPC = Section->CompilePC + ((short)Command.offset << 2) + 4;
if (Section->CompilePC == Section->Jump.TargetPC) {
int EffectDelaySlot;
OPCODE NewCommand;
if (!r4300i_LW_VAddr(Section->CompilePC + 4, &NewCommand.Hex)) {
DisplayError(GS(MSG_FAIL_LOAD_WORD));
ExitThread(0);
}
EffectDelaySlot = false;
if (NewCommand.op == R4300i_CP1) {
if (NewCommand.fmt == R4300i_COP1_S && (NewCommand.funct & 0x30) == 0x30 ) {
EffectDelaySlot = true;
}
if (NewCommand.fmt == R4300i_COP1_D && (NewCommand.funct & 0x30) == 0x30 ) {
EffectDelaySlot = true;
}
}
if (!EffectDelaySlot) {
Section->Jump.PermLoop = true;
}
}
break;
case R4300i_COP1_BC_BCF:
case R4300i_COP1_BC_BCT:
NextInstruction = DELAY_SLOT;
Section->Cont.TargetPC = Section->CompilePC + 8;
Section->Jump.TargetPC = Section->CompilePC + ((short)Command.offset << 2) + 4;
if (Section->CompilePC == Section->Jump.TargetPC) {
int EffectDelaySlot;
OPCODE NewCommand;
if (!r4300i_LW_VAddr(Section->CompilePC + 4, &NewCommand.Hex)) {
DisplayError(GS(MSG_FAIL_LOAD_WORD));
ExitThread(0);
}
EffectDelaySlot = false;
if (NewCommand.op == R4300i_CP1) {
if (NewCommand.fmt == R4300i_COP1_S && (NewCommand.funct & 0x30) == 0x30 ) {
EffectDelaySlot = true;
}
if (NewCommand.fmt == R4300i_COP1_D && (NewCommand.funct & 0x30) == 0x30 ) {
EffectDelaySlot = true;
}
}
if (!EffectDelaySlot) {
Section->Jump.PermLoop = true;
}
}
break;
}
break;
case R4300i_COP1_MT: break;
case R4300i_COP1_DMT: break;
case R4300i_COP1_CT: break;
case R4300i_COP1_S: break;
case R4300i_COP1_D: break;
case R4300i_COP1_W: break;
case R4300i_COP1_L: break;
default:
#ifndef EXTERNAL_RELEASE
DisplayError("Unhandled R4300i OpCode in FillSectionInfo 2\n%s",
R4300iOpcodeName(Command.Hex,Section->CompilePC));
#endif
NextInstruction = END_BLOCK;
Section->CompilePC -= 4;
}
break;
case R4300i_BEQL:
case R4300i_BNEL:
case R4300i_BLEZL:
case R4300i_BGTZL:
NextInstruction = LIKELY_DELAY_SLOT;
Section->Cont.TargetPC = Section->CompilePC + 8;
Section->Jump.TargetPC = Section->CompilePC + ((short)Command.offset << 2) + 4;
if (Section->CompilePC == Section->Jump.TargetPC) {
if (!DelaySlotEffectsCompare(Section->CompilePC,Command.rs,Command.rt)) {
Section->Jump.PermLoop = true;
}
}
break;
case R4300i_DADDI:
case R4300i_DADDIU:
if (Command.rt == 0) { break; }
if (Section->InLoop && Command.rs == Command.rt) {
Section->MipsRegState(Command.rt) = CRegInfo::STATE_UNKNOWN;
}
if (Section->IsConst(Command.rs)) {
if (Section->Is64Bit(Command.rs)) {
int imm32 = (short)Opcode.immediate;
__int64 imm64 = imm32;
Section->MipsReg_S(Command.rt) = Section->MipsRegLo_S(Command.rs) + imm64;
} else {
Section->MipsReg_S(Command.rt) = Section->MipsRegLo_S(Command.rs) + (short)Command.immediate;
}
Section->MipsRegState(Command.rt) = CRegInfo::STATE_CONST_64;
} else {
Section->MipsRegState(Command.rt) = CRegInfo::STATE_UNKNOWN;
}
break;
case R4300i_LDR:
case R4300i_LDL:
case R4300i_LB:
case R4300i_LH:
case R4300i_LWL:
case R4300i_LW:
case R4300i_LWU:
case R4300i_LL:
case R4300i_LBU:
case R4300i_LHU:
case R4300i_LWR:
case R4300i_SC:
if (Command.rt == 0) { break; }
Section->MipsRegState(Command.rt) = CRegInfo::STATE_UNKNOWN;
break;
case R4300i_SB: break;
case R4300i_SH: break;
case R4300i_SWL: break;
case R4300i_SW: break;
case R4300i_SWR: break;
case R4300i_SDL: break;
case R4300i_SDR: break;
case R4300i_CACHE: break;
case R4300i_LWC1: break;
case R4300i_SWC1: break;
case R4300i_LDC1: break;
case R4300i_LD:
if (Command.rt == 0) { break; }
Section->MipsRegState(Command.rt) = CRegInfo::STATE_UNKNOWN;
break;
case R4300i_SDC1: break;
case R4300i_SD: break;
default:
NextInstruction = END_BLOCK;
Section->CompilePC -= 4;
if (Command.Hex == 0x7C1C97C0) { break; }
if (Command.Hex == 0x7FFFFFFF) { break; }
if (Command.Hex == 0xF1F3F5F7) { break; }
if (Command.Hex == 0xC1200000) { break; }
if (Command.Hex == 0x4C5A5353) { break; }
#ifndef EXTERNAL_RELEASE
DisplayError("Unhandled R4300i OpCode in FillSectionInfo 1\n%s\n%X",
R4300iOpcodeName(Command.Hex,Section->CompilePC),Command.Hex);
#endif
}
// if (Section->CompilePC == 0x8005E4B8) {
//CPU_Message("%X: %s %s = %d",Section->CompilePC,R4300iOpcodeName(Command.Hex,Section->CompilePC),
// GPR_Name[8],Section->MipsRegState(8));
//_asm int 3
// }
switch (NextInstruction) {
case NORMAL:
Section->CompilePC += 4;
break;
case DELAY_SLOT:
NextInstruction = DELAY_SLOT_DONE;
Section->CompilePC += 4;
break;
case LIKELY_DELAY_SLOT:
if (Section->Cont.TargetPC == Section->Jump.TargetPC)
{
Section->Jump.RegSet = Section->RegWorking;
Section->Cont.DoneDelaySlot = false;
Section->Cont.RegSet = Section->RegWorking;
Section->Cont.DoneDelaySlot = true;
NextInstruction = END_BLOCK;
} else {
Section->Cont.RegSet = Section->RegWorking;
Section->Cont.DoneDelaySlot = true;
NextInstruction = LIKELY_DELAY_SLOT_DONE;
Section->CompilePC += 4;
}
break;
case DELAY_SLOT_DONE:
Section->Cont.RegSet = Section->RegWorking;
Section->Jump.RegSet = Section->RegWorking;
Section->Cont.DoneDelaySlot = true;
Section->Jump.DoneDelaySlot = true;
NextInstruction = END_BLOCK;
break;
case LIKELY_DELAY_SLOT_DONE:
Section->Jump.RegSet = Section->RegWorking;
Section->Jump.DoneDelaySlot = true;
NextInstruction = END_BLOCK;
break;
}
if ((Section->CompilePC & 0xFFFFF000) != (Section->StartPC & 0xFFFFF000)) {
if (NextInstruction != END_BLOCK && NextInstruction != NORMAL) {
// DisplayError("Branch running over delay slot ???\nNextInstruction == %d",NextInstruction);
Section->Cont.TargetPC = (DWORD)-1;
Section->Jump.TargetPC = (DWORD)-1;
}
NextInstruction = END_BLOCK;
Section->CompilePC -= 4;
}
} while (NextInstruction != END_BLOCK);
if (Section->Cont.TargetPC != (DWORD)-1) {
if ((Section->Cont.TargetPC & 0xFFFFF000) != (Section->StartPC & 0xFFFFF000)) {
Section->Cont.TargetPC = (DWORD)-1;
}
}
if (Section->Jump.TargetPC != (DWORD)-1) {
if (Section->Jump.TargetPC < Section->BlockInfo->StartVAddr)
{
Section->Jump.TargetPC = (DWORD)-1;
}
if ((Section->Jump.TargetPC & 0xFFFFF000) != (Section->StartPC & 0xFFFFF000)) {
Section->Jump.TargetPC = (DWORD)-1;
}
}
return true;
}
void CRecompiler::CompileExitCode ( CBlockInfo & BlockInfo )
{
for (EXIT_LIST::iterator ExitIter = BlockInfo.ExitInfo.begin(); ExitIter != BlockInfo.ExitInfo.end(); ExitIter++)
{
CPU_Message("");
CPU_Message(" $Exit_%d",ExitIter->ID);
SetJump32(ExitIter->JumpLoc,RecompPos);
NextInstruction = ExitIter->NextInstruction;
CompileExit(&BlockInfo.ParentSection, -1, ExitIter->TargetPC,ExitIter->ExitRegSet,ExitIter->reason,true,NULL);
}
}
bool CRecompiler::Compiler4300iBlock(FUNCTION_INFO * info) {
DWORD StartTime = timeGetTime();
WriteTraceF(TraceRecompiler,"Compile Block-Start: %X-%X",info->VStartPC(),info->VEndPC());
if (bProfiling()) { m_Profile.StartTimer(Timer_GetBlockInfo); }
CBlockInfo BlockInfo(PROGRAM_COUNTER, RecompPos);
if (bProfiling()) { m_Profile.StartTimer(Timer_AnalyseBlock); }
if (!AnalyseBlock(BlockInfo)) { return false; }
if (bProfiling()) { m_Profile.StartTimer(Timer_CompileBlock); }
DWORD StartAddress;
if (!_MMU->TranslateVaddr(BlockInfo.StartVAddr,StartAddress))
{
DisplayError("Ummm... Where does this block go\n%X",BlockInfo.StartVAddr);
return false;
}
/* MarkCodeBlock(StartAddress);
if (StartAddress < RdramSize()) {
CPU_Message("====== RDRAM: block (%X:%d) ======", StartAddress>>12,N64_Blocks.NoOfRDRamBlocks[StartAddress>>12]);
} else if (StartAddress >= 0x04000000 && StartAddress <= 0x04000FFC) {
CPU_Message("====== DMEM: block (%d) ======", N64_Blocks.NoOfDMEMBlocks);
} else if (StartAddress >= 0x04001000 && StartAddress <= 0x04001FFC) {
CPU_Message("====== IMEM: block (%d) ======", N64_Blocks.NoOfIMEMBlocks);
} else if (StartAddress >= 0x1FC00000 && StartAddress <= 0x1FC00800) {
CPU_Message("====== PIF ROM: block ======");
} else {
#ifndef ROM_IN_MAPSPACE
#ifndef EXTERNAL_RELEASE
DisplayError("Ummm... Where does this block go");
#endif
ExitThread(0);
#endif
}*/
CPU_Message("x86 code at: %X",BlockInfo.CompiledLocation);
CPU_Message("Start of Block: %X",BlockInfo.StartVAddr );
CPU_Message("No of Sections: %d",BlockInfo.NoOfSections );
CPU_Message("====== recompiled code ======");
if (bLinkBlocks()) {
for (int count = 0; count < BlockInfo.NoOfSections; count ++) {
DisplaySectionInformation(&BlockInfo.ParentSection,count + 1,CBlockSection::GetNewTestValue());
}
}
if (m_SyncSystem) {
//if ((DWORD)BlockInfo.CompiledLocation == 0x60A7B73B) { X86BreakPoint(__FILE__,__LINE__); }
//MoveConstToVariable((DWORD)BlockInfo.CompiledLocation,&CurrentBlock,"CurrentBlock");
}
BlockInfo.ParentSection.RegStart.Initilize();
BlockInfo.ParentSection.RegWorking = BlockInfo.ParentSection.RegStart;
if (bLinkBlocks()) {
while (GenerateX86Code(BlockInfo,&BlockInfo.ParentSection,CBlockSection::GetNewTestValue()));
} else {
GenerateX86Code(BlockInfo,&BlockInfo.ParentSection,CBlockSection::GetNewTestValue());
}
CompileExitCode(BlockInfo);
CPU_Message("====== End of recompiled code ======");
if (bProfiling()) { m_Profile.StartTimer(Timer_CompileDone); }
info->SetVEndPC(BlockInfo.EndVAddr);
info->SetFunctionAddr(BlockInfo.CompiledLocation);
_MMU->VAddrToRealAddr(info->VStartPC(),*(reinterpret_cast<void **>(&info->MemLocation[0])));
info->MemLocation[1] = info->MemLocation[0] + 1;
info->MemContents[0] = *info->MemLocation[0];
info->MemContents[1] = *info->MemLocation[1];
if (bSMM_Protect())
{
_MMU->ProtectMemory(info->VStartPC(),info->VEndPC());
}
NextInstruction = NORMAL;
if (bShowRecompMemSize())
{
DWORD Size = RecompPos - RecompCode;
DWORD MB = Size / 0x100000;
Size -= MB * 0x100000;
DWORD KB = Size / 1024;
Size -= KB * 1024;
DWORD TotalAvaliable = _MMU->GetRecompBufferSize() / 0x100000;
DisplayMessage(0,"Memory used: %d mb %-3d kb %-3d bytes Total Available: %d mb",MB,KB,Size, TotalAvaliable);
}
if (bProfiling()) { m_Profile.StopTimer(); }
DWORD TimeTaken = timeGetTime() - StartTime;
WriteTraceF(TraceRecompiler,"Compile Block-Done: %X-%X - Taken: %d",info->VStartPC(),info->VEndPC(),TimeTaken);
return true;
}
void CRecompiler::RecompilerMain_ChangeMemory ( void )
{
#ifdef tofix
DWORD Value, Addr;
BYTE * Block;
while(!EndEmulation()) {
if (UseTlb) {
if (!TranslateVaddr(PROGRAM_COUNTER, &Addr)) {
DoTLBMiss(NextInstruction == DELAY_SLOT,PROGRAM_COUNTER);
NextInstruction = NORMAL;
if (!TranslateVaddr(PROGRAM_COUNTER, &Addr)) {
#ifndef EXTERNAL_RELEASE
DisplayError("Failed to tranlate PC to a PAddr: %X\n\nEmulation stopped",PROGRAM_COUNTER);
#endif
ExitThread(0);
}
}
} else {
Addr = PROGRAM_COUNTER & 0x1FFFFFFF;
}
if (NextInstruction == DELAY_SLOT) {
__try {
Value = (DWORD)(*(DelaySlotTable + (Addr >> 12)));
} __except(EXCEPTION_EXECUTE_HANDLER) {
#ifndef EXTERNAL_RELEASE
DisplayError("Executing Delay Slot from non maped space\nPROGRAM_COUNTER = 0x%X",PROGRAM_COUNTER);
#endif
ExitThread(0);
}
if ( (Value >> 16) == 0x7C7C) {
DWORD Index = (Value & 0xFFFF);
Block = (BYTE *)OrigMem[Index].CompiledLocation;
if (OrigMem[Index].PAddr != Addr) { Block = NULL; }
if (OrigMem[Index].VAddr != PROGRAM_COUNTER) { Block = NULL; }
if (Index >= TargetIndex) { Block = NULL; }
} else {
Block = NULL;
}
if (Block == NULL) {
DWORD MemValue;
Block = CompileDelaySlot();
Value = 0x7C7C0000;
Value += (WORD)(TargetIndex);
MemValue = *(DWORD *)(N64MEM + Addr);
if ( (MemValue >> 16) == 0x7C7C) {
MemValue = OrigMem[(MemValue & 0xFFFF)].OriginalValue;
}
OrigMem[(WORD)(TargetIndex)].OriginalValue = MemValue;
OrigMem[(WORD)(TargetIndex)].CompiledLocation = Block;
OrigMem[(WORD)(TargetIndex)].PAddr = Addr;
OrigMem[(WORD)(TargetIndex)].VAddr = PROGRAM_COUNTER;
TargetIndex += 1;
*(DelaySlotTable + (Addr >> 12)) = (void *)Value;
NextInstruction = NORMAL;
}
_asm {
pushad
call Block
popad
}
continue;
}
__try {
Value = *(DWORD *)(N64MEM + Addr);
if ( (Value >> 16) == 0x7C7C) {
DWORD Index = (Value & 0xFFFF);
Block = (BYTE *)OrigMem[Index].CompiledLocation;
if (OrigMem[Index].PAddr != Addr) { Block = NULL; }
if (OrigMem[Index].VAddr != PROGRAM_COUNTER) { Block = NULL; }
if (Index >= TargetIndex) { Block = NULL; }
} else {
Block = NULL;
}
} __except(EXCEPTION_EXECUTE_HANDLER) {
DisplayError(GS(MSG_NONMAPPED_SPACE));
ExitThread(0);
}
if (Block == NULL) {
DWORD MemValue;
__try {
Block = Compiler4300iBlock();
} __except(EXCEPTION_EXECUTE_HANDLER) {
ResetRecompCode();
Block = Compiler4300iBlock();
}
if (EndEmulation())
{
continue;
}
if (TargetIndex == MaxOrigMem) {
ResetRecompCode();
continue;
}
Value = 0x7C7C0000;
Value += (WORD)(TargetIndex);
MemValue = *(DWORD *)(N64MEM + Addr);
if ( (MemValue >> 16) == 0x7C7C) {
MemValue = OrigMem[(MemValue & 0xFFFF)].OriginalValue;
}
OrigMem[(WORD)(TargetIndex)].OriginalValue = MemValue;
OrigMem[(WORD)(TargetIndex)].CompiledLocation = Block;
OrigMem[(WORD)(TargetIndex)].PAddr = Addr;
OrigMem[(WORD)(TargetIndex)].VAddr = PROGRAM_COUNTER;
TargetIndex += 1;
*(DWORD *)(N64MEM + Addr) = Value;
NextInstruction = NORMAL;
}
if (Profiling && IndvidualBlock) {
static DWORD ProfAddress = 0;
/*if ((PROGRAM_COUNTER & ~0xFFF) != ProfAddress) {
char Label[100];
ProfAddress = PROGRAM_COUNTER & ~0xFFF;
sprintf(Label,"PC: %X to %X",ProfAddress,ProfAddress+ 0xFFC);
StartTimer(Label);
}*/
/*if (PROGRAM_COUNTER >= 0x800DD000 && PROGRAM_COUNTER <= 0x800DDFFC) {
char Label[100];
sprintf(Label,"PC: %X Block: %X",PROGRAM_COUNTER,Block);
StartTimer(Label);
}*/
// } else if ((Profiling || ShowCPUPer) && ProfilingLabel[0] == 0) {
// StartTimer("r4300i Running");
}
_asm {
pushad
call Block
popad
}
} // end for(;;)
#endif
}
FUNCTION_INFO * CRecompiler::CompilerCode ( void )
{
_MMU->CheckRecompMem(RecompPos);
FUNCTION_INFO * Info = m_Functions.AddFunctionInfo(PROGRAM_COUNTER,_MMU->TranslateVaddr(PROGRAM_COUNTER));
__try {
if (!Compiler4300iBlock(Info))
{
return NULL;
}
return Info;
} __except(EXCEPTION_EXECUTE_HANDLER) {
ResetRecompCode();
Info = m_Functions.AddFunctionInfo(PROGRAM_COUNTER,_MMU->TranslateVaddr(PROGRAM_COUNTER));
if (!Compiler4300iBlock(Info))
{
return NULL;
}
return Info;
}
return NULL;
}
void CRecompiler::DetermineLoop(CBlockSection * Section, DWORD Test, DWORD Test2, DWORD TestID)
{
if (Section == NULL) { return; }
if (Section->SectionID != TestID) {
if (Section->Test2 == Test2) {
return;
}
Section->Test2 = Test2;
DetermineLoop(Section->ContinueSection,Test,Test2,TestID);
DetermineLoop(Section->JumpSection,Test,Test2,TestID);
return;
}
if (Section->Test2 == Test2) {
Section->InLoop = true;
return;
}
Section->Test2 = Test2;
DetermineLoop(Section->ContinueSection,Test,Test2,TestID);
DetermineLoop(Section->JumpSection,Test,Test2,TestID);
if (Section->Test == Test) { return; }
Section->Test = Test;
if (Section->ContinueSection != NULL) {
DetermineLoop(Section->ContinueSection,Test,CBlockSection::GetNewTestValue(),Section->ContinueSection->SectionID);
}
if (Section->JumpSection != NULL) {
DetermineLoop(Section->JumpSection,Test,CBlockSection::GetNewTestValue(),Section->JumpSection->SectionID);
}
}
bool CRecompiler::DisplaySectionInformation (CBlockSection * Section, DWORD ID, DWORD Test)
{
if (!IsX86Logging())
{
return false;
}
if (Section == NULL) { return false; }
if (Section->Test == Test) { return false; }
Section->Test = Test;
if (Section->SectionID != ID) {
if (DisplaySectionInformation(Section->ContinueSection,ID,Test)) { return true; }
if (DisplaySectionInformation(Section->JumpSection,ID,Test)) { return true; }
return false;
}
CPU_Message("====== Section %d ======",Section->SectionID);
CPU_Message("Start PC: %X",Section->StartPC);
CPU_Message("CompiledLocation: %X",RecompPos);
if (!Section->ParentSection.empty())
{
stdstr ParentList;
for (SECTION_LIST::iterator iter = Section->ParentSection.begin(); iter != Section->ParentSection.end(); iter++)
{
CBlockSection * Parent = *iter;
if (!ParentList.empty())
{
ParentList += ", ";
}
ParentList += stdstr_f("%d",Parent->SectionID);
}
CPU_Message("Number of parents: %d (%s)",Section->ParentSection.size(),ParentList.c_str());
}
if (Section->JumpSection != NULL) {
CPU_Message("Jump Section: %d",Section->JumpSection->SectionID);
} else {
CPU_Message("Jump Section: None");
}
if (Section->ContinueSection != NULL) {
CPU_Message("Continue Section: %d",Section->ContinueSection->SectionID);
} else {
CPU_Message("Continue Section: None");
}
CPU_Message("=======================",Section->SectionID);
return true;
}
bool CRecompiler::InheritParentInfo (CBlockSection * Section)
{
/* int count, start, NoOfParents, NoOfCompiledParents, FirstParent,CurrentParent;
BLOCK_PARENT * SectionParents;
BLOCK_SECTION * Parent;
JUMP_INFO * JumpInfo;
char Label[100];
BOOL NeedSync;
*/
DisplaySectionInformation(Section,Section->SectionID,CBlockSection::GetNewTestValue());
if (Section->ParentSection.empty())
{
Section->RegStart.Initilize();
Section->RegWorking = Section->RegStart;
return true;
}
if (Section->ParentSection.size() == 1)
{
CBlockSection * Parent = *(Section->ParentSection.begin());
CJumpInfo * JumpInfo = Section == Parent->ContinueSection ? &Parent->Cont : &Parent->Jump;
Section->RegStart = JumpInfo->RegSet;
if (JumpInfo->LinkLocation != NULL) {
CPU_Message(" Section_%d:",Section->SectionID);
SetJump32(JumpInfo->LinkLocation,RecompPos);
if (JumpInfo->LinkLocation2 != NULL) {
SetJump32(JumpInfo->LinkLocation2,RecompPos);
}
}
Section->RegWorking = Section->RegStart;
return true;
}
//Multiple Parents
BLOCK_PARENT_LIST ParentList;
SECTION_LIST::iterator iter;
for (iter = Section->ParentSection.begin(); iter != Section->ParentSection.end(); iter++)
{
CBlockSection * Parent = *iter;
BLOCK_PARENT BlockParent;
if (Parent->CompiledLocation == NULL) { continue; }
if (Parent->JumpSection != Parent->ContinueSection) {
BlockParent.Parent = Parent;
BlockParent.JumpInfo = Section == Parent->ContinueSection?&Parent->Cont:&Parent->Jump;
ParentList.push_back(BlockParent);
} else {
BlockParent.Parent = Parent;
BlockParent.JumpInfo = &Parent->Cont;
ParentList.push_back(BlockParent);
BlockParent.Parent = Parent;
BlockParent.JumpInfo = &Parent->Jump;
ParentList.push_back(BlockParent);
}
}
int NoOfCompiledParents = ParentList.size();
if (NoOfCompiledParents == 0)
{
DisplayError("No Parent has been compiled ????");
return false;
}
// Add all the uncompiled blocks to the end of the list
for (iter = Section->ParentSection.begin(); iter != Section->ParentSection.end(); iter++)
{
CBlockSection * Parent = *iter;
BLOCK_PARENT BlockParent;
if (Parent->CompiledLocation != NULL) { continue; }
if (Parent->JumpSection != Parent->ContinueSection) {
BlockParent.Parent = Parent;
BlockParent.JumpInfo = Section == Parent->ContinueSection?&Parent->Cont:&Parent->Jump;
ParentList.push_back(BlockParent);
} else {
BlockParent.Parent = Parent;
BlockParent.JumpInfo = &Parent->Cont;
ParentList.push_back(BlockParent);
BlockParent.Parent = Parent;
BlockParent.JumpInfo = &Parent->Jump;
ParentList.push_back(BlockParent);
}
}
int FirstParent = 0;
for (int count = 1;count < NoOfCompiledParents;count++) {
if (ParentList[count].JumpInfo->FallThrough) {
FirstParent = count; break;
}
}
//Link First Parent to start
CBlockSection * Parent = ParentList[FirstParent].Parent;
CJumpInfo * JumpInfo = ParentList[FirstParent].JumpInfo;
Section->RegWorking = JumpInfo->RegSet;
if (JumpInfo->LinkLocation != NULL) {
CPU_Message(" Section_%d (from %d):",Section->SectionID,Parent->SectionID);
SetJump32(JumpInfo->LinkLocation,RecompPos);
JumpInfo->LinkLocation = NULL;
if (JumpInfo->LinkLocation2 != NULL) {
SetJump32(JumpInfo->LinkLocation2,RecompPos);
JumpInfo->LinkLocation2 = NULL;
}
}
if (Section->StartPC < Parent->CompilePC )
{
UpdateCounters(&JumpInfo->RegSet.BlockCycleCount(),&JumpInfo->RegSet.BlockRandomModifier(),true);
CompileSystemCheck(Section->StartPC,JumpInfo->RegSet);
} else {
UpdateCounters(&JumpInfo->RegSet.BlockCycleCount(),&JumpInfo->RegSet.BlockRandomModifier(),false);
}
JumpInfo->FallThrough = false;
//Fix up initial state
UnMap_AllFPRs(Section);
for (count = 0;count < ParentList.size();count++) {
int count2, MemoryStackPos;
if (count == FirstParent) { continue; }
Parent = ParentList[count].Parent;
CRegInfo * RegSet = &ParentList[count].JumpInfo->RegSet;
if (Section->CurrentRoundingModel() != RegSet->CurrentRoundingModel()) { Section->CurrentRoundingModel() = CRegInfo::RoundUnknown; }
if (ParentList.size() != NoOfCompiledParents) { Section->CurrentRoundingModel() = CRegInfo::RoundUnknown; }
//Find Parent MapRegState
MemoryStackPos = -1;
for (count2 = 1; count2 < 10; count2++) {
if (RegSet->x86Mapped(count2) == CRegInfo::Stack_Mapped) {
MemoryStackPos = count2;
break;
}
}
if (MemoryStackPos < 0) {
// if the memory stack position is not mapped then unmap it
int MemStackReg = Map_MemoryStack(Section,x86_Any,false);
if (MemStackReg > 0)
{
UnMap_X86reg(Section,MemStackReg);
}
}
for (count2 = 1; count2 < 32; count2++) {
if (Section->Is32BitMapped(count2)) {
switch (RegSet->MipsRegState(count2)) {
case CRegInfo::STATE_MAPPED_64: Map_GPR_64bit(Section,count2,count2); break;
case CRegInfo::STATE_MAPPED_32_ZERO: break;
case CRegInfo::STATE_MAPPED_32_SIGN:
if (Section->IsUnsigned(count2)) {
Section->MipsRegState(count2) = CRegInfo::STATE_MAPPED_32_SIGN;
}
break;
case CRegInfo::STATE_CONST_64: Map_GPR_64bit(Section,count2,count2); break;
case CRegInfo::STATE_CONST_32:
if ((RegSet->MipsRegLo_S(count2) < 0) && Section->IsUnsigned(count2)) {
Section->MipsRegState(count2) = CRegInfo::STATE_MAPPED_32_SIGN;
}
break;
case CRegInfo::STATE_UNKNOWN:
//Map_GPR_32bit(Section,count2,true,count2);
Map_GPR_64bit(Section,count2,count2); //??
//UnMap_GPR(Section,count2,true); ??
break;
#ifndef EXTERNAL_RELEASE
default:
DisplayError("Unknown CPU State(%d) in InheritParentInfo",RegSet->MipsRegState(count2));
#endif
}
}
if (Section->IsConst(count2)) {
if (Section->MipsRegState(count2) != RegSet->MipsRegState(count2)) {
if (Section->Is32Bit(count2)) {
Map_GPR_32bit(Section,count2,true,count2);
} else {
Map_GPR_32bit(Section,count2,true,count2);
}
} else if (Section->Is32Bit(count2) && Section->MipsRegLo(count2) != RegSet->MipsRegLo(count2)) {
Map_GPR_32bit(Section,count2,true,count2);
} else if (Section->Is64Bit(count2) && Section->MipsReg(count2) != RegSet->MipsReg(count2)) {
Map_GPR_32bit(Section,count2,true,count2);
}
}
Section->ResetX86Protection();
}
if (MemoryStackPos > 0)
{
Map_MemoryStack(Section,MemoryStackPos,true);
}
}
Section->RegStart = Section->RegWorking;
//Sync registers for different blocks
char Label[100];
sprintf(Label,"Section_%d",Section->SectionID);
int CurrentParent = FirstParent;
bool NeedSync = false;
for (count = 0;count < NoOfCompiledParents;count++) {
CRegInfo * RegSet;
int count2;
if (count == FirstParent) { continue; }
Parent = ParentList[count].Parent;
JumpInfo = ParentList[count].JumpInfo;
RegSet = &ParentList[count].JumpInfo->RegSet;
if (JumpInfo->RegSet.BlockCycleCount() != 0) { NeedSync = true; }
if (JumpInfo->RegSet.BlockRandomModifier() != 0) { NeedSync = true; }
for (count2 = 0; count2 < 8; count2++) {
if (Section->FpuMappedTo(count2) == (DWORD)-1) {
NeedSync = true;
}
}
for (count2 = 1; count2 < 10; count2++) {
if (Section->x86Mapped(count2) == CRegInfo::Stack_Mapped) {
if (Section->x86Mapped(count2) != RegSet->x86Mapped(count2)) {
NeedSync = true;
}
break;
}
}
for (count2 = 0; count2 < 32; count2++) {
if (NeedSync == true) { break; }
if (Section->MipsRegState(count2) != RegSet->MipsRegState(count2)) {
NeedSync = true;
continue;
}
switch (Section->MipsRegState(count2)) {
case CRegInfo::STATE_UNKNOWN: break;
case CRegInfo::STATE_MAPPED_64:
if (Section->MipsReg(count2) != RegSet->MipsReg(count2)) {
NeedSync = true;
}
break;
case CRegInfo::STATE_MAPPED_32_ZERO:
case CRegInfo::STATE_MAPPED_32_SIGN:
if (Section->MipsRegLo(count2) != RegSet->MipsRegLo(count2)) {
//DisplayError("Parent: %d",Parent->SectionID);
NeedSync = true;
}
break;
case CRegInfo::STATE_CONST_32:
if (Section->MipsRegLo(count2) != RegSet->MipsRegLo(count2)) {
#if (!defined(EXTERNAL_RELEASE))
DisplayError("Umm.. how ???");
#endif
NeedSync = true;
}
break;
#ifndef EXTERNAL_RELEASE
default:
DisplayError("Unhandled Reg state %d\nin InheritParentInfo",Section->MipsRegState(count2));
#endif
}
}
if (NeedSync == false) { continue; }
Parent = ParentList[CurrentParent].Parent;
JumpInfo = ParentList[CurrentParent].JumpInfo;
JmpLabel32(Label,0);
JumpInfo->LinkLocation = RecompPos - 4;
JumpInfo->LinkLocation2 = NULL;
CurrentParent = count;
Parent = ParentList[CurrentParent].Parent;
JumpInfo = ParentList[CurrentParent].JumpInfo;
CPU_Message(" Section_%d (from %d):",Section->SectionID,Parent->SectionID);
if (JumpInfo->LinkLocation != NULL) {
SetJump32(JumpInfo->LinkLocation,RecompPos);
JumpInfo->LinkLocation = NULL;
if (JumpInfo->LinkLocation2 != NULL) {
SetJump32(JumpInfo->LinkLocation2,RecompPos);
JumpInfo->LinkLocation2 = NULL;
}
}
Section->RegWorking = JumpInfo->RegSet;
if (Section->StartPC < Parent->CompilePC )
{
UpdateCounters(&Section->BlockCycleCount(),&Section->BlockRandomModifier(),true);
CompileSystemCheck(Section->StartPC,Section->RegWorking);
} else {
UpdateCounters(&Section->BlockCycleCount(),&Section->BlockRandomModifier(),false);
}
SyncRegState(Section,&Section->RegStart); //Sync
Section->RegStart = Section->RegWorking;
}
for (count = 0;count < NoOfCompiledParents;count++) {
Parent = ParentList[count].Parent;
JumpInfo = ParentList[count].JumpInfo;
if (JumpInfo->LinkLocation != NULL) {
SetJump32(JumpInfo->LinkLocation,RecompPos);
JumpInfo->LinkLocation = NULL;
if (JumpInfo->LinkLocation2 != NULL) {
SetJump32(JumpInfo->LinkLocation2,RecompPos);
JumpInfo->LinkLocation2 = NULL;
}
}
}
CPU_Message(" Section_%d:",Section->SectionID);
Section->BlockCycleCount() = 0;
Section->BlockRandomModifier() = 0;
return true;
}
bool CRecompiler::GenerateX86Code(CBlockInfo & BlockInfo, CBlockSection * Section, DWORD Test )
{
if (Section == NULL) { return false; }
if (Section->CompiledLocation != NULL) {
if (Section->Test == Test) { return false; }
Section->Test = Test;
if (GenerateX86Code(BlockInfo,Section->ContinueSection,Test)) { return true; }
if (GenerateX86Code(BlockInfo,Section->JumpSection,Test)) { return true; }
return false;
}
if (Section->ParentSection.size() > 0)
{
for (SECTION_LIST::iterator iter = Section->ParentSection.begin(); iter != Section->ParentSection.end(); iter++)
{
CBlockSection * Parent = *iter;
if (Parent->CompiledLocation != NULL) { continue; }
if (Section->IsAllParentLoops(Parent,true,CBlockSection::GetNewTestValue())) { continue; }
return false;
}
}
if (!InheritParentInfo(Section)) { return false; }
Section->CompiledLocation = RecompPos;
Section->CompilePC = Section->StartPC;
NextInstruction = NORMAL;
/*if (m_SyncSystem) {
//if (m_SyncSystem && (DWORD)RecompPos > 0x6094C283) {
MoveConstToVariable(Section->StartPC,&PROGRAM_COUNTER,"PROGRAM_COUNTER");
if (BlockCycleCount != 0) {
AddConstToVariable(BlockCycleCount,&CP0[9],Cop0_Name[9]);
SubConstFromVariable(BlockCycleCount,&Timers.Timer,"Timer");
}
if (BlockRandomModifier != 0) { SubConstFromVariable(BlockRandomModifier,&CP0[1],Cop0_Name[1]); }
BlockCycleCount = 0;
BlockRandomModifier = 0;
Call_Direct(SyncToPC, "SyncToPC");
MoveConstToVariable((DWORD)RecompPos,&CurrentBlock,"CurrentBlock");
}*/
do {
__try {
if (!r4300i_LW_VAddr(Section->CompilePC, &g_Opcode.Hex)) {
DisplayError(GS(MSG_FAIL_LOAD_WORD));
ExitThread(0);
}
} __except( r4300i_CPU_MemoryFilter( GetExceptionCode(), GetExceptionInformation()) ) {
DisplayError(GS(MSG_UNKNOWN_MEM_ACTION));
ExitThread(0);
}
//if (Section->CompilePC == 0x800AA51C && NextInstruction == NORMAL) { _asm int 3 }
// if (Section->CompilePC == 0xF000044 && NextInstruction == NORMAL)
// {
// WriteBackRegisters(Section);
// UpdateCounters(&Section->BlockCycleCount(),&Section->BlockRandomModifier(),false);
//
// CompConstToVariable(0x26D5BB0,&CP0[9],Cop0_Name[9]);
// JlLabel8("blah",0);
// BYTE * Jump = RecompPos - 1;
// // BreakPoint(__FILE__,__LINE__);
// X86BreakPoint(__FILE__,__LINE__);
// *((BYTE *)(Jump))=(BYTE)(RecompPos - Jump - 1);
// }
/*if (Section->CompilePC >= 0x800C4024 && Section->CompilePC < 0x800C4030) {
CurrentRoundingModel = RoundUnknown;
}*/
// if (Section->CompilePC >= 0x800017A8 && Section->CompilePC < 0x800017DC && NextInstruction == NORMAL) {
// WriteBackRegisters(Section);
// UpdateCounters(&Section->BlockCycleCount(),&Section->BlockRandomModifier(),false);
// MoveConstToVariable(Section->CompilePC,&PROGRAM_COUNTER,"PROGRAM_COUNTER");
// //MoveConstToVariable((DWORD)RecompPos,&CurrentBlock,"CurrentBlock");
// if (m_SyncSystem) { Call_Direct(SyncToPC, "SyncToPC"); }
// }
// if (Section->CompilePC >= 0x8005E984 && Section->CompilePC < 0x8005EA84 && NextInstruction == NORMAL) {
// WriteBackRegisters(Section);
// UpdateCounters(&Section->BlockCycleCount(),&Section->BlockRandomModifier(),false);
// MoveConstToVariable(Section->CompilePC,&PROGRAM_COUNTER,"PROGRAM_COUNTER");
// //MoveConstToVariable((DWORD)RecompPos,&CurrentBlock,"CurrentBlock");
// if (m_SyncSystem) { Call_Direct(SyncToPC, "SyncToPC"); }
// }
// if (Section->CompilePC >= 0xF000000 && Section->CompilePC < 0xF000500 && NextInstruction == NORMAL) {
// WriteBackRegisters(Section);
// UpdateCounters(&Section->BlockCycleCount(),&Section->BlockRandomModifier(),false);
// MoveConstToVariable(Section->CompilePC,&PROGRAM_COUNTER,"PROGRAM_COUNTER");
// //MoveConstToVariable((DWORD)RecompPos,&CurrentBlock,"CurrentBlock");
// if (m_SyncSystem) { Call_Direct(SyncToPC, "SyncToPC"); }
// }
/*if (Section->CompilePC == 0x802000D0 && NextInstruction == NORMAL) {
CPU_Message("%s = %d",GPR_Name[14],Section->MipsRegState(14));
}*/
/*if (Section->CompilePC == 0x150A1514 && NextInstruction == NORMAL) {
CPU_Message("%s = %d",GPR_Name[14],Section->MipsRegState(14));
}
if (Section->CompilePC == 0x150A1454 && NextInstruction == NORMAL) {
CPU_Message("%s = %d",GPR_Name[14],Section->MipsRegState(14));
}*/
if (Section->CompilePC > Section->BlockInfo->EndVAddr)
{
Section->BlockInfo->EndVAddr = Section->CompilePC;
}
Section->BlockCycleCount() += CountPerOp();
//CPU_Message("BlockCycleCount = %d",BlockCycleCount);
Section->BlockRandomModifier() += 1;
//CPU_Message("BlockRandomModifier = %d",BlockRandomModifier);
Section->ResetX86Protection();
switch (g_Opcode.op) {
case R4300i_SPECIAL:
switch (g_Opcode.funct) {
case R4300i_SPECIAL_SLL: Compile_R4300i_SPECIAL_SLL(Section); break;
case R4300i_SPECIAL_SRL: Compile_R4300i_SPECIAL_SRL(Section); break;
case R4300i_SPECIAL_SRA: Compile_R4300i_SPECIAL_SRA(Section); break;
case R4300i_SPECIAL_SLLV: Compile_R4300i_SPECIAL_SLLV(Section); break;
case R4300i_SPECIAL_SRLV: Compile_R4300i_SPECIAL_SRLV(Section); break;
case R4300i_SPECIAL_SRAV: Compile_R4300i_SPECIAL_SRAV(Section); break;
case R4300i_SPECIAL_JR: Compile_R4300i_SPECIAL_JR(Section); break;
case R4300i_SPECIAL_JALR: Compile_R4300i_SPECIAL_JALR(Section); break;
case R4300i_SPECIAL_MFLO: Compile_R4300i_SPECIAL_MFLO(Section); break;
case R4300i_SPECIAL_SYSCALL: Compile_R4300i_SPECIAL_SYSCALL(Section); break;
case R4300i_SPECIAL_MTLO: Compile_R4300i_SPECIAL_MTLO(Section); break;
case R4300i_SPECIAL_MFHI: Compile_R4300i_SPECIAL_MFHI(Section); break;
case R4300i_SPECIAL_MTHI: Compile_R4300i_SPECIAL_MTHI(Section); break;
case R4300i_SPECIAL_DSLLV: Compile_R4300i_SPECIAL_DSLLV(Section); break;
case R4300i_SPECIAL_DSRLV: Compile_R4300i_SPECIAL_DSRLV(Section); break;
case R4300i_SPECIAL_DSRAV: Compile_R4300i_SPECIAL_DSRAV(Section); break;
case R4300i_SPECIAL_MULT: Compile_R4300i_SPECIAL_MULT(Section); break;
case R4300i_SPECIAL_DIV: Compile_R4300i_SPECIAL_DIV(Section); break;
case R4300i_SPECIAL_DIVU: Compile_R4300i_SPECIAL_DIVU(Section); break;
case R4300i_SPECIAL_MULTU: Compile_R4300i_SPECIAL_MULTU(Section); break;
case R4300i_SPECIAL_DMULT: Compile_R4300i_SPECIAL_DMULT(Section); break;
case R4300i_SPECIAL_DMULTU: Compile_R4300i_SPECIAL_DMULTU(Section); break;
case R4300i_SPECIAL_DDIV: Compile_R4300i_SPECIAL_DDIV(Section); break;
case R4300i_SPECIAL_DDIVU: Compile_R4300i_SPECIAL_DDIVU(Section); break;
case R4300i_SPECIAL_ADD: Compile_R4300i_SPECIAL_ADD(Section); break;
case R4300i_SPECIAL_ADDU: Compile_R4300i_SPECIAL_ADDU(Section); break;
case R4300i_SPECIAL_SUB: Compile_R4300i_SPECIAL_SUB(Section); break;
case R4300i_SPECIAL_SUBU: Compile_R4300i_SPECIAL_SUBU(Section); break;
case R4300i_SPECIAL_AND: Compile_R4300i_SPECIAL_AND(Section); break;
case R4300i_SPECIAL_OR: Compile_R4300i_SPECIAL_OR(Section); break;
case R4300i_SPECIAL_XOR: Compile_R4300i_SPECIAL_XOR(Section); break;
case R4300i_SPECIAL_NOR: Compile_R4300i_SPECIAL_NOR(Section); break;
case R4300i_SPECIAL_SLT: Compile_R4300i_SPECIAL_SLT(Section); break;
case R4300i_SPECIAL_SLTU: Compile_R4300i_SPECIAL_SLTU(Section); break;
case R4300i_SPECIAL_DADD: Compile_R4300i_SPECIAL_DADD(Section); break;
case R4300i_SPECIAL_DADDU: Compile_R4300i_SPECIAL_DADDU(Section); break;
case R4300i_SPECIAL_DSUB: Compile_R4300i_SPECIAL_DSUB(Section); break;
case R4300i_SPECIAL_DSUBU: Compile_R4300i_SPECIAL_DSUBU(Section); break;
case R4300i_SPECIAL_DSLL: Compile_R4300i_SPECIAL_DSLL(Section); break;
case R4300i_SPECIAL_DSRL: Compile_R4300i_SPECIAL_DSRL(Section); break;
case R4300i_SPECIAL_DSRA: Compile_R4300i_SPECIAL_DSRA(Section); break;
case R4300i_SPECIAL_DSLL32: Compile_R4300i_SPECIAL_DSLL32(Section); break;
case R4300i_SPECIAL_DSRL32: Compile_R4300i_SPECIAL_DSRL32(Section); break;
case R4300i_SPECIAL_DSRA32: Compile_R4300i_SPECIAL_DSRA32(Section); break;
default:
Compile_R4300i_UnknownOpcode(Section); break;
}
break;
case R4300i_REGIMM:
switch (g_Opcode.rt) {
case R4300i_REGIMM_BLTZ:Compile_R4300i_Branch(Section,BLTZ_Compare,BranchTypeRs, false); break;
case R4300i_REGIMM_BGEZ:Compile_R4300i_Branch(Section,BGEZ_Compare,BranchTypeRs, false); break;
case R4300i_REGIMM_BLTZL:Compile_R4300i_BranchLikely(Section,BLTZ_Compare, false); break;
case R4300i_REGIMM_BGEZL:Compile_R4300i_BranchLikely(Section,BGEZ_Compare, false); break;
case R4300i_REGIMM_BLTZAL:Compile_R4300i_Branch(Section,BLTZ_Compare,BranchTypeRs, true); break;
case R4300i_REGIMM_BGEZAL:Compile_R4300i_Branch(Section,BGEZ_Compare,BranchTypeRs, true); break;
default:
Compile_R4300i_UnknownOpcode(Section); break;
}
break;
case R4300i_BEQ: Compile_R4300i_Branch(Section,BEQ_Compare,BranchTypeRsRt,false); break;
case R4300i_BNE: Compile_R4300i_Branch(Section,BNE_Compare,BranchTypeRsRt,false); break;
case R4300i_BGTZ:Compile_R4300i_Branch(Section,BGTZ_Compare,BranchTypeRs,false); break;
case R4300i_BLEZ:Compile_R4300i_Branch(Section,BLEZ_Compare,BranchTypeRs,false); break;
case R4300i_J: Compile_R4300i_J(Section); break;
case R4300i_JAL: Compile_R4300i_JAL(Section); break;
case R4300i_ADDI: Compile_R4300i_ADDI(Section); break;
case R4300i_ADDIU: Compile_R4300i_ADDIU(Section); break;
case R4300i_SLTI: Compile_R4300i_SLTI(Section); break;
case R4300i_SLTIU: Compile_R4300i_SLTIU(Section); break;
case R4300i_ANDI: Compile_R4300i_ANDI(Section); break;
case R4300i_ORI: Compile_R4300i_ORI(Section); break;
case R4300i_XORI: Compile_R4300i_XORI(Section); break;
case R4300i_LUI: Compile_R4300i_LUI(Section); break;
case R4300i_CP0:
switch (g_Opcode.rs) {
case R4300i_COP0_MF: Compile_R4300i_COP0_MF(Section); break;
case R4300i_COP0_MT: Compile_R4300i_COP0_MT(Section); break;
default:
if ( (g_Opcode.rs & 0x10 ) != 0 ) {
switch( g_Opcode.funct ) {
case R4300i_COP0_CO_TLBR: Compile_R4300i_COP0_CO_TLBR(Section); break;
case R4300i_COP0_CO_TLBWI: Compile_R4300i_COP0_CO_TLBWI(Section); break;
case R4300i_COP0_CO_TLBWR: Compile_R4300i_COP0_CO_TLBWR(Section); break;
case R4300i_COP0_CO_TLBP: Compile_R4300i_COP0_CO_TLBP(Section); break;
case R4300i_COP0_CO_ERET: Compile_R4300i_COP0_CO_ERET(Section); break;
default: Compile_R4300i_UnknownOpcode(Section); break;
}
} else {
Compile_R4300i_UnknownOpcode(Section);
}
}
break;
case R4300i_CP1:
switch (g_Opcode.rs) {
case R4300i_COP1_MF: Compile_R4300i_COP1_MF(Section); break;
case R4300i_COP1_DMF: Compile_R4300i_COP1_DMF(Section); break;
case R4300i_COP1_CF: Compile_R4300i_COP1_CF(Section); break;
case R4300i_COP1_MT: Compile_R4300i_COP1_MT(Section); break;
case R4300i_COP1_DMT: Compile_R4300i_COP1_DMT(Section); break;
case R4300i_COP1_CT: Compile_R4300i_COP1_CT(Section); break;
case R4300i_COP1_BC:
switch (g_Opcode.ft) {
case R4300i_COP1_BC_BCF: Compile_R4300i_Branch(Section,COP1_BCF_Compare,BranchTypeCop1,false); break;
case R4300i_COP1_BC_BCT: Compile_R4300i_Branch(Section,COP1_BCT_Compare,BranchTypeCop1,false); break;
case R4300i_COP1_BC_BCFL: Compile_R4300i_BranchLikely(Section,COP1_BCF_Compare,false); break;
case R4300i_COP1_BC_BCTL: Compile_R4300i_BranchLikely(Section,COP1_BCT_Compare,false); break;
default:
Compile_R4300i_UnknownOpcode(Section); break;
}
break;
case R4300i_COP1_S:
switch (g_Opcode.funct) {
case R4300i_COP1_FUNCT_ADD: Compile_R4300i_COP1_S_ADD(Section); break;
case R4300i_COP1_FUNCT_SUB: Compile_R4300i_COP1_S_SUB(Section); break;
case R4300i_COP1_FUNCT_MUL: Compile_R4300i_COP1_S_MUL(Section); break;
case R4300i_COP1_FUNCT_DIV: Compile_R4300i_COP1_S_DIV(Section); break;
case R4300i_COP1_FUNCT_ABS: Compile_R4300i_COP1_S_ABS(Section); break;
case R4300i_COP1_FUNCT_NEG: Compile_R4300i_COP1_S_NEG(Section); break;
case R4300i_COP1_FUNCT_SQRT: Compile_R4300i_COP1_S_SQRT(Section); break;
case R4300i_COP1_FUNCT_MOV: Compile_R4300i_COP1_S_MOV(Section); break;
case R4300i_COP1_FUNCT_TRUNC_L: Compile_R4300i_COP1_S_TRUNC_L(Section); break;
case R4300i_COP1_FUNCT_CEIL_L: Compile_R4300i_COP1_S_CEIL_L(Section); break; //added by Witten
case R4300i_COP1_FUNCT_FLOOR_L: Compile_R4300i_COP1_S_FLOOR_L(Section); break; //added by Witten
case R4300i_COP1_FUNCT_ROUND_W: Compile_R4300i_COP1_S_ROUND_W(Section); break;
case R4300i_COP1_FUNCT_TRUNC_W: Compile_R4300i_COP1_S_TRUNC_W(Section); break;
case R4300i_COP1_FUNCT_CEIL_W: Compile_R4300i_COP1_S_CEIL_W(Section); break; //added by Witten
case R4300i_COP1_FUNCT_FLOOR_W: Compile_R4300i_COP1_S_FLOOR_W(Section); break;
case R4300i_COP1_FUNCT_CVT_D: Compile_R4300i_COP1_S_CVT_D(Section); break;
case R4300i_COP1_FUNCT_CVT_W: Compile_R4300i_COP1_S_CVT_W(Section); break;
case R4300i_COP1_FUNCT_CVT_L: Compile_R4300i_COP1_S_CVT_L(Section); break;
case R4300i_COP1_FUNCT_C_F: case R4300i_COP1_FUNCT_C_UN:
case R4300i_COP1_FUNCT_C_EQ: case R4300i_COP1_FUNCT_C_UEQ:
case R4300i_COP1_FUNCT_C_OLT: case R4300i_COP1_FUNCT_C_ULT:
case R4300i_COP1_FUNCT_C_OLE: case R4300i_COP1_FUNCT_C_ULE:
case R4300i_COP1_FUNCT_C_SF: case R4300i_COP1_FUNCT_C_NGLE:
case R4300i_COP1_FUNCT_C_SEQ: case R4300i_COP1_FUNCT_C_NGL:
case R4300i_COP1_FUNCT_C_LT: case R4300i_COP1_FUNCT_C_NGE:
case R4300i_COP1_FUNCT_C_LE: case R4300i_COP1_FUNCT_C_NGT:
Compile_R4300i_COP1_S_CMP(Section); break;
default:
Compile_R4300i_UnknownOpcode(Section); break;
}
break;
case R4300i_COP1_D:
switch (g_Opcode.funct) {
case R4300i_COP1_FUNCT_ADD: Compile_R4300i_COP1_D_ADD(Section); break;
case R4300i_COP1_FUNCT_SUB: Compile_R4300i_COP1_D_SUB(Section); break;
case R4300i_COP1_FUNCT_MUL: Compile_R4300i_COP1_D_MUL(Section); break;
case R4300i_COP1_FUNCT_DIV: Compile_R4300i_COP1_D_DIV(Section); break;
case R4300i_COP1_FUNCT_ABS: Compile_R4300i_COP1_D_ABS(Section); break;
case R4300i_COP1_FUNCT_NEG: Compile_R4300i_COP1_D_NEG(Section); break;
case R4300i_COP1_FUNCT_SQRT: Compile_R4300i_COP1_D_SQRT(Section); break;
case R4300i_COP1_FUNCT_MOV: Compile_R4300i_COP1_D_MOV(Section); break;
case R4300i_COP1_FUNCT_TRUNC_L: Compile_R4300i_COP1_D_TRUNC_L(Section); break; //added by Witten
case R4300i_COP1_FUNCT_CEIL_L: Compile_R4300i_COP1_D_CEIL_L(Section); break; //added by Witten
case R4300i_COP1_FUNCT_FLOOR_L: Compile_R4300i_COP1_D_FLOOR_L(Section); break; //added by Witten
case R4300i_COP1_FUNCT_ROUND_W: Compile_R4300i_COP1_D_ROUND_W(Section); break;
case R4300i_COP1_FUNCT_TRUNC_W: Compile_R4300i_COP1_D_TRUNC_W(Section); break;
case R4300i_COP1_FUNCT_CEIL_W: Compile_R4300i_COP1_D_CEIL_W(Section); break; //added by Witten
case R4300i_COP1_FUNCT_FLOOR_W: Compile_R4300i_COP1_D_FLOOR_W(Section); break; //added by Witten
case R4300i_COP1_FUNCT_CVT_S: Compile_R4300i_COP1_D_CVT_S(Section); break;
case R4300i_COP1_FUNCT_CVT_W: Compile_R4300i_COP1_D_CVT_W(Section); break;
case R4300i_COP1_FUNCT_CVT_L: Compile_R4300i_COP1_D_CVT_L(Section); break;
case R4300i_COP1_FUNCT_C_F: case R4300i_COP1_FUNCT_C_UN:
case R4300i_COP1_FUNCT_C_EQ: case R4300i_COP1_FUNCT_C_UEQ:
case R4300i_COP1_FUNCT_C_OLT: case R4300i_COP1_FUNCT_C_ULT:
case R4300i_COP1_FUNCT_C_OLE: case R4300i_COP1_FUNCT_C_ULE:
case R4300i_COP1_FUNCT_C_SF: case R4300i_COP1_FUNCT_C_NGLE:
case R4300i_COP1_FUNCT_C_SEQ: case R4300i_COP1_FUNCT_C_NGL:
case R4300i_COP1_FUNCT_C_LT: case R4300i_COP1_FUNCT_C_NGE:
case R4300i_COP1_FUNCT_C_LE: case R4300i_COP1_FUNCT_C_NGT:
Compile_R4300i_COP1_D_CMP(Section); break;
default:
Compile_R4300i_UnknownOpcode(Section); break;
}
break;
case R4300i_COP1_W:
switch (g_Opcode.funct) {
case R4300i_COP1_FUNCT_CVT_S: Compile_R4300i_COP1_W_CVT_S(Section); break;
case R4300i_COP1_FUNCT_CVT_D: Compile_R4300i_COP1_W_CVT_D(Section); break;
default:
Compile_R4300i_UnknownOpcode(Section); break;
}
break;
case R4300i_COP1_L:
switch (g_Opcode.funct) {
case R4300i_COP1_FUNCT_CVT_S: Compile_R4300i_COP1_L_CVT_S(Section); break;
case R4300i_COP1_FUNCT_CVT_D: Compile_R4300i_COP1_L_CVT_D(Section); break;
default:
Compile_R4300i_UnknownOpcode(Section); break;
}
break;
default:
Compile_R4300i_UnknownOpcode(Section); break;
}
break;
case R4300i_BEQL: Compile_R4300i_BranchLikely(Section,BEQ_Compare,false); break;
case R4300i_BNEL: Compile_R4300i_BranchLikely(Section,BNE_Compare,false); break;
case R4300i_BGTZL:Compile_R4300i_BranchLikely(Section,BGTZ_Compare,false); break;
case R4300i_BLEZL:Compile_R4300i_BranchLikely(Section,BLEZ_Compare,false); break;
case R4300i_DADDIU: Compile_R4300i_DADDIU(Section); break;
case R4300i_LDL: Compile_R4300i_LDL(Section); break;
case R4300i_LDR: Compile_R4300i_LDR(Section); break;
case R4300i_LB: Compile_R4300i_LB(Section); break;
case R4300i_LH: Compile_R4300i_LH(Section); break;
case R4300i_LWL: Compile_R4300i_LWL(Section); break;
case R4300i_LW: Compile_R4300i_LW(Section); break;
case R4300i_LBU: Compile_R4300i_LBU(Section); break;
case R4300i_LHU: Compile_R4300i_LHU(Section); break;
case R4300i_LWR: Compile_R4300i_LWR(Section); break;
case R4300i_LWU: Compile_R4300i_LWU(Section); break; //added by Witten
case R4300i_SB: Compile_R4300i_SB(Section); break;
case R4300i_SH: Compile_R4300i_SH(Section); break;
case R4300i_SWL: Compile_R4300i_SWL(Section); break;
case R4300i_SW: Compile_R4300i_SW(Section); break;
case R4300i_SWR: Compile_R4300i_SWR(Section); break;
case R4300i_SDL: Compile_R4300i_SDL(Section); break;
case R4300i_SDR: Compile_R4300i_SDR(Section); break;
case R4300i_CACHE: Compile_R4300i_CACHE(Section); break;
case R4300i_LL: Compile_R4300i_LL(Section); break;
case R4300i_LWC1: Compile_R4300i_LWC1(Section); break;
case R4300i_LDC1: Compile_R4300i_LDC1(Section); break;
case R4300i_SC: Compile_R4300i_SC(Section); break;
case R4300i_LD: Compile_R4300i_LD(Section); break;
case R4300i_SWC1: Compile_R4300i_SWC1(Section); break;
case R4300i_SDC1: Compile_R4300i_SDC1(Section); break;
case R4300i_SD: Compile_R4300i_SD(Section); break;
default:
Compile_R4300i_UnknownOpcode(Section); break;
}
if (!bRegCaching()) { WriteBackRegisters(Section); }
Section->ResetX86Protection();
/*if ((DWORD)RecompPos > 0x60B452E6) {
if (Section->CompilePC == 0x8002D9B8 && Section->CompilePC < 0x8002DA20) {
CurrentRoundingModel = RoundUnknown;
}
}*/
UnMap_AllFPRs(Section);
/*if ((DWORD)RecompPos > 0x60AD0BD3) {
if (Section->CompilePC >= 0x8008B804 && Section->CompilePC < 0x800496D8) {
CPU_Message("Blah *");
WriteBackRegisters(Section);
}
/*if (Section->CompilePC >= 0x80000180 && Section->CompilePC < 0x80000190) {
CPU_Message("Blah *");
//WriteBackRegisters(Section);
}*/
//}
/*for (count = 1; count < 10; count ++) {
if (Section->x86Mapped(count) == CRegInfo::Stack_Mapped) {
UnMap_X86reg (Section, count);
}
}*/
//CPU_Message("MemoryStack = %s",Map_MemoryStack(Section, false) > 0?x86_Name(Map_MemoryStack(Section, false)):"Not Mapped");
if ((Section->CompilePC &0xFFC) == 0xFFC) {
if (NextInstruction == DO_DELAY_SLOT) {
#ifndef EXTERNAL_RELEASE
DisplayError("Wanting to do delay slot over end of block");
#endif
}
if (NextInstruction == NORMAL) {
CompileExit (Section,Section->CompilePC, Section->CompilePC + 4,Section->RegWorking,CExitInfo::Normal,true,NULL);
NextInstruction = END_BLOCK;
}
}
if (Section->DelaySlotSection)
{
Section->Cont.RegSet = Section->RegWorking;
GenerateSectionLinkage(Section);
NextInstruction = END_BLOCK;
}
switch (NextInstruction) {
case NORMAL:
Section->CompilePC += 4;
break;
case DO_DELAY_SLOT:
NextInstruction = DELAY_SLOT;
Section->CompilePC += 4;
break;
case DELAY_SLOT:
NextInstruction = DELAY_SLOT_DONE;
Section->BlockCycleCount() -= CountPerOp();
Section->BlockRandomModifier() -= 1;
Section->CompilePC -= 4;
break;
}
} while (NextInstruction != END_BLOCK);
return true;
}
void CRecompiler::CompileExit ( CBlockSection * Section, DWORD JumpPC, DWORD TargetPC, CRegInfo ExitRegSet, CExitInfo::EXIT_REASON reason, int CompileNow, void (*x86Jmp)(char * Label, DWORD Value))
{
CBlockInfo * const BlockInfo = Section->BlockInfo;
if (!CompileNow)
{
char String[100];
sprintf(String,"Exit_%d",BlockInfo->ExitInfo.size());
if (x86Jmp == NULL)
{
DisplayError("CompileExit error");
ExitThread(0);
}
x86Jmp(String,0);
CExitInfo ExitInfo;
ExitInfo.ID = BlockInfo->ExitInfo.size();
ExitInfo.TargetPC = TargetPC;
ExitInfo.ExitRegSet = ExitRegSet;
ExitInfo.reason = reason;
ExitInfo.NextInstruction = NextInstruction;
ExitInfo.JumpLoc = RecompPos - 4;
BlockInfo->ExitInfo.push_back(ExitInfo);
return;
}
//CPU_Message("CompileExit: %d",reason);
CBlockSection TempSection(BlockInfo,-1,0);
TempSection.AddParent(NULL);
TempSection.RegWorking = ExitRegSet;
if (TargetPC != (DWORD)-1)
{
MoveConstToVariable(TargetPC,&PROGRAM_COUNTER,"PROGRAM_COUNTER");
UpdateCounters(&ExitRegSet.BlockCycleCount(),&ExitRegSet.BlockRandomModifier(),TargetPC <= JumpPC && reason == CExitInfo::Normal);
} else {
UpdateCounters(&ExitRegSet.BlockCycleCount(),&ExitRegSet.BlockRandomModifier(),reason == CExitInfo::Normal);
}
WriteBackRegisters(&TempSection);
switch (reason) {
case CExitInfo::Normal: case CExitInfo::Normal_NoSysCheck:
TempSection.RegWorking.BlockRandomModifier() = 0;
TempSection.RegWorking.BlockCycleCount() = 0;
if (TargetPC != (DWORD)-1)
{
if (TargetPC <= JumpPC && reason == CExitInfo::Normal)
{
CompileSystemCheck((DWORD)-1,TempSection.RegWorking);
}
} else {
if (reason == CExitInfo::Normal) { CompileSystemCheck((DWORD)-1,TempSection.RegWorking); }
}
if (m_SyncSystem) { Call_Direct(SyncToPC, "SyncToPC"); }
#ifdef LinkBlocks
if (bSMM_ValidFunc == false)
{
if (LookUpMode() == FuncFind_ChangeMemory)
{
BreakPoint(__FILE__,__LINE__);
// BYTE * Jump, * Jump2;
// if (TargetPC >= 0x80000000 && TargetPC < 0xC0000000) {
// DWORD pAddr = TargetPC & 0x1FFFFFFF;
//
// MoveVariableToX86reg((BYTE *)N64MEM + pAddr,"N64MEM + pAddr",x86_EAX);
// Jump2 = NULL;
// } else {
// MoveConstToX86reg((TargetPC >> 12),x86_ECX);
// MoveConstToX86reg(TargetPC,x86_EBX);
// MoveVariableDispToX86Reg(TLB_ReadMap,"TLB_ReadMap",x86_ECX,x86_ECX,4);
// TestX86RegToX86Reg(x86_ECX,x86_ECX);
// JeLabel8("NoTlbEntry",0);
// Jump2 = RecompPos - 1;
// MoveX86regPointerToX86reg(x86_ECX, x86_EBX,x86_EAX);
// }
// MoveX86RegToX86Reg(x86_EAX,x86_ECX);
// AndConstToX86Reg(x86_ECX,0xFFFF0000);
// CompConstToX86reg(x86_ECX,0x7C7C0000);
// JneLabel8("NoCode",0);
// Jump = RecompPos - 1;
// AndConstToX86Reg(x86_EAX,0xFFFF);
// ShiftLeftSignImmed(x86_EAX,4);
// AddConstToX86Reg(x86_EAX,0xC);
// MoveVariableDispToX86Reg(OrigMem,"OrigMem",x86_ECX,x86_EAX,1);
// JmpDirectReg(x86_ECX);
// CPU_Message(" NoCode:");
// *((BYTE *)(Jump))=(BYTE)(RecompPos - Jump - 1);
// if (Jump2 != NULL) {
// CPU_Message(" NoTlbEntry:");
// *((BYTE *)(Jump2))=(BYTE)(RecompPos - Jump2 - 1);
// }
}
else if (LookUpMode() == FuncFind_VirtualLookup)
{
MoveConstToX86reg(TargetPC,x86_EDX);
MoveConstToX86reg((DWORD)&m_Functions,x86_ECX);
Call_Direct(AddressOf(CFunctionMap::CompilerFindFunction), "CFunctionMap::CompilerFindFunction");
MoveX86RegToX86Reg(x86_EAX,x86_ECX);
JecxzLabel8("NullPointer",0);
BYTE * Jump = RecompPos - 1;
MoveX86PointerToX86regDisp(x86_EBX,x86_ECX,0xC);
JmpDirectReg(x86_EBX);
CPU_Message(" NullPointer:");
*((BYTE *)(Jump))=(BYTE)(RecompPos - Jump - 1);
}
else if (LookUpMode() == FuncFind_PhysicalLookup)
{
BYTE * Jump2 = NULL;
if (TargetPC >= 0x80000000 && TargetPC < 0x90000000) {
DWORD pAddr = TargetPC & 0x1FFFFFFF;
MoveVariableToX86reg((BYTE *)JumpTable + pAddr,"JumpTable + pAddr",x86_ECX);
} else if (TargetPC >= 0x90000000 && TargetPC < 0xC0000000) {
} else {
MoveConstToX86reg((TargetPC >> 12),x86_ECX);
MoveConstToX86reg(TargetPC,x86_EBX);
MoveVariableDispToX86Reg(TLB_ReadMap,"TLB_ReadMap",x86_ECX,x86_ECX,4);
TestX86RegToX86Reg(x86_ECX,x86_ECX);
JeLabel8("NoTlbEntry",0);
Jump2 = RecompPos - 1;
AddConstToX86Reg(x86_ECX,(DWORD)JumpTable - (DWORD)N64MEM);
MoveX86regPointerToX86reg(x86_ECX, x86_EBX,x86_ECX);
}
if (TargetPC < 0x90000000 || TargetPC >= 0xC0000000)
{
JecxzLabel8("NullPointer",0);
BYTE * Jump = RecompPos - 1;
MoveX86PointerToX86regDisp(x86_EAX,x86_ECX,0xC);
JmpDirectReg(x86_EAX);
CPU_Message(" NullPointer:");
*((BYTE *)(Jump))=(BYTE)(RecompPos - Jump - 1);
if (Jump2 != NULL) {
CPU_Message(" NoTlbEntry:");
*((BYTE *)(Jump2))=(BYTE)(RecompPos - Jump2 - 1);
}
}
}
}
Ret();
#else
Ret();
#endif
break;
case CExitInfo::DoCPU_Action:
Call_Direct(DoSomething,"DoSomething");
if (m_SyncSystem) { Call_Direct(SyncToPC, "SyncToPC"); }
Ret();
break;
case CExitInfo::DoSysCall:
MoveConstToX86reg(NextInstruction == JUMP || NextInstruction == DELAY_SLOT,x86_ECX);
Call_Direct(DoSysCallException,"DoSysCallException");
if (m_SyncSystem) { Call_Direct(SyncToPC, "SyncToPC"); }
Ret();
break;
case CExitInfo::COP1_Unuseable:
MoveConstToX86reg(NextInstruction == JUMP || NextInstruction == DELAY_SLOT,x86_ECX);
MoveConstToX86reg(1,x86_EDX);
Call_Direct(DoCopUnusableException,"DoCopUnusableException");
if (m_SyncSystem) { Call_Direct(SyncToPC, "SyncToPC"); }
Ret();
break;
case CExitInfo::ExitResetRecompCode:
if (NextInstruction == JUMP || NextInstruction == DELAY_SLOT) {
X86BreakPoint(__FILE__,__LINE__);
}
if (m_SyncSystem) { Call_Direct(SyncToPC, "SyncToPC"); }
X86BreakPoint(__FILE__,__LINE__);
MoveVariableToX86reg(this,"this",x86_ECX);
Call_Direct(AddressOf(ResetRecompCode), "ResetRecompCode");
Ret();
break;
case CExitInfo::TLBReadMiss:
MoveConstToX86reg(NextInstruction == JUMP || NextInstruction == DELAY_SLOT,x86_ECX);
MoveVariableToX86reg(&TLBLoadAddress,"TLBLoadAddress",x86_EDX);
Call_Direct(DoTLBMiss,"DoTLBMiss");
if (m_SyncSystem) { Call_Direct(SyncToPC, "SyncToPC"); }
Ret();
break;
default:
DisplayError("how did you want to exit on reason (%d) ???",reason);
}
}
void CRecompiler::UpdateCounters ( DWORD * Cycles, DWORD * RandomMod, BOOL CheckTimer)
{
if (Cycles == NULL || RandomMod == NULL)
{
BreakPoint(__FILE__,__LINE__);
}
if (*RandomMod != 0 || *Cycles != 0) {
WriteX86Comment("Update Counters");
}
if (*RandomMod != 0) { SubConstFromVariable(*RandomMod,&CP0[1],Cop0_Name[1]); }
if (*Cycles != 0) {
if (m_SyncSystem) {
char text[100];
WriteX86Comment("Sync CPU after update of cycles");
Pushad();
sprintf(text,"%d",(DWORD)*Cycles);
PushImm32(text,(DWORD)*Cycles);
Call_Direct(UpdateSyncCPU,"UpdateSyncCPU");
Popad();
}
AddConstToVariable(*Cycles,&CP0[9],Cop0_Name[9]);
SubConstFromVariable(*Cycles,g_Timer,"Timer");
}
*Cycles = 0;
*RandomMod = 0;
if (CheckTimer)
{
BYTE * Jump;
// Timer
if (*Cycles == 0) {
CompConstToVariable(0,g_Timer,"Timer");
//} else{
// uses SubConstFromVariable(Cycles,g_Timer,"Timer"); for compare flag
}
JnsLabel8("Continue_From_Timer_Test",0);
Jump = RecompPos - 1;
Pushad();
Call_Direct(TimerDone,"TimerDone");
Popad();
CPU_Message("");
CPU_Message(" $Continue_From_Timer_Test:");
SetJump8(Jump,RecompPos);
}
/* if (CheckTimer)
{
x86ops.CompConstToVariable(0,(DWORD *)&_Reg->Timer,"_Reg->Timer");
x86ops.JgLabel8("Timer_Fine",0); BYTE * Jump = x86ops.RecompPos.WritePos() - 1;
Section->SaveX86Registers();
x86ops.Call_NonStatic_Direct((CSystemTimer *)_Reg,AddressOf(CSystemTimer::CheckTimer),"CSystemTimer::CheckTimer");
Section->RestoreX86Registers();
x86ops.WriteLabel("Timer_Fine"); x86ops.SetJump8(Jump, x86ops.RecompPos.WritePos());
}*/
}
void CRecompiler::CompileSystemCheck (DWORD TargetPC, CRegInfo & RegSet)
{
CompConstToVariable(0,&CPU_Action.DoSomething,"CPU_Action.DoSomething");
JeLabel32("Continue_From_Interrupt_Test",0);
BYTE * Jump = RecompPos - 4;
if (TargetPC != (DWORD)-1)
{
MoveConstToVariable(TargetPC,&PROGRAM_COUNTER,"PROGRAM_COUNTER");
}
CBlockSection Section(NULL,-1,0);
Section.AddParent(NULL);
Section.RegWorking = RegSet;
WriteBackRegisters(&Section);
CompileExit(&Section,-1, -1,Section.RegWorking,CExitInfo::DoCPU_Action,true,NULL);
CPU_Message("");
CPU_Message(" $Continue_From_Interrupt_Test:");
SetJump32(Jump,RecompPos);
}
void SyncRegState (CBlockSection * Section, CRegInfo * SyncTo) {
int count, x86Reg,x86RegHi, changed;
changed = false;
UnMap_AllFPRs(Section);
if (Section->CurrentRoundingModel() != SyncTo->CurrentRoundingModel()) { Section->CurrentRoundingModel() = CRegInfo::RoundUnknown; }
x86Reg = Map_MemoryStack(Section, x86_Any, false);
//CPU_Message("MemoryStack for Original State = %s",x86Reg > 0?x86_Name(x86Reg):"Not Mapped");
for (x86Reg = 1; x86Reg < 10; x86Reg ++) {
if (Section->x86Mapped(x86Reg) != CRegInfo::Stack_Mapped) { continue; }
if (SyncTo->x86Mapped(x86Reg) != CRegInfo::Stack_Mapped) {
UnMap_X86reg(Section,x86Reg);
for (count = 1; count < 10; count ++) {
if (SyncTo->x86Mapped(count) == CRegInfo::Stack_Mapped) {
MoveX86RegToX86Reg(count,x86Reg);
changed = true;
}
}
if (!changed) {
MoveVariableToX86reg(g_MemoryStack,"MemoryStack",x86Reg);
}
changed = true;
}
}
for (x86Reg = 1; x86Reg < 10; x86Reg ++) {
if (SyncTo->x86Mapped(x86Reg) != CRegInfo::Stack_Mapped) { continue; }
//CPU_Message("MemoryStack for Sync State = %s",x86Reg > 0?x86_Name(x86Reg):"Not Mapped");
if (Section->x86Mapped(x86Reg) == CRegInfo::Stack_Mapped) { break; }
UnMap_X86reg(Section,x86Reg);
}
for (count = 1; count < 32; count ++) {
if (Section->MipsRegState(count) == SyncTo->MipsRegState(count)) {
switch (Section->MipsRegState(count)) {
case CRegInfo::STATE_UNKNOWN: continue;
case CRegInfo::STATE_MAPPED_64:
if (Section->MipsReg(count) == SyncTo->MipsReg(count)) {
continue;
}
break;
case CRegInfo::STATE_MAPPED_32_ZERO:
case CRegInfo::STATE_MAPPED_32_SIGN:
if (Section->MipsRegLo(count) == SyncTo->MipsRegLo(count)) {
continue;
}
break;
case CRegInfo::STATE_CONST_64:
if (Section->MipsReg(count) != SyncTo->MipsReg(count)) {
#if (!defined(EXTERNAL_RELEASE))
DisplayError("Umm.. how ???");
#endif
}
continue;
case CRegInfo::STATE_CONST_32:
if (Section->MipsRegLo(count) != SyncTo->MipsRegLo(count)) {
#if (!defined(EXTERNAL_RELEASE))
DisplayError("Umm.. how ???");
#endif
}
continue;
#ifndef EXTERNAL_RELEASE
default:
DisplayError("Unhandled Reg state %d\nin SyncRegState",Section->MipsRegState(count));
#endif
}
}
changed = true;
switch (SyncTo->MipsRegState(count)) {
case CRegInfo::STATE_UNKNOWN: UnMap_GPR(Section,count,true); break;
case CRegInfo::STATE_MAPPED_64:
x86Reg = SyncTo->MipsRegLo(count);
x86RegHi = SyncTo->MipsRegHi(count);
UnMap_X86reg(Section,x86Reg);
UnMap_X86reg(Section,x86RegHi);
switch (Section->MipsRegState(count)) {
case CRegInfo::STATE_UNKNOWN:
MoveVariableToX86reg(&GPR[count].UW[0],GPR_NameLo[count],x86Reg);
MoveVariableToX86reg(&GPR[count].UW[1],GPR_NameHi[count],x86RegHi);
break;
case CRegInfo::STATE_MAPPED_64:
MoveX86RegToX86Reg(Section->MipsRegLo(count),x86Reg);
Section->x86Mapped(Section->MipsRegLo(count)) = CRegInfo::NotMapped;
MoveX86RegToX86Reg(Section->MipsRegHi(count),x86RegHi);
Section->x86Mapped(Section->MipsRegHi(count)) = CRegInfo::NotMapped;
break;
case CRegInfo::STATE_MAPPED_32_SIGN:
MoveX86RegToX86Reg(Section->MipsRegLo(count),x86RegHi);
ShiftRightSignImmed(x86RegHi,31);
MoveX86RegToX86Reg(Section->MipsRegLo(count),x86Reg);
Section->x86Mapped(Section->MipsRegLo(count)) = CRegInfo::NotMapped;
break;
case CRegInfo::STATE_MAPPED_32_ZERO:
XorX86RegToX86Reg(x86RegHi,x86RegHi);
MoveX86RegToX86Reg(Section->MipsRegLo(count),x86Reg);
Section->x86Mapped(Section->MipsRegLo(count)) = CRegInfo::NotMapped;
break;
case CRegInfo::STATE_CONST_64:
MoveConstToX86reg(Section->MipsRegHi(count),x86RegHi);
MoveConstToX86reg(Section->MipsRegLo(count),x86Reg);
break;
case CRegInfo::STATE_CONST_32:
MoveConstToX86reg(Section->MipsRegLo_S(count) >> 31,x86RegHi);
MoveConstToX86reg(Section->MipsRegLo(count),x86Reg);
break;
default:
#ifndef EXTERNAL_RELEASE
CPU_Message("Do something with states in SyncRegState\nSTATE_MAPPED_64\n%d",Section->MipsRegState(count));
DisplayError("Do something with states in SyncRegState\nSTATE_MAPPED_64\n%d",Section->MipsRegState(count));
#endif
continue;
}
Section->MipsRegLo(count) = x86Reg;
Section->MipsRegHi(count) = x86RegHi;
Section->MipsRegState(count) = CRegInfo::STATE_MAPPED_64;
Section->x86Mapped(x86Reg) = CRegInfo::GPR_Mapped;
Section->x86Mapped(x86RegHi) = CRegInfo::GPR_Mapped;
Section->x86MapOrder(x86Reg) = 1;
Section->x86MapOrder(x86RegHi) = 1;
break;
case CRegInfo::STATE_MAPPED_32_SIGN:
x86Reg = SyncTo->MipsRegLo(count);
UnMap_X86reg(Section,x86Reg);
switch (Section->MipsRegState(count)) {
case CRegInfo::STATE_UNKNOWN: MoveVariableToX86reg(&GPR[count].UW[0],GPR_NameLo[count],x86Reg); break;
case CRegInfo::STATE_CONST_32: MoveConstToX86reg(Section->MipsRegLo(count),x86Reg); break;
case CRegInfo::STATE_MAPPED_32_SIGN:
MoveX86RegToX86Reg(Section->MipsRegLo(count),x86Reg);
Section->x86Mapped(Section->MipsRegLo(count)) = CRegInfo::NotMapped;
break;
case CRegInfo::STATE_MAPPED_32_ZERO:
if (Section->MipsRegLo(count) != (DWORD)x86Reg) {
MoveX86RegToX86Reg(Section->MipsRegLo(count),x86Reg);
Section->x86Mapped(Section->MipsRegLo(count)) = CRegInfo::NotMapped;
}
break;
case CRegInfo::STATE_MAPPED_64:
MoveX86RegToX86Reg(Section->MipsRegLo(count),x86Reg);
Section->x86Mapped(Section->MipsRegLo(count)) = CRegInfo::NotMapped;
Section->x86Mapped(Section->MipsRegHi(count)) = CRegInfo::NotMapped;
break;
#ifndef EXTERNAL_RELEASE
case CRegInfo::STATE_CONST_64:
DisplayError("hi %X\nLo %X",Section->MipsRegHi(count),Section->MipsRegLo(count));
default:
CPU_Message("Do something with states in SyncRegState\nSTATE_MAPPED_32_SIGN\n%d",Section->MipsRegState(count));
DisplayError("Do something with states in SyncRegState\nSTATE_MAPPED_32_SIGN\n%d",Section->MipsRegState(count));
#endif
}
Section->MipsRegLo(count) = x86Reg;
Section->MipsRegState(count) = CRegInfo::STATE_MAPPED_32_SIGN;
Section->x86Mapped(x86Reg) = CRegInfo::GPR_Mapped;
Section->x86MapOrder(x86Reg) = 1;
break;
case CRegInfo::STATE_MAPPED_32_ZERO:
x86Reg = SyncTo->MipsRegLo(count);
UnMap_X86reg(Section,x86Reg);
switch (Section->MipsRegState(count)) {
case CRegInfo::STATE_MAPPED_64:
case CRegInfo::STATE_UNKNOWN:
MoveVariableToX86reg(&GPR[count].UW[0],GPR_NameLo[count],x86Reg);
break;
case CRegInfo::STATE_MAPPED_32_ZERO:
MoveX86RegToX86Reg(Section->MipsRegLo(count),x86Reg);
Section->x86Mapped(Section->MipsRegLo(count)) = CRegInfo::NotMapped;
break;
case CRegInfo::STATE_CONST_32:
if (Section->MipsRegLo_S(count) < 0) {
CPU_Message("Sign Problems in SyncRegState\nSTATE_MAPPED_32_ZERO");
CPU_Message("%s: %X",GPR_Name[count],Section->MipsRegLo_S(count));
#ifndef EXTERNAL_RELEASE
DisplayError("Sign Problems in SyncRegState\nSTATE_MAPPED_32_ZERO");
#endif
}
MoveConstToX86reg(Section->MipsRegLo(count),x86Reg);
break;
#ifndef EXTERNAL_RELEASE
default:
CPU_Message("Do something with states in SyncRegState\nSTATE_MAPPED_32_ZERO\n%d",Section->MipsRegState(count));
DisplayError("Do something with states in SyncRegState\nSTATE_MAPPED_32_ZERO\n%d",Section->MipsRegState(count));
#endif
}
Section->MipsRegLo(count) = x86Reg;
Section->MipsRegState(count) = SyncTo->MipsRegState(count);
Section->x86Mapped(x86Reg) = CRegInfo::GPR_Mapped;
Section->x86MapOrder(x86Reg) = 1;
break;
default:
#if (!defined(EXTERNAL_RELEASE))
CPU_Message("%d\n%d\nreg: %s (%d)",SyncTo->MipsRegState(count),Section->MipsRegState(count),GPR_Name[count],count);
DisplayError("%d\n%d\nreg: %s (%d)",SyncTo->MipsRegState(count),Section->MipsRegState(count),GPR_Name[count],count);
DisplayError("Do something with states in SyncRegState");
#endif
changed = false;
}
}
}
void CRecompiler::GenerateSectionLinkage (CBlockSection * Section) {
CBlockSection ** TargetSection[2];
CJumpInfo * JumpInfo[2];
BYTE * Jump;
int count;
TargetSection[0] = &Section->ContinueSection;
TargetSection[1] = &Section->JumpSection;
JumpInfo[0] = &Section->Cont;
JumpInfo[1] = &Section->Jump;
for (count = 0; count < 2; count ++) {
if (JumpInfo[count]->LinkLocation == NULL && JumpInfo[count]->FallThrough == false) {
JumpInfo[count]->TargetPC = -1;
}
}
if ((Section->CompilePC & 0xFFC) == 0xFFC) {
//Handle Fall througth
Jump = NULL;
for (count = 0; count < 2; count ++) {
if (!JumpInfo[count]->FallThrough) { continue; }
JumpInfo[count]->FallThrough = false;
if (JumpInfo[count]->LinkLocation != NULL) {
SetJump32(JumpInfo[count]->LinkLocation,RecompPos);
JumpInfo[count]->LinkLocation = NULL;
if (JumpInfo[count]->LinkLocation2 != NULL) {
SetJump32(JumpInfo[count]->LinkLocation2,RecompPos);
JumpInfo[count]->LinkLocation2 = NULL;
}
}
MoveConstToVariable(JumpInfo[count]->TargetPC,&JumpToLocation,"JumpToLocation");
if (JumpInfo[(count + 1) & 1]->LinkLocation == NULL) { break; }
JmpLabel8("FinishBlock",0);
Jump = RecompPos - 1;
}
for (count = 0; count < 2; count ++) {
if (JumpInfo[count]->LinkLocation == NULL) { continue; }
JumpInfo[count]->FallThrough = false;
if (JumpInfo[count]->LinkLocation != NULL) {
SetJump32(JumpInfo[count]->LinkLocation,RecompPos);
JumpInfo[count]->LinkLocation = NULL;
if (JumpInfo[count]->LinkLocation2 != NULL) {
SetJump32(JumpInfo[count]->LinkLocation2,RecompPos);
JumpInfo[count]->LinkLocation2 = NULL;
}
}
MoveConstToVariable(JumpInfo[count]->TargetPC,&JumpToLocation,"JumpToLocation");
if (JumpInfo[(count + 1) & 1]->LinkLocation == NULL) { break; }
JmpLabel8("FinishBlock",0);
Jump = RecompPos - 1;
}
if (Jump != NULL) {
CPU_Message(" $FinishBlock:");
SetJump8(Jump,RecompPos);
}
MoveConstToVariable(Section->CompilePC + 4,g_PROGRAM_COUNTER,"PROGRAM_COUNTER");
WriteBackRegisters(Section);
g_N64System->GetRecompiler()->UpdateCounters(&Section->BlockCycleCount(),&Section->BlockRandomModifier(),false);
// WriteBackRegisters(Section);
// if (m_SyncSystem) { Call_Direct(SyncToPC, "SyncToPC"); }
MoveConstToVariable(DELAY_SLOT,&NextInstruction,"NextInstruction");
Ret();
return;
}
if (!UseLinking) {
if (Section->CompilePC == Section->Jump.TargetPC && (Section->Cont.FallThrough == false)) {
if (!DelaySlotEffectsJump(Section->CompilePC)) {
CPU_Message("PermLoop *** a");
MoveConstToVariable(Section->CompilePC,g_PROGRAM_COUNTER,"PROGRAM_COUNTER");
WriteBackRegisters(Section);
Section->RegWorking.BlockCycleCount() -= CountPerOp();
g_N64System->GetRecompiler()->UpdateCounters(&Section->RegWorking.BlockCycleCount(),&Section->RegWorking.BlockRandomModifier(), false);
Call_Direct(InPermLoop,"InPermLoop");
Section->RegWorking.BlockCycleCount() += CountPerOp();
g_N64System->GetRecompiler()->UpdateCounters(&Section->RegWorking.BlockCycleCount(),&Section->RegWorking.BlockRandomModifier(), true);
g_N64System->GetRecompiler()->CompileSystemCheck(-1,Section->RegWorking);
}
}
}
if ((*TargetSection[0]) != (*TargetSection[1]) || (*TargetSection[0]) == NULL) {
for (count = 0; count < 2; count ++) {
if (JumpInfo[count]->LinkLocation == NULL && JumpInfo[count]->FallThrough == false) {
if ((*TargetSection[count]))
{
(*TargetSection[count])->UnlinkParent(Section,true, count == 0);
}
} else if ((*TargetSection[count]) == NULL && JumpInfo[count]->FallThrough) {
if (JumpInfo[count]->LinkLocation != NULL) {
SetJump32(JumpInfo[count]->LinkLocation,RecompPos);
JumpInfo[count]->LinkLocation = NULL;
if (JumpInfo[count]->LinkLocation2 != NULL) {
SetJump32(JumpInfo[count]->LinkLocation2,RecompPos);
JumpInfo[count]->LinkLocation2 = NULL;
}
}
g_N64System->GetRecompiler()->CompileExit (Section,Section->CompilePC, JumpInfo[count]->TargetPC,JumpInfo[count]->RegSet,CExitInfo::Normal,true,NULL);
JumpInfo[count]->FallThrough = false;
} else if ((*TargetSection[count]) != NULL && JumpInfo[count] != NULL) {
if (!JumpInfo[count]->FallThrough) { continue; }
if (JumpInfo[count]->TargetPC == (*TargetSection[count])->StartPC) { continue; }
if (JumpInfo[count]->LinkLocation != NULL) {
SetJump32(JumpInfo[count]->LinkLocation,RecompPos);
JumpInfo[count]->LinkLocation = NULL;
if (JumpInfo[count]->LinkLocation2 != NULL) {
SetJump32(JumpInfo[count]->LinkLocation2,RecompPos);
JumpInfo[count]->LinkLocation2 = NULL;
}
}
g_N64System->GetRecompiler()->CompileExit (Section,Section->CompilePC, JumpInfo[count]->TargetPC,JumpInfo[count]->RegSet,CExitInfo::Normal,true,NULL);
//FreeSection((*TargetSection[count]),Section);
}
}
} else {
if (Section->Cont.LinkLocation == NULL && Section->Cont.FallThrough == false) { Section->ContinueSection = NULL; }
if (Section->Jump.LinkLocation == NULL && Section->Jump.FallThrough == false) { Section->JumpSection = NULL; }
if (Section->JumpSection == NULL && Section->ContinueSection == NULL) {
//FreeSection(TargetSection[0],Section);
}
}
TargetSection[0] = &Section->ContinueSection;
TargetSection[1] = &Section->JumpSection;
for (count = 0; count < 2; count ++) {
if ((*TargetSection[count]) == NULL) { continue; }
if (!JumpInfo[count]->FallThrough) { continue; }
if ((*TargetSection[count])->CompiledLocation != NULL) {
char Label[100];
sprintf(Label,"Section_%d",(*TargetSection[count])->SectionID);
JumpInfo[count]->FallThrough = false;
if (JumpInfo[count]->LinkLocation != NULL) {
SetJump32(JumpInfo[count]->LinkLocation,RecompPos);
JumpInfo[count]->LinkLocation = NULL;
if (JumpInfo[count]->LinkLocation2 != NULL) {
SetJump32(JumpInfo[count]->LinkLocation2,RecompPos);
JumpInfo[count]->LinkLocation2 = NULL;
}
}
if (JumpInfo[count]->TargetPC <= Section->CompilePC) {
if (JumpInfo[count]->PermLoop) {
CPU_Message("PermLoop *** 1");
MoveConstToVariable(JumpInfo[count]->TargetPC,g_PROGRAM_COUNTER,"PROGRAM_COUNTER");
JumpInfo[count]->RegSet.BlockCycleCount() -= CountPerOp();
g_N64System->GetRecompiler()->UpdateCounters(&JumpInfo[count]->RegSet.BlockCycleCount(),&JumpInfo[count]->RegSet.BlockRandomModifier(), false);
Call_Direct(InPermLoop,"InPermLoop");
JumpInfo[count]->RegSet.BlockCycleCount() += CountPerOp();
g_N64System->GetRecompiler()->UpdateCounters(&JumpInfo[count]->RegSet.BlockCycleCount(),&JumpInfo[count]->RegSet.BlockRandomModifier(), true);
g_N64System->GetRecompiler()->CompileSystemCheck(-1,JumpInfo[count]->RegSet);
} else {
g_N64System->GetRecompiler()->UpdateCounters(&JumpInfo[count]->RegSet.BlockCycleCount(), &JumpInfo[count]->RegSet.BlockRandomModifier(), true);
g_N64System->GetRecompiler()->CompileSystemCheck(JumpInfo[count]->TargetPC,JumpInfo[count]->RegSet);
}
} else {
g_N64System->GetRecompiler()->UpdateCounters(&JumpInfo[count]->RegSet.BlockCycleCount(), &JumpInfo[count]->RegSet.BlockRandomModifier(), false);
}
JumpInfo[count]->RegSet.BlockRandomModifier() = 0;
JumpInfo[count]->RegSet.BlockCycleCount() = 0;
Section->RegWorking = JumpInfo[count]->RegSet;
SyncRegState(Section,&(*TargetSection[count])->RegStart);
JmpLabel32(Label,0);
SetJump32((DWORD *)RecompPos - 1,(*TargetSection[count])->CompiledLocation);
}
}
//Section->BlockCycleCount() = 0;
//Section->BlockRandomModifier() = 0;
for (count = 0; count < 2; count ++) {
if ((*TargetSection[count]) == NULL) { continue; }
if ((*TargetSection[count])->ParentSection.empty()) { continue; }
for (SECTION_LIST::iterator iter = (*TargetSection[count])->ParentSection.begin(); iter != (*TargetSection[count])->ParentSection.end(); iter++)
{
CBlockSection * Parent = *iter;
if (Parent->CompiledLocation != NULL) { continue; }
if (JumpInfo[count]->PermLoop) {
CPU_Message("PermLoop *** 2");
MoveConstToVariable(JumpInfo[count]->TargetPC,g_PROGRAM_COUNTER,"PROGRAM_COUNTER");
JumpInfo[count]->RegSet.BlockCycleCount() -= CountPerOp();
g_N64System->GetRecompiler()->UpdateCounters(&JumpInfo[count]->RegSet.BlockCycleCount(),&JumpInfo[count]->RegSet.BlockRandomModifier(), false);
Call_Direct(InPermLoop,"InPermLoop");
JumpInfo[count]->RegSet.BlockCycleCount() += CountPerOp();
g_N64System->GetRecompiler()->UpdateCounters(&JumpInfo[count]->RegSet.BlockCycleCount(),&JumpInfo[count]->RegSet.BlockRandomModifier(), true);
g_N64System->GetRecompiler()->CompileSystemCheck(-1,JumpInfo[count]->RegSet);
}
if (JumpInfo[count]->FallThrough) {
JumpInfo[count]->FallThrough = false;
JmpLabel32(JumpInfo[count]->BranchLabel,0);
JumpInfo[count]->LinkLocation = RecompPos - 4;
}
}
}
for (count = 0; count < 2; count ++) {
if (JumpInfo[count]->FallThrough) {
if (JumpInfo[count]->TargetPC < Section->CompilePC) {
g_N64System->GetRecompiler()->UpdateCounters(&JumpInfo[count]->RegSet.BlockCycleCount(),&JumpInfo[count]->RegSet.BlockRandomModifier(),true);
g_N64System->GetRecompiler()->CompileSystemCheck(JumpInfo[count]->TargetPC,JumpInfo[count]->RegSet);
}
}
}
CPU_Message("====== End of Section %d ======",Section->SectionID);
for (count = 0; count < 2; count ++) {
if (JumpInfo[count]->FallThrough) {
g_N64System->GetRecompiler()->GenerateX86Code(*(Section->BlockInfo),(*TargetSection[count]),CBlockSection::GetNewTestValue());
}
}
//CPU_Message("Section %d",Section->SectionID);
for (count = 0; count < 2; count ++) {
if (JumpInfo[count]->LinkLocation == NULL) { continue; }
if ((*TargetSection[count]) == NULL) {
CPU_Message("ExitBlock (from %d):",Section->SectionID);
SetJump32(JumpInfo[count]->LinkLocation,RecompPos);
JumpInfo[count]->LinkLocation = NULL;
if (JumpInfo[count]->LinkLocation2 != NULL) {
SetJump32(JumpInfo[count]->LinkLocation2,RecompPos);
JumpInfo[count]->LinkLocation2 = NULL;
}
g_N64System->GetRecompiler()->CompileExit (Section,Section->CompilePC,JumpInfo[count]->TargetPC,JumpInfo[count]->RegSet,CExitInfo::Normal,true,NULL);
continue;
}
if (JumpInfo[count]->TargetPC != (*TargetSection[count])->StartPC) {
DisplayError("I need to add more code in GenerateSectionLinkage cause this is going to cause an exception");
BreakPoint(__FILE__,__LINE__);
}
if ((*TargetSection[count])->CompiledLocation == NULL) {
g_N64System->GetRecompiler()->GenerateX86Code(*(*TargetSection[count])->BlockInfo,(*TargetSection[count]),CBlockSection::GetNewTestValue());
} else {
char Label[100];
CPU_Message("Section_%d (from %d):",(*TargetSection[count])->SectionID,Section->SectionID);
SetJump32(JumpInfo[count]->LinkLocation,RecompPos);
JumpInfo[count]->LinkLocation = NULL;
if (JumpInfo[count]->LinkLocation2 != NULL) {
SetJump32(JumpInfo[count]->LinkLocation2,RecompPos);
JumpInfo[count]->LinkLocation2 = NULL;
}
Section->RegWorking = JumpInfo[count]->RegSet;
if (JumpInfo[count]->TargetPC <= Section->CompilePC) {
g_N64System->GetRecompiler()->UpdateCounters(&JumpInfo[count]->RegSet.BlockCycleCount(),&JumpInfo[count]->RegSet.BlockRandomModifier(), true);
if (JumpInfo[count]->PermLoop) {
CPU_Message("PermLoop *** 3");
MoveConstToVariable(JumpInfo[count]->TargetPC,g_PROGRAM_COUNTER,"PROGRAM_COUNTER");
Call_Direct(InPermLoop,"InPermLoop");
g_N64System->GetRecompiler()->CompileSystemCheck(-1,JumpInfo[count]->RegSet);
} else {
g_N64System->GetRecompiler()->CompileSystemCheck(JumpInfo[count]->TargetPC,JumpInfo[count]->RegSet);
}
} else{
g_N64System->GetRecompiler()->UpdateCounters(&JumpInfo[count]->RegSet.BlockCycleCount(),&JumpInfo[count]->RegSet.BlockRandomModifier(), false);
}
Section->RegWorking = JumpInfo[count]->RegSet;
SyncRegState(Section,&(*TargetSection[count])->RegStart);
JmpLabel32(Label,0);
SetJump32((DWORD *)RecompPos - 1,(*TargetSection[count])->CompiledLocation);
}
}
}
void CRecompiler::RemoveFunction (FUNCTION_INFO * FunInfo, bool DelaySlot, REMOVE_REASON Reason )
{
LPCSTR lpReason = "Unknown";
switch (Reason)
{
case Remove_InitialCode: lpReason = "Remove_InitialCode"; break;
case Remove_Cache: lpReason = "Remove_Cache"; break;
case Remove_ProtectedMem: lpReason = "Remove_ProtectedMem"; break;
case Remove_ValidateFunc: lpReason = "Remove_ValidateFunc"; break;
case Remove_TLB: lpReason = "Remove_TLB"; break;
case Remove_DMA: lpReason = "Remove_DMA"; break;
}
WriteTraceF(TraceRecompiler,"Remove Func (%s): %X-%X",lpReason, FunInfo->VStartPC(), FunInfo->VEndPC());
if (JumpTable && !DelaySlot)
{
FUNCTION_INFO * Info = FunInfo;
while (Info)
{
if (*(JumpTable + (Info->PStartPC() >> 2)) == Info)
{
*(JumpTable + (Info->PStartPC() >> 2)) = NULL;
}
Info = Info->Next;
}
}
/*
TlbLog.Log("Clear %X",FunInfo->StartPC());
//Remove from the list of called functions
FunInfo->RemoveFromCallList();
//remove all functions that call this
if (_Settings->LoadDword(SMM_Linked)) {
for (FUNCTION_PTR_MAP::iterator item = FunInfo->CallingList().begin();
FunInfo->CallingList().begin() != FunInfo->CallingList().end();
item = FunInfo->CallingList().begin())
{
RemoveFunction(m_Functions.find(item->first));
}
} else {
//Remove from the list of called functions
FunInfo->RemoveFromCallingList();
}
*/
DWORD StartBlock = FunInfo->VStartPC() & ~0xFFF;
DWORD EndBlock = FunInfo->VEndPC() & ~0xFFF;
//Remove this item from the main list
if (DelaySlot)
{
m_FunctionsDelaySlot.Remove(FunInfo);
} else {
m_Functions.Remove(FunInfo);
}
//if no more functions in this block then unprotect the memory
if (bSMM_Protect())
{
for (DWORD Addr = StartBlock; Addr <= EndBlock; Addr += 0x1000 ){
FUNCTION_INFO * info = m_Functions.FindFunction(Addr,0xFFF);
if (info == NULL)
{
_MMU->UnProtectMemory(Addr,Addr + 0xFFC);
}
}
}
}
bool CRecompiler::ClearRecompCode_Phys(DWORD Address, int length, REMOVE_REASON Reason ) {
bool Result = true;
if (!ClearRecompCode_Virt(Address + 0x80000000,length,Reason)) { Result = false; }
if (!ClearRecompCode_Virt(Address + 0xA0000000,length,Reason)) { Result = false; }
if (g_UseTlb)
{
DWORD VAddr, Index = 0;
while (_MMU->PAddrToVAddr(Address,VAddr,Index))
{
WriteTraceF(TraceRecompiler,"ClearRecompCode Vaddr %X len: %d",VAddr,length);
if (!ClearRecompCode_Virt(VAddr,length,Reason))
{
Result = false;
}
}
}
if (LookUpMode() == FuncFind_PhysicalLookup)
{
WriteTraceF(TraceRecompiler,"Reseting Jump Table, Addr: %X len: %d",Address,((length + 3) & ~3));
memset((BYTE *)JumpTable + Address,0,((length + 3) & ~3));
}
return Result;
}
bool CRecompiler::ClearRecompCode_Virt(DWORD Address, int length,REMOVE_REASON Reason )
{
FUNCTION_INFO * info;
do
{
info = m_Functions.FindFunction(Address,length);
if (info)
{
RemoveFunction(info,false,Reason);
}
} while (info != NULL);
do
{
info = m_FunctionsDelaySlot.FindFunction(Address,length);
if (info)
{
RemoveFunction(info,true,Reason);
}
} while (info != NULL);
if (bSMM_Protect())
{
DWORD Start = Address & ~0xFFF;
info = m_Functions.FindFunction(Start,0xFFF);
if (info)
{
WriteTraceF(TraceDebug,"Function exists at %X End: %X",info->VStartPC(),info->VEndPC());
return false;
}
info = m_FunctionsDelaySlot.FindFunction(Start,0xFFF);
if (info)
{
WriteTraceF(TraceDebug,"Delay function exists at %X End: %X",info->VStartPC(),info->VEndPC());
return false;
}
return true;
}
return true;
}
void CRecompiler::SyncRegState (CBlockSection * Section, CRegInfo * SyncTo)
{
int count, x86Reg,x86RegHi;
bool changed = FALSE;
UnMap_AllFPRs(Section);
if (Section->CurrentRoundingModel() != SyncTo->CurrentRoundingModel()) { Section->CurrentRoundingModel() = CRegInfo::RoundUnknown; }
//x86Reg = Map_MemoryStack(Section, x86_Any, FALSE);
//CPU_Message("MemoryStack for Original State = %s",x86Reg > 0?x86_Name(x86Reg):"Not Mapped");
for (x86Reg = 1; x86Reg < 10; x86Reg ++) {
if (Section->x86Mapped(x86Reg) != CRegInfo::Stack_Mapped) { continue; }
if (SyncTo->x86Mapped(x86Reg) != CRegInfo::Stack_Mapped) {
UnMap_X86reg(Section,x86Reg);
for (count = 1; count < 10; count ++) {
if (SyncTo->x86Mapped(count) == CRegInfo::Stack_Mapped) {
MoveX86RegToX86Reg(count,x86Reg);
changed = TRUE;
}
}
if (!changed) {
MoveVariableToX86reg(g_MemoryStack,"MemoryStack",x86Reg);
}
changed = TRUE;
}
}
for (x86Reg = 1; x86Reg < 10; x86Reg ++) {
if (SyncTo->x86Mapped(x86Reg) != CRegInfo::Stack_Mapped) { continue; }
//CPU_Message("MemoryStack for Sync State = %s",x86Reg > 0?x86_Name(x86Reg):"Not Mapped");
if (Section->x86Mapped(x86Reg) == CRegInfo::Stack_Mapped) { break; }
UnMap_X86reg(Section,x86Reg);
}
for (count = 1; count < 32; count ++) {
if (Section->MipsRegState(count) == SyncTo->MipsRegState(count)) {
switch (Section->MipsRegState(count)) {
case CRegInfo::STATE_UNKNOWN: continue;
case CRegInfo::STATE_MAPPED_64:
if (Section->MipsReg(count) == SyncTo->MipsReg(count)) {
continue;
}
break;
case CRegInfo::STATE_MAPPED_32_ZERO:
case CRegInfo::STATE_MAPPED_32_SIGN:
if (Section->MipsRegLo(count) == SyncTo->MipsRegLo(count)) {
continue;
}
break;
case CRegInfo::STATE_CONST_64:
if (Section->MipsReg(count) != SyncTo->MipsReg(count)) {
#if (!defined(EXTERNAL_RELEASE))
DisplayError("Umm.. how ???");
#endif
}
continue;
case CRegInfo::STATE_CONST_32:
if (Section->MipsRegLo(count) != SyncTo->MipsRegLo(count)) {
#if (!defined(EXTERNAL_RELEASE))
DisplayError("Umm.. how ???");
#endif
}
continue;
#ifndef EXTERNAL_RELEASE
default:
DisplayError("Unhandled Reg state %d\nin SyncRegState",Section->MipsRegState(count));
#endif
}
}
changed = TRUE;
switch (SyncTo->MipsRegState(count)) {
case CRegInfo::STATE_UNKNOWN: UnMap_GPR(Section,count,TRUE); break;
case CRegInfo::STATE_MAPPED_64:
x86Reg = SyncTo->MipsRegLo(count);
x86RegHi = SyncTo->MipsRegHi(count);
UnMap_X86reg(Section,x86Reg);
UnMap_X86reg(Section,x86RegHi);
switch (Section->MipsRegState(count)) {
case CRegInfo::STATE_UNKNOWN:
MoveVariableToX86reg(&GPR[count].UW[0],GPR_NameLo[count],x86Reg);
MoveVariableToX86reg(&GPR[count].UW[1],GPR_NameHi[count],x86RegHi);
break;
case CRegInfo::STATE_MAPPED_64:
MoveX86RegToX86Reg(Section->MipsRegLo(count),x86Reg);
Section->x86Mapped(Section->MipsRegLo(count)) = CRegInfo::NotMapped;
MoveX86RegToX86Reg(Section->MipsRegHi(count),x86RegHi);
Section->x86Mapped(Section->MipsRegHi(count)) = CRegInfo::NotMapped;
break;
case CRegInfo::STATE_MAPPED_32_SIGN:
MoveX86RegToX86Reg(Section->MipsRegLo(count),x86RegHi);
ShiftRightSignImmed(x86RegHi,31);
MoveX86RegToX86Reg(Section->MipsRegLo(count),x86Reg);
Section->x86Mapped(Section->MipsRegLo(count)) = CRegInfo::NotMapped;
break;
case CRegInfo::STATE_MAPPED_32_ZERO:
XorX86RegToX86Reg(x86RegHi,x86RegHi);
MoveX86RegToX86Reg(Section->MipsRegLo(count),x86Reg);
Section->x86Mapped(Section->MipsRegLo(count)) = CRegInfo::NotMapped;
break;
case CRegInfo::STATE_CONST_64:
MoveConstToX86reg(Section->MipsRegHi(count),x86RegHi);
MoveConstToX86reg(Section->MipsRegLo(count),x86Reg);
break;
case CRegInfo::STATE_CONST_32:
MoveConstToX86reg(Section->MipsRegLo_S(count) >> 31,x86RegHi);
MoveConstToX86reg(Section->MipsRegLo(count),x86Reg);
break;
default:
#ifndef EXTERNAL_RELEASE
CPU_Message("Do something with states in SyncRegState\nSTATE_MAPPED_64\n%d",Section->MipsRegState(count));
DisplayError("Do something with states in SyncRegState\nSTATE_MAPPED_64\n%d",Section->MipsRegState(count));
#endif
continue;
}
Section->MipsRegLo(count) = x86Reg;
Section->MipsRegHi(count) = x86RegHi;
Section->MipsRegState(count) = CRegInfo::STATE_MAPPED_64;
Section->x86Mapped(x86Reg) = CRegInfo::GPR_Mapped;
Section->x86Mapped(x86RegHi) = CRegInfo::GPR_Mapped;
Section->x86MapOrder(x86Reg) = 1;
Section->x86MapOrder(x86RegHi) = 1;
break;
case CRegInfo::STATE_MAPPED_32_SIGN:
x86Reg = SyncTo->MipsRegLo(count);
UnMap_X86reg(Section,x86Reg);
switch (Section->MipsRegState(count)) {
case CRegInfo::STATE_UNKNOWN: MoveVariableToX86reg(&GPR[count].UW[0],GPR_NameLo[count],x86Reg); break;
case CRegInfo::STATE_CONST_32: MoveConstToX86reg(Section->MipsRegLo(count),x86Reg); break;
case CRegInfo::STATE_MAPPED_32_SIGN:
MoveX86RegToX86Reg(Section->MipsRegLo(count),x86Reg);
Section->x86Mapped(Section->MipsRegLo(count)) = CRegInfo::NotMapped;
break;
case CRegInfo::STATE_MAPPED_32_ZERO:
if (Section->MipsRegLo(count) != (DWORD)x86Reg) {
MoveX86RegToX86Reg(Section->MipsRegLo(count),x86Reg);
Section->x86Mapped(Section->MipsRegLo(count)) = CRegInfo::NotMapped;
}
break;
case CRegInfo::STATE_MAPPED_64:
MoveX86RegToX86Reg(Section->MipsRegLo(count),x86Reg);
Section->x86Mapped(Section->MipsRegLo(count)) = CRegInfo::NotMapped;
Section->x86Mapped(Section->MipsRegHi(count)) = CRegInfo::NotMapped;
break;
#ifndef EXTERNAL_RELEASE
case CRegInfo::STATE_CONST_64:
DisplayError("hi %X\nLo %X",Section->MipsRegHi(count),Section->MipsRegLo(count));
default:
CPU_Message("Do something with states in SyncRegState\nSTATE_MAPPED_32_SIGN\n%d",Section->MipsRegState(count));
DisplayError("Do something with states in SyncRegState\nSTATE_MAPPED_32_SIGN\n%d",Section->MipsRegState(count));
#endif
}
Section->MipsRegLo(count) = x86Reg;
Section->MipsRegState(count) = CRegInfo::STATE_MAPPED_32_SIGN;
Section->x86Mapped(x86Reg) = CRegInfo::GPR_Mapped;
Section->x86MapOrder(x86Reg) = 1;
break;
case CRegInfo::STATE_MAPPED_32_ZERO:
x86Reg = SyncTo->MipsRegLo(count);
UnMap_X86reg(Section,x86Reg);
switch (Section->MipsRegState(count)) {
case CRegInfo::STATE_MAPPED_64:
case CRegInfo::STATE_UNKNOWN:
MoveVariableToX86reg(&GPR[count].UW[0],GPR_NameLo[count],x86Reg);
break;
case CRegInfo::STATE_MAPPED_32_ZERO:
MoveX86RegToX86Reg(Section->MipsRegLo(count),x86Reg);
Section->x86Mapped(Section->MipsRegLo(count)) = CRegInfo::NotMapped;
break;
case CRegInfo::STATE_CONST_32:
if (Section->MipsRegLo_S(count) < 0) {
CPU_Message("Sign Problems in SyncRegState\nSTATE_MAPPED_32_ZERO");
CPU_Message("%s: %X",GPR_Name[count],Section->MipsRegLo_S(count));
#ifndef EXTERNAL_RELEASE
DisplayError("Sign Problems in SyncRegState\nSTATE_MAPPED_32_ZERO");
#endif
}
MoveConstToX86reg(Section->MipsRegLo(count),x86Reg);
break;
#ifndef EXTERNAL_RELEASE
default:
CPU_Message("Do something with states in SyncRegState\nSTATE_MAPPED_32_ZERO\n%d",Section->MipsRegState(count));
DisplayError("Do something with states in SyncRegState\nSTATE_MAPPED_32_ZERO\n%d",Section->MipsRegState(count));
#endif
}
Section->MipsRegLo(count) = x86Reg;
Section->MipsRegState(count) = SyncTo->MipsRegState(count);
Section->x86Mapped(x86Reg) = CRegInfo::GPR_Mapped;
Section->x86MapOrder(x86Reg) = 1;
break;
default:
#if (!defined(EXTERNAL_RELEASE))
CPU_Message("%d\n%d\nreg: %s (%d)",SyncTo->MipsRegState(count),Section->MipsRegState(count),GPR_Name[count],count);
DisplayError("%d\n%d\nreg: %s (%d)",SyncTo->MipsRegState(count),Section->MipsRegState(count),GPR_Name[count],count);
DisplayError("Do something with states in SyncRegState");
#endif
changed = FALSE;
}
}
}