Files
Project64-Legacy/Recompiler CPU.c
Jay Oster f113c8482d Improve watchpoints performance (#7)
- Split virtual memory reads into functions that should trigger watchpoints (for CPU Interpreter) and functions that do not (various debug tools, cheat search, and instruction fetch).
2023-08-19 16:29:30 +02:00

3383 lines
127 KiB
C

/*
* Project 64 - A Nintendo 64 emulator.
*
* (c) Copyright 2001 zilmar (zilmar@emulation64.com) and
* Jabo (jabo@emulation64.com).
*
* pj64 homepage: www.pj64.net
*
* Permission to use, copy, modify and distribute Project64 in both binary and
* source form, for non-commercial purposes, is hereby granted without fee,
* providing that this license information and copyright notice appear with
* all copies and any derived work.
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event shall the authors be held liable for any damages
* arising from the use of this software.
*
* Project64 is freeware for PERSONAL USE only. Commercial users should
* seek permission of the copyright holders first. Commercial use includes
* charging money for Project64 or software derived from Project64.
*
* The copyright holders request that bug fixes and improvements to the code
* should be forwarded to them so if they want them.
*
*/
#include <Windows.h>
#include <commctrl.h>
#include <stdio.h>
#include "main.h"
#include "cpu.h"
#include "x86.h"
#include "debugger.h"
#include "plugin.h"
void _fastcall CreateSectionLinkage (BLOCK_SECTION * Section);
void _fastcall DetermineLoop(BLOCK_SECTION * Section, DWORD Test, DWORD Test2, DWORD TestID);
BOOL DisplaySectionInformation (BLOCK_SECTION * Section, DWORD ID, DWORD Test);
BLOCK_SECTION * ExistingSection(BLOCK_SECTION * StartSection, DWORD Addr, DWORD Test);
void _fastcall FillSectionInfo(BLOCK_SECTION * Section);
void _fastcall FixConstants ( BLOCK_SECTION * Section, DWORD Test,int * Changed );
BOOL GenerateX86Code (BLOCK_SECTION * Section, DWORD Test );
DWORD GetNewTestValue( void );
void _fastcall InheritConstants(BLOCK_SECTION * Section);
BOOL InheritParentInfo (BLOCK_SECTION * Section);
void _fastcall InitilzeSection(BLOCK_SECTION * Section, BLOCK_SECTION * Parent, DWORD StartAddr, DWORD ID);
void InitilizeRegSet(REG_INFO * RegSet);
BOOL IsAllParentLoops(BLOCK_SECTION * Section, BLOCK_SECTION * Parent, BOOL IgnoreIfCompiled, DWORD Test);
void MarkCodeBlock (DWORD PAddr);
void SyncRegState (BLOCK_SECTION * Section, REG_INFO * SyncTo);
DWORD TLBLoadAddress, TargetIndex;
TARGET_INFO * TargetInfo = NULL;
BLOCK_INFO BlockInfo;
ORIGINAL_MEMMARKER * OrigMem = NULL;
void InitilizeInitialCompilerVariable ( void)
{
memset(&BlockInfo,0,sizeof(BlockInfo));
}
void _fastcall AddParent(BLOCK_SECTION * Section, BLOCK_SECTION * Parent){
int NoOfParents, count;
if (Section == NULL) { return; }
if (Parent == NULL) {
InitilizeRegSet(&Section->RegStart);
memcpy(&Section->RegWorking,&Section->RegStart,sizeof(REG_INFO));
return;
}
if (Section->ParentSection != NULL) {
for (NoOfParents = 0;Section->ParentSection[NoOfParents] != NULL;NoOfParents++) {
if (Section->ParentSection[NoOfParents] == Parent) {
return;
}
}
for (NoOfParents = 0;Section->ParentSection[NoOfParents] != NULL;NoOfParents++);
NoOfParents += 1;
} else {
NoOfParents = 1;
}
if (NoOfParents == 1) {
Section->ParentSection = malloc((NoOfParents + 1)*sizeof(void *));
} else {
Section->ParentSection = realloc(Section->ParentSection,(NoOfParents + 1)*sizeof(void *));
}
Section->ParentSection[NoOfParents - 1] = Parent;
Section->ParentSection[NoOfParents] = NULL;
if (NoOfParents == 1) {
if (Parent->ContinueSection == Section) {
memcpy(&Section->RegStart,&Parent->Cont.RegSet,sizeof(REG_INFO));
} else if (Parent->JumpSection == Section) {
memcpy(&Section->RegStart,&Parent->Jump.RegSet,sizeof(REG_INFO));
} else {
if (ShowDebugMessages)
DisplayError("How are these sections joined?????");
}
memcpy(&Section->RegWorking,&Section->RegStart,sizeof(REG_INFO));
} else {
if (Parent->ContinueSection == Section) {
for (count = 0; count < 32; count++) {
if (Section->RegStart.MIPS_RegState[count] != Parent->Cont.RegSet.MIPS_RegState[count]) {
Section->RegStart.MIPS_RegState[count] = STATE_UNKNOWN;
}
}
}
if (Parent->JumpSection == Section) {
for (count = 0; count < 32; count++) {
if (Section->RegStart.MIPS_RegState[count] != Parent->Jump.RegSet.MIPS_RegState[count]) {
Section->RegStart.MIPS_RegState[count] = STATE_UNKNOWN;
}
}
}
memcpy(&Section->RegWorking,&Section->RegStart,sizeof(REG_INFO));
}
}
void AnalyseBlock (void) {
int Changed;
BLOCK_SECTION * Section = &BlockInfo.BlockInfo;
BlockInfo.NoOfSections = 1;
InitilzeSection (Section, NULL, BlockInfo.StartVAddr, BlockInfo.NoOfSections);
if (UseLinking) {
CreateSectionLinkage (Section);
DetermineLoop(Section,GetNewTestValue(),GetNewTestValue(), Section->SectionID);
do {
Changed = FALSE;
FixConstants(Section,GetNewTestValue(),&Changed);
} while (Changed == TRUE);
}
}
int ConstantsType (__int64 Value) {
if (((Value >> 32) == -1) && ((Value & 0x80000000) != 0)) { return STATE_CONST_32; }
if (((Value >> 32) == 0) && ((Value & 0x80000000) == 0)) { return STATE_CONST_32; }
return STATE_CONST_64;
}
BYTE * Compiler4300iBlock(void) {
DWORD StartAddress;
int count;
//reset BlockInfo
if (BlockInfo.ExitInfo)
{
for (count = 0; count < BlockInfo.ExitCount; count ++) {
free(BlockInfo.ExitInfo[count]);
}
if (BlockInfo.ExitInfo) { free(BlockInfo.ExitInfo); }
BlockInfo.ExitInfo = NULL;
}
memset(&BlockInfo,0,sizeof(BlockInfo));
BlockInfo.CompiledLocation = RecompPos;
BlockInfo.StartVAddr = PROGRAM_COUNTER;
AnalyseBlock();
StartAddress = BlockInfo.StartVAddr;
TranslateVaddr(&StartAddress);
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
if (ShowDebugMessages)
DisplayError("Ummm... Where does this block go");
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 (UseLinking) {
/*for (count = 0; count < BlockInfo.NoOfSections; count ++) {
DisplaySectionInformation(&BlockInfo.BlockInfo,count + 1,BlockInfo.BlockInfo.Test + 1);
}*/
}
if (CPU_Type == CPU_SyncCores) {
//if ((DWORD)BlockInfo.CompiledLocation == 0x60A7B73B) { BreakPoint(); }
MoveConstToVariable((DWORD)BlockInfo.CompiledLocation,&CurrentBlock,"CurrentBlock");
}
if (UseLinking) {
while (GenerateX86Code(&BlockInfo.BlockInfo,GetNewTestValue()));
} else {
GenerateX86Code(&BlockInfo.BlockInfo,GetNewTestValue());
}
for (count = 0; count < BlockInfo.ExitCount; count ++) {
CPU_Message("");
CPU_Message(" $Exit_%d",count);
SetJump32(BlockInfo.ExitInfo[count]->JumpLoc,RecompPos);
NextInstruction = BlockInfo.ExitInfo[count]->NextInstruction;
CompileExit(BlockInfo.ExitInfo[count]->TargetPC,BlockInfo.ExitInfo[count]->ExitRegSet,
BlockInfo.ExitInfo[count]->reason,TRUE,NULL);
}
CPU_Message("====== End of recompiled code ======");
FreeSection (BlockInfo.BlockInfo.ContinueSection,&BlockInfo.BlockInfo);
FreeSection (BlockInfo.BlockInfo.JumpSection,&BlockInfo.BlockInfo);
for (count = 0; count < BlockInfo.ExitCount; count ++) {
free(BlockInfo.ExitInfo[count]);
}
if (BlockInfo.ExitInfo) { free(BlockInfo.ExitInfo); }
BlockInfo.ExitInfo = NULL;
BlockInfo.ExitCount = 0;
if (ShowCompMem) {
char StatusString[256];
DWORD Size, MB, KB;
Size = RecompPos - RecompCode;
MB = Size / 0x100000;
Size -= MB * 0x100000;
KB = Size / 1024;
Size -= KB * 1024;
sprintf(StatusString,"Memory used: %d mb %d kb %d bytes ",MB,KB,Size);
SendMessage( hStatusWnd, SB_SETTEXT, 0, (LPARAM)StatusString );
}
return BlockInfo.CompiledLocation;
}
BYTE * CompileDelaySlot(void) {
DWORD StartAddress = PROGRAM_COUNTER;
BLOCK_SECTION *Section, DelaySection;
BYTE * Block = RecompPos;
int count, x86Reg;
Section = &DelaySection;
if ((StartAddress & 0xFFC) != 0) {
if (ShowDebugMessages)
DisplayError("Why are you compiling the Delay Slot at %X",StartAddress);
ExitThread(0);
}
if (!r4300i_LW_VAddr_NonCPU(StartAddress, &Opcode.Hex)) {
if (ShowDebugMessages)
DisplayError("TLB Miss in delay slot\nEmulation will now stop");
ExitThread(0);
}
TranslateVaddr(&StartAddress);
if (StartAddress < RdramSize) {
CPU_Message("====== RDRAM: Delay Slot ======", 1);
} 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 {
#ifndef ROM_IN_MAPSPACE
if (ShowDebugMessages)
DisplayError("Ummm... Where does this block go");
ExitThread(0);
#endif
}
MarkCodeBlock(StartAddress);
CPU_Message("x86 code at: %X",Block);
CPU_Message("Delay Slot location: %X",PROGRAM_COUNTER );
CPU_Message("====== recompiled code ======");
InitilzeSection (Section, NULL, PROGRAM_COUNTER, 0);
InitilizeRegSet(&Section->RegStart);
memcpy(&Section->RegWorking,&Section->RegStart,sizeof(REG_INFO));
if (CPU_Type == CPU_SyncCores) {
MoveConstToVariable((DWORD)Block,&CurrentBlock,"CurrentBlock");
}
BlockCycleCount += CountPerOp;
//CPU_Message("BlockCycleCount = %d",BlockCycleCount);
BlockRandomModifier += 1;
//CPU_Message("BlockRandomModifier = %d",BlockRandomModifier);
switch (Opcode.BRANCH.op) {
case R4300i_SPECIAL:
switch (Opcode.REG.funct) {
case R4300i_SPECIAL_SYNC: break;
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.BRANCH.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.REG.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.REG.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.REG.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;
}
for (count = 1; count < 10; count ++) { x86Protected(count) = FALSE; }
WriteBackRegisters(Section);
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]); }
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();
CPU_Message("====== End of recompiled code ======");
return Block;
}
void CompileExit (DWORD TargetPC, REG_INFO ExitRegSet, int reason, int CompileNow, void (*x86Jmp)(char * Label, DWORD Value)) {
BLOCK_SECTION Section;
if (!CompileNow) {
char String[100];
if (BlockInfo.ExitCount == 0) {
BlockInfo.ExitInfo = malloc(sizeof(void *));
} else {
BlockInfo.ExitInfo = realloc(BlockInfo.ExitInfo,(BlockInfo.ExitCount + 1) * sizeof(void *));
}
sprintf(String,"Exit_%d",BlockInfo.ExitCount);
if (x86Jmp == NULL) {
if (ShowDebugMessages)
DisplayError("CompileExit error");
ExitThread(0);
}
x86Jmp(String,0);
BlockInfo.ExitInfo[BlockInfo.ExitCount] = malloc(sizeof(EXIT_INFO));
BlockInfo.ExitInfo[BlockInfo.ExitCount]->TargetPC = TargetPC;
BlockInfo.ExitInfo[BlockInfo.ExitCount]->ExitRegSet = ExitRegSet;
BlockInfo.ExitInfo[BlockInfo.ExitCount]->reason = reason;
BlockInfo.ExitInfo[BlockInfo.ExitCount]->NextInstruction = NextInstruction;
BlockInfo.ExitInfo[BlockInfo.ExitCount]->JumpLoc = RecompPos - 4;
BlockInfo.ExitCount += 1;
return;
}
//CPU_Message("CompileExit: %d",reason);
InitilzeSection (&Section, NULL, (DWORD)-1, 0);
memcpy(&Section.RegWorking, &ExitRegSet, sizeof(REG_INFO));
if (TargetPC != (DWORD)-1) { MoveConstToVariable(TargetPC,&PROGRAM_COUNTER,"PROGRAM_COUNTER"); }
if (ExitRegSet.CycleCount != 0) {
AddConstToVariable(ExitRegSet.CycleCount,&CP0[9],Cop0_Name[9]);
SubConstFromVariable(ExitRegSet.CycleCount,&Timers.Timer,"Timer");
}
if (ExitRegSet.RandomModifier != 0) { SubConstFromVariable(ExitRegSet.RandomModifier,&CP0[1],Cop0_Name[1]); }
WriteBackRegisters(&Section);
switch (reason) {
case Normal: case Normal_NoSysCheck:
if (CPU_Type == CPU_SyncCores) { Call_Direct(SyncToPC, "SyncToPC"); }
Section.RegWorking.RandomModifier = 0;
Section.RegWorking.CycleCount = 0;
if (reason == Normal) { CompileSystemCheck(0,(DWORD)-1,Section.RegWorking); }
#ifdef LinkBlocks
if (SelfModCheck == ModCode_ChangeMemory) {
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 (SelfModCheck == ModCode_CheckMemoryCache) {
} else if (SelfModCheck == ModCode_CheckMemory2) { // *** Add in Build 53
} else {
BYTE * Jump, * Jump2;
if (TargetPC >= 0x80000000 && TargetPC < 0x90000000) {
DWORD pAddr = TargetPC & 0x1FFFFFFF;
MoveVariableToX86reg((BYTE *)JumpTable + pAddr,"JumpTable + pAddr",x86_ECX);
Jump2 = NULL;
} 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);
Jump = RecompPos - 1;
JmpDirectReg(x86_ECX);
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 DoCPU_Action:
if (CPU_Type == CPU_SyncCores) { Call_Direct(SyncToPC, "SyncToPC"); }
Call_Direct(DoSomething,"DoSomething");
if (CPU_Type == CPU_SyncCores) { Call_Direct(SyncToPC, "SyncToPC"); }
Ret();
break;
case DoSysCall:
MoveConstToX86reg(NextInstruction == JUMP || NextInstruction == DELAY_SLOT,x86_ECX);
Call_Direct(DoSysCallException,"DoSysCallException");
if (CPU_Type == CPU_SyncCores) { Call_Direct(SyncToPC, "SyncToPC"); }
Ret();
break;
case COP1_Unuseable:
MoveConstToX86reg(NextInstruction == JUMP || NextInstruction == DELAY_SLOT,x86_ECX);
MoveConstToX86reg(1,x86_EDX);
Call_Direct(DoCopUnusableException,"DoCopUnusableException");
if (CPU_Type == CPU_SyncCores) { Call_Direct(SyncToPC, "SyncToPC"); }
Ret();
break;
case ExitResetRecompCode:
if (NextInstruction == JUMP || NextInstruction == DELAY_SLOT) {
BreakPoint();
}
if (CPU_Type == CPU_SyncCores) { Call_Direct(SyncToPC, "SyncToPC"); }
Call_Direct(ResetRecompCode, "ResetRecompCode");
Ret();
break;
case TLBReadMiss:
MoveConstToX86reg(NextInstruction == JUMP || NextInstruction == DELAY_SLOT,x86_ECX);
MoveVariableToX86reg(&TLBLoadAddress,"TLBLoadAddress",x86_EDX);
Call_Direct(DoTLBMiss,"DoTLBMiss");
if (CPU_Type == CPU_SyncCores) { Call_Direct(SyncToPC, "SyncToPC"); }
Ret();
break;
default:
if (ShowDebugMessages)
DisplayError("how did you want to exit on reason (%d) ???",reason);
}
}
void CompileSystemCheck (DWORD TimerModifier, DWORD TargetPC, REG_INFO RegSet) {
BLOCK_SECTION Section;
BYTE *Jump, *Jump2;
// Timer
if (TimerModifier != 0) {
SubConstFromVariable(TimerModifier,&Timers.Timer,"Timer");
} else {
CompConstToVariable(0,&Timers.Timer,"Timer");
}
JnsLabel32("Continue_From_Timer_Test",0);
Jump = RecompPos - 4;
Pushad();
if (TargetPC != (DWORD)-1) { MoveConstToVariable(TargetPC,&PROGRAM_COUNTER,"PROGRAM_COUNTER"); }
InitilzeSection (&Section, NULL, (DWORD)-1, 0);
memcpy(&Section.RegWorking, &RegSet, sizeof(REG_INFO));
WriteBackRegisters(&Section);
if (CPU_Type == CPU_SyncCores) { Call_Direct(SyncToPC, "SyncToPC"); }
Call_Direct(TimerDone,"TimerDone");
if (CPU_Type == CPU_SyncCores) { Call_Direct(SyncToPC, "SyncToPC"); }
Popad();
//Interrupt
CompConstToVariable(0,&CPU_Action.DoSomething,"CPU_Action.DoSomething");
JeLabel32("Continue_From_Interrupt_Test",0);
Jump2 = RecompPos - 4;
CompileExit(-1,Section.RegWorking,DoCPU_Action,TRUE,NULL);
CPU_Message("");
CPU_Message(" $Continue_From_Interrupt_Test:");
SetJump32(Jump2,RecompPos);
Ret();
CPU_Message("");
CPU_Message(" $Continue_From_Timer_Test:");
SetJump32(Jump,RecompPos);
//Interrupt 2
CompConstToVariable(0,&CPU_Action.DoSomething,"CPU_Action.DoSomething");
JeLabel32("Continue_From_Interrupt_Test",0);
Jump = RecompPos - 4;
if (TargetPC != (DWORD)-1) { MoveConstToVariable(TargetPC,&PROGRAM_COUNTER,"PROGRAM_COUNTER"); }
InitilzeSection (&Section, NULL, (DWORD)-1, 0);
memcpy(&Section.RegWorking, &RegSet, sizeof(REG_INFO));
WriteBackRegisters(&Section);
CompileExit(-1,Section.RegWorking,DoCPU_Action,TRUE,NULL);
CPU_Message("");
CPU_Message(" $Continue_From_Interrupt_Test:");
SetJump32(Jump,RecompPos);
return;
}
void _fastcall CreateSectionLinkage (BLOCK_SECTION * Section) {
BLOCK_SECTION ** TargetSection[2];
DWORD * TargetPC[2], count;
InheritConstants(Section);
__try {
FillSectionInfo(Section);
} __except( r4300i_CPU_MemoryFilter( GetExceptionCode(), GetExceptionInformation()) ) {
DisplayError(GS(MSG_UNKNOWN_MEM_ACTION));
ExitThread(0);
}
if (Section->Jump.TargetPC < Section->Cont.TargetPC) {
TargetSection[0] = (BLOCK_SECTION **)&Section->JumpSection;
TargetSection[1] = (BLOCK_SECTION **)&Section->ContinueSection;
TargetPC[0] = &Section->Jump.TargetPC;
TargetPC[1] = &Section->Cont.TargetPC;
} else {
TargetSection[0] = (BLOCK_SECTION **)&Section->ContinueSection;
TargetSection[1] = (BLOCK_SECTION **)&Section->JumpSection;
TargetPC[0] = &Section->Cont.TargetPC;
TargetPC[1] = &Section->Jump.TargetPC;
}
for (count = 0; count < 2; count ++) {
if (*TargetPC[count] != (DWORD)-1 && *TargetSection[count] == NULL) {
*TargetSection[count] = ExistingSection(BlockInfo.BlockInfo.ContinueSection,*TargetPC[count],GetNewTestValue());
if (*TargetSection[count] == NULL) {
*TargetSection[count] = ExistingSection(BlockInfo.BlockInfo.JumpSection,*TargetPC[count],GetNewTestValue());
}
if (*TargetSection[count] == NULL) {
BlockInfo.NoOfSections += 1;
*TargetSection[count] = malloc(sizeof(BLOCK_SECTION));
InitilzeSection (*TargetSection[count], Section, *TargetPC[count], BlockInfo.NoOfSections);
CreateSectionLinkage(*TargetSection[count]);
} else {
AddParent(*TargetSection[count],Section);
}
}
}
}
void _fastcall DetermineLoop(BLOCK_SECTION * 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,GetNewTestValue(),((BLOCK_SECTION *)Section->ContinueSection)->SectionID);
}
if (Section->JumpSection != NULL) {
DetermineLoop(Section->JumpSection,Test,GetNewTestValue(),((BLOCK_SECTION *)Section->JumpSection)->SectionID);
}
}
BOOL DisplaySectionInformation (BLOCK_SECTION * Section, DWORD ID, DWORD Test) {
int NoOfParents;
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);
if (Section->ParentSection != NULL) {
for (NoOfParents = 0;Section->ParentSection[NoOfParents] != NULL;NoOfParents++);
CPU_Message("Number of parents: %d",NoOfParents);
}
if (Section->JumpSection != NULL) {
CPU_Message("Jump Section: %d",((BLOCK_SECTION *)Section->JumpSection)->SectionID);
} else {
CPU_Message("Jump Section: None");
}
if (Section->ContinueSection != NULL) {
CPU_Message("Continue Section: %d",((BLOCK_SECTION *)Section->ContinueSection)->SectionID);
} else {
CPU_Message("Continue Section: None");
}
CPU_Message("=======================",Section->SectionID);
return TRUE;
}
BLOCK_SECTION * ExistingSection(BLOCK_SECTION * StartSection, DWORD Addr, DWORD Test) {
BLOCK_SECTION * Section;
if (StartSection == NULL) { return NULL; }
if (StartSection->StartPC == Addr) { return StartSection; }
if (StartSection->Test == Test) { return NULL; }
StartSection->Test = Test;
Section = ExistingSection(StartSection->JumpSection,Addr,Test);
if (Section != NULL) { return Section; }
Section = ExistingSection(StartSection->ContinueSection,Addr,Test);
if (Section != NULL) { return Section; }
return NULL;
}
void _fastcall FillSectionInfo(BLOCK_SECTION * Section) {
OPCODE Command;
if (Section->CompiledLocation != NULL) { return; }
Section->CompilePC = Section->StartPC;
memcpy(&Section->RegWorking,&Section->RegStart,sizeof(REG_INFO));
NextInstruction = NORMAL;
do {
if (!r4300i_LW_VAddr_NonCPU(Section->CompilePC, &Command.Hex)) {
DisplayError(GS(MSG_FAIL_LOAD_WORD));
ExitThread(0);
}
if (SelfModCheck == ModCode_ChangeMemory) {
if ( (Command.Hex >> 16) == 0x7C7C) {
Command.Hex = OrigMem[(Command.Hex & 0xFFFF)].OriginalValue;
}
}
switch (Command.BRANCH.op) {
case R4300i_SPECIAL:
switch (Command.REG.funct) {
case R4300i_SPECIAL_SYNC:
break;
case R4300i_SPECIAL_SLL:
if (Command.REG.rd == 0) { break; }
if (Section->InLoop && Command.BRANCH.rt == Command.REG.rd) {
MipsRegState(Command.REG.rd) = STATE_UNKNOWN;
}
if (IsConst(Command.BRANCH.rt)) {
MipsRegState(Command.REG.rd) = STATE_CONST_32;
MipsRegLo(Command.REG.rd) = MipsRegLo(Command.BRANCH.rt) << Command.REG.sa;
} else {
MipsRegState(Command.REG.rd) = STATE_UNKNOWN;
}
break;
case R4300i_SPECIAL_SRL:
if (Command.REG.rd == 0) { break; }
if (Section->InLoop && Command.BRANCH.rt == Command.REG.rd) {
MipsRegState(Command.REG.rd) = STATE_UNKNOWN;
}
if (IsConst(Command.BRANCH.rt)) {
MipsRegState(Command.REG.rd) = STATE_CONST_32;
MipsRegLo(Command.REG.rd) = MipsRegLo(Command.BRANCH.rt) >> Command.REG.sa;
} else {
MipsRegState(Command.REG.rd) = STATE_UNKNOWN;
}
break;
case R4300i_SPECIAL_SRA:
if (Command.REG.rd == 0) { break; }
if (Section->InLoop && Command.BRANCH.rt == Command.REG.rd) {
MipsRegState(Command.REG.rd) = STATE_UNKNOWN;
}
if (IsConst(Command.BRANCH.rt)) {
MipsRegState(Command.REG.rd) = STATE_CONST_32;
MipsRegLo(Command.REG.rd) = MipsRegLo_S(Command.BRANCH.rt) >> Command.REG.sa;
} else {
MipsRegState(Command.REG.rd) = STATE_UNKNOWN;
}
break;
case R4300i_SPECIAL_SLLV:
if (Command.REG.rd == 0) { break; }
if (Section->InLoop && (Command.BRANCH.rt == Command.REG.rd || Command.BRANCH.rs == Command.REG.rd)) {
MipsRegState(Command.REG.rd) = STATE_UNKNOWN;
}
if (IsConst(Command.BRANCH.rt) && IsConst(Command.BRANCH.rs)) {
MipsRegState(Command.REG.rd) = STATE_CONST_32;
MipsRegLo(Command.REG.rd) = MipsRegLo(Command.BRANCH.rt) << (MipsRegLo(Command.BRANCH.rs) & 0x1F);
} else {
MipsRegState(Command.REG.rd) = STATE_UNKNOWN;
}
break;
case R4300i_SPECIAL_SRLV:
if (Command.REG.rd == 0) { break; }
if (Section->InLoop && (Command.BRANCH.rt == Command.REG.rd || Command.BRANCH.rs == Command.REG.rd)) {
MipsRegState(Command.REG.rd) = STATE_UNKNOWN;
}
if (IsConst(Command.BRANCH.rt) && IsConst(Command.BRANCH.rs)) {
MipsRegState(Command.REG.rd) = STATE_CONST_32;
MipsRegLo(Command.REG.rd) = MipsRegLo(Command.BRANCH.rt) >> (MipsRegLo(Command.BRANCH.rs) & 0x1F);
} else {
MipsRegState(Command.REG.rd) = STATE_UNKNOWN;
}
break;
case R4300i_SPECIAL_SRAV:
if (Command.REG.rd == 0) { break; }
if (Section->InLoop && (Command.BRANCH.rt == Command.REG.rd || Command.BRANCH.rs == Command.REG.rd)) {
MipsRegState(Command.REG.rd) = STATE_UNKNOWN;
}
if (IsConst(Command.BRANCH.rt) && IsConst(Command.BRANCH.rs)) {
MipsRegState(Command.REG.rd) = STATE_CONST_32;
MipsRegLo(Command.REG.rd) = MipsRegLo_S(Command.BRANCH.rt) >> (MipsRegLo(Command.BRANCH.rs) & 0x1F);
} else {
MipsRegState(Command.REG.rd) = STATE_UNKNOWN;
}
break;
case R4300i_SPECIAL_JR:
if (IsConst(Command.BRANCH.rs)) {
Section->Jump.TargetPC = MipsRegLo(Command.BRANCH.rs);
} else {
Section->Jump.TargetPC = (DWORD)-1;
}
NextInstruction = DELAY_SLOT;
break;
case R4300i_SPECIAL_JALR:
MipsRegLo(Opcode.REG.rd) = Section->CompilePC + 8;
MipsRegState(Opcode.REG.rd) = STATE_CONST_32;
if (IsConst(Command.BRANCH.rs)) {
Section->Jump.TargetPC = MipsRegLo(Command.BRANCH.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: MipsRegState(Command.REG.rd) = STATE_UNKNOWN; break;
case R4300i_SPECIAL_MTHI: break;
case R4300i_SPECIAL_MFLO: MipsRegState(Command.REG.rd) = STATE_UNKNOWN; break;
case R4300i_SPECIAL_MTLO: break;
case R4300i_SPECIAL_DSLLV:
if (Command.REG.rd == 0) { break; }
if (Section->InLoop && (Command.BRANCH.rt == Command.REG.rd || Command.BRANCH.rs == Command.REG.rd)) {
MipsRegState(Command.REG.rd) = STATE_UNKNOWN;
}
if (IsConst(Command.BRANCH.rt) && IsConst(Command.BRANCH.rs)) {
MipsRegState(Command.REG.rd) = STATE_CONST_64;
MipsReg(Command.REG.rd) = Is64Bit(Command.BRANCH.rt)?MipsReg(Command.BRANCH.rt):(QWORD)MipsRegLo_S(Command.BRANCH.rt) << (MipsRegLo(Command.BRANCH.rs) & 0x3F);
} else {
MipsRegState(Command.REG.rd) = STATE_UNKNOWN;
}
break;
case R4300i_SPECIAL_DSRLV:
if (Command.REG.rd == 0) { break; }
if (Section->InLoop && (Command.BRANCH.rt == Command.REG.rd || Command.BRANCH.rs == Command.REG.rd)) {
MipsRegState(Command.REG.rd) = STATE_UNKNOWN;
}
if (IsConst(Command.BRANCH.rt) && IsConst(Command.BRANCH.rs)) {
MipsRegState(Command.REG.rd) = STATE_CONST_64;
MipsReg(Command.REG.rd) = Is64Bit(Command.BRANCH.rt)?MipsReg(Command.BRANCH.rt):(QWORD)MipsRegLo_S(Command.BRANCH.rt) >> (MipsRegLo(Command.BRANCH.rs) & 0x3F);
} else {
MipsRegState(Command.REG.rd) = STATE_UNKNOWN;
}
break;
case R4300i_SPECIAL_DSRAV:
if (Command.REG.rd == 0) { break; }
if (Section->InLoop && (Command.BRANCH.rt == Command.REG.rd || Command.BRANCH.rs == Command.REG.rd)) {
MipsRegState(Command.REG.rd) = STATE_UNKNOWN;
}
if (IsConst(Command.BRANCH.rt) && IsConst(Command.BRANCH.rs)) {
MipsRegState(Command.REG.rd) = STATE_CONST_64;
MipsReg(Command.REG.rd) = Is64Bit(Command.BRANCH.rt)?MipsReg_S(Command.BRANCH.rt):(_int64)MipsRegLo_S(Command.BRANCH.rt) >> (MipsRegLo(Command.BRANCH.rs) & 0x3F);
} else {
MipsRegState(Command.REG.rd) = 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.REG.rd == 0) { break; }
if (Section->InLoop && (Command.BRANCH.rt == Command.REG.rd || Command.BRANCH.rs == Command.REG.rd)) {
MipsRegState(Command.REG.rd) = STATE_UNKNOWN;
}
if (IsConst(Command.BRANCH.rt) && IsConst(Command.BRANCH.rs)) {
MipsRegLo(Command.REG.rd) = MipsRegLo(Command.BRANCH.rs) + MipsRegLo(Command.BRANCH.rt);
MipsRegState(Command.REG.rd) = STATE_CONST_32;
} else {
MipsRegState(Command.REG.rd) = STATE_UNKNOWN;
}
break;
case R4300i_SPECIAL_SUB:
case R4300i_SPECIAL_SUBU:
if (Command.REG.rd == 0) { break; }
if (Section->InLoop && (Command.BRANCH.rt == Command.REG.rd || Command.BRANCH.rs == Command.REG.rd)) {
MipsRegState(Command.REG.rd) = STATE_UNKNOWN;
}
if (IsConst(Command.BRANCH.rt) && IsConst(Command.BRANCH.rs)) {
MipsRegLo(Command.REG.rd) = MipsRegLo(Command.BRANCH.rs) - MipsRegLo(Command.BRANCH.rt);
MipsRegState(Command.REG.rd) = STATE_CONST_32;
} else {
MipsRegState(Command.REG.rd) = STATE_UNKNOWN;
}
break;
case R4300i_SPECIAL_AND:
if (Command.REG.rd == 0) { break; }
if (Section->InLoop && (Command.BRANCH.rt == Command.REG.rd || Command.BRANCH.rs == Command.REG.rd)) {
MipsRegState(Command.REG.rd) = STATE_UNKNOWN;
}
if (IsConst(Command.BRANCH.rt) && IsConst(Command.BRANCH.rs)) {
if (Is64Bit(Command.BRANCH.rt) && Is64Bit(Command.BRANCH.rs)) {
MipsReg(Command.REG.rd) = MipsReg(Command.BRANCH.rt) & MipsReg(Command.BRANCH.rs);
MipsRegState(Command.REG.rd) = STATE_CONST_64;
} else if (Is64Bit(Command.BRANCH.rt) || Is64Bit(Command.BRANCH.rs)) {
if (Is64Bit(Command.BRANCH.rt)) {
MipsReg(Command.REG.rd) = MipsReg(Command.BRANCH.rt) & MipsRegLo(Command.BRANCH.rs);
} else {
MipsReg(Command.REG.rd) = MipsRegLo(Command.BRANCH.rt) & MipsReg(Command.BRANCH.rs);
}
MipsRegState(Command.REG.rd) = ConstantsType(MipsReg(Command.REG.rd));
} else {
MipsRegLo(Command.REG.rd) = MipsRegLo(Command.BRANCH.rt) & MipsRegLo(Command.BRANCH.rs);
MipsRegState(Command.REG.rd) = STATE_CONST_32;
}
} else {
MipsRegState(Command.REG.rd) = STATE_UNKNOWN;
}
break;
case R4300i_SPECIAL_OR:
if (Command.REG.rd == 0) { break; }
if (Section->InLoop && (Command.BRANCH.rt == Command.REG.rd || Command.BRANCH.rs == Command.REG.rd)) {
MipsRegState(Command.REG.rd) = STATE_UNKNOWN;
}
if (IsConst(Command.BRANCH.rt) && IsConst(Command.BRANCH.rs)) {
if (Is64Bit(Command.BRANCH.rt) && Is64Bit(Command.BRANCH.rs)) {
MipsReg(Command.REG.rd) = MipsReg(Command.BRANCH.rt) | MipsReg(Command.BRANCH.rs);
MipsRegState(Command.REG.rd) = STATE_CONST_64;
} else if (Is64Bit(Command.BRANCH.rt) || Is64Bit(Command.BRANCH.rs)) {
if (Is64Bit(Command.BRANCH.rt)) {
MipsReg(Command.REG.rd) = MipsReg(Command.BRANCH.rt) | MipsRegLo(Command.BRANCH.rs);
} else {
MipsReg(Command.REG.rd) = MipsRegLo(Command.BRANCH.rt) | MipsReg(Command.BRANCH.rs);
}
MipsRegState(Command.REG.rd) = STATE_CONST_64;
} else {
MipsRegLo(Command.REG.rd) = MipsRegLo(Command.BRANCH.rt) | MipsRegLo(Command.BRANCH.rs);
MipsRegState(Command.REG.rd) = STATE_CONST_32;
}
} else {
MipsRegState(Command.REG.rd) = STATE_UNKNOWN;
}
break;
case R4300i_SPECIAL_XOR:
if (Command.REG.rd == 0) { break; }
if (Section->InLoop && (Command.BRANCH.rt == Command.REG.rd || Command.BRANCH.rs == Command.REG.rd)) {
MipsRegState(Command.REG.rd) = STATE_UNKNOWN;
}
if (IsConst(Command.BRANCH.rt) && IsConst(Command.BRANCH.rs)) {
if (Is64Bit(Command.BRANCH.rt) && Is64Bit(Command.BRANCH.rs)) {
MipsReg(Command.REG.rd) = MipsReg(Command.BRANCH.rt) ^ MipsReg(Command.BRANCH.rs);
MipsRegState(Command.REG.rd) = STATE_CONST_64;
} else if (Is64Bit(Command.BRANCH.rt) || Is64Bit(Command.BRANCH.rs)) {
if (Is64Bit(Command.BRANCH.rt)) {
MipsReg(Command.REG.rd) = MipsReg(Command.BRANCH.rt) ^ MipsRegLo(Command.BRANCH.rs);
} else {
MipsReg(Command.REG.rd) = MipsRegLo(Command.BRANCH.rt) ^ MipsReg(Command.BRANCH.rs);
}
MipsRegState(Command.REG.rd) = STATE_CONST_64;
} else {
MipsRegLo(Command.REG.rd) = MipsRegLo(Command.BRANCH.rt) ^ MipsRegLo(Command.BRANCH.rs);
MipsRegState(Command.REG.rd) = STATE_CONST_32;
}
} else {
MipsRegState(Command.REG.rd) = STATE_UNKNOWN;
}
break;
case R4300i_SPECIAL_NOR:
if (Command.REG.rd == 0) { break; }
if (Section->InLoop && (Command.BRANCH.rt == Command.REG.rd || Command.BRANCH.rs == Command.REG.rd)) {
MipsRegState(Command.REG.rd) = STATE_UNKNOWN;
}
if (IsConst(Command.BRANCH.rt) && IsConst(Command.BRANCH.rs)) {
if (Is64Bit(Command.BRANCH.rt) && Is64Bit(Command.BRANCH.rs)) {
MipsReg(Command.REG.rd) = ~(MipsReg(Command.BRANCH.rt) | MipsReg(Command.BRANCH.rs));
MipsRegState(Command.REG.rd) = STATE_CONST_64;
} else if (Is64Bit(Command.BRANCH.rt) || Is64Bit(Command.BRANCH.rs)) {
if (Is64Bit(Command.BRANCH.rt)) {
MipsReg(Command.REG.rd) = ~(MipsReg(Command.BRANCH.rt) | MipsRegLo(Command.BRANCH.rs));
} else {
MipsReg(Command.REG.rd) = ~(MipsRegLo(Command.BRANCH.rt) | MipsReg(Command.BRANCH.rs));
}
MipsRegState(Command.REG.rd) = STATE_CONST_64;
} else {
MipsRegLo(Command.REG.rd) = ~(MipsRegLo(Command.BRANCH.rt) | MipsRegLo(Command.BRANCH.rs));
MipsRegState(Command.REG.rd) = STATE_CONST_32;
}
} else {
MipsRegState(Command.REG.rd) = STATE_UNKNOWN;
}
break;
case R4300i_SPECIAL_SLT:
if (Command.REG.rd == 0) { break; }
if (IsConst(Command.BRANCH.rt) && IsConst(Command.BRANCH.rs)) {
if (Is64Bit(Command.BRANCH.rt) || Is64Bit(Command.BRANCH.rs)) {
if (Is64Bit(Command.BRANCH.rt)) {
MipsRegLo(Command.REG.rd) = (MipsRegLo_S(Command.BRANCH.rs) < MipsReg_S(Command.BRANCH.rt))?1:0;
} else {
MipsRegLo(Command.REG.rd) = (MipsReg_S(Command.BRANCH.rs) < MipsRegLo_S(Command.BRANCH.rt))?1:0;
}
} else {
MipsRegLo(Command.REG.rd) = (MipsRegLo_S(Command.BRANCH.rs) < MipsRegLo_S(Command.BRANCH.rt))?1:0;
}
MipsRegState(Command.REG.rd) = STATE_CONST_32;
} else {
MipsRegState(Command.REG.rd) = STATE_UNKNOWN;
}
break;
case R4300i_SPECIAL_SLTU:
if (Command.REG.rd == 0) { break; }
if (IsConst(Command.BRANCH.rt) && IsConst(Command.BRANCH.rs)) {
if (Is64Bit(Command.BRANCH.rt) || Is64Bit(Command.BRANCH.rs)) {
if (Is64Bit(Command.BRANCH.rt)) {
MipsRegLo(Command.REG.rd) = (MipsRegLo(Command.BRANCH.rs) < MipsReg(Command.BRANCH.rt))?1:0;
} else {
MipsRegLo(Command.REG.rd) = (MipsReg(Command.BRANCH.rs) < MipsRegLo(Command.BRANCH.rt))?1:0;
}
} else {
MipsRegLo(Command.REG.rd) = (MipsRegLo(Command.BRANCH.rs) < MipsRegLo(Command.BRANCH.rt))?1:0;
}
MipsRegState(Command.REG.rd) = STATE_CONST_32;
} else {
MipsRegState(Command.REG.rd) = STATE_UNKNOWN;
}
break;
case R4300i_SPECIAL_DADD:
case R4300i_SPECIAL_DADDU:
if (Command.REG.rd == 0) { break; }
if (Section->InLoop && (Command.BRANCH.rt == Command.REG.rd || Command.BRANCH.rs == Command.REG.rd)) {
MipsRegState(Command.REG.rd) = STATE_UNKNOWN;
}
if (IsConst(Command.BRANCH.rt) && IsConst(Command.BRANCH.rs)) {
MipsReg(Command.REG.rd) =
Is64Bit(Command.BRANCH.rs)?MipsReg(Command.BRANCH.rs):(_int64)MipsRegLo_S(Command.BRANCH.rs) +
Is64Bit(Command.BRANCH.rt)?MipsReg(Command.BRANCH.rt):(_int64)MipsRegLo_S(Command.BRANCH.rt);
MipsRegState(Command.REG.rd) = STATE_CONST_64;
} else {
MipsRegState(Command.REG.rd) = STATE_UNKNOWN;
}
break;
case R4300i_SPECIAL_DSUB:
case R4300i_SPECIAL_DSUBU:
if (Command.REG.rd == 0) { break; }
if (Section->InLoop && (Command.BRANCH.rt == Command.REG.rd || Command.BRANCH.rs == Command.REG.rd)) {
MipsRegState(Command.REG.rd) = STATE_UNKNOWN;
}
if (IsConst(Command.BRANCH.rt) && IsConst(Command.BRANCH.rs)) {
MipsReg(Command.REG.rd) =
Is64Bit(Command.BRANCH.rs)?MipsReg(Command.BRANCH.rs):(_int64)MipsRegLo_S(Command.BRANCH.rs) -
Is64Bit(Command.BRANCH.rt)?MipsReg(Command.BRANCH.rt):(_int64)MipsRegLo_S(Command.BRANCH.rt);
MipsRegState(Command.REG.rd) = STATE_CONST_64;
} else {
MipsRegState(Command.REG.rd) = STATE_UNKNOWN;
}
break;
case R4300i_SPECIAL_DSLL:
if (Command.REG.rd == 0) { break; }
if (Section->InLoop && Command.BRANCH.rt == Command.REG.rd) {
MipsRegState(Command.REG.rd) = STATE_UNKNOWN;
}
if (IsConst(Command.BRANCH.rt)) {
MipsRegState(Command.REG.rd) = STATE_CONST_64;
MipsReg(Command.REG.rd) = Is64Bit(Command.BRANCH.rt)?MipsReg(Command.BRANCH.rt):(_int64)MipsRegLo_S(Command.BRANCH.rt) << Command.REG.sa;
} else {
MipsRegState(Command.REG.rd) = STATE_UNKNOWN;
}
break;
case R4300i_SPECIAL_DSRL:
if (Command.REG.rd == 0) { break; }
if (Section->InLoop && Command.BRANCH.rt == Command.REG.rd) {
MipsRegState(Command.REG.rd) = STATE_UNKNOWN;
}
if (IsConst(Command.BRANCH.rt)) {
MipsRegState(Command.REG.rd) = STATE_CONST_64;
MipsReg(Command.REG.rd) = Is64Bit(Command.BRANCH.rt)?MipsReg(Command.BRANCH.rt):(QWORD)MipsRegLo_S(Command.BRANCH.rt) >> Command.REG.sa;
} else {
MipsRegState(Command.REG.rd) = STATE_UNKNOWN;
}
break;
case R4300i_SPECIAL_DSRA:
if (Command.REG.rd == 0) { break; }
if (Section->InLoop && Command.BRANCH.rt == Command.REG.rd) {
MipsRegState(Command.REG.rd) = STATE_UNKNOWN;
}
if (IsConst(Command.BRANCH.rt)) {
MipsRegState(Command.REG.rd) = STATE_CONST_64;
MipsReg_S(Command.REG.rd) = Is64Bit(Command.BRANCH.rt)?MipsReg_S(Command.BRANCH.rt):(_int64)MipsRegLo_S(Command.BRANCH.rt) >> Command.REG.sa;
} else {
MipsRegState(Command.REG.rd) = STATE_UNKNOWN;
}
break;
case R4300i_SPECIAL_DSLL32:
if (Command.REG.rd == 0) { break; }
if (Section->InLoop && Command.BRANCH.rt == Command.REG.rd) {
MipsRegState(Command.REG.rd) = STATE_UNKNOWN;
}
if (IsConst(Command.BRANCH.rt)) {
MipsRegState(Command.REG.rd) = STATE_CONST_64;
MipsReg(Command.REG.rd) = MipsRegLo(Command.BRANCH.rt) << (Command.REG.sa + 32);
} else {
MipsRegState(Command.REG.rd) = STATE_UNKNOWN;
}
break;
case R4300i_SPECIAL_DSRL32:
if (Command.REG.rd == 0) { break; }
if (Section->InLoop && Command.BRANCH.rt == Command.REG.rd) {
MipsRegState(Command.REG.rd) = STATE_UNKNOWN;
}
if (IsConst(Command.BRANCH.rt)) {
MipsRegState(Command.REG.rd) = STATE_CONST_32;
MipsRegLo(Command.REG.rd) = (DWORD)(MipsReg(Command.BRANCH.rt) >> (Command.REG.sa + 32));
} else {
MipsRegState(Command.REG.rd) = STATE_UNKNOWN;
}
break;
case R4300i_SPECIAL_DSRA32:
if (Command.REG.rd == 0) { break; }
if (Section->InLoop && Command.BRANCH.rt == Command.REG.rd) {
MipsRegState(Command.REG.rd) = STATE_UNKNOWN;
}
if (IsConst(Command.BRANCH.rt)) {
MipsRegState(Command.REG.rd) = STATE_CONST_32;
MipsRegLo(Command.REG.rd) = (DWORD)(MipsReg_S(Command.BRANCH.rt) >> (Command.REG.sa + 32));
} else {
MipsRegState(Command.REG.rd) = STATE_UNKNOWN;
}
break;
default:
if (ShowDebugMessages) {
if (Command.Hex == 0x00000001) { break; }
DisplayError("Unhandled R4300i OpCode in FillSectionInfo 5\n%s",
R4300iOpcodeName(Command.Hex, Section->CompilePC));
}
NextInstruction = END_BLOCK;
Section->CompilePC -= 4;
}
break;
case R4300i_REGIMM:
switch (Command.BRANCH.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.BRANCH.offset << 2) + 4;
if (Section->CompilePC == Section->Jump.TargetPC) {
if (!DelaySlotEffectsCompare(Section->CompilePC,Command.BRANCH.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.BRANCH.offset << 2) + 4;
if (Section->CompilePC == Section->Jump.TargetPC) {
if (!DelaySlotEffectsCompare(Section->CompilePC,Command.BRANCH.rs,0)) {
Section->Jump.PermLoop = TRUE;
}
}
break;
case R4300i_REGIMM_BLTZAL:
case R4300i_REGIMM_BGEZAL:
NextInstruction = DELAY_SLOT;
MipsRegLo(31) = Section->CompilePC + 8;
MipsRegState(31) = STATE_CONST_32;
Section->Cont.TargetPC = Section->CompilePC + 8;
Section->Jump.TargetPC = Section->CompilePC + ((short)Command.BRANCH.offset << 2) + 4;
if (Section->CompilePC == Section->Jump.TargetPC) {
if (!DelaySlotEffectsCompare(Section->CompilePC,Command.BRANCH.rs,0)) {
Section->Jump.PermLoop = TRUE;
}
}
break;
default:
if (ShowDebugMessages) {
if (Command.Hex == 0x0407000D) { break; }
DisplayError("Unhandled R4300i OpCode in FillSectionInfo 4\n%s",
R4300iOpcodeName(Command.Hex, Section->CompilePC));
}
NextInstruction = END_BLOCK;
Section->CompilePC -= 4;
}
break;
case R4300i_JAL:
NextInstruction = DELAY_SLOT;
MipsRegLo(31) = Section->CompilePC + 8;
MipsRegState(31) = STATE_CONST_32;
Section->Jump.TargetPC = (Section->CompilePC & 0xF0000000) + (Command.JMP.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.JMP.target << 2);
if (Section->CompilePC == Section->Jump.TargetPC) { Section->Jump.PermLoop = TRUE; }
break;
case R4300i_BEQ:
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.BRANCH.offset << 2) + 4;
if (Section->CompilePC == Section->Jump.TargetPC) {
if (!DelaySlotEffectsCompare(Section->CompilePC,Command.BRANCH.rs,Command.BRANCH.rt)) {
Section->Jump.PermLoop = TRUE;
}
}
break;
case R4300i_ADDI:
case R4300i_ADDIU:
if (Command.BRANCH.rt == 0) { break; }
if (Section->InLoop && Command.BRANCH.rs == Command.BRANCH.rt) {
MipsRegState(Command.BRANCH.rt) = STATE_UNKNOWN;
}
if (IsConst(Command.BRANCH.rs)) {
MipsRegLo(Command.BRANCH.rt) = MipsRegLo(Command.BRANCH.rs) + (short)Command.IMM.immediate;
MipsRegState(Command.BRANCH.rt) = STATE_CONST_32;
} else {
MipsRegState(Command.BRANCH.rt) = STATE_UNKNOWN;
}
break;
case R4300i_SLTI:
if (Command.BRANCH.rt == 0) { break; }
if (IsConst(Command.BRANCH.rs)) {
if (Is64Bit(Command.BRANCH.rs)) {
MipsRegLo(Command.BRANCH.rt) = (MipsReg_S(Command.BRANCH.rs) < (_int64)((short)Command.IMM.immediate))?1:0;
} else {
MipsRegLo(Command.BRANCH.rt) = (MipsRegLo_S(Command.BRANCH.rs) < (int)((short)Command.IMM.immediate))?1:0;
}
MipsRegState(Command.BRANCH.rt) = STATE_CONST_32;
} else {
MipsRegState(Command.BRANCH.rt) = STATE_UNKNOWN;
}
break;
case R4300i_SLTIU:
if (Command.BRANCH.rt == 0) { break; }
if (IsConst(Command.BRANCH.rs)) {
if (Is64Bit(Command.BRANCH.rs)) {
MipsRegLo(Command.BRANCH.rt) = (MipsReg(Command.BRANCH.rs) < (unsigned _int64)((short)Command.IMM.immediate))?1:0;
} else {
MipsRegLo(Command.BRANCH.rt) = (MipsRegLo(Command.BRANCH.rs) < (DWORD)((short)Command.IMM.immediate))?1:0;
}
MipsRegState(Command.BRANCH.rt) = STATE_CONST_32;
} else {
MipsRegState(Command.BRANCH.rt) = STATE_UNKNOWN;
}
break;
case R4300i_LUI:
if (Command.BRANCH.rt == 0) { break; }
MipsRegLo(Command.BRANCH.rt) = ((short)Command.BRANCH.offset << 16);
MipsRegState(Command.BRANCH.rt) = STATE_CONST_32;
break;
case R4300i_ANDI:
if (Command.BRANCH.rt == 0) { break; }
if (Section->InLoop && Command.BRANCH.rs == Command.BRANCH.rt) {
MipsRegState(Command.BRANCH.rt) = STATE_UNKNOWN;
}
if (IsConst(Command.BRANCH.rs)) {
MipsRegState(Command.BRANCH.rt) = STATE_CONST_32;
MipsRegLo(Command.BRANCH.rt) = MipsRegLo(Command.BRANCH.rs) & Command.IMM.immediate;
} else {
MipsRegState(Command.BRANCH.rt) = STATE_UNKNOWN;
}
break;
case R4300i_ORI:
if (Command.BRANCH.rt == 0) { break; }
if (Section->InLoop && Command.BRANCH.rs == Command.BRANCH.rt) {
MipsRegState(Command.BRANCH.rt) = STATE_UNKNOWN;
}
if (IsConst(Command.BRANCH.rs)) {
MipsRegState(Command.BRANCH.rt) = STATE_CONST_32;
MipsRegLo(Command.BRANCH.rt) = MipsRegLo(Command.BRANCH.rs) | Command.IMM.immediate;
} else {
MipsRegState(Command.BRANCH.rt) = STATE_UNKNOWN;
}
break;
case R4300i_XORI:
if (Command.BRANCH.rt == 0) { break; }
if (Section->InLoop && Command.BRANCH.rs == Command.BRANCH.rt) {
MipsRegState(Command.BRANCH.rt) = STATE_UNKNOWN;
}
if (IsConst(Command.BRANCH.rs)) {
MipsRegState(Command.BRANCH.rt) = STATE_CONST_32;
MipsRegLo(Command.BRANCH.rt) = MipsRegLo(Command.BRANCH.rs) ^ Command.IMM.immediate;
} else {
MipsRegState(Command.BRANCH.rt) = STATE_UNKNOWN;
}
break;
case R4300i_CP0:
switch (Command.BRANCH.rs) {
case R4300i_COP0_MF:
if (Command.BRANCH.rt == 0) { break; }
MipsRegState(Command.BRANCH.rt) = STATE_UNKNOWN;
break;
case R4300i_COP0_MT: break;
default:
if ( (Command.BRANCH.rs & 0x10 ) != 0 ) {
switch( Command.REG.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:
if (ShowDebugMessages)
DisplayError("Unhandled R4300i OpCode in FillSectionInfo\n%s",
R4300iOpcodeName(Command.Hex,Section->CompilePC));
NextInstruction = END_BLOCK;
Section->CompilePC -= 4;
}
} else {
if (ShowDebugMessages)
DisplayError("Unhandled R4300i OpCode in FillSectionInfo 3\n%s",
R4300iOpcodeName(Command.Hex,Section->CompilePC));
NextInstruction = END_BLOCK;
Section->CompilePC -= 4;
}
}
break;
case R4300i_CP1:
switch (Command.FP.fmt) {
case R4300i_COP1_CF:
case R4300i_COP1_MF:
case R4300i_COP1_DMF:
if (Command.BRANCH.rt == 0) { break; }
MipsRegState(Command.BRANCH.rt) = STATE_UNKNOWN;
break;
case R4300i_COP1_BC:
switch (Command.FP.ft) {
case R4300i_COP1_BC_BCF:
case R4300i_COP1_BC_BCT:
case R4300i_COP1_BC_BCFL:
case R4300i_COP1_BC_BCTL:
NextInstruction = DELAY_SLOT;
Section->Cont.TargetPC = Section->CompilePC + 8;
Section->Jump.TargetPC = Section->CompilePC + ((short)Command.BRANCH.offset << 2) + 4;
if (Section->CompilePC == Section->Jump.TargetPC) {
int EffectDelaySlot;
OPCODE NewCommand;
if (!r4300i_LW_VAddr_NonCPU(Section->CompilePC + 4, &NewCommand.Hex)) {
DisplayError(GS(MSG_FAIL_LOAD_WORD));
ExitThread(0);
}
EffectDelaySlot = FALSE;
if (NewCommand.BRANCH.op == R4300i_CP1) {
if (NewCommand.FP.fmt == R4300i_COP1_S && (NewCommand.REG.funct & 0x30) == 0x30 ) {
EffectDelaySlot = TRUE;
}
if (NewCommand.FP.fmt == R4300i_COP1_D && (NewCommand.REG.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:
if (ShowDebugMessages)
DisplayError("Unhandled R4300i OpCode in FillSectionInfo 2\n%s",
R4300iOpcodeName(Command.Hex,Section->CompilePC));
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.BRANCH.offset << 2) + 4;
if (Section->CompilePC == Section->Jump.TargetPC) {
if (!DelaySlotEffectsCompare(Section->CompilePC,Command.BRANCH.rs,Command.BRANCH.rt)) {
Section->Jump.PermLoop = TRUE;
}
}
break;
case R4300i_DADDI:
case R4300i_DADDIU:
if (Command.BRANCH.rt == 0) { break; }
if (Section->InLoop && Command.BRANCH.rs == Command.BRANCH.rt) {
MipsRegState(Command.BRANCH.rt) = STATE_UNKNOWN;
}
if (IsConst(Command.BRANCH.rs)) {
if (Is64Bit(Command.BRANCH.rs)) {
int imm32 = (short)Opcode.IMM.immediate;
__int64 imm64 = imm32;
MipsReg_S(Command.BRANCH.rt) = MipsRegLo_S(Command.BRANCH.rs) + imm64;
} else {
MipsReg_S(Command.BRANCH.rt) = MipsRegLo_S(Command.BRANCH.rs) + (short)Command.IMM.immediate;
}
MipsRegState(Command.BRANCH.rt) = STATE_CONST_64;
} else {
MipsRegState(Command.BRANCH.rt) = 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.BRANCH.rt == 0) { break; }
MipsRegState(Command.BRANCH.rt) = 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.BRANCH.rt == 0) { break; }
MipsRegState(Command.BRANCH.rt) = 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; }
if (ShowDebugMessages)
DisplayError("Unhandled R4300i OpCode in FillSectionInfo 1\n%s\n%X",
R4300iOpcodeName(Command.Hex,Section->CompilePC),Command.Hex);
}
// if (Section->CompilePC == 0x8005E4B8) {
//CPU_Message("%X: %s %s = %d",Section->CompilePC,R4300iOpcodeName(Command.Hex,Section->CompilePC),
// GPR_Name[8],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:
memcpy(&Section->Cont.RegSet,&Section->RegWorking,sizeof(REG_INFO));
NextInstruction = LIKELY_DELAY_SLOT_DONE;
Section->CompilePC += 4;
break;
case DELAY_SLOT_DONE:
memcpy(&Section->Cont.RegSet,&Section->RegWorking,sizeof(REG_INFO));
memcpy(&Section->Jump.RegSet,&Section->RegWorking,sizeof(REG_INFO));
NextInstruction = END_BLOCK;
break;
case LIKELY_DELAY_SLOT_DONE:
memcpy(&Section->Jump.RegSet,&Section->RegWorking,sizeof(REG_INFO));
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 & 0xFFFFF000) != (Section->StartPC & 0xFFFFF000)) {
Section->Jump.TargetPC = (DWORD)-1;
}
}
}
void _fastcall FixConstants (BLOCK_SECTION * Section, DWORD Test, int * Changed) {
BLOCK_SECTION * Parent;
int count, NoOfParents;
REG_INFO Original[2];
if (Section == NULL) { return; }
if (Section->Test == Test) { return; }
Section->Test = Test;
InheritConstants(Section);
memcpy(&Original[0],&Section->Cont.RegSet,sizeof(REG_INFO));
memcpy(&Original[1],&Section->Jump.RegSet,sizeof(REG_INFO));
if (Section->ParentSection) {
for (NoOfParents = 0;Section->ParentSection[NoOfParents] != NULL;NoOfParents++) {
Parent = Section->ParentSection[NoOfParents];
if (Parent->ContinueSection == Section) {
for (count = 0; count < 32; count++) {
if (Section->RegStart.MIPS_RegState[count] != Parent->Cont.RegSet.MIPS_RegState[count]) {
Section->RegStart.MIPS_RegState[count] = STATE_UNKNOWN;
//*Changed = TRUE;
}
Section->RegStart.MIPS_RegState[count] = STATE_UNKNOWN;
}
}
if (Parent->JumpSection == Section) {
for (count = 0; count < 32; count++) {
if (Section->RegStart.MIPS_RegState[count] != Parent->Jump.RegSet.MIPS_RegState[count]) {
Section->RegStart.MIPS_RegState[count] = STATE_UNKNOWN;
//*Changed = TRUE;
}
}
}
memcpy(&Section->RegWorking,&Section->RegStart,sizeof(REG_INFO));
}
}
FillSectionInfo(Section);
if (memcmp(&Original[0],&Section->Cont.RegSet,sizeof(REG_INFO)) != 0) { *Changed = TRUE; }
if (memcmp(&Original[1],&Section->Jump.RegSet,sizeof(REG_INFO)) != 0) { *Changed = TRUE; }
if (Section->JumpSection) { FixConstants(Section->JumpSection,Test,Changed); }
if (Section->ContinueSection) { FixConstants(Section->ContinueSection,Test,Changed); }
}
void FixRandomReg (void) {
while ((int)Registers.CP0[1] < (int)Registers.CP0[6]) {
Registers.CP0[1] += 32 - Registers.CP0[6];
}
}
void FreeSection (BLOCK_SECTION * Section, BLOCK_SECTION * Parent) {
if (Section == NULL) { return; }
if (Section->ParentSection) {
int NoOfParents, count;
for (NoOfParents = 0;Section->ParentSection[NoOfParents] != NULL;NoOfParents++);
for (count = 0; count < NoOfParents; count++) {
if (Section->ParentSection[count] == Parent) {
if (NoOfParents == 1) {
free(Section->ParentSection);
//CPU_Message("Free Parent Section (Section: %d)",Section->SectionID);
Section->ParentSection = NULL;
} else {
memmove(&Section->ParentSection[count],&Section->ParentSection[count + 1],
sizeof(void*) * (NoOfParents - count));
Section->ParentSection = realloc(Section->ParentSection,NoOfParents*sizeof(void *));
}
NoOfParents -= 1;
}
}
if (Parent->JumpSection == Section) { Parent->JumpSection = NULL; }
if (Parent->ContinueSection == Section) { Parent->ContinueSection = NULL; }
if (Section->ParentSection) {
for (count = 0; count < NoOfParents; count++) {
if (!IsAllParentLoops(Section,Section->ParentSection[count],FALSE,GetNewTestValue())) { return; }
}
for (count = 0; count < NoOfParents; count++) {
Parent = Section->ParentSection[count];
if (Parent->JumpSection == Section) { Parent->JumpSection = NULL; }
if (Parent->ContinueSection == Section) { Parent->ContinueSection = NULL; }
}
free(Section->ParentSection);
//CPU_Message("Free Parent Section (Section: %d)",Section->SectionID);
Section->ParentSection = NULL;
}
}
if (Section->ParentSection == NULL) {
FreeSection(Section->JumpSection,Section);
FreeSection(Section->ContinueSection,Section);
//CPU_Message("Free Section (Section: %d)",Section->SectionID);
free(Section);
}
}
void GenerateBasicSectionLinkage (BLOCK_SECTION * Section) {
_asm int 3
}
void GenerateSectionLinkage (BLOCK_SECTION * Section) {
BLOCK_SECTION * TargetSection[2], *Parent;
JUMP_INFO * 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,&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]); }
WriteBackRegisters(Section);
if (CPU_Type == CPU_SyncCores) { Call_Direct(SyncToPC, "SyncToPC"); }
MoveConstToVariable(DELAY_SLOT,&NextInstruction,"NextInstruction");
Ret();
return;
}
if (!UseLinking) {
if (Section->CompilePC == Section->Jump.TargetPC && (Section->Cont.TargetPC == -1)) {
if (!DelaySlotEffectsJump(Section->CompilePC)) {
WriteBackRegisters(Section);
memcpy(&Section->Jump.RegSet,&Section->RegWorking, sizeof(REG_INFO));
Call_Direct(InPermLoop,"InPermLoop");
}
}
}
if (TargetSection[0] != TargetSection[1] || TargetSection[0] == NULL) {
for (count = 0; count < 2; count ++) {
if (JumpInfo[count]->LinkLocation == NULL && JumpInfo[count]->FallThrough == FALSE) {
FreeSection(TargetSection[count],Section);
} 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;
}
}
if (JumpInfo[count]->TargetPC > (Section->CompilePC + 4)) {
CompileExit (JumpInfo[count]->TargetPC,JumpInfo[count]->RegSet,Normal,TRUE,NULL);
} else {
CompileExit (JumpInfo[count]->TargetPC,JumpInfo[count]->RegSet,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;
}
}
CompileExit (JumpInfo[count]->TargetPC,JumpInfo[count]->RegSet,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]->RegSet.RandomModifier != 0) {
SubConstFromVariable(JumpInfo[count]->RegSet.RandomModifier,&CP0[1],Cop0_Name[1]);
JumpInfo[count]->RegSet.RandomModifier = 0;
}
if (JumpInfo[count]->RegSet.CycleCount != 0) {
AddConstToVariable(JumpInfo[count]->RegSet.CycleCount,&CP0[9],Cop0_Name[9]);
}
if (JumpInfo[count]->TargetPC <= Section->CompilePC) {
DWORD CycleCount = JumpInfo[count]->RegSet.CycleCount;
JumpInfo[count]->RegSet.CycleCount = 0;
CPU_Message("PermLoop ***");
if (JumpInfo[count]->PermLoop) {
MoveConstToVariable(JumpInfo[count]->TargetPC,&PROGRAM_COUNTER,"PROGRAM_COUNTER");
Call_Direct(InPermLoop,"InPermLoop");
CompileSystemCheck(0,-1,JumpInfo[count]->RegSet);
} else {
CompileSystemCheck(CycleCount,JumpInfo[count]->TargetPC,JumpInfo[count]->RegSet);
}
} else {
if (JumpInfo[count]->RegSet.CycleCount != 0) {
SubConstFromVariable(JumpInfo[count]->RegSet.CycleCount,&Timers.Timer,"Timer");
JumpInfo[count]->RegSet.CycleCount = 0;
}
}
memcpy(&Section->RegWorking, &JumpInfo[count]->RegSet,sizeof(REG_INFO));
SyncRegState(Section,&TargetSection[count]->RegStart);
JmpLabel32(Label,0);
SetJump32((DWORD *)RecompPos - 1,TargetSection[count]->CompiledLocation);
}
}
//Section->CycleCount = 0;
//Section->RandomModifier = 0;
for (count = 0; count < 2; count ++) {
int count2;
if (TargetSection[count] == NULL) { continue; }
if (TargetSection[count]->ParentSection == NULL) { continue; }
for (count2 = 0;TargetSection[count]->ParentSection[count2] != NULL;count2++) {
Parent = TargetSection[count]->ParentSection[count2];
if (Parent->CompiledLocation != NULL) { continue; }
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) {
DWORD CycleCount = JumpInfo[count]->RegSet.CycleCount;;
if (JumpInfo[count]->RegSet.RandomModifier != 0) {
SubConstFromVariable(JumpInfo[count]->RegSet.RandomModifier,&CP0[1],Cop0_Name[1]);
JumpInfo[count]->RegSet.RandomModifier = 0;
}
if (JumpInfo[count]->RegSet.CycleCount != 0) {
AddConstToVariable(JumpInfo[count]->RegSet.CycleCount,&CP0[9],Cop0_Name[9]);
}
JumpInfo[count]->RegSet.CycleCount = 0;
CompileSystemCheck(CycleCount,JumpInfo[count]->TargetPC,JumpInfo[count]->RegSet);
}
}
}
CPU_Message("====== End of Section %d ======",Section->SectionID);
for (count = 0; count < 2; count ++) {
if (JumpInfo[count]->FallThrough) {
GenerateX86Code(TargetSection[count],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;
}
CompileExit (JumpInfo[count]->TargetPC,JumpInfo[count]->RegSet,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");
_asm int 3
}
if (TargetSection[count]->CompiledLocation == NULL) {
GenerateX86Code(TargetSection[count],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;
}
memcpy(&Section->RegWorking,&JumpInfo[count]->RegSet,sizeof(REG_INFO));
if (JumpInfo[count]->RegSet.RandomModifier != 0) {
SubConstFromVariable(JumpInfo[count]->RegSet.RandomModifier,&CP0[1],Cop0_Name[1]);
JumpInfo[count]->RegSet.RandomModifier = 0;
}
if (JumpInfo[count]->RegSet.CycleCount != 0) {
AddConstToVariable(JumpInfo[count]->RegSet.CycleCount,&CP0[9],Cop0_Name[9]);
}
if (JumpInfo[count]->TargetPC <= Section->CompilePC) {
DWORD CycleCount = JumpInfo[count]->RegSet.CycleCount;
JumpInfo[count]->RegSet.CycleCount = 0;
CPU_Message("PermLoop ***");
if (JumpInfo[count]->PermLoop) {
MoveConstToVariable(JumpInfo[count]->TargetPC,&PROGRAM_COUNTER,"PROGRAM_COUNTER");
Call_Direct(InPermLoop,"InPermLoop");
CompileSystemCheck(0,-1,JumpInfo[count]->RegSet);
} else {
CompileSystemCheck(CycleCount,JumpInfo[count]->TargetPC,JumpInfo[count]->RegSet);
}
} else {
if (JumpInfo[count]->RegSet.CycleCount != 0) {
SubConstFromVariable(JumpInfo[count]->RegSet.CycleCount,&Timers.Timer,"Timer");
JumpInfo[count]->RegSet.CycleCount = 0;
}
}
memcpy(&Section->RegWorking, &JumpInfo[count]->RegSet,sizeof(REG_INFO));
SyncRegState(Section,&TargetSection[count]->RegStart);
JmpLabel32(Label,0);
SetJump32((DWORD *)RecompPos - 1,TargetSection[count]->CompiledLocation);
}
}
}
BOOL GenerateX86Code (BLOCK_SECTION * Section, DWORD Test) {
int count;
if (Section == NULL) { return FALSE; }
//CPU_Message("Section: %d",Section->SectionID);
if (Section->CompiledLocation != NULL) {
if (Section->Test == Test) { return FALSE; }
Section->Test = Test;
if (GenerateX86Code(Section->ContinueSection,Test)) { return TRUE; }
if (GenerateX86Code(Section->JumpSection,Test)) { return TRUE; }
return FALSE;
}
if (Section->ParentSection) {
for (count = 0;Section->ParentSection[count] != NULL;count++) {
BLOCK_SECTION * Parent;
Parent = Section->ParentSection[count];
if (Parent->CompiledLocation != NULL) { continue; }
if (IsAllParentLoops(Section,Parent,TRUE,GetNewTestValue())) { continue; }
return FALSE;
}
}
if (!InheritParentInfo(Section)) { return FALSE; }
Section->CompiledLocation = RecompPos;
Section->CompilePC = Section->StartPC;
NextInstruction = NORMAL;
/*if (CPU_Type == CPU_SyncCores) {
//if (CPU_Type == CPU_SyncCores && (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_NonCPU(Section->CompilePC, &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 (SelfModCheck == ModCode_ChangeMemory) {
if ( (Opcode.Hex >> 16) == 0x7C7C) {
Opcode.Hex = OrigMem[(Opcode.Hex & 0xFFFF)].OriginalValue;
}
}
//if (Section->CompilePC == 0x800AA51C && NextInstruction == NORMAL) { _asm int 3 }
//if (Section->CompilePC == 0x80000050 && NextInstruction == NORMAL) { BreakPoint(); }
/*if (Section->CompilePC >= 0x800C4024 && Section->CompilePC < 0x800C4030) {
CurrentRoundingModel = RoundUnknown;
}*/
/*if (Section->CompilePC >= 0x8006F970 && Section->CompilePC < 0x8006F9A0 && NextInstruction == NORMAL) {
WriteBackRegisters(Section);
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;
MoveConstToVariable(Section->CompilePC,&PROGRAM_COUNTER,"PROGRAM_COUNTER");
MoveConstToVariable((DWORD)RecompPos,&CurrentBlock,"CurrentBlock");
if (CPU_Type == CPU_SyncCores) { Call_Direct(SyncToPC, "SyncToPC"); }
}*/
/*if (Section->CompilePC == 0x80000054 && NextInstruction == NORMAL) {
WriteBackRegisters(Section);
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;
MoveConstToVariable(Section->CompilePC,&PROGRAM_COUNTER,"PROGRAM_COUNTER");
MoveConstToVariable((DWORD)RecompPos,&CurrentBlock,"CurrentBlock");
if (CPU_Type == CPU_SyncCores) { Call_Direct(SyncToPC, "SyncToPC"); }
}*/
/*if (Section->CompilePC == 0x8005E460 && NextInstruction == NORMAL) {
WriteBackRegisters(Section);
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;
MoveConstToVariable(Section->CompilePC,&PROGRAM_COUNTER,"PROGRAM_COUNTER");
MoveConstToVariable((DWORD)RecompPos,&CurrentBlock,"CurrentBlock");
if (CPU_Type == CPU_SyncCores) { Call_Direct(SyncToPC, "SyncToPC"); }
}*/
/*if (Section->CompilePC == 0x150A1570 && NextInstruction == NORMAL) {
CPU_Message("%s = %d",GPR_Name[14],MipsRegState(14));
}
if (Section->CompilePC == 0x150A1514 && NextInstruction == NORMAL) {
CPU_Message("%s = %d",GPR_Name[14],MipsRegState(14));
}
if (Section->CompilePC == 0x150A1454 && NextInstruction == NORMAL) {
CPU_Message("%s = %d",GPR_Name[14],MipsRegState(14));
}*/
/*if (Section->CompilePC == 0x150A1570 && NextInstruction == NORMAL) {
WriteBackRegisters(Section);
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;
MoveConstToVariable(Section->CompilePC,&PROGRAM_COUNTER,"PROGRAM_COUNTER");
MoveConstToVariable((DWORD)RecompPos,&CurrentBlock,"CurrentBlock");
if (CPU_Type == CPU_SyncCores) { Call_Direct(SyncToPC, "SyncToPC"); }
}
if (Section->CompilePC == 0x150A1514 && NextInstruction == NORMAL) {
WriteBackRegisters(Section);
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;
MoveConstToVariable(Section->CompilePC,&PROGRAM_COUNTER,"PROGRAM_COUNTER");
MoveConstToVariable((DWORD)RecompPos,&CurrentBlock,"CurrentBlock");
if (CPU_Type == CPU_SyncCores) { Call_Direct(SyncToPC, "SyncToPC"); }
}
if (Section->CompilePC == 0x150A1454 && NextInstruction == NORMAL) {
WriteBackRegisters(Section);
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;
MoveConstToVariable(Section->CompilePC,&PROGRAM_COUNTER,"PROGRAM_COUNTER");
MoveConstToVariable((DWORD)RecompPos,&CurrentBlock,"CurrentBlock");
if (CPU_Type == CPU_SyncCores) { Call_Direct(SyncToPC, "SyncToPC"); }
}*/
BlockCycleCount += CountPerOp;
//CPU_Message("BlockCycleCount = %d",BlockCycleCount);
BlockRandomModifier += 1;
//CPU_Message("BlockRandomModifier = %d",BlockRandomModifier);
for (count = 1; count < 10; count ++) { x86Protected(count) = FALSE; }
switch (Opcode.BRANCH.op) {
case R4300i_SPECIAL:
switch (Opcode.REG.funct) {
case R4300i_SPECIAL_SYNC: break;
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;
case R4300i_SPECIAL_BREAK: R4300i_SPECIAL_BREAK; break;
default:
Compile_R4300i_UnknownOpcode(Section); break;
}
break;
case R4300i_REGIMM:
switch (Opcode.BRANCH.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 (Opcode.BRANCH.rs) {
case R4300i_COP0_MF: Compile_R4300i_COP0_MF(Section); break;
case R4300i_COP0_MT: Compile_R4300i_COP0_MT(Section); break;
default:
if ( (Opcode.BRANCH.rs & 0x10 ) != 0 ) {
switch( Opcode.REG.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 (Opcode.BRANCH.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 (Opcode.FP.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 (Opcode.REG.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 (Opcode.REG.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 (Opcode.REG.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 (Opcode.REG.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 (DisableRegCaching) { WriteBackRegisters(Section); }
for (count = 1; count < 10; count ++) { x86Protected(count) = FALSE; }
/*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 (x86Mapped(count) == 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) {
if (ShowDebugMessages)
DisplayError("Wanting to do delay slot over end of block");
}
if (NextInstruction == NORMAL) {
CompileExit (Section->CompilePC + 4,Section->RegWorking,Normal,TRUE,NULL);
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;
BlockCycleCount -= CountPerOp;
BlockRandomModifier -= 1;
Section->CompilePC -= 4;
break;
}
} while (NextInstruction != END_BLOCK);
return TRUE;
}
DWORD GetNewTestValue(void) {
static DWORD LastTest = 0;
if (LastTest == 0xFFFFFFFF) { LastTest = 0; }
LastTest += 1;
return LastTest;
}
void InitilizeRegSet(REG_INFO * RegSet) {
int count;
RegSet->MIPS_RegState[0] = STATE_CONST_32;
RegSet->MIPS_RegVal[0].DW = 0;
for (count = 1; count < 32; count ++ ) {
RegSet->MIPS_RegState[count] = STATE_UNKNOWN;
RegSet->MIPS_RegVal[count].DW = 0;
}
for (count = 0; count < 10; count ++ ) {
RegSet->x86reg_MappedTo[count] = NotMapped;
RegSet->x86reg_Protected[count] = FALSE;
RegSet->x86reg_MapOrder[count] = 0;
}
RegSet->CycleCount = 0;
RegSet->RandomModifier = 0;
RegSet->Stack_TopPos = 0;
for (count = 0; count < 8; count ++ ) {
RegSet->x86fpu_MappedTo[count] = -1;
RegSet->x86fpu_State[count] = FPU_Unkown;
RegSet->x86fpu_RoundingModel[count] = RoundDefault;
}
RegSet->Fpu_Used = FALSE;
RegSet->RoundingModel = RoundUnknown;
}
void _fastcall InheritConstants(BLOCK_SECTION * Section) {
int NoOfParents, count;
BLOCK_SECTION * Parent;
REG_INFO * RegSet;
if (Section->ParentSection == NULL) {
InitilizeRegSet(&Section->RegStart);
memcpy(&Section->RegWorking,&Section->RegStart,sizeof(REG_INFO));
return;
}
Parent = Section->ParentSection[0];
RegSet = Section == Parent->ContinueSection?&Parent->Cont.RegSet:&Parent->Jump.RegSet;
memcpy(&Section->RegStart,RegSet,sizeof(REG_INFO));
memcpy(&Section->RegWorking,&Section->RegStart,sizeof(REG_INFO));
for (NoOfParents = 1;Section->ParentSection[NoOfParents] != NULL;NoOfParents++) {
Parent = Section->ParentSection[NoOfParents];
RegSet = Section == Parent->ContinueSection?&Parent->Cont.RegSet:&Parent->Jump.RegSet;
for (count = 0; count < 32; count++) {
if (IsConst(count)) {
if (MipsRegState(count) != RegSet->MIPS_RegState[count]) {
MipsRegState(count) = STATE_UNKNOWN;
} else if (Is32Bit(count) && MipsRegLo(count) != RegSet->MIPS_RegVal[count].UW[0]) {
MipsRegState(count) = STATE_UNKNOWN;
} else if (Is64Bit(count) && MipsReg(count) != RegSet->MIPS_RegVal[count].UDW) {
MipsRegState(count) = STATE_UNKNOWN;
}
}
}
}
memcpy(&Section->RegStart,&Section->RegWorking,sizeof(REG_INFO));
}
BOOL InheritParentInfo (BLOCK_SECTION * 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,GetNewTestValue());
if (Section->ParentSection == NULL) {
InitilizeRegSet(&Section->RegStart);
memcpy(&Section->RegWorking,&Section->RegStart,sizeof(REG_INFO));
return TRUE;
}
NoOfParents = 0;
for (count = 0;Section->ParentSection[count] != NULL;count++) {
Parent = Section->ParentSection[count];
NoOfParents += Parent->JumpSection != Parent->ContinueSection?1:2;
}
if (NoOfParents == 0) {
if (ShowDebugMessages)
DisplayError("No Parents ???");
return FALSE;
} else if (NoOfParents == 1) {
Parent = Section->ParentSection[0];
if (Section == Parent->ContinueSection) { JumpInfo = &Parent->Cont; }
else if (Section == Parent->JumpSection) { JumpInfo = &Parent->Jump; }
else {
if (ShowDebugMessages)
DisplayError("How are these sections joined?????"); return FALSE;
}
memcpy(&Section->RegStart,&JumpInfo->RegSet,sizeof(REG_INFO));
if (JumpInfo->LinkLocation != NULL) {
CPU_Message(" Section_%d:",Section->SectionID);
SetJump32(JumpInfo->LinkLocation,RecompPos);
if (JumpInfo->LinkLocation2 != NULL) {
SetJump32(JumpInfo->LinkLocation2,RecompPos);
}
}
memcpy(&Section->RegWorking,&Section->RegStart,sizeof(REG_INFO));
return TRUE;
}
//Multiple Parents
for (count = 0, NoOfCompiledParents = 0;Section->ParentSection[count] != NULL;count++) {
Parent = Section->ParentSection[count];
if (Parent->CompiledLocation != NULL) {
NoOfCompiledParents += Parent->JumpSection != Parent->ContinueSection?1:2;
}
}
if (NoOfCompiledParents == 0){ DisplayError("No Parent has been compiled ????"); return FALSE; }
SectionParents = (BLOCK_PARENT *)malloc(NoOfParents * sizeof(BLOCK_PARENT));
for (count = 0, NoOfCompiledParents = 0;Section->ParentSection[count] != NULL;count++) {
Parent = Section->ParentSection[count];
if (Parent->CompiledLocation == NULL) { continue; }
if (Parent->JumpSection != Parent->ContinueSection) {
SectionParents[NoOfCompiledParents].Parent = Parent;
SectionParents[NoOfCompiledParents].JumpInfo =
Section == Parent->ContinueSection?&Parent->Cont:&Parent->Jump;
NoOfCompiledParents += 1;
} else {
SectionParents[NoOfCompiledParents].Parent = Parent;
SectionParents[NoOfCompiledParents].JumpInfo = &Parent->Cont;
NoOfCompiledParents += 1;
SectionParents[NoOfCompiledParents].Parent = Parent;
SectionParents[NoOfCompiledParents].JumpInfo = &Parent->Jump;
NoOfCompiledParents += 1;
}
}
start = NoOfCompiledParents;
for (count = 0;Section->ParentSection[count] != NULL;count++) {
Parent = Section->ParentSection[count];
if (Parent->CompiledLocation != NULL) { continue; }
if (Parent->JumpSection != Parent->ContinueSection) {
SectionParents[start].Parent = Parent;
SectionParents[start].JumpInfo =
Section == Parent->ContinueSection?&Parent->Cont:&Parent->Jump;
start += 1;
} else {
SectionParents[start].Parent = Parent;
SectionParents[start].JumpInfo = &Parent->Cont;
start += 1;
SectionParents[start].Parent = Parent;
SectionParents[start].JumpInfo = &Parent->Jump;
start += 1;
}
}
FirstParent = 0;
for (count = 1;count < NoOfCompiledParents;count++) {
if (SectionParents[count].JumpInfo->FallThrough) {
FirstParent = count; break;
}
}
//Link First Parent to start
Parent = SectionParents[FirstParent].Parent;
JumpInfo = SectionParents[FirstParent].JumpInfo;
memcpy(&Section->RegWorking,&JumpInfo->RegSet,sizeof(REG_INFO));
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 (BlockRandomModifier != 0) { SubConstFromVariable(BlockRandomModifier,&CP0[1],Cop0_Name[1]); }
if (BlockCycleCount != 0) {
AddConstToVariable(BlockCycleCount,&CP0[9],Cop0_Name[9]);
SubConstFromVariable(BlockCycleCount,&Timers.Timer,"Timer");
}
JumpInfo->FallThrough = FALSE;
//Fix up initial state
UnMap_AllFPRs(Section);
for (count = 0;count < NoOfParents;count++) {
int count2, count3, MemoryStackPos;
REG_INFO * RegSet;
if (count == FirstParent) { continue; }
Parent = SectionParents[count].Parent;
RegSet = &SectionParents[count].JumpInfo->RegSet;
if (CurrentRoundingModel != RegSet->RoundingModel) { CurrentRoundingModel = RoundUnknown; }
if (NoOfParents != NoOfCompiledParents) { CurrentRoundingModel = RoundUnknown; }
//Find Parent MapRegState
MemoryStackPos = -1;
for (count2 = 1; count2 < 10; count2++) {
if (RegSet->x86reg_MappedTo[count2] == Stack_Mapped) {
MemoryStackPos = count2;
break;
}
}
if (MemoryStackPos < 0) {
if (Map_MemoryStack(Section,FALSE) > 0) {
UnMap_X86reg(Section,Map_MemoryStack(Section,FALSE));
}
}
for (count2 = 1; count2 < 32; count2++) {
if (Is32BitMapped(count2)) {
switch (RegSet->MIPS_RegState[count2]) {
case STATE_MAPPED_64: Map_GPR_64bit(Section,count2,count2); break;
case STATE_MAPPED_32_ZERO: break;
case STATE_MAPPED_32_SIGN:
if (IsUnsigned(count2)) {
MipsRegState(count2) = STATE_MAPPED_32_SIGN;
}
break;
case STATE_CONST_64: Map_GPR_64bit(Section,count2,count2); break;
case STATE_CONST_32:
if ((RegSet->MIPS_RegVal[count2].W[0] < 0) && IsUnsigned(count2)) {
MipsRegState(count2) = STATE_MAPPED_32_SIGN;
}
break;
case STATE_UNKNOWN:
//Map_GPR_32bit(Section,count2,TRUE,count2);
Map_GPR_64bit(Section,count2,count2); //??
//UnMap_GPR(Section,count2,TRUE); ??
break;
default:
if (ShowDebugMessages)
DisplayError("Unknown CPU State(%d) in InheritParentInfo",RegSet->MIPS_RegState[count2]);
}
}
if (IsConst(count2)) {
if (MipsRegState(count2) != RegSet->MIPS_RegState[count2]) {
if (Is32Bit(count2)) {
Map_GPR_32bit(Section,count2,TRUE,count2);
} else {
Map_GPR_32bit(Section,count2,TRUE,count2);
}
} else if (Is32Bit(count2) && MipsRegLo(count2) != RegSet->MIPS_RegVal[count2].UW[0]) {
Map_GPR_32bit(Section,count2,TRUE,count2);
} else if (Is64Bit(count2) && MipsReg(count2) != RegSet->MIPS_RegVal[count2].UDW) {
Map_GPR_32bit(Section,count2,TRUE,count2);
}
}
for (count3 = 1; count3 < 10; count3 ++) { x86Protected(count3) = FALSE; }
}
}
memcpy(&Section->RegStart,&Section->RegWorking,sizeof(REG_INFO));
//Sync registers for different blocks
sprintf(Label,"Section_%d",Section->SectionID);
CurrentParent = FirstParent;
NeedSync = FALSE;
for (count = 0;count < NoOfCompiledParents;count++) {
REG_INFO * RegSet;
int count2;
if (count == FirstParent) { continue; }
Parent = SectionParents[count].Parent;
JumpInfo = SectionParents[count].JumpInfo;
RegSet = &SectionParents[count].JumpInfo->RegSet;
if (JumpInfo->RegSet.CycleCount != 0) { NeedSync = TRUE; }
if (JumpInfo->RegSet.RandomModifier != 0) { NeedSync = TRUE; }
for (count2 = 0; count2 < 8; count2++) {
if (FpuMappedTo(count2) == (DWORD)-1) {
NeedSync = TRUE;
}
}
for (count2 = 1; count2 < 10; count2++) {
if (x86Mapped(count2) == Stack_Mapped) {
if (x86Mapped(count2) != RegSet->x86reg_MappedTo[count2]) {
NeedSync = TRUE;
}
break;
}
}
for (count2 = 0; count2 < 32; count2++) {
if (NeedSync == TRUE) { break; }
if (MipsRegState(count2) != RegSet->MIPS_RegState[count2]) {
NeedSync = TRUE;
continue;
}
switch (MipsRegState(count2)) {
case STATE_UNKNOWN: break;
case STATE_MAPPED_64:
if (MipsReg(count2) != RegSet->MIPS_RegVal[count2].UDW) {
NeedSync = TRUE;
}
break;
case STATE_MAPPED_32_ZERO:
case STATE_MAPPED_32_SIGN:
if (MipsRegLo(count2) != RegSet->MIPS_RegVal[count2].UW[0]) {
//DisplayError("Parent: %d",Parent->SectionID);
NeedSync = TRUE;
}
break;
case STATE_CONST_32:
if (MipsRegLo(count2) != RegSet->MIPS_RegVal[count2].UW[0]) {
if (ShowDebugMessages)
DisplayError("Umm.. how ???");
NeedSync = TRUE;
}
break;
default:
if (ShowDebugMessages)
DisplayError("Unhandled Reg state %d\nin InheritParentInfo",MipsRegState(count2));
}
}
if (NeedSync == FALSE) { continue; }
Parent = SectionParents[CurrentParent].Parent;
JumpInfo = SectionParents[CurrentParent].JumpInfo;
JmpLabel32(Label,0);
JumpInfo->LinkLocation = RecompPos - 4;
JumpInfo->LinkLocation2 = NULL;
CurrentParent = count;
Parent = SectionParents[CurrentParent].Parent;
JumpInfo = SectionParents[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;
}
}
memcpy(&Section->RegWorking,&JumpInfo->RegSet,sizeof(REG_INFO));
if (BlockRandomModifier != 0) { SubConstFromVariable(BlockRandomModifier,&CP0[1],Cop0_Name[1]); }
if (BlockCycleCount != 0) {
AddConstToVariable(BlockCycleCount,&CP0[9],Cop0_Name[9]);
SubConstFromVariable(BlockCycleCount,&Timers.Timer,"Timer");
}
SyncRegState(Section,&Section->RegStart); //Sync
memcpy(&Section->RegStart,&Section->RegWorking,sizeof(REG_INFO));
}
for (count = 0;count < NoOfCompiledParents;count++) {
Parent = SectionParents[count].Parent;
JumpInfo = SectionParents[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);
BlockCycleCount = 0;
BlockRandomModifier = 0;
free(SectionParents);
return TRUE;
}
BOOL IsAllParentLoops(BLOCK_SECTION * Section, BLOCK_SECTION * Parent, BOOL IgnoreIfCompiled, DWORD Test) {
int count;
if (IgnoreIfCompiled && Parent->CompiledLocation != NULL) { return TRUE; }
if (!Section->InLoop) { return FALSE; }
if (!Parent->InLoop) { return FALSE; }
if (Parent->ParentSection == NULL) { return FALSE; }
if (Section == Parent) { return TRUE; }
if (Parent->Test == Test) { return TRUE; }
Parent->Test = Test;
for (count = 0;Parent->ParentSection[count] != NULL;count++) {
if (!IsAllParentLoops(Section,Parent->ParentSection[count],IgnoreIfCompiled,Test)) { return FALSE; }
}
return TRUE;
}
void _fastcall InitilzeSection (BLOCK_SECTION * Section, BLOCK_SECTION * Parent, DWORD StartAddr, DWORD ID) {
Section->ParentSection = NULL;
Section->JumpSection = NULL;
Section->ContinueSection = NULL;
Section->CompiledLocation = NULL;
Section->SectionID = ID;
Section->Test = 0;
Section->Test2 = 0;
Section->InLoop = FALSE;
Section->StartPC = StartAddr;
Section->CompilePC = Section->StartPC;
Section->Jump.BranchLabel = NULL;
Section->Jump.LinkLocation = NULL;
Section->Jump.LinkLocation2 = NULL;
Section->Jump.FallThrough = FALSE;
Section->Jump.PermLoop = FALSE;
Section->Jump.TargetPC = (DWORD)-1;
Section->Cont.BranchLabel = NULL;
Section->Cont.LinkLocation = NULL;
Section->Cont.LinkLocation2 = NULL;
Section->Cont.FallThrough = FALSE;
Section->Cont.PermLoop = FALSE;
Section->Cont.TargetPC = (DWORD)-1;
AddParent(Section,Parent);
}
void MarkCodeBlock (DWORD PAddr) {
if (PAddr < RdramSize) {
N64_Blocks.NoOfRDRamBlocks[PAddr >> 12] += 1;
} else if (PAddr >= 0x04000000 && PAddr <= 0x04000FFC) {
N64_Blocks.NoOfDMEMBlocks += 1;
} else if (PAddr >= 0x04001000 && PAddr <= 0x04001FFC) {
N64_Blocks.NoOfIMEMBlocks += 1;
} else if (PAddr >= 0x1FC00000 && PAddr <= 0x1FC00800) {
N64_Blocks.NoOfPifRomBlocks += 1;
} else {
#ifndef ROM_IN_MAPSPACE
if (ShowDebugMessages)
DisplayError("Ummm... Which code block should be marked on\nPC = 0x%08X\nRdramSize: %X",PAddr,RdramSize);
ExitThread(0);
#endif
}
}
void __cdecl StartRecompilerCPU (void ) {
DWORD Addr;
BYTE * Block;
CoInitialize(NULL);
#ifdef Log_x86Code
Start_x86_Log();
#endif
if (SelfModCheck == ModCode_CheckMemoryCache || SelfModCheck == ModCode_CheckMemory2) {// *** Add in Build 53
if (TargetInfo == NULL) {
TargetInfo = VirtualAlloc(NULL,MaxCodeBlocks * sizeof(TARGET_INFO),MEM_COMMIT|MEM_RESERVE,PAGE_READWRITE);
if (TargetInfo == NULL) {
DisplayError(GS(MSG_MEM_ALLOC_ERROR));
ExitThread(0);
}
}
TargetIndex = 0;
}
if (SelfModCheck == ModCode_ChangeMemory) {
if (OrigMem == NULL) {
OrigMem = VirtualAlloc(NULL,MaxOrigMem * sizeof(ORIGINAL_MEMMARKER),MEM_COMMIT|MEM_RESERVE,PAGE_READWRITE);
if (OrigMem == NULL) {
DisplayError(GS(MSG_MEM_ALLOC_ERROR));
ExitThread(0);
}
}
TargetIndex = 0;
} else {
if (OrigMem != NULL) {
VirtualFree(OrigMem,0,MEM_RELEASE);
OrigMem = NULL;
}
}
if (GfxRomOpen != NULL) { GfxRomOpen(); }
if (ContRomOpen != NULL) { ContRomOpen(); }
ResetRecompCode();
memset(&N64_Blocks,0,sizeof(N64_Blocks));
NextInstruction = NORMAL;
__try {
if (SelfModCheck == ModCode_ChangeMemory) {
DWORD Value;
for (;;) {
Addr = PROGRAM_COUNTER;
if (UseTlb) {
if (!TranslateVaddr(&Addr)) {
DoTLBMiss(NextInstruction == DELAY_SLOT,PROGRAM_COUNTER);
NextInstruction = NORMAL;
Addr = PROGRAM_COUNTER;
if (!TranslateVaddr(&Addr)) {
DisplayError("Failed to tranlate PC to a PAddr: %X\n\nEmulation stopped",PROGRAM_COUNTER);
ExitThread(0);
}
}
} else {
Addr &= 0x1FFFFFFF;
}
if (NextInstruction == DELAY_SLOT) {
__try {
Value = (DWORD)(*(DelaySlotTable + (Addr >> 12)));
} __except(EXCEPTION_EXECUTE_HANDLER) {
DisplayError("Executing Delay Slot from non maped space\nPROGRAM_COUNTER = 0x%X\nEmulation stopped",PROGRAM_COUNTER);
ExitThread(0);
}
if ( (Value >> 16) == 0x7C7C) {
DWORD Index = (Value & 0xFFFF);
Block = 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 = 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 (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 && IndividualBlock) {
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(;;)
} // end if (SelfModCheck == ModCode_ChangeMemory) {
for (;;) {
Addr = PROGRAM_COUNTER;
if (UseTlb) {
if (!TranslateVaddr(&Addr)) {
DoTLBMiss(NextInstruction == DELAY_SLOT,PROGRAM_COUNTER);
NextInstruction = NORMAL;
Addr = PROGRAM_COUNTER;
if (!TranslateVaddr(&Addr)) {
DisplayError("Failed to tranlate PC to a PAddr: %X\n\nEmulation stopped",PROGRAM_COUNTER);
ExitThread(0);
}
}
} else {
Addr &= 0x1FFFFFFF;
}
if (NextInstruction == DELAY_SLOT) {
__try {
Block = *(DelaySlotTable + (Addr >> 12));
} __except(EXCEPTION_EXECUTE_HANDLER) {
DisplayError(GS(MSG_NONMAPPED_SPACE));
ExitThread(0);
}
if (Block == NULL) {
DWORD OldProtect;
Block = CompileDelaySlot();
*(DelaySlotTable + (Addr >> 12)) = Block;
if (SelfModCheck == ModCode_ProtectedMemory) {
VirtualProtect(N64MEM + Addr, 4, PAGE_READONLY, &OldProtect);
}
NextInstruction = NORMAL;
}
_asm {
pushad
call Block
popad
}
continue;
}
__try {
if (Addr > 0x10000000)
{
if (PROGRAM_COUNTER >= 0xB0000000 && PROGRAM_COUNTER < (RomFileSize | 0xB0000000)) {
while (PROGRAM_COUNTER >= 0xB0000000 && PROGRAM_COUNTER < (RomFileSize | 0xB0000000)) {
ExecuteInterpreterOpCode();
}
continue;
} else {
DisplayError(GS(MSG_NONMAPPED_SPACE));
ExitThread(0);
}
}
Block = *(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 {
DisplayError(GS(MSG_NONMAPPED_SPACE));
ExitThread(0);
}
}
if (SelfModCheck == ModCode_CheckMemoryCache && Block != NULL) {
TARGET_INFO * Target = (TARGET_INFO *)Block;
if (*(QWORD *)(N64MEM+Addr) != Target->OriginalMemory) {
Block = NULL;
} else {
Block = Target->CodeBlock;
}
}
if (SelfModCheck == ModCode_CheckMemory2 && Block != NULL) {
TARGET_INFO * Target = (TARGET_INFO *)Block;
if (*(QWORD *)(N64MEM+Addr) != Target->OriginalMemory) {
DWORD Start = (Addr & ~0xFFF) - 0x10000;
DWORD End = Start + 0x20000;
DWORD count;
if (End < RdramSize) { End = RdramSize; }
for (count = (Start >> 12); count < (End >> 12); count ++ ) {
if (N64_Blocks.NoOfRDRamBlocks[count] > 0) {
N64_Blocks.NoOfRDRamBlocks[count] = 0;
memset(JumpTable + (count << 10),0,0x1000);
*(DelaySlotTable + count) = NULL;
}
}
//ResetRecompCode();
Block = NULL;
} else {
Block = Target->CodeBlock;
}
}
if (Block == NULL) {
DWORD OldProtect;
char Label[100];
if (Profiling) { strncpy(Label, ProfilingLabel, sizeof(Label)); }
if (Profiling) { StartTimer("Compiling Block"); }
__try {
Block = Compiler4300iBlock();
} __except(EXCEPTION_EXECUTE_HANDLER) {
//DisplayError("Reset Recompiler Code %X",RecompPos - RecompCode);
ResetRecompCode();
Block = Compiler4300iBlock();
}
if (Profiling) { StartTimer(Label); }
if (SelfModCheck == ModCode_CheckMemoryCache || SelfModCheck == ModCode_CheckMemory2) {
TargetInfo[TargetIndex].CodeBlock = Block;
TargetInfo[TargetIndex].OriginalMemory = *(QWORD *)(N64MEM+Addr);
*(JumpTable + (Addr >> 2)) = &TargetInfo[TargetIndex];
TargetIndex += 1;
if (TargetIndex == MaxCodeBlocks) {
ResetRecompCode();
continue;
}
} else {
*(JumpTable + (Addr >> 2)) = Block;
}
if (SelfModCheck == ModCode_ProtectedMemory) {
VirtualProtect(N64MEM + Addr, 4, PAGE_READONLY, &OldProtect);
}
NextInstruction = NORMAL;
}
if (Profiling && IndividualBlock) {
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
}
}
} __except( r4300i_CPU_MemoryFilter( GetExceptionCode(), GetExceptionInformation()) ) {
DisplayError(GS(MSG_UNKNOWN_MEM_ACTION));
ExitThread(0);
}
}
void SyncRegState (BLOCK_SECTION * Section, REG_INFO * SyncTo) {
int count, x86Reg,x86RegHi, changed;
changed = FALSE;
UnMap_AllFPRs(Section);
if (CurrentRoundingModel != SyncTo->RoundingModel) { CurrentRoundingModel = RoundUnknown; }
x86Reg = Map_MemoryStack(Section, FALSE);
//CPU_Message("MemoryStack for Original State = %s",x86Reg > 0?x86_Name(x86Reg):"Not Mapped");
for (x86Reg = 1; x86Reg < 10; x86Reg ++) {
if (x86Mapped(x86Reg) != Stack_Mapped) { continue; }
if (SyncTo->x86reg_MappedTo[x86Reg] != Stack_Mapped) {
UnMap_X86reg(Section,x86Reg);
for (count = 1; count < 10; count ++) {
if (SyncTo->x86reg_MappedTo[count] == Stack_Mapped) {
MoveX86RegToX86Reg(count,x86Reg);
changed = TRUE;
}
}
if (!changed) {
MoveVariableToX86reg(&MemoryStack,"MemoryStack",x86Reg);
}
changed = TRUE;
}
}
for (x86Reg = 1; x86Reg < 10; x86Reg ++) {
if (SyncTo->x86reg_MappedTo[x86Reg] != Stack_Mapped) { continue; }
//CPU_Message("MemoryStack for Sync State = %s",x86Reg > 0?x86_Name(x86Reg):"Not Mapped");
if (x86Mapped(x86Reg) == Stack_Mapped) { break; }
UnMap_X86reg(Section,x86Reg);
}
for (count = 1; count < 32; count ++) {
if (MipsRegState(count) == SyncTo->MIPS_RegState[count]) {
switch (MipsRegState(count)) {
case STATE_UNKNOWN: continue;
case STATE_MAPPED_64:
if (MipsReg(count) == SyncTo->MIPS_RegVal[count].UDW) {
continue;
}
break;
case STATE_MAPPED_32_ZERO:
case STATE_MAPPED_32_SIGN:
if (MipsRegLo(count) == SyncTo->MIPS_RegVal[count].UW[0]) {
continue;
}
break;
case STATE_CONST_64:
if (MipsReg(count) != SyncTo->MIPS_RegVal[count].UDW) {
if (ShowDebugMessages)
DisplayError("Umm.. how ???");
}
continue;
case STATE_CONST_32:
if (MipsRegLo(count) != SyncTo->MIPS_RegVal[count].UW[0]) {
if (ShowDebugMessages)
DisplayError("Umm.. how ???");
}
continue;
default:
if (ShowDebugMessages)
DisplayError("Unhandled Reg state %d\nin SyncRegState",MipsRegState(count));
}
}
changed = TRUE;
switch (SyncTo->MIPS_RegState[count]) {
case STATE_UNKNOWN: UnMap_GPR(Section, count, TRUE); break;
case STATE_MAPPED_64:
x86Reg = SyncTo->MIPS_RegVal[count].UW[0];
x86RegHi = SyncTo->MIPS_RegVal[count].UW[1];
UnMap_X86reg(Section, x86Reg);
UnMap_X86reg(Section, x86RegHi);
switch (MipsRegState(count)) {
case STATE_UNKNOWN:
MoveVariableToX86reg(&GPR[count].UW[0], GPR_NameLo[count], x86Reg);
MoveVariableToX86reg(&GPR[count].UW[1], GPR_NameHi[count], x86RegHi);
break;
case STATE_MAPPED_64:
MoveX86RegToX86Reg(MipsRegLo(count), x86Reg);
x86Mapped(MipsRegLo(count)) = NotMapped;
MoveX86RegToX86Reg(MipsRegHi(count), x86RegHi);
x86Mapped(MipsRegHi(count)) = NotMapped;
break;
case STATE_MAPPED_32_SIGN:
MoveX86RegToX86Reg(MipsRegLo(count), x86RegHi);
ShiftRightSignImmed(x86RegHi, 31);
MoveX86RegToX86Reg(MipsRegLo(count), x86Reg);
x86Mapped(MipsRegLo(count)) = NotMapped;
break;
case STATE_MAPPED_32_ZERO:
XorX86RegToX86Reg(x86RegHi, x86RegHi);
MoveX86RegToX86Reg(MipsRegLo(count), x86Reg);
x86Mapped(MipsRegLo(count)) = NotMapped;
break;
case STATE_CONST_64:
MoveConstToX86reg(MipsRegHi(count), x86RegHi);
MoveConstToX86reg(MipsRegLo(count), x86Reg);
break;
case STATE_CONST_32:
MoveConstToX86reg(MipsRegLo_S(count) >> 31, x86RegHi);
MoveConstToX86reg(MipsRegLo(count), x86Reg);
break;
default:
if (ShowDebugMessages) {
CPU_Message("Do something with states in SyncRegState\nSTATE_MAPPED_64\n%d", MipsRegState(count));
DisplayError("Do something with states in SyncRegState\nSTATE_MAPPED_64\n%d", MipsRegState(count));
}
continue;
}
MipsRegLo(count) = x86Reg;
MipsRegHi(count) = x86RegHi;
MipsRegState(count) = STATE_MAPPED_64;
x86Mapped(x86Reg) = GPR_Mapped;
x86Mapped(x86RegHi) = GPR_Mapped;
x86MapOrder(x86Reg) = 1;
x86MapOrder(x86RegHi) = 1;
break;
case STATE_MAPPED_32_SIGN:
x86Reg = SyncTo->MIPS_RegVal[count].UW[0];
UnMap_X86reg(Section, x86Reg);
switch (MipsRegState(count)) {
case STATE_UNKNOWN: MoveVariableToX86reg(&GPR[count].UW[0], GPR_NameLo[count], x86Reg); break;
case STATE_CONST_32: MoveConstToX86reg(MipsRegLo(count), x86Reg); break;
case STATE_MAPPED_32_SIGN:
MoveX86RegToX86Reg(MipsRegLo(count), x86Reg);
x86Mapped(MipsRegLo(count)) = NotMapped;
break;
case STATE_MAPPED_32_ZERO:
if (MipsRegLo(count) != (DWORD)x86Reg) {
MoveX86RegToX86Reg(MipsRegLo(count), x86Reg);
x86Mapped(MipsRegLo(count)) = NotMapped;
}
break;
case STATE_MAPPED_64:
MoveX86RegToX86Reg(MipsRegLo(count), x86Reg);
x86Mapped(MipsRegLo(count)) = NotMapped;
x86Mapped(MipsRegHi(count)) = NotMapped;
break;
case STATE_CONST_64:
if (ShowDebugMessages)
DisplayError("hi %X\nLo %X", MipsRegHi(count), MipsRegLo(count));
default:
if (ShowDebugMessages) {
CPU_Message("Do something with states in SyncRegState\nSTATE_MAPPED_32_SIGN\n%d", MipsRegState(count));
DisplayError("Do something with states in SyncRegState\nSTATE_MAPPED_32_SIGN\n%d", MipsRegState(count));
}
}
MipsRegLo(count) = x86Reg;
MipsRegState(count) = STATE_MAPPED_32_SIGN;
x86Mapped(x86Reg) = GPR_Mapped;
x86MapOrder(x86Reg) = 1;
break;
case STATE_MAPPED_32_ZERO:
x86Reg = SyncTo->MIPS_RegVal[count].UW[0];
UnMap_X86reg(Section, x86Reg);
switch (MipsRegState(count)) {
case STATE_MAPPED_64:
case STATE_UNKNOWN:
MoveVariableToX86reg(&GPR[count].UW[0], GPR_NameLo[count], x86Reg);
break;
case STATE_MAPPED_32_ZERO:
MoveX86RegToX86Reg(MipsRegLo(count), x86Reg);
x86Mapped(MipsRegLo(count)) = NotMapped;
break;
case STATE_CONST_32:
if (MipsRegLo_S(count) < 0) {
CPU_Message("Sign Problems in SyncRegState\nSTATE_MAPPED_32_ZERO");
CPU_Message("%s: %X", GPR_Name[count], MipsRegLo_S(count));
if (ShowDebugMessages)
DisplayError("Sign Problems in SyncRegState\nSTATE_MAPPED_32_ZERO");
}
MoveConstToX86reg(MipsRegLo(count), x86Reg);
break;
default:
if (ShowDebugMessages) {
CPU_Message("Do something with states in SyncRegState\nSTATE_MAPPED_32_ZERO\n%d", MipsRegState(count));
DisplayError("Do something with states in SyncRegState\nSTATE_MAPPED_32_ZERO\n%d", MipsRegState(count));
}
}
MipsRegLo(count) = x86Reg;
MipsRegState(count) = SyncTo->MIPS_RegState[count];
x86Mapped(x86Reg) = GPR_Mapped;
x86MapOrder(x86Reg) = 1;
break;
default:
if (ShowDebugMessages) {
CPU_Message("%d\n%d\nreg: %s (%d)", SyncTo->MIPS_RegState[count], MipsRegState(count), GPR_Name[count], count);
DisplayError("%d\n%d\nreg: %s (%d)", SyncTo->MIPS_RegState[count], MipsRegState(count), GPR_Name[count], count);
DisplayError("Do something with states in SyncRegState");
}
changed = FALSE;
}
}
}