project64/Source/Project64/N64 System/C Core/Registers.cpp

1429 lines
49 KiB
C++
Raw Normal View History

/*
* 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 <stdio.h>
#include "c core.h"
#include "main.h"
#include "cpu.h"
#include "x86.h"
#include "debugger.h"
char *GPR_Name[32] = {"r0","at","v0","v1","a0","a1","a2","a3",
"t0","t1","t2","t3","t4","t5","t6","t7",
"s0","s1","s2","s3","s4","s5","s6","s7",
"t8","t9","k0","k1","gp","sp","s8","ra"};
char *GPR_NameHi[32] = {"r0.HI","at.HI","v0.HI","v1.HI","a0.HI","a1.HI",
"a2.HI","a3.HI","t0.HI","t1.HI","t2.HI","t3.HI",
"t4.HI","t5.HI","t6.HI","t7.HI","s0.HI","s1.HI",
"s2.HI","s3.HI","s4.HI","s5.HI","s6.HI","s7.HI",
"t8.HI","t9.HI","k0.HI","k1.HI","gp.HI","sp.HI",
"s8.HI","ra.HI"};
char *GPR_NameLo[32] = {"r0.LO","at.LO","v0.LO","v1.LO","a0.LO","a1.LO",
"a2.LO","a3.LO","t0.LO","t1.LO","t2.LO","t3.LO",
"t4.LO","t5.LO","t6.LO","t7.LO","s0.LO","s1.LO",
"s2.LO","s3.LO","s4.LO","s5.LO","s6.LO","s7.LO",
"t8.LO","t9.LO","k0.LO","k1.LO","gp.LO","sp.LO",
"s8.LO","ra.LO"};
char *FPR_Name[32] = {"f0","f1","f2","f3","f4","f5","f6","f7",
"f8","f9","f10","f11","f12","f13","f14","f15",
"f16","f17","f18","f19","f20","f21","f22","f23",
"f24","f25","f26","f27","f28","f29","f30","f31"};
char *FPR_NameHi[32] = {"f0.hi","f1.hi","f2.hi","f3.hi","f4.hi","f5.hi","f6.hi","f7.hi",
"f8.hi","f9.hi","f10.hi","f11.hi","f12.hi","f13.hi","f14.hi","f15.hi",
"f16.hi","f17.hi","f18.hi","f19.hi","f20.hi","f21.hi","f22.hi","f23.hi",
"f24.hi","f25.hi","f26.hi","f27.hi","f28.hi","f29.hi","f30.hi","f31.hi"};
char *FPR_NameLo[32] = {"f0.lo","f1.lo","f2.lo","f3.lo","f4.lo","f5.lo","f6.lo","f7.lo",
"f8.lo","f9.lo","f10.lo","f11.lo","f12.lo","f13.lo","f14.lo","f15.lo",
"f16.lo","f17.lo","f18.lo","f19.lo","f20.lo","f21.lo","f22.lo","f23.lo",
"f24.lo","f25.lo","f26.lo","f27.lo","f28.lo","f29.lo","f30.lo","f31.lo"};
char *FPR_Ctrl_Name[32] = {"Revision","Unknown","Unknown","Unknown","Unknown",
"Unknown","Unknown","Unknown","Unknown","Unknown","Unknown",
"Unknown","Unknown","Unknown","Unknown","Unknown","Unknown",
"Unknown","Unknown","Unknown","Unknown","Unknown","Unknown",
"Unknown","Unknown","Unknown","Unknown","Unknown","Unknown",
"Unknown","Unknown","FCSR"};
DWORD RegModValue;
//DWORD RegModValue, ViFieldNumber, LLBit, LLAddr;
//N64_REGISTERS Registers;
int fpuControl;
int UnMap_8BitTempReg (CBlockSection * Section);
int UnMap_TempReg (CBlockSection * Section);
BOOL UnMap_X86reg (CBlockSection * Section, DWORD x86Reg);
char *Format_Name[] = {"Unkown","dword","qword","float","double"};
void ChangeFPURegFormat (CBlockSection * Section, int Reg, CRegInfo::FPU_STATE OldFormat, CRegInfo::FPU_STATE NewFormat, CRegInfo::FPU_ROUND RoundingModel) {
DWORD i;
for (i = 0; i < 8; i++) {
if (Section->FpuMappedTo(i) == (DWORD)Reg) {
if (Section->FpuState(i) != OldFormat) {
UnMap_FPR(Section,Reg,TRUE);
Load_FPR_ToTop(Section,Reg,Reg,OldFormat);
ChangeFPURegFormat(Section,Reg,OldFormat,NewFormat,RoundingModel);
return;
}
CPU_Message(" regcache: Changed format of ST(%d) from %s to %s",
(i - Section->StackTopPos() + 8) & 7,Format_Name[OldFormat],Format_Name[NewFormat]);
Section->FpuRoundingModel(i) = RoundingModel;
Section->FpuState(i) = NewFormat;
return;
}
}
#ifndef EXTERNAL_RELEASE
DisplayError("ChangeFormat: Register not on stack!!");
#endif
}
void ChangeMiIntrMask (void) {
if ( ( RegModValue & MI_INTR_MASK_CLR_SP ) != 0 ) { MI_INTR_MASK_REG &= ~MI_INTR_MASK_SP; }
if ( ( RegModValue & MI_INTR_MASK_SET_SP ) != 0 ) { MI_INTR_MASK_REG |= MI_INTR_MASK_SP; }
if ( ( RegModValue & MI_INTR_MASK_CLR_SI ) != 0 ) { MI_INTR_MASK_REG &= ~MI_INTR_MASK_SI; }
if ( ( RegModValue & MI_INTR_MASK_SET_SI ) != 0 ) { MI_INTR_MASK_REG |= MI_INTR_MASK_SI; }
if ( ( RegModValue & MI_INTR_MASK_CLR_AI ) != 0 ) { MI_INTR_MASK_REG &= ~MI_INTR_MASK_AI; }
if ( ( RegModValue & MI_INTR_MASK_SET_AI ) != 0 ) { MI_INTR_MASK_REG |= MI_INTR_MASK_AI; }
if ( ( RegModValue & MI_INTR_MASK_CLR_VI ) != 0 ) { MI_INTR_MASK_REG &= ~MI_INTR_MASK_VI; }
if ( ( RegModValue & MI_INTR_MASK_SET_VI ) != 0 ) { MI_INTR_MASK_REG |= MI_INTR_MASK_VI; }
if ( ( RegModValue & MI_INTR_MASK_CLR_PI ) != 0 ) { MI_INTR_MASK_REG &= ~MI_INTR_MASK_PI; }
if ( ( RegModValue & MI_INTR_MASK_SET_PI ) != 0 ) { MI_INTR_MASK_REG |= MI_INTR_MASK_PI; }
if ( ( RegModValue & MI_INTR_MASK_CLR_DP ) != 0 ) { MI_INTR_MASK_REG &= ~MI_INTR_MASK_DP; }
if ( ( RegModValue & MI_INTR_MASK_SET_DP ) != 0 ) { MI_INTR_MASK_REG |= MI_INTR_MASK_DP; }
}
void ChangeMiModeReg (void) {
MI_MODE_REG &= ~0x7F;
MI_MODE_REG |= (RegModValue & 0x7F);
if ( ( RegModValue & MI_CLR_INIT ) != 0 ) { MI_MODE_REG &= ~MI_MODE_INIT; }
if ( ( RegModValue & MI_SET_INIT ) != 0 ) { MI_MODE_REG |= MI_MODE_INIT; }
if ( ( RegModValue & MI_CLR_EBUS ) != 0 ) { MI_MODE_REG &= ~MI_MODE_EBUS; }
if ( ( RegModValue & MI_SET_EBUS ) != 0 ) { MI_MODE_REG |= MI_MODE_EBUS; }
if ( ( RegModValue & MI_CLR_DP_INTR ) != 0 ) { MI_INTR_REG &= ~MI_INTR_DP; }
if ( ( RegModValue & MI_CLR_RDRAM ) != 0 ) { MI_MODE_REG &= ~MI_MODE_RDRAM; }
if ( ( RegModValue & MI_SET_RDRAM ) != 0 ) { MI_MODE_REG |= MI_MODE_RDRAM; }
}
void ChangeSpStatus (void) {
if ( ( RegModValue & SP_CLR_HALT ) != 0) { SP_STATUS_REG &= ~SP_STATUS_HALT; }
if ( ( RegModValue & SP_SET_HALT ) != 0) { SP_STATUS_REG |= SP_STATUS_HALT; }
if ( ( RegModValue & SP_CLR_BROKE ) != 0) { SP_STATUS_REG &= ~SP_STATUS_BROKE; }
if ( ( RegModValue & SP_CLR_INTR ) != 0) {
MI_INTR_REG &= ~MI_INTR_SP;
CheckInterrupts();
}
#ifndef EXTERNAL_RELEASE
if ( ( RegModValue & SP_SET_INTR ) != 0) { DisplayError("SP_SET_INTR"); }
#endif
if ( ( RegModValue & SP_CLR_SSTEP ) != 0) { SP_STATUS_REG &= ~SP_STATUS_SSTEP; }
if ( ( RegModValue & SP_SET_SSTEP ) != 0) { SP_STATUS_REG |= SP_STATUS_SSTEP; }
if ( ( RegModValue & SP_CLR_INTR_BREAK ) != 0) { SP_STATUS_REG &= ~SP_STATUS_INTR_BREAK; }
if ( ( RegModValue & SP_SET_INTR_BREAK ) != 0) { SP_STATUS_REG |= SP_STATUS_INTR_BREAK; }
if ( ( RegModValue & SP_CLR_SIG0 ) != 0) { SP_STATUS_REG &= ~SP_STATUS_SIG0; }
if ( ( RegModValue & SP_SET_SIG0 ) != 0) { SP_STATUS_REG |= SP_STATUS_SIG0; }
if ( ( RegModValue & SP_CLR_SIG1 ) != 0) { SP_STATUS_REG &= ~SP_STATUS_SIG1; }
if ( ( RegModValue & SP_SET_SIG1 ) != 0) { SP_STATUS_REG |= SP_STATUS_SIG1; }
if ( ( RegModValue & SP_CLR_SIG2 ) != 0) { SP_STATUS_REG &= ~SP_STATUS_SIG2; }
if ( ( RegModValue & SP_SET_SIG2 ) != 0) { SP_STATUS_REG |= SP_STATUS_SIG2; }
if ( ( RegModValue & SP_CLR_SIG3 ) != 0) { SP_STATUS_REG &= ~SP_STATUS_SIG3; }
if ( ( RegModValue & SP_SET_SIG3 ) != 0) { SP_STATUS_REG |= SP_STATUS_SIG3; }
if ( ( RegModValue & SP_CLR_SIG4 ) != 0) { SP_STATUS_REG &= ~SP_STATUS_SIG4; }
if ( ( RegModValue & SP_SET_SIG4 ) != 0) { SP_STATUS_REG |= SP_STATUS_SIG4; }
if ( ( RegModValue & SP_CLR_SIG5 ) != 0) { SP_STATUS_REG &= ~SP_STATUS_SIG5; }
if ( ( RegModValue & SP_SET_SIG5 ) != 0) { SP_STATUS_REG |= SP_STATUS_SIG5; }
if ( ( RegModValue & SP_CLR_SIG6 ) != 0) { SP_STATUS_REG &= ~SP_STATUS_SIG6; }
if ( ( RegModValue & SP_SET_SIG6 ) != 0) { SP_STATUS_REG |= SP_STATUS_SIG6; }
if ( ( RegModValue & SP_CLR_SIG7 ) != 0) { SP_STATUS_REG &= ~SP_STATUS_SIG7; }
if ( ( RegModValue & SP_SET_SIG7 ) != 0) { SP_STATUS_REG |= SP_STATUS_SIG7; }
if ( ( RegModValue & SP_SET_SIG0 ) != 0 && AudioSignal)
{
MI_INTR_REG |= MI_INTR_SP;
CheckInterrupts();
}
//if (*( DWORD *)(DMEM + 0xFC0) == 1) {
// ChangeTimer(RspTimer,0x40000);
//} else {
RunRsp();
//}
}
int Free8BitX86Reg (CBlockSection * Section) {
int x86Reg, count, MapCount[10], MapReg[10];
if (Section->x86Mapped(x86_EBX) == CRegInfo::NotMapped && !Section->x86Protected(x86_EBX)) {return x86_EBX; }
if (Section->x86Mapped(x86_EAX) == CRegInfo::NotMapped && !Section->x86Protected(x86_EAX)) {return x86_EAX; }
if (Section->x86Mapped(x86_EDX) == CRegInfo::NotMapped && !Section->x86Protected(x86_EDX)) {return x86_EDX; }
if (Section->x86Mapped(x86_ECX) == CRegInfo::NotMapped && !Section->x86Protected(x86_ECX)) {return x86_ECX; }
x86Reg = UnMap_8BitTempReg(Section);
if (x86Reg > 0) { return x86Reg; }
for (count = 0; count < 10; count ++) {
MapCount[count] = Section->x86MapOrder(count);
MapReg[count] = count;
}
for (count = 0; count < 10; count ++) {
int i;
for (i = 0; i < 9; i ++) {
int temp;
if (MapCount[i] < MapCount[i+1]) {
temp = MapCount[i];
MapCount[i] = MapCount[i+1];
MapCount[i+1] = temp;
temp = MapReg[i];
MapReg[i] = MapReg[i+1];
MapReg[i+1] = temp;
}
}
}
for (count = 0; count < 10; count ++) {
if (MapCount[count] > 0) {
if (!Is8BitReg(count)) { continue; }
if (UnMap_X86reg(Section,count)) {
return count;
}
}
}
return -1;
}
int FreeX86Reg (CBlockSection * Section) {
int x86Reg, count, MapCount[10], MapReg[10], StackReg;
if (Section->x86Mapped(x86_EDI) == CRegInfo::NotMapped && !Section->x86Protected(x86_EDI)) {return x86_EDI; }
if (Section->x86Mapped(x86_ESI) == CRegInfo::NotMapped && !Section->x86Protected(x86_ESI)) {return x86_ESI; }
if (Section->x86Mapped(x86_EBX) == CRegInfo::NotMapped && !Section->x86Protected(x86_EBX)) {return x86_EBX; }
if (Section->x86Mapped(x86_EAX) == CRegInfo::NotMapped && !Section->x86Protected(x86_EAX)) {return x86_EAX; }
if (Section->x86Mapped(x86_EDX) == CRegInfo::NotMapped && !Section->x86Protected(x86_EDX)) {return x86_EDX; }
if (Section->x86Mapped(x86_ECX) == CRegInfo::NotMapped && !Section->x86Protected(x86_ECX)) {return x86_ECX; }
x86Reg = UnMap_TempReg(Section);
if (x86Reg > 0) { return x86Reg; }
for (count = 0; count < 10; count ++) {
MapCount[count] = Section->x86MapOrder(count);
MapReg[count] = count;
}
for (count = 0; count < 10; count ++) {
int i;
for (i = 0; i < 9; i ++) {
int temp;
if (MapCount[i] < MapCount[i+1]) {
temp = MapCount[i];
MapCount[i] = MapCount[i+1];
MapCount[i+1] = temp;
temp = MapReg[i];
MapReg[i] = MapReg[i+1];
MapReg[i+1] = temp;
}
}
}
StackReg = -1;
for (count = 0; count < 10; count ++) {
if (MapCount[count] > 0 && Section->x86Mapped(MapReg[count]) != CRegInfo::Stack_Mapped) {
if (UnMap_X86reg(Section,MapReg[count])) {
return MapReg[count];
}
}
if (Section->x86Mapped(MapReg[count]) == CRegInfo::Stack_Mapped) { StackReg = MapReg[count]; }
}
if (StackReg > 0) {
UnMap_X86reg(Section,StackReg);
return StackReg;
}
return -1;
}
#ifdef ggg
void InitalizeR4300iRegisters (int UsePif, int Country, int CIC_Chip) {
memset(CP0,0,sizeof(Registers.CP0));
memset(FPCR,0,sizeof(Registers.FPCR));
memset(RegRDRAM,0,sizeof(Registers.RDRAM));
memset(RegSP,0,sizeof(Registers.SP));
memset(RegDPC,0,sizeof(Registers.DPC));
memset(RegMI,0,sizeof(Registers.MI));
memset(RegVI,0,sizeof(Registers.VI));
memset(RegAI,0,sizeof(Registers.AI));
memset(RegPI,0,sizeof(Registers.PI));
memset(RegRI,0,sizeof(Registers.RI));
memset(RegSI,0,sizeof(Registers.SI));
memset(GPR,0,sizeof(Registers.GPR));
memset(FPR,0,sizeof(Registers.FPR));
if (CIC_Chip < 0) {
DisplayError(GS(MSG_UNKNOWN_CIC_CHIP));
CIC_Chip = 2;
}
LO.DW = 0x0;
HI.DW = 0x0;
RANDOM_REGISTER = 0x1F;
COUNT_REGISTER = 0x5000;
MI_VERSION_REG = 0x02020102;
SP_STATUS_REG = 0x00000001;
CAUSE_REGISTER = 0x0000005C;
//ENTRYHI_REGISTER = 0xFFFFE0FF;
CONTEXT_REGISTER = 0x007FFFF0;
EPC_REGISTER = 0xFFFFFFFF;
BAD_VADDR_REGISTER = 0xFFFFFFFF;
ERROREPC_REGISTER = 0xFFFFFFFF;
CONFIG_REGISTER = 0x0006E463;
REVISION_REGISTER = 0x00000511;
STATUS_REGISTER = 0x34000000;
SetFpuLocations();
if (UsePif) {
PROGRAM_COUNTER = 0xBFC00000;
switch (CIC_Chip) {
case 1:
PIF_Ram[36] = 0x00;
PIF_Ram[37] = 0x06;
PIF_Ram[38] = 0x3F;
PIF_Ram[39] = 0x3F;
break;
case 2:
PIF_Ram[36] = 0x00;
PIF_Ram[37] = 0x02;
PIF_Ram[38] = 0x3F;
PIF_Ram[39] = 0x3F;
break;
case 3:
PIF_Ram[36] = 0x00;
PIF_Ram[37] = 0x02;
PIF_Ram[38] = 0x78;
PIF_Ram[39] = 0x3F;
break;
case 5:
PIF_Ram[36] = 0x00;
PIF_Ram[37] = 0x02;
PIF_Ram[38] = 0x91;
PIF_Ram[39] = 0x3F;
break;
case 6:
PIF_Ram[36] = 0x00;
PIF_Ram[37] = 0x02;
PIF_Ram[38] = 0x85;
PIF_Ram[39] = 0x3F;
break;
}
} else {
memcpy( (N64MEM+0x4000040), (ROM + 0x040), 0xFBC);
PROGRAM_COUNTER = 0xA4000040;
GPR[0].DW=0x0000000000000000;
GPR[6].DW=0xFFFFFFFFA4001F0C;
GPR[7].DW=0xFFFFFFFFA4001F08;
GPR[8].DW=0x00000000000000C0;
GPR[9].DW=0x0000000000000000;
GPR[10].DW=0x0000000000000040;
GPR[11].DW=0xFFFFFFFFA4000040;
GPR[16].DW=0x0000000000000000;
GPR[17].DW=0x0000000000000000;
GPR[18].DW=0x0000000000000000;
GPR[19].DW=0x0000000000000000;
GPR[21].DW=0x0000000000000000;
GPR[26].DW=0x0000000000000000;
GPR[27].DW=0x0000000000000000;
GPR[28].DW=0x0000000000000000;
GPR[29].DW=0xFFFFFFFFA4001FF0;
GPR[30].DW=0x0000000000000000;
switch (Country) {
case 0x44: //Germany
case 0x46: //french
case 0x49: //Italian
case 0x50: //Europe
case 0x53: //Spanish
case 0x55: //Australia
case 0x58: // ????
case 0x59: // X (PAL)
switch (CIC_Chip) {
case 2:
GPR[5].DW=0xFFFFFFFFC0F1D859;
GPR[14].DW=0x000000002DE108EA;
GPR[24].DW=0x0000000000000000;
break;
case 3:
GPR[5].DW=0xFFFFFFFFD4646273;
GPR[14].DW=0x000000001AF99984;
GPR[24].DW=0x0000000000000000;
break;
case 5:
*(DWORD *)&IMEM[0x04] = 0xBDA807FC;
GPR[5].DW=0xFFFFFFFFDECAAAD1;
GPR[14].DW=0x000000000CF85C13;
GPR[24].DW=0x0000000000000002;
break;
case 6:
GPR[5].DW=0xFFFFFFFFB04DC903;
GPR[14].DW=0x000000001AF99984;
GPR[24].DW=0x0000000000000002;
break;
}
GPR[20].DW=0x0000000000000000;
GPR[23].DW=0x0000000000000006;
GPR[31].DW=0xFFFFFFFFA4001554;
break;
case 0x37: // 7 (Beta)
case 0x41: // ????
case 0x45: //USA
case 0x4A: //Japan
default:
switch (CIC_Chip) {
case 2:
GPR[5].DW=0xFFFFFFFFC95973D5;
GPR[14].DW=0x000000002449A366;
break;
case 3:
GPR[5].DW=0xFFFFFFFF95315A28;
GPR[14].DW=0x000000005BACA1DF;
break;
case 5:
*(DWORD *)&IMEM[0x04] = 0x8DA807FC;
GPR[5].DW=0x000000005493FB9A;
GPR[14].DW=0xFFFFFFFFC2C20384;
case 6:
GPR[5].DW=0xFFFFFFFFE067221F;
GPR[14].DW=0x000000005CD2B70F;
break;
}
GPR[20].DW=0x0000000000000001;
GPR[23].DW=0x0000000000000000;
GPR[24].DW=0x0000000000000003;
GPR[31].DW=0xFFFFFFFFA4001550;
}
switch (CIC_Chip) {
case 1:
GPR[22].DW=0x000000000000003F;
break;
case 2:
GPR[1].DW=0x0000000000000001;
GPR[2].DW=0x000000000EBDA536;
GPR[3].DW=0x000000000EBDA536;
GPR[4].DW=0x000000000000A536;
GPR[12].DW=0xFFFFFFFFED10D0B3;
GPR[13].DW=0x000000001402A4CC;
GPR[15].DW=0x000000003103E121;
GPR[22].DW=0x000000000000003F;
GPR[25].DW=0xFFFFFFFF9DEBB54F;
break;
case 3:
GPR[1].DW=0x0000000000000001;
GPR[2].DW=0x0000000049A5EE96;
GPR[3].DW=0x0000000049A5EE96;
GPR[4].DW=0x000000000000EE96;
GPR[12].DW=0xFFFFFFFFCE9DFBF7;
GPR[13].DW=0xFFFFFFFFCE9DFBF7;
GPR[15].DW=0x0000000018B63D28;
GPR[22].DW=0x0000000000000078;
GPR[25].DW=0xFFFFFFFF825B21C9;
break;
case 5:
*(DWORD *)&IMEM[0x00] = 0x3C0DBFC0;
*(DWORD *)&IMEM[0x08] = 0x25AD07C0;
*(DWORD *)&IMEM[0x0C] = 0x31080080;
*(DWORD *)&IMEM[0x10] = 0x5500FFFC;
*(DWORD *)&IMEM[0x14] = 0x3C0DBFC0;
*(DWORD *)&IMEM[0x18] = 0x8DA80024;
*(DWORD *)&IMEM[0x1C] = 0x3C0BB000;
GPR[1].DW=0x0000000000000000;
GPR[2].DW=0xFFFFFFFFF58B0FBF;
GPR[3].DW=0xFFFFFFFFF58B0FBF;
GPR[4].DW=0x0000000000000FBF;
GPR[12].DW=0xFFFFFFFF9651F81E;
GPR[13].DW=0x000000002D42AAC5;
GPR[15].DW=0x0000000056584D60;
GPR[22].DW=0x0000000000000091;
GPR[25].DW=0xFFFFFFFFCDCE565F;
break;
case 6:
GPR[1].DW=0x0000000000000000;
GPR[2].DW=0xFFFFFFFFA95930A4;
GPR[3].DW=0xFFFFFFFFA95930A4;
GPR[4].DW=0x00000000000030A4;
GPR[12].DW=0xFFFFFFFFBCB59510;
GPR[13].DW=0xFFFFFFFFBCB59510;
GPR[15].DW=0x000000007A3C07F4;
GPR[22].DW=0x0000000000000085;
GPR[25].DW=0x00000000465E3F72;
break;
}
}
#ifdef Interpreter_StackTest
StackValue = GPR[29].W[0];
#endif
MemoryStack = (DWORD)(N64MEM+(GPR[29].W[0] & 0x1FFFFFFF));
}
#endif
BOOL Is8BitReg (int x86Reg) {
if (x86Reg == x86_EAX) { return TRUE; }
if (x86Reg == x86_EBX) { return TRUE; }
if (x86Reg == x86_ECX) { return TRUE; }
if (x86Reg == x86_EDX) { return TRUE; }
return FALSE;
}
void Load_FPR_ToTop (CBlockSection * Section, int Reg, int RegToLoad, CRegInfo::FPU_STATE Format) {
int i;
if (RegToLoad < 0) { DisplayError("Load_FPR_ToTop\nRegToLoad < 0 ???"); return; }
if (Reg < 0) { DisplayError("Load_FPR_ToTop\nReg < 0 ???"); return; }
if (Format == CRegInfo::FPU_Double || Format == CRegInfo::FPU_Qword) {
UnMap_FPR(Section,Reg + 1,TRUE);
UnMap_FPR(Section,RegToLoad + 1,TRUE);
} else {
if ((Reg & 1) != 0) {
for (i = 0; i < 8; i++) {
if (Section->FpuMappedTo(i) == (DWORD)(Reg - 1)) {
if (Section->FpuState(i) == CRegInfo::FPU_Double || Section->FpuState(i) == CRegInfo::FPU_Qword) {
UnMap_FPR(Section,Reg,TRUE);
}
i = 8;
}
}
}
if ((RegToLoad & 1) != 0) {
for (i = 0; i < 8; i++) {
if (Section->FpuMappedTo(i) == (DWORD)(RegToLoad - 1)) {
if (Section->FpuState(i) == CRegInfo::FPU_Double || Section->FpuState(i) == CRegInfo::FPU_Qword) {
UnMap_FPR(Section,RegToLoad,TRUE);
}
i = 8;
}
}
}
}
if (Reg == RegToLoad) {
//if different format then unmap original reg from stack
for (i = 0; i < 8; i++) {
if (Section->FpuMappedTo(i) == (DWORD)Reg) {
if (Section->FpuState(i) != (DWORD)Format) {
UnMap_FPR(Section,Reg,TRUE);
}
i = 8;
}
}
} else {
UnMap_FPR(Section,Reg,FALSE);
}
if (RegInStack(Section,RegToLoad,Format)) {
if (Reg != RegToLoad) {
if (Section->FpuMappedTo((Section->StackTopPos() - 1) & 7) != (DWORD)RegToLoad) {
UnMap_FPR(Section,Section->FpuMappedTo((Section->StackTopPos() - 1) & 7),TRUE);
CPU_Message(" regcache: allocate ST(0) to %s", FPR_Name[Reg]);
fpuLoadReg(&Section->StackTopPos(),StackPosition(Section,RegToLoad));
Section->FpuRoundingModel(Section->StackTopPos()) = CRegInfo::RoundDefault;
Section->FpuMappedTo(Section->StackTopPos()) = Reg;
Section->FpuState(Section->StackTopPos()) = Format;
} else {
UnMap_FPR(Section,Section->FpuMappedTo((Section->StackTopPos() - 1) & 7),TRUE);
Load_FPR_ToTop (Section,Reg, RegToLoad, Format);
}
} else {
DWORD RegPos, StackPos, i;
for (i = 0; i < 8; i++) {
if (Section->FpuMappedTo(i) == (DWORD)Reg) {
RegPos = i;
i = 8;
}
}
if (RegPos == Section->StackTopPos()) {
return;
}
StackPos = StackPosition(Section,Reg);
Section->FpuRoundingModel(RegPos) = Section->FpuRoundingModel(Section->StackTopPos());
Section->FpuMappedTo(RegPos) = Section->FpuMappedTo(Section->StackTopPos());
Section->FpuState(RegPos) = Section->FpuState(Section->StackTopPos());
CPU_Message(" regcache: allocate ST(%d) to %s", StackPos,FPR_Name[Section->FpuMappedTo(RegPos)]);
CPU_Message(" regcache: allocate ST(0) to %s", FPR_Name[Reg]);
fpuExchange(StackPos);
Section->FpuRoundingModel(Section->StackTopPos()) = CRegInfo::RoundDefault;
Section->FpuMappedTo(Section->StackTopPos()) = Reg;
Section->FpuState(Section->StackTopPos()) = Format;
}
} else {
char Name[50];
int TempReg;
UnMap_FPR(Section,Section->FpuMappedTo((Section->StackTopPos() - 1) & 7),TRUE);
for (i = 0; i < 8; i++) {
if (Section->FpuMappedTo(i) == (DWORD)RegToLoad) {
UnMap_FPR(Section,RegToLoad,TRUE);
i = 8;
}
}
CPU_Message(" regcache: allocate ST(0) to %s", FPR_Name[Reg]);
TempReg = Map_TempReg(Section,x86_Any,-1,FALSE);
switch (Format) {
case CRegInfo::FPU_Dword:
sprintf(Name,"FPRFloatLocation[%d]",RegToLoad);
MoveVariableToX86reg(&FPRFloatLocation[RegToLoad],Name,TempReg);
fpuLoadIntegerDwordFromX86Reg(&Section->StackTopPos(),TempReg);
break;
case CRegInfo::FPU_Qword:
sprintf(Name,"FPRDoubleLocation[%d]",RegToLoad);
MoveVariableToX86reg(&FPRDoubleLocation[RegToLoad],Name,TempReg);
fpuLoadIntegerQwordFromX86Reg(&Section->StackTopPos(),TempReg);
break;
case CRegInfo::FPU_Float:
sprintf(Name,"FPRFloatLocation[%d]",RegToLoad);
MoveVariableToX86reg(&FPRFloatLocation[RegToLoad],Name,TempReg);
fpuLoadDwordFromX86Reg(&Section->StackTopPos(),TempReg);
break;
case CRegInfo::FPU_Double:
sprintf(Name,"FPRDoubleLocation[%d]",RegToLoad);
MoveVariableToX86reg(&FPRDoubleLocation[RegToLoad],Name,TempReg);
fpuLoadQwordFromX86Reg(&Section->StackTopPos(),TempReg);
break;
#ifndef EXTERNAL_RELEASE
default:
DisplayError("Load_FPR_ToTop\nUnkown format to load %d",Format);
#endif
}
Section->x86Protected(TempReg) = FALSE;
Section->FpuRoundingModel(Section->StackTopPos()) = CRegInfo::RoundDefault;
Section->FpuMappedTo(Section->StackTopPos()) = Reg;
Section->FpuState(Section->StackTopPos()) = Format;
}
CPU_Message("CurrentRoundingModel: %d FpuRoundingModel(StackTopPos()): %d",
Section->CurrentRoundingModel(),Section->FpuRoundingModel(Section->StackTopPos()));
}
void Map_GPR_32bit (CBlockSection * Section, int Reg, BOOL SignValue, int MipsRegToLoad) {
int x86Reg,count;
if (Reg == 0) {
#ifndef EXTERNAL_RELEASE
DisplayError("Map_GPR_32bit\n\nWhy are you trying to map reg 0");
#endif
return;
}
if (Section->IsUnknown(Reg) || Section->IsConst(Reg)) {
x86Reg = FreeX86Reg(Section);
if (x86Reg < 0) {
#ifndef EXTERNAL_RELEASE
DisplayError("Map_GPR_32bit\n\nOut of registers");
BreakPoint(__FILE__,__LINE__);
#endif
return;
}
CPU_Message(" regcache: allocate %s to %s",x86_Name(x86Reg),GPR_Name[Reg]);
} else {
if (Section->Is64Bit(Reg)) {
CPU_Message(" regcache: unallocate %s from high 32bit of %s",x86_Name(Section->MipsRegHi(Reg)),GPR_NameHi[Reg]);
Section->x86MapOrder(Section->MipsRegHi(Reg)) = 0;
Section->x86Mapped(Section->MipsRegHi(Reg)) = CRegInfo::NotMapped;
Section->x86Protected(Section->MipsRegHi(Reg)) = FALSE;
Section->MipsRegHi(Reg) = 0;
}
x86Reg = Section->MipsRegLo(Reg);
}
for (count = 0; count < 10; count ++) {
if (Section->x86MapOrder(count) > 0) {
Section->x86MapOrder(count) += 1;
}
}
Section->x86MapOrder(x86Reg) = 1;
if (MipsRegToLoad > 0) {
if (Section->IsUnknown(MipsRegToLoad)) {
MoveVariableToX86reg(&GPR[MipsRegToLoad].UW[0],GPR_NameLo[MipsRegToLoad],x86Reg);
} else if (Section->IsMapped(MipsRegToLoad)) {
if (Reg != MipsRegToLoad) {
MoveX86RegToX86Reg(Section->MipsRegLo(MipsRegToLoad),x86Reg);
}
} else {
if (Section->MipsRegLo(MipsRegToLoad) != 0) {
MoveConstToX86reg(Section->MipsRegLo(MipsRegToLoad),x86Reg);
} else {
XorX86RegToX86Reg(x86Reg,x86Reg);
}
}
} else if (MipsRegToLoad == 0) {
XorX86RegToX86Reg(x86Reg,x86Reg);
}
Section->x86Mapped(x86Reg) = CRegInfo::GPR_Mapped;
Section->x86Protected(x86Reg) = TRUE;
Section->MipsRegLo(Reg) = x86Reg;
Section->MipsRegState(Reg) = SignValue ? CRegInfo::STATE_MAPPED_32_SIGN : CRegInfo::STATE_MAPPED_32_ZERO;
}
void Map_GPR_64bit (CBlockSection * Section, int Reg, int MipsRegToLoad) {
int x86Hi, x86lo, count;
if (Reg == 0) {
#ifndef EXTERNAL_RELEASE
DisplayError("Map_GPR_32bit\n\nWhy are you trying to map reg 0");
#endif
return;
}
ProtectGPR(Section,Reg);
if (Section->IsUnknown(Reg) || Section->IsConst(Reg)) {
x86Hi = FreeX86Reg(Section);
if (x86Hi < 0) { DisplayError("Map_GPR_64bit\n\nOut of registers"); return; }
Section->x86Protected(x86Hi) = TRUE;
x86lo = FreeX86Reg(Section);
if (x86lo < 0) { DisplayError("Map_GPR_64bit\n\nOut of registers"); return; }
Section->x86Protected(x86lo) = TRUE;
CPU_Message(" regcache: allocate %s to hi word of %s",x86_Name(x86Hi),GPR_Name[Reg]);
CPU_Message(" regcache: allocate %s to low word of %s",x86_Name(x86lo),GPR_Name[Reg]);
} else {
x86lo = Section->MipsRegLo(Reg);
if (Section->Is32Bit(Reg)) {
Section->x86Protected(x86lo) = TRUE;
x86Hi = FreeX86Reg(Section);
if (x86Hi < 0) { DisplayError("Map_GPR_64bit\n\nOut of registers"); return; }
Section->x86Protected(x86Hi) = TRUE;
} else {
x86Hi = Section->MipsRegHi(Reg);
}
}
for (count = 0; count < 10; count ++) {
if (Section->x86MapOrder(count) > 0) { Section->x86MapOrder(count) += 1; }
}
Section->x86MapOrder(x86Hi) = 1;
Section->x86MapOrder(x86lo) = 1;
if (MipsRegToLoad > 0) {
if (Section->IsUnknown(MipsRegToLoad)) {
MoveVariableToX86reg(&GPR[MipsRegToLoad].UW[1],GPR_NameHi[MipsRegToLoad],x86Hi);
MoveVariableToX86reg(&GPR[MipsRegToLoad].UW[0],GPR_NameLo[MipsRegToLoad],x86lo);
} else if (Section->IsMapped(MipsRegToLoad)) {
if (Section->Is32Bit(MipsRegToLoad)) {
if (Section->IsSigned(MipsRegToLoad)) {
MoveX86RegToX86Reg(Section->MipsRegLo(MipsRegToLoad),x86Hi);
ShiftRightSignImmed(x86Hi,31);
} else {
XorX86RegToX86Reg(x86Hi,x86Hi);
}
if (Reg != MipsRegToLoad) {
MoveX86RegToX86Reg(Section->MipsRegLo(MipsRegToLoad),x86lo);
}
} else {
if (Reg != MipsRegToLoad) {
MoveX86RegToX86Reg(Section->MipsRegHi(MipsRegToLoad),x86Hi);
MoveX86RegToX86Reg(Section->MipsRegLo(MipsRegToLoad),x86lo);
}
}
} else {
CPU_Message("Map_GPR_64bit 11");
if (Section->Is32Bit(MipsRegToLoad)) {
if (Section->IsSigned(MipsRegToLoad)) {
if (Section->MipsRegLo((int)Section->MipsRegLo(MipsRegToLoad) >> 31) != 0) {
MoveConstToX86reg((int)Section->MipsRegLo(MipsRegToLoad) >> 31,x86Hi);
} else {
XorX86RegToX86Reg(x86Hi,x86Hi);
}
} else {
XorX86RegToX86Reg(x86Hi,x86Hi);
}
} else {
if (Section->MipsRegHi(MipsRegToLoad) != 0) {
MoveConstToX86reg(Section->MipsRegHi(MipsRegToLoad),x86Hi);
} else {
XorX86RegToX86Reg(x86Hi,x86Hi);
}
}
if (Section->MipsRegLo(MipsRegToLoad) != 0) {
MoveConstToX86reg(Section->MipsRegLo(MipsRegToLoad),x86lo);
} else {
XorX86RegToX86Reg(x86lo,x86lo);
}
}
} else if (MipsRegToLoad == 0) {
XorX86RegToX86Reg(x86Hi,x86Hi);
XorX86RegToX86Reg(x86lo,x86lo);
}
Section->x86Mapped(x86Hi) = CRegInfo::GPR_Mapped;
Section->x86Mapped(x86lo) = CRegInfo::GPR_Mapped;
Section->MipsRegHi(Reg) = x86Hi;
Section->MipsRegLo(Reg) = x86lo;
Section->MipsRegState(Reg) = CRegInfo::STATE_MAPPED_64;
}
int Map_MemoryStack (CBlockSection * Section, int Reg, bool MapRegister)
{
int CurrentMap = -1;
// check to see what the current mapping is
for (int x86Reg = 0; x86Reg < 10; x86Reg ++ ) {
if (Section->x86Mapped(x86Reg) == CRegInfo::Stack_Mapped) {
CurrentMap = x86Reg;
}
}
if (!MapRegister)
{
//if not mapping then just return what the current mapping is
return CurrentMap;
}
if (CurrentMap > 0 && CurrentMap == Reg)
{
//already mapped to correct reg
return CurrentMap;
}
// map a register
if (Reg == x86_Any)
{
if (CurrentMap > 0)
{
return CurrentMap;
}
x86Reg = FreeX86Reg(Section);
if (x86Reg < 0) {
#ifndef EXTERNAL_RELEASE
DisplayError("Map_MemoryStack\n\nOut of registers");
BreakPoint(__FILE__,__LINE__);
#endif
}
Section->x86Mapped(x86Reg) = CRegInfo::Stack_Mapped;
CPU_Message(" regcache: allocate %s as Memory Stack",x86_Name(x86Reg));
MoveVariableToX86reg(g_MemoryStack,"MemoryStack",x86Reg);
return x86Reg;
}
//move to a register/allocate register
UnMap_X86reg(Section, Reg);
if (CurrentMap >= 0)
{
CPU_Message(" regcache: change allocation of Memory Stack from %s to %s",x86_Name(CurrentMap),x86_Name(Reg));
Section->x86Mapped(Reg) = CRegInfo::Stack_Mapped;
Section->x86Mapped(CurrentMap) = CRegInfo::NotMapped;
MoveX86RegToX86Reg(CurrentMap,Reg);
} else {
Section->x86Mapped(Reg) = CRegInfo::Stack_Mapped;
CPU_Message(" regcache: allocate %s as Memory Stack",x86_Name(Reg));
MoveVariableToX86reg(g_MemoryStack,"MemoryStack",Reg);
}
return Reg;
}
int Map_TempReg (CBlockSection * Section, int x86Reg, int MipsReg, BOOL LoadHiWord) {
int count;
if (x86Reg == x86_Any) {
for (count = 0; count < 10; count ++ ) {
if (Section->x86Mapped(count) == CRegInfo::Temp_Mapped) {
if (Section->x86Protected(count) == FALSE) { x86Reg = count; }
}
}
if (x86Reg == x86_Any) {
x86Reg = FreeX86Reg(Section);
if (x86Reg < 0) {
#ifndef EXTERNAL_RELEASE
DisplayError("Map_TempReg\n\nOut of registers");
BreakPoint(__FILE__,__LINE__);
#endif
x86Reg = FreeX86Reg(Section);
return -1;
}
CPU_Message(" regcache: allocate %s as temp storage",x86_Name(x86Reg));
}
} else if (x86Reg == x86_Any8Bit) {
if (Section->x86Mapped(x86_EBX) == CRegInfo::Temp_Mapped && !Section->x86Protected(x86_EBX)) { x86Reg = x86_EBX; }
if (Section->x86Mapped(x86_EAX) == CRegInfo::Temp_Mapped && !Section->x86Protected(x86_EAX)) { x86Reg = x86_EAX; }
if (Section->x86Mapped(x86_EDX) == CRegInfo::Temp_Mapped && !Section->x86Protected(x86_EDX)) { x86Reg = x86_EDX; }
if (Section->x86Mapped(x86_ECX) == CRegInfo::Temp_Mapped && !Section->x86Protected(x86_ECX)) { x86Reg = x86_ECX; }
if (x86Reg == x86_Any8Bit) {
x86Reg = Free8BitX86Reg(Section);
if (x86Reg < 0) {
#ifndef EXTERNAL_RELEASE
DisplayError("Map_GPR_8bit\n\nOut of registers");
BreakPoint(__FILE__,__LINE__);
#endif
return -1;
}
}
} else {
int NewReg;
if (Section->x86Mapped(x86Reg) == CRegInfo::GPR_Mapped) {
if (Section->x86Protected(x86Reg) == TRUE) {
#ifndef EXTERNAL_RELEASE
DisplayError("Map_TempReg\nRegister is protected !!!");
#endif
return -1;
}
Section->x86Protected(x86Reg) = TRUE;
NewReg = FreeX86Reg(Section);
for (count = 1; count < 32; count ++) {
if (Section->IsMapped(count)) {
if (Section->MipsRegLo(count) == (DWORD)x86Reg) {
if (NewReg < 0) {
UnMap_GPR(Section,count,TRUE);
count = 32;
continue;
}
CPU_Message(" regcache: change allocation of %s from %s to %s",
GPR_Name[count],x86_Name(x86Reg),x86_Name(NewReg));
Section->x86Mapped(NewReg) = CRegInfo::GPR_Mapped;
Section->x86MapOrder(NewReg) = Section->x86MapOrder(x86Reg);
Section->MipsRegLo(count) = NewReg;
MoveX86RegToX86Reg(x86Reg,NewReg);
if (MipsReg == count && LoadHiWord == FALSE) { MipsReg = -1; }
count = 32;
}
if (Section->Is64Bit(count) && Section->MipsRegHi(count) == (DWORD)x86Reg) {
if (NewReg < 0) {
UnMap_GPR(Section,count,TRUE);
count = 32;
continue;
}
CPU_Message(" regcache: change allocation of %s from %s to %s",
GPR_NameHi[count],x86_Name(x86Reg),x86_Name(NewReg));
Section->x86Mapped(NewReg) = CRegInfo::GPR_Mapped;
Section->x86MapOrder(NewReg) = Section->x86MapOrder(x86Reg);
Section->MipsRegHi(count) = NewReg;
MoveX86RegToX86Reg(x86Reg,NewReg);
if (MipsReg == count && LoadHiWord == TRUE) { MipsReg = -1; }
count = 32;
}
}
}
}
if (Section->x86Mapped(x86Reg) == CRegInfo::Stack_Mapped) {
UnMap_X86reg(Section,x86Reg);
}
CPU_Message(" regcache: allocate %s as temp storage",x86_Name(x86Reg));
}
if (MipsReg >= 0) {
if (LoadHiWord) {
if (Section->IsUnknown(MipsReg)) {
MoveVariableToX86reg(&GPR[MipsReg].UW[1],GPR_NameHi[MipsReg],x86Reg);
} else if (Section->IsMapped(MipsReg)) {
if (Section->Is64Bit(MipsReg)) {
MoveX86RegToX86Reg(Section->MipsRegHi(MipsReg),x86Reg);
} else if (Section->IsSigned(MipsReg)){
MoveX86RegToX86Reg(Section->MipsRegLo(MipsReg),x86Reg);
ShiftRightSignImmed(x86Reg,31);
} else {
MoveConstToX86reg(0,x86Reg);
}
} else {
if (Section->Is64Bit(MipsReg)) {
if (Section->MipsRegHi(MipsReg) != 0) {
MoveConstToX86reg(Section->MipsRegHi(MipsReg),x86Reg);
} else {
XorX86RegToX86Reg(x86Reg,x86Reg);
}
} else {
if ((int)Section->MipsRegLo(MipsReg) >> 31 != 0) {
MoveConstToX86reg((int)Section->MipsRegLo(MipsReg) >> 31,x86Reg);
} else {
XorX86RegToX86Reg(x86Reg,x86Reg);
}
}
}
} else {
if (Section->IsUnknown(MipsReg)) {
MoveVariableToX86reg(&GPR[MipsReg].UW[0],GPR_NameLo[MipsReg],x86Reg);
} else if (Section->IsMapped(MipsReg)) {
MoveX86RegToX86Reg(Section->MipsRegLo(MipsReg),x86Reg);
} else {
if (Section->MipsRegLo(MipsReg) != 0) {
MoveConstToX86reg(Section->MipsRegLo(MipsReg),x86Reg);
} else {
XorX86RegToX86Reg(x86Reg,x86Reg);
}
}
}
}
Section->x86Mapped(x86Reg) = CRegInfo::Temp_Mapped;
Section->x86Protected(x86Reg) = TRUE;
for (count = 0; count < 10; count ++) {
if (Section->x86MapOrder(count) > 0) {
Section->x86MapOrder(count) += 1;
}
}
Section->x86MapOrder(x86Reg) = 1;
return x86Reg;
}
void ProtectGPR(CBlockSection * Section, DWORD Reg) {
if (Section->IsUnknown(Reg)) { return; }
if (Section->IsConst(Reg)) { return; }
if (Section->Is64Bit(Reg)) {
Section->x86Protected(Section->MipsRegHi(Reg)) = TRUE;
}
Section->x86Protected(Section->MipsRegLo(Reg)) = TRUE;
}
BOOL RegInStack(CBlockSection * Section,int Reg, int Format) {
int i;
for (i = 0; i < 8; i++) {
if (Section->FpuMappedTo(i) == (DWORD)Reg) {
if (Section->FpuState(i) == (DWORD)Format) { return TRUE; }
else if (Format == -1) { return TRUE; }
return FALSE;
}
}
return FALSE;
}
#ifdef ggg
void SetFpuLocations (void) {
int count;
if ((STATUS_REGISTER & STATUS_FR) == 0) {
for (count = 0; count < 32; count ++) {
FPRFloatLocation[count] = (void *)(&FPR[count >> 1].W[count & 1]);
//FPRDoubleLocation[count] = FPRFloatLocation[count];
FPRDoubleLocation[count] = (void *)(&FPR[count >> 1].DW);
}
} else {
for (count = 0; count < 32; count ++) {
FPRFloatLocation[count] = (void *)(&FPR[count].W[1]);
//FPRDoubleLocation[count] = FPRFloatLocation[count];
FPRDoubleLocation[count] = (void *)(&FPR[count].DW);
}
}
}
void SetupRegisters(N64_REGISTERS * n64_Registers) {
PROGRAM_COUNTER = n64_Registers->PROGRAM_COUNTER;
HI.DW = n64_Registers->HI.DW;
LO.DW = n64_Registers->LO.DW;
CP0 = n64_Registers->CP0;
GPR = n64_Registers->GPR;
FPR = n64_Registers->FPR;
FPCR = n64_Registers->FPCR;
RegRDRAM = n64_Registers->RDRAM;
RegSP = n64_Registers->SP;
RegDPC = n64_Registers->DPC;
RegMI = n64_Registers->MI;
RegVI = n64_Registers->VI;
RegAI = n64_Registers->AI;
RegPI = n64_Registers->PI;
RegRI = n64_Registers->RI;
RegSI = n64_Registers->SI;
PIF_Ram = n64_Registers->PIF_Ram;
DMAUsed = n64_Registers->DMAUsed;
}
#endif
int StackPosition (CBlockSection * Section,int Reg) {
int i;
for (i = 0; i < 8; i++) {
if (Section->FpuMappedTo(i) == (DWORD)Reg) {
return ((i - Section->StackTopPos()) & 7);
}
}
return -1;
}
int UnMap_8BitTempReg (CBlockSection * Section) {
int count;
for (count = 0; count < 10; count ++) {
if (!Is8BitReg(count)) { continue; }
if (Section->MipsRegState(count) == CRegInfo::Temp_Mapped) {
if (Section->x86Protected(count) == FALSE) {
CPU_Message(" regcache: unallocate %s from temp storage",x86_Name(count));
Section->x86Mapped(count) = CRegInfo::NotMapped;
return count;
}
}
}
return -1;
}
void UnMap_AllFPRs ( CBlockSection * Section ) {
DWORD StackPos;
for (;;) {
int i, StartPos;
StackPos = Section->StackTopPos();
if (Section->FpuMappedTo(Section->StackTopPos()) != -1 ) {
UnMap_FPR(Section,Section->FpuMappedTo(Section->StackTopPos()),TRUE);
continue;
}
//see if any more registers mapped
StartPos = Section->StackTopPos();
for (i = 0; i < 8; i++) {
if (Section->FpuMappedTo((StartPos + i) & 7) != -1 ) { fpuIncStack(&Section->StackTopPos()); }
}
if (StackPos != Section->StackTopPos()) { continue; }
return;
}
}
void FixRoundModel(CBlockSection * Section, CRegInfo::FPU_ROUND RoundMethod )
{
if (Section->CurrentRoundingModel() == RoundMethod)
{
return;
}
fpuControl = 0;
fpuStoreControl(&fpuControl, "fpuControl");
int x86reg = Map_TempReg(Section,x86_Any,-1,FALSE);
MoveVariableToX86reg(&fpuControl, "fpuControl", x86reg);
AndConstToX86Reg(x86reg, 0xF3FF);
switch (RoundMethod) {
case CRegInfo::RoundDefault: OrVariableToX86Reg(&FPU_RoundingMode,"FPU_RoundingMode", x86reg); break;
case CRegInfo::RoundTruncate: OrConstToX86Reg(0x0C00, x86reg); break;
case CRegInfo::RoundNearest: /*OrConstToX86Reg(0x0000, x86reg);*/ break;
case CRegInfo::RoundDown: OrConstToX86Reg(0x0400, x86reg); break;
case CRegInfo::RoundUp: OrConstToX86Reg(0x0800, x86reg); break;
default:
DisplayError("Unknown Rounding model");
}
MoveX86regToVariable(x86reg, &fpuControl, "fpuControl");
fpuLoadControl(&fpuControl, "fpuControl");
Section->CurrentRoundingModel() = RoundMethod;
}
void UnMap_FPR (CBlockSection * Section, int Reg, int WriteBackValue ) {
char Name[50];
int TempReg;
int i;
if (Reg < 0) { return; }
for (i = 0; i < 8; i++) {
if (Section->FpuMappedTo(i) != (DWORD)Reg) { continue; }
CPU_Message(" regcache: unallocate %s from ST(%d)",FPR_Name[Reg],(i - Section->StackTopPos() + 8) & 7);
if (WriteBackValue) {
int RegPos;
if (((i - Section->StackTopPos() + 8) & 7) != 0) {
CRegInfo::FPU_ROUND RoundingModel = Section->FpuRoundingModel(Section->StackTopPos());
CRegInfo::FPU_STATE RegState = Section->FpuState(Section->StackTopPos());
DWORD MappedTo = Section->FpuMappedTo(Section->StackTopPos());
Section->FpuRoundingModel(Section->StackTopPos()) = Section->FpuRoundingModel(i);
Section->FpuMappedTo(Section->StackTopPos()) = Section->FpuMappedTo(i);
Section->FpuState(Section->StackTopPos()) = Section->FpuState(i);
Section->FpuRoundingModel(i) = RoundingModel;
Section->FpuMappedTo(i) = MappedTo;
Section->FpuState(i) = RegState;
fpuExchange((i - Section->StackTopPos()) & 7);
}
CPU_Message("CurrentRoundingModel: %d Section->FpuRoundingModel(i): %d",
Section->CurrentRoundingModel(),Section->FpuRoundingModel(i));
FixRoundModel(Section,Section->FpuRoundingModel(i));
RegPos = Section->StackTopPos();
TempReg = Map_TempReg(Section,x86_Any,-1,FALSE);
switch (Section->FpuState(Section->StackTopPos())) {
case CRegInfo::FPU_Dword:
sprintf(Name,"FPRFloatLocation[%d]",Section->FpuMappedTo(Section->StackTopPos()));
MoveVariableToX86reg(&FPRFloatLocation[Section->FpuMappedTo(Section->StackTopPos())],Name,TempReg);
fpuStoreIntegerDwordFromX86Reg(&Section->StackTopPos(),TempReg, TRUE);
break;
case CRegInfo::FPU_Qword:
sprintf(Name,"FPRDoubleLocation[%d]",Section->FpuMappedTo(Section->StackTopPos()));
MoveVariableToX86reg(&FPRDoubleLocation[Section->FpuMappedTo(Section->StackTopPos())],Name,TempReg);
fpuStoreIntegerQwordFromX86Reg(&Section->StackTopPos(),TempReg, TRUE);
break;
case CRegInfo::FPU_Float:
sprintf(Name,"FPRFloatLocation[%d]",Section->FpuMappedTo(Section->StackTopPos()));
MoveVariableToX86reg(&FPRFloatLocation[Section->FpuMappedTo(Section->StackTopPos())],Name,TempReg);
fpuStoreDwordFromX86Reg(&Section->StackTopPos(),TempReg, TRUE);
break;
case CRegInfo::FPU_Double:
sprintf(Name,"FPRDoubleLocation[%d]",Section->FpuMappedTo(Section->StackTopPos()));
MoveVariableToX86reg(&FPRDoubleLocation[Section->FpuMappedTo(Section->StackTopPos())],Name,TempReg);
fpuStoreQwordFromX86Reg(&Section->StackTopPos(),TempReg, TRUE);
break;
#ifndef EXTERNAL_RELEASE
default:
DisplayError("UnMap_FPR\nUnknown format to load %d",Section->FpuState(Section->StackTopPos()));
#endif
}
Section->x86Protected(TempReg) = FALSE;
Section->FpuRoundingModel(RegPos) = CRegInfo::RoundDefault;
Section->FpuMappedTo(RegPos) = -1;
Section->FpuState(RegPos) = CRegInfo::FPU_Unkown;
} else {
fpuFree((i - Section->StackTopPos()) & 7);
Section->FpuRoundingModel(i) = CRegInfo::RoundDefault;
Section->FpuMappedTo(i) = -1;
Section->FpuState(i) = CRegInfo::FPU_Unkown;
}
return;
}
}
void UnMap_GPR (CBlockSection * Section, DWORD Reg, int WriteBackValue) {
if (Reg == 0) {
#ifndef EXTERNAL_RELEASE
DisplayError("UnMap_GPR\n\nWhy are you trying to unmap reg 0");
#endif
return;
}
if (Section->IsUnknown(Reg)) { return; }
//CPU_Message("UnMap_GPR: State: %X\tReg: %s\tWriteBack: %s",State,GPR_Name[Reg],WriteBackValue?"TRUE":"FALSE");
if (Section->IsConst(Reg)) {
if (!WriteBackValue) {
Section->MipsRegState(Reg) = CRegInfo::STATE_UNKNOWN;
return;
}
if (Section->Is64Bit(Reg)) {
MoveConstToVariable(Section->MipsRegHi(Reg),&GPR[Reg].UW[1],GPR_NameHi[Reg]);
MoveConstToVariable(Section->MipsRegLo(Reg),&GPR[Reg].UW[0],GPR_NameLo[Reg]);
Section->MipsRegState(Reg) = CRegInfo::STATE_UNKNOWN;
return;
}
if ((Section->MipsRegLo(Reg) & 0x80000000) != 0) {
MoveConstToVariable(0xFFFFFFFF,&GPR[Reg].UW[1],GPR_NameHi[Reg]);
} else {
MoveConstToVariable(0,&GPR[Reg].UW[1],GPR_NameHi[Reg]);
}
MoveConstToVariable(Section->MipsRegLo(Reg),&GPR[Reg].UW[0],GPR_NameLo[Reg]);
Section->MipsRegState(Reg) = CRegInfo::STATE_UNKNOWN;
return;
}
if (Section->Is64Bit(Reg)) {
CPU_Message(" regcache: unallocate %s from %s",x86_Name(Section->MipsRegHi(Reg)),GPR_NameHi[Reg]);
Section->x86Mapped(Section->MipsRegHi(Reg)) = CRegInfo::NotMapped;
Section->x86Protected(Section->MipsRegHi(Reg)) = FALSE;
}
CPU_Message(" regcache: unallocate %s from %s",x86_Name(Section->MipsRegLo(Reg)),GPR_NameLo[Reg]);
Section->x86Mapped(Section->MipsRegLo(Reg)) = CRegInfo::NotMapped;
Section->x86Protected(Section->MipsRegLo(Reg)) = FALSE;
if (!WriteBackValue) {
Section->MipsRegState(Reg) = CRegInfo::STATE_UNKNOWN;
return;
}
MoveX86regToVariable(Section->MipsRegLo(Reg),&GPR[Reg].UW[0],GPR_NameLo[Reg]);
if (Section->Is64Bit(Reg)) {
MoveX86regToVariable(Section->MipsRegHi(Reg),&GPR[Reg].UW[1],GPR_NameHi[Reg]);
} else {
if (Section->IsSigned(Reg)) {
ShiftRightSignImmed(Section->MipsRegLo(Reg),31);
MoveX86regToVariable(Section->MipsRegLo(Reg),&GPR[Reg].UW[1],GPR_NameHi[Reg]);
} else {
MoveConstToVariable(0,&GPR[Reg].UW[1],GPR_NameHi[Reg]);
}
}
Section->MipsRegState(Reg) = CRegInfo::STATE_UNKNOWN;
}
int UnMap_TempReg (CBlockSection * Section) {
int count;
for (count = 0; count < 10; count ++) {
if (Section->x86Mapped(count) == CRegInfo::Temp_Mapped) {
if (Section->x86Protected(count) == FALSE) {
CPU_Message(" regcache: unallocate %s from temp storage",x86_Name(count));
Section->x86Mapped(count) = CRegInfo::NotMapped;
return count;
}
}
}
return -1;
}
BOOL UnMap_X86reg (CBlockSection * Section, DWORD x86Reg) {
int count;
if (Section->x86Mapped(x86Reg) == CRegInfo::NotMapped && Section->x86Protected(x86Reg) == FALSE) { return TRUE; }
if (Section->x86Mapped(x86Reg) == CRegInfo::Temp_Mapped) {
if (Section->x86Protected(x86Reg) == FALSE) {
CPU_Message(" regcache: unallocate %s from temp storage",x86_Name(x86Reg));
Section->x86Mapped(x86Reg) = CRegInfo::NotMapped;
return TRUE;
}
return FALSE;
}
for (count = 1; count < 32; count ++) {
if (Section->IsMapped(count)) {
if (Section->Is64Bit(count)) {
if (Section->MipsRegHi(count) == x86Reg) {
if (Section->x86Protected(x86Reg) == FALSE) {
UnMap_GPR(Section,count,TRUE);
return TRUE;
}
break;
}
}
if (Section->MipsRegLo(count) == x86Reg) {
if (Section->x86Protected(x86Reg) == FALSE) {
UnMap_GPR(Section,count,TRUE);
return TRUE;
}
break;
}
}
}
if (Section->x86Mapped(x86Reg) == CRegInfo::Stack_Mapped) {
CPU_Message(" regcache: unallocate %s from Memory Stack",x86_Name(x86Reg));
MoveX86regToVariable(x86Reg,g_MemoryStack,"MemoryStack");
Section->x86Mapped(x86Reg) = CRegInfo::NotMapped;
return TRUE;
}
return FALSE;
}
void UnProtectGPR(CBlockSection * Section, DWORD Reg) {
if (Section->IsUnknown(Reg)) { return; }
if (Section->IsConst(Reg)) { return; }
if (Section->Is64Bit(Reg)) {
Section->x86Protected(Section->MipsRegHi(Reg)) = FALSE;
}
Section->x86Protected(Section->MipsRegLo(Reg)) = FALSE;
}
/*void WriteBackRegisters (CBlockSection * Section) {
int count;
for (count = 1; count < 10; count ++) { Section->x86Protected(count) = FALSE; }
for (count = 1; count < 10; count ++) { UnMap_X86reg (Section, count); }
for (count = 1; count < 32; count ++) {
switch (Section->MipsRegState(count)) {
case CRegInfo::STATE_UNKNOWN: break;
case STATE_CONST_32:
if ((Section->MipsRegLo(count) & 0x80000000) != 0) {
MoveConstToVariable(0xFFFFFFFF,&GPR[count].UW[1],GPR_NameHi[count]);
} else {
MoveConstToVariable(0,&GPR[count].UW[1],GPR_NameHi[count]);
}
MoveConstToVariable(Section->MipsRegLo(count),&GPR[count].UW[0],GPR_NameLo[count]);
Section->MipsRegState(count) = CRegInfo::STATE_UNKNOWN;
break;
default:
DisplayError("Unknown State: %d\nin WriteBackRegisters",Section->MipsRegState(count));
}
}
UnMap_AllFPRs(Section);
}*/
void WriteBackRegisters (CBlockSection * Section) {
int count;
BOOL bEdiZero = FALSE;
BOOL bEsiSign = FALSE;
/*** coming soon ***/
BOOL bEaxGprLo = FALSE;
BOOL bEbxGprHi = FALSE;
for (count = 1; count < 10; count ++) { Section->x86Protected(count) = FALSE; }
for (count = 1; count < 10; count ++) { UnMap_X86reg (Section, count); }
/*************************************/
for (count = 1; count < 32; count ++) {
switch (Section->MipsRegState(count)) {
case CRegInfo::STATE_UNKNOWN: break;
case CRegInfo::STATE_CONST_32:
if (!bEdiZero && (!Section->MipsRegLo(count) || !(Section->MipsRegLo(count) & 0x80000000))) {
XorX86RegToX86Reg(x86_EDI, x86_EDI);
bEdiZero = TRUE;
}
if (!bEsiSign && (Section->MipsRegLo(count) & 0x80000000)) {
MoveConstToX86reg(0xFFFFFFFF, x86_ESI);
bEsiSign = TRUE;
}
if ((Section->MipsRegLo(count) & 0x80000000) != 0) {
MoveX86regToVariable(x86_ESI,&GPR[count].UW[1],GPR_NameHi[count]);
} else {
MoveX86regToVariable(x86_EDI,&GPR[count].UW[1],GPR_NameHi[count]);
}
if (Section->MipsRegLo(count) == 0) {
MoveX86regToVariable(x86_EDI,&GPR[count].UW[0],GPR_NameLo[count]);
} else if (Section->MipsRegLo(count) == 0xFFFFFFFF) {
MoveX86regToVariable(x86_ESI,&GPR[count].UW[0],GPR_NameLo[count]);
} else
MoveConstToVariable(Section->MipsRegLo(count),&GPR[count].UW[0],GPR_NameLo[count]);
Section->MipsRegState(count) = CRegInfo::STATE_UNKNOWN;
break;
case CRegInfo::STATE_CONST_64:
if (Section->MipsRegLo(count) == 0 || Section->MipsRegHi(count) == 0) {
XorX86RegToX86Reg(x86_EDI, x86_EDI);
bEdiZero = TRUE;
}
if (Section->MipsRegLo(count) == 0xFFFFFFFF || Section->MipsRegHi(count) == 0xFFFFFFFF) {
MoveConstToX86reg(0xFFFFFFFF, x86_ESI);
bEsiSign = TRUE;
}
if (Section->MipsRegHi(count) == 0) {
MoveX86regToVariable(x86_EDI,&GPR[count].UW[1],GPR_NameHi[count]);
} else if (Section->MipsRegLo(count) == 0xFFFFFFFF) {
MoveX86regToVariable(x86_ESI,&GPR[count].UW[1],GPR_NameHi[count]);
} else {
MoveConstToVariable(Section->MipsRegHi(count),&GPR[count].UW[1],GPR_NameHi[count]);
}
if (Section->MipsRegLo(count) == 0) {
MoveX86regToVariable(x86_EDI,&GPR[count].UW[0],GPR_NameLo[count]);
} else if (Section->MipsRegLo(count) == 0xFFFFFFFF) {
MoveX86regToVariable(x86_ESI,&GPR[count].UW[0],GPR_NameLo[count]);
} else {
MoveConstToVariable(Section->MipsRegLo(count),&GPR[count].UW[0],GPR_NameLo[count]);
}
Section->MipsRegState(count) = CRegInfo::STATE_UNKNOWN;
break;
#ifndef EXTERNAL_RELEASE
default:
DisplayError("Unknown State: %d\nin WriteBackRegisters",Section->MipsRegState(count));
#endif
}
}
UnMap_AllFPRs(Section);
}