project64/Source/Project64/N64 System/C Core/Recompiler CPU.cpp

385 lines
13 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 "c core.h"
#include "main.h"
#include "C Global Variable.h"
#include "cpu.h"
#include "x86.h"
#include "debugger.h"
#include "plugin.h"
#include "Recompiler CPU.h"
N64_BLOCKS N64_Blocks;
DWORD TLBLoadAddress, TLBStoreAddress;
void FixRandomReg (void) {
while ((int)_CP0[1] < (int)_CP0[6]) {
_CP0[1] += 32 - _CP0[6];
}
}
#ifdef tofix
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 = (void **)malloc((NoOfParents + 1)*sizeof(void *));
} else {
Section->ParentSection = (void **)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 {
#ifndef EXTERNAL_RELEASE
DisplayError("How are these sections joined?????");
#endif
}
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 _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((BLOCK_SECTION *)Section->ContinueSection,Test,Test2,TestID);
DetermineLoop((BLOCK_SECTION *)Section->JumpSection,Test,Test2,TestID);
return;
}
if (Section->Test2 == Test2) {
Section->InLoop = TRUE;
return;
}
Section->Test2 = Test2;
DetermineLoop((BLOCK_SECTION *)Section->ContinueSection,Test,Test2,TestID);
DetermineLoop((BLOCK_SECTION *)Section->JumpSection,Test,Test2,TestID);
if (Section->Test == Test) { return; }
Section->Test = Test;
if (Section->ContinueSection != NULL) {
DetermineLoop((BLOCK_SECTION *)Section->ContinueSection,Test,GetNewTestValue(),((BLOCK_SECTION *)Section->ContinueSection)->SectionID);
}
if (Section->JumpSection != NULL) {
DetermineLoop((BLOCK_SECTION *)Section->JumpSection,Test,GetNewTestValue(),((BLOCK_SECTION *)Section->JumpSection)->SectionID);
}
}
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 = (BLOCK_SECTION *)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((BLOCK_SECTION *)Section->JumpSection,Test,Changed); }
if (Section->ContinueSection) { FixConstants((BLOCK_SECTION *)Section->ContinueSection,Test,Changed); }
}
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 = (void **)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,(BLOCK_SECTION *)Section->ParentSection[count],FALSE,GetNewTestValue())) { return; }
}
for (count = 0; count < NoOfParents; count++) {
Parent = (BLOCK_SECTION *)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((BLOCK_SECTION *)Section->JumpSection,Section);
FreeSection((BLOCK_SECTION *)Section->ContinueSection,Section);
//CPU_Message("Free Section (Section: %d)",Section->SectionID);
free(Section);
}
}
void GenerateBasicSectionLinkage (BLOCK_SECTION * Section) {
BreakPoint(__FILE__,__LINE__);
}
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 = (BLOCK_SECTION *)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 = (BLOCK_SECTION *)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));
}
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
#ifndef EXTERNAL_RELEASE
DisplayError("Ummm... Which code block should be marked on\nPC = 0x%08X\nRdramSize: %X",PAddr,RdramSize);
#endif
ExitThread(0);
#endif
}
}
#endif