project64/Source/Project64/N64 System/C Core/Recompiler Fpu Ops.cpp

1168 lines
50 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 <stdio.h>
#include "main.h"
#include "cpu.h"
#include "x86.h"
#include "debugger.h"
#include "Recompiler Ops.h"
#include "../System Globals.h"
WORD FPU_RoundingMode = 0x0000;//_RC_NEAR
char Name[50];
void ChangeDefaultRoundingModel (void) {
switch((_FPCR[31] & 3)) {
case 0: FPU_RoundingMode = 0x0000; break; //_RC_NEAR
case 1: FPU_RoundingMode = 0x0C00; break; //_RC_CHOP
case 2: FPU_RoundingMode = 0x0800; break; //_RC_UP
case 3: FPU_RoundingMode = 0x0400; break; //_RC_UP
}
}
void CompileCop1Test (CCodeSection * Section) {
if (Section->FpuBeenUsed()) { return; }
TestVariable(STATUS_CU1,&_Reg->STATUS_REGISTER,"STATUS_REGISTER");
_N64System->GetRecompiler()->CompileExit(Section,Section->m_CompilePC,Section->m_CompilePC,Section->RegWorking,CExitInfo::COP1_Unuseable,FALSE,JeLabel32);
Section->FpuBeenUsed() = TRUE;
}
/********************** Load/store functions ************************/
#ifdef tofix
void Compile_R4300i_LWC1 (CCodeSection * Section) {
DWORD TempReg1, TempReg2, TempReg3;
char Name[50];
CPU_Message(" %X %s",Section->m_CompilePC,R4300iOpcodeName(m_CompileOpcode.Hex,Section->m_CompilePC));
CompileCop1Test(Section);
if ((m_CompileOpcode.ft & 1) != 0) {
if (RegInStack(Section,m_CompileOpcode.ft-1,CRegInfo::FPU_Double) || RegInStack(Section,m_CompileOpcode.ft-1,CRegInfo::FPU_Qword)) {
UnMap_FPR(Section,m_CompileOpcode.ft-1,TRUE);
}
}
if (RegInStack(Section,m_CompileOpcode.ft,CRegInfo::FPU_Double) || RegInStack(Section,m_CompileOpcode.ft,CRegInfo::FPU_Qword)) {
UnMap_FPR(Section,m_CompileOpcode.ft,TRUE);
} else {
UnMap_FPR(Section,m_CompileOpcode.ft,FALSE);
}
if (Section->IsConst(m_CompileOpcode.base)) {
DWORD Address = Section->MipsRegLo(m_CompileOpcode.base) + (short)m_CompileOpcode.offset;
TempReg1 = Map_TempReg(Section,x86_Any,-1,FALSE);
_MMU->Compile_LW(Section, TempReg1,Address);
TempReg2 = Map_TempReg(Section,x86_Any,-1,FALSE);
sprintf(Name,"_FPRFloatLocation[%d]",m_CompileOpcode.ft);
MoveVariableToX86reg(&_FPRFloatLocation[m_CompileOpcode.ft],Name,TempReg2);
MoveX86regToX86Pointer(TempReg1,TempReg2);
return;
}
if (Section->IsMapped(m_CompileOpcode.base) && m_CompileOpcode.offset == 0) {
if (UseTlb) {
ProtectGPR(Section,m_CompileOpcode.base);
TempReg1 = Section->MipsRegLo(m_CompileOpcode.base);
} else {
TempReg1 = Map_TempReg(Section,x86_Any,m_CompileOpcode.base,FALSE);
}
} else {
if (Section->IsMapped(m_CompileOpcode.base)) {
ProtectGPR(Section,m_CompileOpcode.base);
if (m_CompileOpcode.offset != 0) {
TempReg1 = Map_TempReg(Section,x86_Any,-1,FALSE);
LeaSourceAndOffset(TempReg1,Section->MipsRegLo(m_CompileOpcode.base),(short)m_CompileOpcode.offset);
} else {
TempReg1 = Map_TempReg(Section,x86_Any,m_CompileOpcode.base,FALSE);
}
UnProtectGPR(Section,m_CompileOpcode.base);
} else {
TempReg1 = Map_TempReg(Section,x86_Any,m_CompileOpcode.base,FALSE);
if (m_CompileOpcode.immediate == 0) {
} else if (m_CompileOpcode.immediate == 1) {
IncX86reg(TempReg1);
} else if (m_CompileOpcode.immediate == 0xFFFF) {
DecX86reg(TempReg1);
} else {
AddConstToX86Reg(TempReg1,(short)m_CompileOpcode.immediate);
}
}
}
TempReg2 = Map_TempReg(Section,x86_Any,-1,FALSE);
if (UseTlb) {
MoveX86RegToX86Reg(TempReg1, TempReg2);
ShiftRightUnsignImmed(TempReg2,12);
MoveVariableDispToX86Reg(TLB_ReadMap,"TLB_ReadMap",TempReg2,TempReg2,4);
CompileReadTLBMiss(Section,TempReg1,TempReg2);
TempReg3 = Map_TempReg(Section,x86_Any,-1,FALSE);
MoveX86regPointerToX86reg(TempReg1, TempReg2,TempReg3);
} else {
AndConstToX86Reg(TempReg1,0x1FFFFFFF);
TempReg3 = Map_TempReg(Section,x86_Any,-1,FALSE);
MoveN64MemToX86reg(TempReg3,TempReg1);
}
sprintf(Name,"_FPRFloatLocation[%d]",m_CompileOpcode.ft);
MoveVariableToX86reg(&_FPRFloatLocation[m_CompileOpcode.ft],Name,TempReg2);
MoveX86regToX86Pointer(TempReg3,TempReg2);
}
void Compile_R4300i_LDC1 (CCodeSection * Section) {
DWORD TempReg1, TempReg2, TempReg3;
CPU_Message(" %X %s",Section->m_CompilePC,R4300iOpcodeName(m_CompileOpcode.Hex,Section->m_CompilePC));
CompileCop1Test(Section);
UnMap_FPR(Section,m_CompileOpcode.ft,FALSE);
if (Section->IsConst(m_CompileOpcode.base)) {
DWORD Address = Section->MipsRegLo(m_CompileOpcode.base) + (short)m_CompileOpcode.offset;
TempReg1 = Map_TempReg(Section,x86_Any,-1,FALSE);
_MMU->Compile_LW(Section, TempReg1,Address);
TempReg2 = Map_TempReg(Section,x86_Any,-1,FALSE);
sprintf(Name,"_FPRDoubleLocation[%d]",m_CompileOpcode.ft);
MoveVariableToX86reg(&_FPRDoubleLocation[m_CompileOpcode.ft],Name,TempReg2);
AddConstToX86Reg(TempReg2,4);
MoveX86regToX86Pointer(TempReg1,TempReg2);
_MMU->Compile_LW(Section,TempReg1,Address + 4);
sprintf(Name,"_FPRFloatLocation[%d]",m_CompileOpcode.ft);
MoveVariableToX86reg(&_FPRDoubleLocation[m_CompileOpcode.ft],Name,TempReg2);
MoveX86regToX86Pointer(TempReg1,TempReg2);
return;
}
if (Section->IsMapped(m_CompileOpcode.base) && m_CompileOpcode.offset == 0) {
if (UseTlb) {
ProtectGPR(Section,m_CompileOpcode.base);
TempReg1 = Section->MipsRegLo(m_CompileOpcode.base);
} else {
TempReg1 = Map_TempReg(Section,x86_Any,m_CompileOpcode.base,FALSE);
}
} else {
if (Section->IsMapped(m_CompileOpcode.base)) {
ProtectGPR(Section,m_CompileOpcode.base);
if (m_CompileOpcode.offset != 0) {
TempReg1 = Map_TempReg(Section,x86_Any,-1,FALSE);
LeaSourceAndOffset(TempReg1,Section->MipsRegLo(m_CompileOpcode.base),(short)m_CompileOpcode.offset);
} else {
TempReg1 = Map_TempReg(Section,x86_Any,m_CompileOpcode.base,FALSE);
}
} else {
TempReg1 = Map_TempReg(Section,x86_Any,m_CompileOpcode.base,FALSE);
if (m_CompileOpcode.immediate == 0) {
} else if (m_CompileOpcode.immediate == 1) {
IncX86reg(TempReg1);
} else if (m_CompileOpcode.immediate == 0xFFFF) {
DecX86reg(TempReg1);
} else {
AddConstToX86Reg(TempReg1,(short)m_CompileOpcode.immediate);
}
}
}
TempReg2 = Map_TempReg(Section,x86_Any,-1,FALSE);
if (UseTlb) {
MoveX86RegToX86Reg(TempReg1, TempReg2);
ShiftRightUnsignImmed(TempReg2,12);
MoveVariableDispToX86Reg(TLB_ReadMap,"TLB_ReadMap",TempReg2,TempReg2,4);
CompileReadTLBMiss(Section,TempReg1,TempReg2);
TempReg3 = Map_TempReg(Section,x86_Any,-1,FALSE);
MoveX86regPointerToX86reg(TempReg1, TempReg2,TempReg3);
Push(TempReg2);
sprintf(Name,"_FPRFloatLocation[%d]",m_CompileOpcode.ft);
MoveVariableToX86reg(&_FPRDoubleLocation[m_CompileOpcode.ft],Name,TempReg2);
AddConstToX86Reg(TempReg2,4);
MoveX86regToX86Pointer(TempReg3,TempReg2);
Pop(TempReg2);
MoveX86regPointerToX86regDisp8(TempReg1, TempReg2,TempReg3,4);
sprintf(Name,"_FPRFloatLocation[%d]",m_CompileOpcode.ft);
MoveVariableToX86reg(&_FPRDoubleLocation[m_CompileOpcode.ft],Name,TempReg2);
MoveX86regToX86Pointer(TempReg3,TempReg2);
} else {
AndConstToX86Reg(TempReg1,0x1FFFFFFF);
TempReg3 = Map_TempReg(Section,x86_Any,-1,FALSE);
MoveN64MemToX86reg(TempReg3,TempReg1);
sprintf(Name,"_FPRFloatLocation[%d]",m_CompileOpcode.ft);
MoveVariableToX86reg(&_FPRDoubleLocation[m_CompileOpcode.ft],Name,TempReg2);
AddConstToX86Reg(TempReg2,4);
MoveX86regToX86Pointer(TempReg3,TempReg2);
MoveN64MemDispToX86reg(TempReg3,TempReg1,4);
sprintf(Name,"_FPRFloatLocation[%d]",m_CompileOpcode.ft);
MoveVariableToX86reg(&_FPRDoubleLocation[m_CompileOpcode.ft],Name,TempReg2);
MoveX86regToX86Pointer(TempReg3,TempReg2);
}
}
void Compile_R4300i_SWC1 (CCodeSection * Section){
DWORD TempReg1, TempReg2, TempReg3;
CPU_Message(" %X %s",Section->m_CompilePC,R4300iOpcodeName(m_CompileOpcode.Hex,Section->m_CompilePC));
CompileCop1Test(Section);
if (Section->IsConst(m_CompileOpcode.base)) {
DWORD Address = Section->MipsRegLo(m_CompileOpcode.base) + (short)m_CompileOpcode.offset;
UnMap_FPR(Section,m_CompileOpcode.ft,TRUE);
TempReg1 = Map_TempReg(Section,x86_Any,-1,FALSE);
sprintf(Name,"_FPRFloatLocation[%d]",m_CompileOpcode.ft);
MoveVariableToX86reg(&_FPRFloatLocation[m_CompileOpcode.ft],Name,TempReg1);
MoveX86PointerToX86reg(TempReg1,TempReg1);
_MMU->Compile_SW_Register(Section,TempReg1, Address);
return;
}
if (Section->IsMapped(m_CompileOpcode.base)) {
ProtectGPR(Section,m_CompileOpcode.base);
if (m_CompileOpcode.offset != 0) {
TempReg1 = Map_TempReg(Section,x86_Any,-1,FALSE);
LeaSourceAndOffset(TempReg1,Section->MipsRegLo(m_CompileOpcode.base),(short)m_CompileOpcode.offset);
} else {
TempReg1 = Map_TempReg(Section,x86_Any,m_CompileOpcode.base,FALSE);
}
} else {
TempReg1 = Map_TempReg(Section,x86_Any,m_CompileOpcode.base,FALSE);
if (m_CompileOpcode.immediate == 0) {
} else if (m_CompileOpcode.immediate == 1) {
IncX86reg(TempReg1);
} else if (m_CompileOpcode.immediate == 0xFFFF) {
DecX86reg(TempReg1);
} else {
AddConstToX86Reg(TempReg1,(short)m_CompileOpcode.immediate);
}
}
if (UseTlb) {
TempReg2 = Map_TempReg(Section,x86_Any,-1,FALSE);
MoveX86RegToX86Reg(TempReg1, TempReg2);
ShiftRightUnsignImmed(TempReg2,12);
MoveVariableDispToX86Reg(TLB_WriteMap,"TLB_WriteMap",TempReg2,TempReg2,4);
//For tlb miss
//0041C522 85 C0 test eax,eax
//0041C524 75 01 jne 0041C527
UnMap_FPR(Section,m_CompileOpcode.ft,TRUE);
TempReg3 = Map_TempReg(Section,x86_Any,-1,FALSE);
sprintf(Name,"_FPRFloatLocation[%d]",m_CompileOpcode.ft);
MoveVariableToX86reg(&_FPRFloatLocation[m_CompileOpcode.ft],Name,TempReg3);
MoveX86PointerToX86reg(TempReg3,TempReg3);
MoveX86regToX86regPointer(TempReg3,TempReg1, TempReg2);
} else {
TempReg2 = Map_TempReg(Section,x86_Any,-1,FALSE);
UnMap_FPR(Section,m_CompileOpcode.ft,TRUE);
sprintf(Name,"_FPRFloatLocation[%d]",m_CompileOpcode.ft);
MoveVariableToX86reg(&_FPRFloatLocation[m_CompileOpcode.ft],Name,TempReg2);
MoveX86PointerToX86reg(TempReg2,TempReg2);
AndConstToX86Reg(TempReg1,0x1FFFFFFF);
MoveX86regToN64Mem(TempReg2, TempReg1);
}
}
void Compile_R4300i_SDC1 (CCodeSection * Section){
DWORD TempReg1, TempReg2, TempReg3;
CPU_Message(" %X %s",Section->m_CompilePC,R4300iOpcodeName(m_CompileOpcode.Hex,Section->m_CompilePC));
CompileCop1Test(Section);
if (Section->IsConst(m_CompileOpcode.base)) {
DWORD Address = Section->MipsRegLo(m_CompileOpcode.base) + (short)m_CompileOpcode.offset;
TempReg1 = Map_TempReg(Section,x86_Any,-1,FALSE);
sprintf(Name,"_FPRDoubleLocation[%d]",m_CompileOpcode.ft);
MoveVariableToX86reg((BYTE *)&_FPRDoubleLocation[m_CompileOpcode.ft],Name,TempReg1);
AddConstToX86Reg(TempReg1,4);
MoveX86PointerToX86reg(TempReg1,TempReg1);
_MMU->Compile_SW_Register(Section,TempReg1, Address);
sprintf(Name,"_FPRDoubleLocation[%d]",m_CompileOpcode.ft);
MoveVariableToX86reg(&_FPRDoubleLocation[m_CompileOpcode.ft],Name,TempReg1);
MoveX86PointerToX86reg(TempReg1,TempReg1);
_MMU->Compile_SW_Register(Section,TempReg1, Address + 4);
return;
}
if (Section->IsMapped(m_CompileOpcode.base)) {
ProtectGPR(Section,m_CompileOpcode.base);
if (m_CompileOpcode.offset != 0) {
TempReg1 = Map_TempReg(Section,x86_Any,-1,FALSE);
LeaSourceAndOffset(TempReg1,Section->MipsRegLo(m_CompileOpcode.base),(short)m_CompileOpcode.offset);
} else {
TempReg1 = Map_TempReg(Section,x86_Any,m_CompileOpcode.base,FALSE);
}
} else {
TempReg1 = Map_TempReg(Section,x86_Any,m_CompileOpcode.base,FALSE);
if (m_CompileOpcode.immediate == 0) {
} else if (m_CompileOpcode.immediate == 1) {
IncX86reg(TempReg1);
} else if (m_CompileOpcode.immediate == 0xFFFF) {
DecX86reg(TempReg1);
} else {
AddConstToX86Reg(TempReg1,(short)m_CompileOpcode.immediate);
}
}
if (UseTlb) {
TempReg2 = Map_TempReg(Section,x86_Any,-1,FALSE);
MoveX86RegToX86Reg(TempReg1, TempReg2);
ShiftRightUnsignImmed(TempReg2,12);
MoveVariableDispToX86Reg(TLB_WriteMap,"TLB_WriteMap",TempReg2,TempReg2,4);
//For tlb miss
//0041C522 85 C0 test eax,eax
//0041C524 75 01 jne 0041C527
TempReg3 = Map_TempReg(Section,x86_Any,-1,FALSE);
sprintf(Name,"_FPRDoubleLocation[%d]",m_CompileOpcode.ft);
MoveVariableToX86reg((BYTE *)&_FPRDoubleLocation[m_CompileOpcode.ft],Name,TempReg3);
AddConstToX86Reg(TempReg3,4);
MoveX86PointerToX86reg(TempReg3,TempReg3);
MoveX86regToX86regPointer(TempReg3,TempReg1, TempReg2);
AddConstToX86Reg(TempReg1,4);
sprintf(Name,"_FPRDoubleLocation[%d]",m_CompileOpcode.ft);
MoveVariableToX86reg((BYTE *)&_FPRDoubleLocation[m_CompileOpcode.ft],Name,TempReg3);
MoveX86PointerToX86reg(TempReg3,TempReg3);
MoveX86regToX86regPointer(TempReg3,TempReg1, TempReg2);
} else {
AndConstToX86Reg(TempReg1,0x1FFFFFFF);
TempReg3 = Map_TempReg(Section,x86_Any,-1,FALSE);
sprintf(Name,"_FPRDoubleLocation[%d]",m_CompileOpcode.ft);
MoveVariableToX86reg((BYTE *)&_FPRDoubleLocation[m_CompileOpcode.ft],Name,TempReg3);
AddConstToX86Reg(TempReg3,4);
MoveX86PointerToX86reg(TempReg3,TempReg3);
MoveX86regToN64Mem(TempReg3, TempReg1);
sprintf(Name,"_FPRDoubleLocation[%d]",m_CompileOpcode.ft);
MoveVariableToX86reg((BYTE *)&_FPRDoubleLocation[m_CompileOpcode.ft],Name,TempReg3);
MoveX86PointerToX86reg(TempReg3,TempReg3);
MoveX86regToN64MemDisp(TempReg3, TempReg1,4);
}
}
/************************** COP1 functions **************************/
void Compile_R4300i_COP1_MF (CCodeSection * Section) {
DWORD TempReg;
CPU_Message(" %X %s",Section->m_CompilePC,R4300iOpcodeName(m_CompileOpcode.Hex,Section->m_CompilePC));
CompileCop1Test(Section);
UnMap_FPR(Section,m_CompileOpcode.fs,TRUE);
Map_GPR_32bit(Section,m_CompileOpcode.rt, TRUE, -1);
TempReg = Map_TempReg(Section,x86_Any,-1,FALSE);
sprintf(Name,"_FPRFloatLocation[%d]",m_CompileOpcode.fs);
MoveVariableToX86reg((BYTE *)&_FPRFloatLocation[m_CompileOpcode.fs],Name,TempReg);
MoveX86PointerToX86reg(Section->MipsRegLo(m_CompileOpcode.rt),TempReg);
}
void Compile_R4300i_COP1_DMF (CCodeSection * Section) {
DWORD TempReg;
CPU_Message(" %X %s",Section->m_CompilePC,R4300iOpcodeName(m_CompileOpcode.Hex,Section->m_CompilePC));
CompileCop1Test(Section);
UnMap_FPR(Section,m_CompileOpcode.fs,TRUE);
Map_GPR_64bit(Section,m_CompileOpcode.rt, -1);
TempReg = Map_TempReg(Section,x86_Any,-1,FALSE);
sprintf(Name,"_FPRDoubleLocation[%d]",m_CompileOpcode.fs);
MoveVariableToX86reg((BYTE *)&_FPRDoubleLocation[m_CompileOpcode.fs],Name,TempReg);
AddConstToX86Reg(TempReg,4);
MoveX86PointerToX86reg(Section->MipsRegHi(m_CompileOpcode.rt),TempReg);
sprintf(Name,"_FPRDoubleLocation[%d]",m_CompileOpcode.fs);
MoveVariableToX86reg((BYTE *)&_FPRDoubleLocation[m_CompileOpcode.fs],Name,TempReg);
MoveX86PointerToX86reg(Section->MipsRegLo(m_CompileOpcode.rt),TempReg);
}
void Compile_R4300i_COP1_CF(CCodeSection * Section) {
CPU_Message(" %X %s",Section->m_CompilePC,R4300iOpcodeName(m_CompileOpcode.Hex,Section->m_CompilePC));
CompileCop1Test(Section);
if (m_CompileOpcode.fs != 31 && m_CompileOpcode.fs != 0) { Compile_R4300i_UnknownOpcode (Section); return; }
Map_GPR_32bit(Section,m_CompileOpcode.rt,TRUE,-1);
MoveVariableToX86reg(&_FPCR[m_CompileOpcode.fs],CRegName::FPR_Ctrl[m_CompileOpcode.fs],Section->MipsRegLo(m_CompileOpcode.rt));
}
void Compile_R4300i_COP1_MT( CCodeSection * Section) {
DWORD TempReg;
CPU_Message(" %X %s",Section->m_CompilePC,R4300iOpcodeName(m_CompileOpcode.Hex,Section->m_CompilePC));
CompileCop1Test(Section);
if ((m_CompileOpcode.fs & 1) != 0) {
if (RegInStack(Section,m_CompileOpcode.fs-1,CRegInfo::FPU_Double) || RegInStack(Section,m_CompileOpcode.fs-1,CRegInfo::FPU_Qword)) {
UnMap_FPR(Section,m_CompileOpcode.fs-1,TRUE);
}
}
UnMap_FPR(Section,m_CompileOpcode.fs,TRUE);
TempReg = Map_TempReg(Section,x86_Any,-1,FALSE);
sprintf(Name,"_FPRFloatLocation[%d]",m_CompileOpcode.fs);
MoveVariableToX86reg((BYTE *)&_FPRFloatLocation[m_CompileOpcode.fs],Name,TempReg);
if (Section->IsConst(m_CompileOpcode.rt)) {
MoveConstToX86Pointer(Section->MipsRegLo(m_CompileOpcode.rt),TempReg);
} else if (Section->IsMapped(m_CompileOpcode.rt)) {
MoveX86regToX86Pointer(Section->MipsRegLo(m_CompileOpcode.rt),TempReg);
} else {
MoveX86regToX86Pointer(Map_TempReg(Section,x86_Any, m_CompileOpcode.rt, FALSE),TempReg);
}
}
void Compile_R4300i_COP1_DMT( CCodeSection * Section) {
DWORD TempReg;
CPU_Message(" %X %s",Section->m_CompilePC,R4300iOpcodeName(m_CompileOpcode.Hex,Section->m_CompilePC));
CompileCop1Test(Section);
if ((m_CompileOpcode.fs & 1) == 0) {
if (RegInStack(Section,m_CompileOpcode.fs+1,CRegInfo::FPU_Float) || RegInStack(Section,m_CompileOpcode.fs+1,CRegInfo::FPU_Dword)) {
UnMap_FPR(Section,m_CompileOpcode.fs+1,TRUE);
}
}
UnMap_FPR(Section,m_CompileOpcode.fs,TRUE);
TempReg = Map_TempReg(Section,x86_Any,-1,FALSE);
sprintf(Name,"_FPRDoubleLocation[%d]",m_CompileOpcode.fs);
MoveVariableToX86reg((BYTE *)&_FPRDoubleLocation[m_CompileOpcode.fs],Name,TempReg);
if (Section->IsConst(m_CompileOpcode.rt)) {
MoveConstToX86Pointer(Section->MipsRegLo(m_CompileOpcode.rt),TempReg);
AddConstToX86Reg(TempReg,4);
if (Section->Is64Bit(m_CompileOpcode.rt)) {
MoveConstToX86Pointer(Section->MipsRegHi(m_CompileOpcode.rt),TempReg);
} else {
MoveConstToX86Pointer(Section->MipsRegLo_S(m_CompileOpcode.rt) >> 31,TempReg);
}
} else if (Section->IsMapped(m_CompileOpcode.rt)) {
MoveX86regToX86Pointer(Section->MipsRegLo(m_CompileOpcode.rt),TempReg);
AddConstToX86Reg(TempReg,4);
if (Section->Is64Bit(m_CompileOpcode.rt)) {
MoveX86regToX86Pointer(Section->MipsRegHi(m_CompileOpcode.rt),TempReg);
} else {
MoveX86regToX86Pointer(Map_TempReg(Section,x86_Any, m_CompileOpcode.rt, TRUE),TempReg);
}
} else {
int x86Reg = Map_TempReg(Section,x86_Any, m_CompileOpcode.rt, FALSE);
MoveX86regToX86Pointer(x86Reg,TempReg);
AddConstToX86Reg(TempReg,4);
MoveX86regToX86Pointer(Map_TempReg(Section,x86Reg, m_CompileOpcode.rt, TRUE),TempReg);
}
}
void Compile_R4300i_COP1_CT(CCodeSection * Section) {
CPU_Message(" %X %s",Section->m_CompilePC,R4300iOpcodeName(m_CompileOpcode.Hex,Section->m_CompilePC));
CompileCop1Test(Section);
if (m_CompileOpcode.fs != 31) { Compile_R4300i_UnknownOpcode (Section); return; }
if (Section->IsConst(m_CompileOpcode.rt)) {
MoveConstToVariable(Section->MipsRegLo(m_CompileOpcode.rt),&_FPCR[m_CompileOpcode.fs],CRegName::FPR_Ctrl[m_CompileOpcode.fs]);
} else if (Section->IsMapped(m_CompileOpcode.rt)) {
MoveX86regToVariable(Section->MipsRegLo(m_CompileOpcode.rt),&_FPCR[m_CompileOpcode.fs],CRegName::FPR_Ctrl[m_CompileOpcode.fs]);
} else {
MoveX86regToVariable(Map_TempReg(Section,x86_Any,m_CompileOpcode.rt,FALSE),&_FPCR[m_CompileOpcode.fs],CRegName::FPR_Ctrl[m_CompileOpcode.fs]);
}
Pushad();
Call_Direct(ChangeDefaultRoundingModel, "ChangeDefaultRoundingModel");
Popad();
Section->CurrentRoundingModel() = CRegInfo::RoundUnknown;
}
/************************** COP1: S functions ************************/
void Compile_R4300i_COP1_S_ADD (CCodeSection * Section) {
DWORD Reg1 = m_CompileOpcode.ft == m_CompileOpcode.fd?m_CompileOpcode.ft:m_CompileOpcode.fs;
DWORD Reg2 = m_CompileOpcode.ft == m_CompileOpcode.fd?m_CompileOpcode.fs:m_CompileOpcode.ft;
CPU_Message(" %X %s",Section->m_CompilePC,R4300iOpcodeName(m_CompileOpcode.Hex,Section->m_CompilePC));
CompileCop1Test(Section);
FixRoundModel(Section,CRegInfo::RoundDefault);
Load_FPR_ToTop(Section,m_CompileOpcode.fd,Reg1, CRegInfo::FPU_Float);
if (RegInStack(Section,Reg2, CRegInfo::FPU_Float)) {
fpuAddReg(StackPosition(Section,Reg2));
} else {
DWORD TempReg;
UnMap_FPR(Section,Reg2,TRUE);
TempReg = Map_TempReg(Section,x86_Any,-1,FALSE);
sprintf(Name,"_FPRFloatLocation[%d]",Reg2);
MoveVariableToX86reg((BYTE *)&_FPRFloatLocation[Reg2],Name,TempReg);
Load_FPR_ToTop(Section,m_CompileOpcode.fd,m_CompileOpcode.fd, CRegInfo::FPU_Float);
fpuAddDwordRegPointer(TempReg);
}
UnMap_FPR(Section,m_CompileOpcode.fd,TRUE);
}
void Compile_R4300i_COP1_S_SUB (CCodeSection * Section) {
DWORD Reg1 = m_CompileOpcode.ft == m_CompileOpcode.fd?m_CompileOpcode.ft:m_CompileOpcode.fs;
DWORD Reg2 = m_CompileOpcode.ft == m_CompileOpcode.fd?m_CompileOpcode.fs:m_CompileOpcode.ft;
DWORD TempReg;
CPU_Message(" %X %s",Section->m_CompilePC,R4300iOpcodeName(m_CompileOpcode.Hex,Section->m_CompilePC));
CompileCop1Test(Section);
FixRoundModel(Section,CRegInfo::RoundDefault);
if (m_CompileOpcode.fd == m_CompileOpcode.ft) {
UnMap_FPR(Section,m_CompileOpcode.fd,TRUE);
Load_FPR_ToTop(Section,m_CompileOpcode.fd,m_CompileOpcode.fs,CRegInfo::FPU_Float);
TempReg = Map_TempReg(Section,x86_Any,-1,FALSE);
sprintf(Name,"_FPRFloatLocation[%d]",m_CompileOpcode.ft);
MoveVariableToX86reg((BYTE *)&_FPRFloatLocation[m_CompileOpcode.ft],Name,TempReg);
fpuSubDwordRegPointer(TempReg);
} else {
Load_FPR_ToTop(Section,m_CompileOpcode.fd,Reg1, CRegInfo::FPU_Float);
if (RegInStack(Section,Reg2, CRegInfo::FPU_Float)) {
fpuSubReg(StackPosition(Section,Reg2));
} else {
UnMap_FPR(Section,Reg2,TRUE);
Load_FPR_ToTop(Section,m_CompileOpcode.fd,m_CompileOpcode.fd, CRegInfo::FPU_Float);
TempReg = Map_TempReg(Section,x86_Any,-1,FALSE);
sprintf(Name,"_FPRFloatLocation[%d]",Reg2);
MoveVariableToX86reg((BYTE *)&_FPRFloatLocation[Reg2],Name,TempReg);
fpuSubDwordRegPointer(TempReg);
}
}
UnMap_FPR(Section,m_CompileOpcode.fd,TRUE);
}
void Compile_R4300i_COP1_S_MUL (CCodeSection * Section) {
DWORD Reg1 = m_CompileOpcode.ft == m_CompileOpcode.fd?m_CompileOpcode.ft:m_CompileOpcode.fs;
DWORD Reg2 = m_CompileOpcode.ft == m_CompileOpcode.fd?m_CompileOpcode.fs:m_CompileOpcode.ft;
DWORD TempReg;
CPU_Message(" %X %s",Section->m_CompilePC,R4300iOpcodeName(m_CompileOpcode.Hex,Section->m_CompilePC));
CompileCop1Test(Section);
FixRoundModel(Section,CRegInfo::RoundDefault);
Load_FPR_ToTop(Section,m_CompileOpcode.fd,Reg1, CRegInfo::FPU_Float);
if (RegInStack(Section,Reg2, CRegInfo::FPU_Float)) {
fpuMulReg(StackPosition(Section,Reg2));
} else {
UnMap_FPR(Section,Reg2,TRUE);
Load_FPR_ToTop(Section,m_CompileOpcode.fd,m_CompileOpcode.fd, CRegInfo::FPU_Float);
TempReg = Map_TempReg(Section,x86_Any,-1,FALSE);
sprintf(Name,"_FPRFloatLocation[%d]",Reg2);
MoveVariableToX86reg((BYTE *)&_FPRFloatLocation[Reg2],Name,TempReg);
fpuMulDwordRegPointer(TempReg);
}
UnMap_FPR(Section,m_CompileOpcode.fd,TRUE);
}
void Compile_R4300i_COP1_S_DIV (CCodeSection * Section) {
DWORD Reg1 = m_CompileOpcode.ft == m_CompileOpcode.fd?m_CompileOpcode.ft:m_CompileOpcode.fs;
DWORD Reg2 = m_CompileOpcode.ft == m_CompileOpcode.fd?m_CompileOpcode.fs:m_CompileOpcode.ft;
DWORD TempReg;
CPU_Message(" %X %s",Section->m_CompilePC,R4300iOpcodeName(m_CompileOpcode.Hex,Section->m_CompilePC));
CompileCop1Test(Section);
FixRoundModel(Section,CRegInfo::RoundDefault);
if (m_CompileOpcode.fd == m_CompileOpcode.ft) {
UnMap_FPR(Section,m_CompileOpcode.fd,TRUE);
Load_FPR_ToTop(Section,m_CompileOpcode.fd,m_CompileOpcode.fs,CRegInfo::FPU_Float);
TempReg = Map_TempReg(Section,x86_Any,-1,FALSE);
sprintf(Name,"_FPRFloatLocation[%d]",m_CompileOpcode.ft);
MoveVariableToX86reg((BYTE *)&_FPRFloatLocation[m_CompileOpcode.ft],Name,TempReg);
fpuDivDwordRegPointer(TempReg);
} else {
Load_FPR_ToTop(Section,m_CompileOpcode.fd,Reg1, CRegInfo::FPU_Float);
if (RegInStack(Section,Reg2, CRegInfo::FPU_Float)) {
fpuDivReg(StackPosition(Section,Reg2));
} else {
UnMap_FPR(Section,Reg2,TRUE);
Load_FPR_ToTop(Section,m_CompileOpcode.fd,m_CompileOpcode.fd, CRegInfo::FPU_Float);
TempReg = Map_TempReg(Section,x86_Any,-1,FALSE);
sprintf(Name,"_FPRFloatLocation[%d]",Reg2);
MoveVariableToX86reg((BYTE *)&_FPRFloatLocation[Reg2],Name,TempReg);
fpuDivDwordRegPointer(TempReg);
}
}
UnMap_FPR(Section,m_CompileOpcode.fd,TRUE);
}
void Compile_R4300i_COP1_S_ABS (CCodeSection * Section) {
CPU_Message(" %X %s",Section->m_CompilePC,R4300iOpcodeName(m_CompileOpcode.Hex,Section->m_CompilePC));
CompileCop1Test(Section);
FixRoundModel(Section,CRegInfo::RoundDefault);
Load_FPR_ToTop(Section,m_CompileOpcode.fd,m_CompileOpcode.fs,CRegInfo::FPU_Float);
fpuAbs();
UnMap_FPR(Section,m_CompileOpcode.fd,TRUE);
}
void Compile_R4300i_COP1_S_NEG (CCodeSection * Section) {
CPU_Message(" %X %s",Section->m_CompilePC,R4300iOpcodeName(m_CompileOpcode.Hex,Section->m_CompilePC));
CompileCop1Test(Section);
FixRoundModel(Section,CRegInfo::RoundDefault);
Load_FPR_ToTop(Section,m_CompileOpcode.fd,m_CompileOpcode.fs,CRegInfo::FPU_Float);
fpuNeg();
UnMap_FPR(Section,m_CompileOpcode.fd,TRUE);
}
void Compile_R4300i_COP1_S_SQRT (CCodeSection * Section) {
CPU_Message(" %X %s",Section->m_CompilePC,R4300iOpcodeName(m_CompileOpcode.Hex,Section->m_CompilePC));
CompileCop1Test(Section);
FixRoundModel(Section,CRegInfo::RoundDefault);
Load_FPR_ToTop(Section,m_CompileOpcode.fd,m_CompileOpcode.fs,CRegInfo::FPU_Float);
fpuSqrt();
UnMap_FPR(Section,m_CompileOpcode.fd,TRUE);
}
void Compile_R4300i_COP1_S_MOV (CCodeSection * Section) {
CPU_Message(" %X %s",Section->m_CompilePC,R4300iOpcodeName(m_CompileOpcode.Hex,Section->m_CompilePC));
CompileCop1Test(Section);
FixRoundModel(Section,CRegInfo::RoundDefault);
Load_FPR_ToTop(Section,m_CompileOpcode.fd,m_CompileOpcode.fs,CRegInfo::FPU_Float);
}
void Compile_R4300i_COP1_S_TRUNC_L (CCodeSection * Section) {
CPU_Message(" %X %s",Section->m_CompilePC,R4300iOpcodeName(m_CompileOpcode.Hex,Section->m_CompilePC));
CompileCop1Test(Section);
if (m_CompileOpcode.fd != m_CompileOpcode.fs || !RegInStack(Section,m_CompileOpcode.fd,CRegInfo::FPU_Float)) {
Load_FPR_ToTop(Section,m_CompileOpcode.fd,m_CompileOpcode.fs,CRegInfo::FPU_Float);
}
ChangeFPURegFormat(Section,m_CompileOpcode.fd,CRegInfo::FPU_Float,CRegInfo::FPU_Qword,CRegInfo::RoundTruncate);
}
void Compile_R4300i_COP1_S_CEIL_L (CCodeSection * Section) { //added by Witten
CPU_Message(" %X %s",Section->m_CompilePC,R4300iOpcodeName(m_CompileOpcode.Hex,Section->m_CompilePC));
CompileCop1Test(Section);
if (m_CompileOpcode.fd != m_CompileOpcode.fs || !RegInStack(Section,m_CompileOpcode.fd,CRegInfo::FPU_Float)) {
Load_FPR_ToTop(Section,m_CompileOpcode.fd,m_CompileOpcode.fs,CRegInfo::FPU_Float);
}
ChangeFPURegFormat(Section,m_CompileOpcode.fd,CRegInfo::FPU_Float,CRegInfo::FPU_Qword,CRegInfo::RoundUp);
}
void Compile_R4300i_COP1_S_FLOOR_L (CCodeSection * Section) { //added by Witten
CPU_Message(" %X %s",Section->m_CompilePC,R4300iOpcodeName(m_CompileOpcode.Hex,Section->m_CompilePC));
CompileCop1Test(Section);
if (m_CompileOpcode.fd != m_CompileOpcode.fs || !RegInStack(Section,m_CompileOpcode.fd,CRegInfo::FPU_Float)) {
Load_FPR_ToTop(Section,m_CompileOpcode.fd,m_CompileOpcode.fs,CRegInfo::FPU_Float);
}
ChangeFPURegFormat(Section,m_CompileOpcode.fd,CRegInfo::FPU_Float,CRegInfo::FPU_Qword,CRegInfo::RoundDown);
}
void Compile_R4300i_COP1_S_ROUND_W (CCodeSection * Section) {
CPU_Message(" %X %s",Section->m_CompilePC,R4300iOpcodeName(m_CompileOpcode.Hex,Section->m_CompilePC));
CompileCop1Test(Section);
if (m_CompileOpcode.fd != m_CompileOpcode.fs || !RegInStack(Section,m_CompileOpcode.fd,CRegInfo::FPU_Float)) {
Load_FPR_ToTop(Section,m_CompileOpcode.fd,m_CompileOpcode.fs,CRegInfo::FPU_Float);
}
ChangeFPURegFormat(Section,m_CompileOpcode.fd,CRegInfo::FPU_Float,CRegInfo::FPU_Dword,CRegInfo::RoundNearest);
}
void Compile_R4300i_COP1_S_TRUNC_W (CCodeSection * Section) {
CPU_Message(" %X %s",Section->m_CompilePC,R4300iOpcodeName(m_CompileOpcode.Hex,Section->m_CompilePC));
CompileCop1Test(Section);
if (m_CompileOpcode.fd != m_CompileOpcode.fs || !RegInStack(Section,m_CompileOpcode.fd,CRegInfo::FPU_Float)) {
Load_FPR_ToTop(Section,m_CompileOpcode.fd,m_CompileOpcode.fs,CRegInfo::FPU_Float);
}
ChangeFPURegFormat(Section,m_CompileOpcode.fd,CRegInfo::FPU_Float,CRegInfo::FPU_Dword,CRegInfo::RoundTruncate);
}
void Compile_R4300i_COP1_S_CEIL_W (CCodeSection * Section) { // added by Witten
CPU_Message(" %X %s",Section->m_CompilePC,R4300iOpcodeName(m_CompileOpcode.Hex,Section->m_CompilePC));
CompileCop1Test(Section);
if (m_CompileOpcode.fd != m_CompileOpcode.fs || !RegInStack(Section,m_CompileOpcode.fd,CRegInfo::FPU_Float)) {
Load_FPR_ToTop(Section,m_CompileOpcode.fd,m_CompileOpcode.fs,CRegInfo::FPU_Float);
}
ChangeFPURegFormat(Section,m_CompileOpcode.fd,CRegInfo::FPU_Float,CRegInfo::FPU_Dword,CRegInfo::RoundUp);
}
void Compile_R4300i_COP1_S_FLOOR_W (CCodeSection * Section) {
CPU_Message(" %X %s",Section->m_CompilePC,R4300iOpcodeName(m_CompileOpcode.Hex,Section->m_CompilePC));
CompileCop1Test(Section);
if (m_CompileOpcode.fd != m_CompileOpcode.fs || !RegInStack(Section,m_CompileOpcode.fd,CRegInfo::FPU_Float)) {
Load_FPR_ToTop(Section,m_CompileOpcode.fd,m_CompileOpcode.fs,CRegInfo::FPU_Float);
}
ChangeFPURegFormat(Section,m_CompileOpcode.fd,CRegInfo::FPU_Float,CRegInfo::FPU_Dword,CRegInfo::RoundDown);
}
void Compile_R4300i_COP1_S_CVT_D (CCodeSection * Section) {
CPU_Message(" %X %s",Section->m_CompilePC,R4300iOpcodeName(m_CompileOpcode.Hex,Section->m_CompilePC));
CompileCop1Test(Section);
if (m_CompileOpcode.fd != m_CompileOpcode.fs || !RegInStack(Section,m_CompileOpcode.fd,CRegInfo::FPU_Float)) {
Load_FPR_ToTop(Section,m_CompileOpcode.fd,m_CompileOpcode.fs,CRegInfo::FPU_Float);
}
ChangeFPURegFormat(Section,m_CompileOpcode.fd,CRegInfo::FPU_Float,CRegInfo::FPU_Double,CRegInfo::RoundDefault);
}
void Compile_R4300i_COP1_S_CVT_W (CCodeSection * Section) {
CPU_Message(" %X %s",Section->m_CompilePC,R4300iOpcodeName(m_CompileOpcode.Hex,Section->m_CompilePC));
CompileCop1Test(Section);
if (m_CompileOpcode.fd != m_CompileOpcode.fs || !RegInStack(Section,m_CompileOpcode.fd,CRegInfo::FPU_Float)) {
Load_FPR_ToTop(Section,m_CompileOpcode.fd,m_CompileOpcode.fs,CRegInfo::FPU_Float);
}
ChangeFPURegFormat(Section,m_CompileOpcode.fd,CRegInfo::FPU_Float,CRegInfo::FPU_Dword,CRegInfo::RoundDefault);
}
void Compile_R4300i_COP1_S_CVT_L (CCodeSection * Section) {
CPU_Message(" %X %s",Section->m_CompilePC,R4300iOpcodeName(m_CompileOpcode.Hex,Section->m_CompilePC));
CompileCop1Test(Section);
if (m_CompileOpcode.fd != m_CompileOpcode.fs || !RegInStack(Section,m_CompileOpcode.fd,CRegInfo::FPU_Float)) {
Load_FPR_ToTop(Section,m_CompileOpcode.fd,m_CompileOpcode.fs,CRegInfo::FPU_Float);
}
ChangeFPURegFormat(Section,m_CompileOpcode.fd,CRegInfo::FPU_Float,CRegInfo::FPU_Qword,CRegInfo::RoundDefault);
}
void Compile_R4300i_COP1_S_CMP (CCodeSection * Section) {
DWORD Reg1 = RegInStack(Section,m_CompileOpcode.ft, CRegInfo::FPU_Float)?m_CompileOpcode.ft:m_CompileOpcode.fs;
DWORD Reg2 = RegInStack(Section,m_CompileOpcode.ft, CRegInfo::FPU_Float)?m_CompileOpcode.fs:m_CompileOpcode.ft;
int x86reg, cmp = 0;
CPU_Message(" %X %s",Section->m_CompilePC,R4300iOpcodeName(m_CompileOpcode.Hex,Section->m_CompilePC));
CompileCop1Test(Section);
//if ((m_CompileOpcode.funct & 1) != 0) { Compile_R4300i_UnknownOpcode(Section); }
if ((m_CompileOpcode.funct & 2) != 0) { cmp |= 0x4000; }
if ((m_CompileOpcode.funct & 4) != 0) { cmp |= 0x0100; }
Load_FPR_ToTop(Section,Reg1,Reg1, CRegInfo::FPU_Float);
Map_TempReg(Section,x86_EAX, 0, FALSE);
if (RegInStack(Section,Reg2, CRegInfo::FPU_Float)) {
fpuComReg(StackPosition(Section,Reg2),FALSE);
} else {
DWORD TempReg;
UnMap_FPR(Section,Reg2,TRUE);
Load_FPR_ToTop(Section,Reg1,Reg1, CRegInfo::FPU_Float);
TempReg = Map_TempReg(Section,x86_Any,-1,FALSE);
sprintf(Name,"_FPRFloatLocation[%d]",Reg2);
MoveVariableToX86reg((BYTE *)&_FPRFloatLocation[Reg2],Name,TempReg);
fpuComDwordRegPointer(TempReg,FALSE);
}
_Notify->BreakPoint(__FILE__,__LINE__);
#ifdef tofix
AndConstToVariable(~FPCSR_C, &FSTATUS_REGISTER, "FSTATUS_REGISTER");
#endif
fpuStoreStatus();
x86reg = Map_TempReg(Section,x86_Any8Bit, 0, FALSE);
TestConstToX86Reg(cmp,x86_EAX);
Setnz(x86reg);
if (cmp != 0) {
TestConstToX86Reg(cmp,x86_EAX);
Setnz(x86reg);
if ((m_CompileOpcode.funct & 1) != 0) {
int x86reg2 = Map_TempReg(Section,x86_Any8Bit, 0, FALSE);
AndConstToX86Reg(x86_EAX, 0x4300);
CompConstToX86reg(x86_EAX, 0x4300);
Setz(x86reg2);
OrX86RegToX86Reg(x86reg, x86reg2);
}
} else if ((m_CompileOpcode.funct & 1) != 0) {
AndConstToX86Reg(x86_EAX, 0x4300);
CompConstToX86reg(x86_EAX, 0x4300);
Setz(x86reg);
}
ShiftLeftSignImmed(x86reg, 23);
OrX86RegToVariable(&_FPCR[31], "_FPCR[31]", x86reg);
}
/************************** COP1: D functions ************************/
void Compile_R4300i_COP1_D_ADD (CCodeSection * Section) {
DWORD Reg1 = m_CompileOpcode.ft == m_CompileOpcode.fd?m_CompileOpcode.ft:m_CompileOpcode.fs;
DWORD Reg2 = m_CompileOpcode.ft == m_CompileOpcode.fd?m_CompileOpcode.fs:m_CompileOpcode.ft;
CPU_Message(" %X %s",Section->m_CompilePC,R4300iOpcodeName(m_CompileOpcode.Hex,Section->m_CompilePC));
CompileCop1Test(Section);
Load_FPR_ToTop(Section,m_CompileOpcode.fd,Reg1, CRegInfo::FPU_Double);
if (RegInStack(Section,Reg2, CRegInfo::FPU_Double)) {
fpuAddReg(StackPosition(Section,Reg2));
} else {
DWORD TempReg;
UnMap_FPR(Section,Reg2,TRUE);
TempReg = Map_TempReg(Section,x86_Any,-1,FALSE);
sprintf(Name,"_FPRDoubleLocation[%d]",Reg2);
MoveVariableToX86reg((BYTE *)&_FPRDoubleLocation[Reg2],Name,TempReg);
Load_FPR_ToTop(Section,m_CompileOpcode.fd,m_CompileOpcode.fd, CRegInfo::FPU_Double);
fpuAddQwordRegPointer(TempReg);
}
}
void Compile_R4300i_COP1_D_SUB (CCodeSection * Section) {
DWORD Reg1 = m_CompileOpcode.ft == m_CompileOpcode.fd?m_CompileOpcode.ft:m_CompileOpcode.fs;
DWORD Reg2 = m_CompileOpcode.ft == m_CompileOpcode.fd?m_CompileOpcode.fs:m_CompileOpcode.ft;
DWORD TempReg;
CPU_Message(" %X %s",Section->m_CompilePC,R4300iOpcodeName(m_CompileOpcode.Hex,Section->m_CompilePC));
CompileCop1Test(Section);
if (m_CompileOpcode.fd == m_CompileOpcode.ft) {
UnMap_FPR(Section,m_CompileOpcode.fd,TRUE);
TempReg = Map_TempReg(Section,x86_Any,-1,FALSE);
sprintf(Name,"_FPRDoubleLocation[%d]",m_CompileOpcode.ft);
MoveVariableToX86reg((BYTE *)&_FPRDoubleLocation[m_CompileOpcode.ft],Name,TempReg);
Load_FPR_ToTop(Section,m_CompileOpcode.fd,m_CompileOpcode.fs,CRegInfo::FPU_Double);
fpuSubQwordRegPointer(TempReg);
} else {
Load_FPR_ToTop(Section,m_CompileOpcode.fd,Reg1, CRegInfo::FPU_Double);
if (RegInStack(Section,Reg2, CRegInfo::FPU_Double)) {
fpuSubReg(StackPosition(Section,Reg2));
} else {
UnMap_FPR(Section,Reg2,TRUE);
TempReg = Map_TempReg(Section,x86_Any,-1,FALSE);
sprintf(Name,"_FPRDoubleLocation[%d]",Reg2);
MoveVariableToX86reg((BYTE *)&_FPRDoubleLocation[Reg2],Name,TempReg);
Load_FPR_ToTop(Section,m_CompileOpcode.fd,m_CompileOpcode.fd, CRegInfo::FPU_Double);
fpuSubQwordRegPointer(TempReg);
}
}
}
void Compile_R4300i_COP1_D_MUL (CCodeSection * Section) {
DWORD Reg1 = m_CompileOpcode.ft == m_CompileOpcode.fd?m_CompileOpcode.ft:m_CompileOpcode.fs;
DWORD Reg2 = m_CompileOpcode.ft == m_CompileOpcode.fd?m_CompileOpcode.fs:m_CompileOpcode.ft;
DWORD TempReg;
CPU_Message(" %X %s",Section->m_CompilePC,R4300iOpcodeName(m_CompileOpcode.Hex,Section->m_CompilePC));
CompileCop1Test(Section);
FixRoundModel(Section,CRegInfo::RoundDefault);
Load_FPR_ToTop(Section,m_CompileOpcode.fd,Reg1, CRegInfo::FPU_Double);
if (RegInStack(Section,Reg2, CRegInfo::FPU_Double)) {
fpuMulReg(StackPosition(Section,Reg2));
} else {
UnMap_FPR(Section,Reg2,TRUE);
Load_FPR_ToTop(Section,m_CompileOpcode.fd,m_CompileOpcode.fd, CRegInfo::FPU_Double);
TempReg = Map_TempReg(Section,x86_Any,-1,FALSE);
sprintf(Name,"_FPRDoubleLocation[%d]",Reg2);
MoveVariableToX86reg((BYTE *)&_FPRDoubleLocation[Reg2],Name,TempReg);
fpuMulQwordRegPointer(TempReg);
}
}
void Compile_R4300i_COP1_D_DIV (CCodeSection * Section) {
DWORD Reg1 = m_CompileOpcode.ft == m_CompileOpcode.fd?m_CompileOpcode.ft:m_CompileOpcode.fs;
DWORD Reg2 = m_CompileOpcode.ft == m_CompileOpcode.fd?m_CompileOpcode.fs:m_CompileOpcode.ft;
DWORD TempReg;
CPU_Message(" %X %s",Section->m_CompilePC,R4300iOpcodeName(m_CompileOpcode.Hex,Section->m_CompilePC));
CompileCop1Test(Section);
if (m_CompileOpcode.fd == m_CompileOpcode.ft) {
UnMap_FPR(Section,m_CompileOpcode.fd,TRUE);
TempReg = Map_TempReg(Section,x86_Any,-1,FALSE);
sprintf(Name,"_FPRDoubleLocation[%d]",m_CompileOpcode.ft);
MoveVariableToX86reg((BYTE *)&_FPRDoubleLocation[m_CompileOpcode.ft],Name,TempReg);
Load_FPR_ToTop(Section,m_CompileOpcode.fd,m_CompileOpcode.fs,CRegInfo::FPU_Double);
fpuDivQwordRegPointer(TempReg);
} else {
Load_FPR_ToTop(Section,m_CompileOpcode.fd,Reg1, CRegInfo::FPU_Double);
if (RegInStack(Section,Reg2, CRegInfo::FPU_Double)) {
fpuDivReg(StackPosition(Section,Reg2));
} else {
UnMap_FPR(Section,Reg2,TRUE);
TempReg = Map_TempReg(Section,x86_Any,-1,FALSE);
sprintf(Name,"_FPRDoubleLocation[%d]",Reg2);
MoveVariableToX86reg((BYTE *)&_FPRDoubleLocation[Reg2],Name,TempReg);
Load_FPR_ToTop(Section,m_CompileOpcode.fd,m_CompileOpcode.fd, CRegInfo::FPU_Double);
fpuDivQwordRegPointer(TempReg);
}
}
}
void Compile_R4300i_COP1_D_ABS (CCodeSection * Section) {
CPU_Message(" %X %s",Section->m_CompilePC,R4300iOpcodeName(m_CompileOpcode.Hex,Section->m_CompilePC));
Load_FPR_ToTop(Section,m_CompileOpcode.fd,m_CompileOpcode.fs,CRegInfo::FPU_Double);
fpuAbs();
}
void Compile_R4300i_COP1_D_NEG (CCodeSection * Section) {
CPU_Message(" %X %s",Section->m_CompilePC,R4300iOpcodeName(m_CompileOpcode.Hex,Section->m_CompilePC));
Load_FPR_ToTop(Section,m_CompileOpcode.fd,m_CompileOpcode.fs,CRegInfo::FPU_Double);
fpuNeg();
}
void Compile_R4300i_COP1_D_SQRT (CCodeSection * Section) {
CPU_Message(" %X %s",Section->m_CompilePC,R4300iOpcodeName(m_CompileOpcode.Hex,Section->m_CompilePC));
Load_FPR_ToTop(Section,m_CompileOpcode.fd,m_CompileOpcode.fs,CRegInfo::FPU_Double);
fpuSqrt();
}
void Compile_R4300i_COP1_D_MOV (CCodeSection * Section) {
CPU_Message(" %X %s",Section->m_CompilePC,R4300iOpcodeName(m_CompileOpcode.Hex,Section->m_CompilePC));
Load_FPR_ToTop(Section,m_CompileOpcode.fd,m_CompileOpcode.fs,CRegInfo::FPU_Double);
}
void Compile_R4300i_COP1_D_TRUNC_L (CCodeSection * Section) { //added by Witten
CPU_Message(" %X %s",Section->m_CompilePC,R4300iOpcodeName(m_CompileOpcode.Hex,Section->m_CompilePC));
CompileCop1Test(Section);
if (RegInStack(Section,m_CompileOpcode.fs,CRegInfo::FPU_Double) || RegInStack(Section,m_CompileOpcode.fs,CRegInfo::FPU_Qword)) {
UnMap_FPR(Section,m_CompileOpcode.fs,TRUE);
}
if (m_CompileOpcode.fd != m_CompileOpcode.fs || !RegInStack(Section,m_CompileOpcode.fd,CRegInfo::FPU_Double)) {
Load_FPR_ToTop(Section,m_CompileOpcode.fd,m_CompileOpcode.fs,CRegInfo::FPU_Double);
}
ChangeFPURegFormat(Section,m_CompileOpcode.fd,CRegInfo::FPU_Double,CRegInfo::FPU_Qword,CRegInfo::RoundTruncate);
}
void Compile_R4300i_COP1_D_CEIL_L (CCodeSection * Section) { //added by Witten
CPU_Message(" %X %s",Section->m_CompilePC,R4300iOpcodeName(m_CompileOpcode.Hex,Section->m_CompilePC));
CompileCop1Test(Section);
if (RegInStack(Section,m_CompileOpcode.fs,CRegInfo::FPU_Double) || RegInStack(Section,m_CompileOpcode.fs,CRegInfo::FPU_Qword)) {
UnMap_FPR(Section,m_CompileOpcode.fs,TRUE);
}
if (m_CompileOpcode.fd != m_CompileOpcode.fs || !RegInStack(Section,m_CompileOpcode.fd,CRegInfo::FPU_Double)) {
Load_FPR_ToTop(Section,m_CompileOpcode.fd,m_CompileOpcode.fs,CRegInfo::FPU_Double);
}
ChangeFPURegFormat(Section,m_CompileOpcode.fd,CRegInfo::FPU_Double,CRegInfo::FPU_Qword,CRegInfo::RoundUp);
}
void Compile_R4300i_COP1_D_FLOOR_L (CCodeSection * Section) { //added by Witten
CPU_Message(" %X %s",Section->m_CompilePC,R4300iOpcodeName(m_CompileOpcode.Hex,Section->m_CompilePC));
CompileCop1Test(Section);
if (RegInStack(Section,m_CompileOpcode.fs,CRegInfo::FPU_Double) || RegInStack(Section,m_CompileOpcode.fs,CRegInfo::FPU_Qword)) {
UnMap_FPR(Section,m_CompileOpcode.fs,TRUE);
}
if (m_CompileOpcode.fd != m_CompileOpcode.fs || !RegInStack(Section,m_CompileOpcode.fd,CRegInfo::FPU_Double)) {
Load_FPR_ToTop(Section,m_CompileOpcode.fd,m_CompileOpcode.fs,CRegInfo::FPU_Double);
}
ChangeFPURegFormat(Section,m_CompileOpcode.fd,CRegInfo::FPU_Double,CRegInfo::FPU_Qword,CRegInfo::RoundDown);
}
void Compile_R4300i_COP1_D_ROUND_W (CCodeSection * Section) {
CPU_Message(" %X %s",Section->m_CompilePC,R4300iOpcodeName(m_CompileOpcode.Hex,Section->m_CompilePC));
CompileCop1Test(Section);
if (RegInStack(Section,m_CompileOpcode.fs,CRegInfo::FPU_Double) || RegInStack(Section,m_CompileOpcode.fs,CRegInfo::FPU_Qword)) {
UnMap_FPR(Section,m_CompileOpcode.fs,TRUE);
}
if (m_CompileOpcode.fd != m_CompileOpcode.fs || !RegInStack(Section,m_CompileOpcode.fd,CRegInfo::FPU_Double)) {
Load_FPR_ToTop(Section,m_CompileOpcode.fd,m_CompileOpcode.fs,CRegInfo::FPU_Double);
}
ChangeFPURegFormat(Section,m_CompileOpcode.fd,CRegInfo::FPU_Double,CRegInfo::FPU_Dword,CRegInfo::RoundNearest);
}
void Compile_R4300i_COP1_D_TRUNC_W (CCodeSection * Section) {
CPU_Message(" %X %s",Section->m_CompilePC,R4300iOpcodeName(m_CompileOpcode.Hex,Section->m_CompilePC));
CompileCop1Test(Section);
if (RegInStack(Section,m_CompileOpcode.fs,CRegInfo::FPU_Double) || RegInStack(Section,m_CompileOpcode.fs,CRegInfo::FPU_Qword)) {
UnMap_FPR(Section,m_CompileOpcode.fs,TRUE);
}
if (m_CompileOpcode.fd != m_CompileOpcode.fs || !RegInStack(Section,m_CompileOpcode.fd,CRegInfo::FPU_Double)) {
Load_FPR_ToTop(Section,m_CompileOpcode.fd,m_CompileOpcode.fs,CRegInfo::FPU_Double);
}
ChangeFPURegFormat(Section,m_CompileOpcode.fd,CRegInfo::FPU_Double,CRegInfo::FPU_Dword,CRegInfo::RoundTruncate);
}
void Compile_R4300i_COP1_D_CEIL_W (CCodeSection * Section) { // added by Witten
CPU_Message(" %X %s",Section->m_CompilePC,R4300iOpcodeName(m_CompileOpcode.Hex,Section->m_CompilePC));
CompileCop1Test(Section);
if (RegInStack(Section,m_CompileOpcode.fs,CRegInfo::FPU_Double) || RegInStack(Section,m_CompileOpcode.fs,CRegInfo::FPU_Qword)) {
UnMap_FPR(Section,m_CompileOpcode.fs,TRUE);
}
if (m_CompileOpcode.fd != m_CompileOpcode.fs || !RegInStack(Section,m_CompileOpcode.fd,CRegInfo::FPU_Double)) {
Load_FPR_ToTop(Section,m_CompileOpcode.fd,m_CompileOpcode.fs,CRegInfo::FPU_Double);
}
ChangeFPURegFormat(Section,m_CompileOpcode.fd,CRegInfo::FPU_Double,CRegInfo::FPU_Dword,CRegInfo::RoundUp);
}
void Compile_R4300i_COP1_D_FLOOR_W (CCodeSection * Section) { //added by Witten
CPU_Message(" %X %s",Section->m_CompilePC,R4300iOpcodeName(m_CompileOpcode.Hex,Section->m_CompilePC));
CompileCop1Test(Section);
if (RegInStack(Section,m_CompileOpcode.fs,CRegInfo::FPU_Double) || RegInStack(Section,m_CompileOpcode.fs,CRegInfo::FPU_Qword)) {
UnMap_FPR(Section,m_CompileOpcode.fs,TRUE);
}
if (m_CompileOpcode.fd != m_CompileOpcode.fs || !RegInStack(Section,m_CompileOpcode.fd,CRegInfo::FPU_Double)) {
Load_FPR_ToTop(Section,m_CompileOpcode.fd,m_CompileOpcode.fs,CRegInfo::FPU_Double);
}
ChangeFPURegFormat(Section,m_CompileOpcode.fd,CRegInfo::FPU_Double,CRegInfo::FPU_Dword,CRegInfo::RoundDown);
}
void Compile_R4300i_COP1_D_CVT_S (CCodeSection * Section) {
CPU_Message(" %X %s",Section->m_CompilePC,R4300iOpcodeName(m_CompileOpcode.Hex,Section->m_CompilePC));
CompileCop1Test(Section);
if (RegInStack(Section,m_CompileOpcode.fs,CRegInfo::FPU_Double) || RegInStack(Section,m_CompileOpcode.fs,CRegInfo::FPU_Qword)) {
UnMap_FPR(Section,m_CompileOpcode.fs,TRUE);
}
if (m_CompileOpcode.fd != m_CompileOpcode.fs || !RegInStack(Section,m_CompileOpcode.fd,CRegInfo::FPU_Double)) {
Load_FPR_ToTop(Section,m_CompileOpcode.fd,m_CompileOpcode.fs,CRegInfo::FPU_Double);
}
ChangeFPURegFormat(Section,m_CompileOpcode.fd,CRegInfo::FPU_Double,CRegInfo::FPU_Float,CRegInfo::RoundDefault);
}
void Compile_R4300i_COP1_D_CVT_W (CCodeSection * Section) {
CPU_Message(" %X %s",Section->m_CompilePC,R4300iOpcodeName(m_CompileOpcode.Hex,Section->m_CompilePC));
CompileCop1Test(Section);
if (RegInStack(Section,m_CompileOpcode.fs,CRegInfo::FPU_Double) || RegInStack(Section,m_CompileOpcode.fs,CRegInfo::FPU_Qword)) {
UnMap_FPR(Section,m_CompileOpcode.fs,TRUE);
}
if (m_CompileOpcode.fd != m_CompileOpcode.fs || !RegInStack(Section,m_CompileOpcode.fd,CRegInfo::FPU_Double)) {
Load_FPR_ToTop(Section,m_CompileOpcode.fd,m_CompileOpcode.fs,CRegInfo::FPU_Double);
}
ChangeFPURegFormat(Section,m_CompileOpcode.fd,CRegInfo::FPU_Double,CRegInfo::FPU_Dword,CRegInfo::RoundDefault);
}
void Compile_R4300i_COP1_D_CVT_L (CCodeSection * Section) {
CPU_Message(" %X %s",Section->m_CompilePC,R4300iOpcodeName(m_CompileOpcode.Hex,Section->m_CompilePC));
CompileCop1Test(Section);
if (RegInStack(Section,m_CompileOpcode.fs,CRegInfo::FPU_Double) || RegInStack(Section,m_CompileOpcode.fs,CRegInfo::FPU_Qword)) {
UnMap_FPR(Section,m_CompileOpcode.fs,TRUE);
}
if (m_CompileOpcode.fd != m_CompileOpcode.fs || !RegInStack(Section,m_CompileOpcode.fd,CRegInfo::FPU_Double)) {
Load_FPR_ToTop(Section,m_CompileOpcode.fd,m_CompileOpcode.fs,CRegInfo::FPU_Double);
}
ChangeFPURegFormat(Section,m_CompileOpcode.fd,CRegInfo::FPU_Double,CRegInfo::FPU_Qword,CRegInfo::RoundDefault);
}
void Compile_R4300i_COP1_D_CMP (CCodeSection * Section) {
DWORD Reg1 = RegInStack(Section,m_CompileOpcode.ft, CRegInfo::FPU_Float)?m_CompileOpcode.ft:m_CompileOpcode.fs;
DWORD Reg2 = RegInStack(Section,m_CompileOpcode.ft, CRegInfo::FPU_Float)?m_CompileOpcode.fs:m_CompileOpcode.ft;
int x86reg, cmp = 0;
CPU_Message(" %X %s",Section->m_CompilePC,R4300iOpcodeName(m_CompileOpcode.Hex,Section->m_CompilePC));
CompileCop1Test(Section);
//if ((m_CompileOpcode.funct & 1) != 0) { Compile_R4300i_UnknownOpcode(Section); }
if ((m_CompileOpcode.funct & 2) != 0) { cmp |= 0x4000; }
if ((m_CompileOpcode.funct & 4) != 0) { cmp |= 0x0100; }
Load_FPR_ToTop(Section,Reg1,Reg1, CRegInfo::FPU_Double);
Map_TempReg(Section,x86_EAX, 0, FALSE);
if (RegInStack(Section,Reg2, CRegInfo::FPU_Double)) {
fpuComReg(StackPosition(Section,Reg2),FALSE);
} else {
DWORD TempReg;
UnMap_FPR(Section,Reg2,TRUE);
TempReg = Map_TempReg(Section,x86_Any,-1,FALSE);
sprintf(Name,"_FPRDoubleLocation[%d]",Reg2);
MoveVariableToX86reg((BYTE *)&_FPRDoubleLocation[Reg2],Name,TempReg);
Load_FPR_ToTop(Section,Reg1,Reg1, CRegInfo::FPU_Double);
fpuComQwordRegPointer(TempReg,FALSE);
}
_Notify->BreakPoint(__FILE__,__LINE__);
#ifdef tofix
AndConstToVariable(~FPCSR_C, &FSTATUS_REGISTER, "FSTATUS_REGISTER");
#endif
fpuStoreStatus();
x86reg = Map_TempReg(Section,x86_Any8Bit, 0, FALSE);
TestConstToX86Reg(cmp,x86_EAX);
Setnz(x86reg);
if (cmp != 0) {
TestConstToX86Reg(cmp,x86_EAX);
Setnz(x86reg);
if ((m_CompileOpcode.funct & 1) != 0) {
int x86reg2 = Map_TempReg(Section,x86_Any8Bit, 0, FALSE);
AndConstToX86Reg(x86_EAX, 0x4300);
CompConstToX86reg(x86_EAX, 0x4300);
Setz(x86reg2);
OrX86RegToX86Reg(x86reg, x86reg2);
}
} else if ((m_CompileOpcode.funct & 1) != 0) {
AndConstToX86Reg(x86_EAX, 0x4300);
CompConstToX86reg(x86_EAX, 0x4300);
Setz(x86reg);
}
ShiftLeftSignImmed(x86reg, 23);
OrX86RegToVariable(&_FPCR[31], "_FPCR[31]", x86reg);
}
/************************** COP1: W functions ************************/
void Compile_R4300i_COP1_W_CVT_S (CCodeSection * Section) {
CPU_Message(" %X %s",Section->m_CompilePC,R4300iOpcodeName(m_CompileOpcode.Hex,Section->m_CompilePC));
CompileCop1Test(Section);
if (m_CompileOpcode.fd != m_CompileOpcode.fs || !RegInStack(Section,m_CompileOpcode.fd,CRegInfo::FPU_Dword)) {
Load_FPR_ToTop(Section,m_CompileOpcode.fd,m_CompileOpcode.fs,CRegInfo::FPU_Dword);
}
ChangeFPURegFormat(Section,m_CompileOpcode.fd,CRegInfo::FPU_Dword,CRegInfo::FPU_Float,CRegInfo::RoundDefault);
}
void Compile_R4300i_COP1_W_CVT_D (CCodeSection * Section) {
CPU_Message(" %X %s",Section->m_CompilePC,R4300iOpcodeName(m_CompileOpcode.Hex,Section->m_CompilePC));
CompileCop1Test(Section);
if (m_CompileOpcode.fd != m_CompileOpcode.fs || !RegInStack(Section,m_CompileOpcode.fd,CRegInfo::FPU_Dword)) {
Load_FPR_ToTop(Section,m_CompileOpcode.fd,m_CompileOpcode.fs,CRegInfo::FPU_Dword);
}
ChangeFPURegFormat(Section,m_CompileOpcode.fd,CRegInfo::FPU_Dword,CRegInfo::FPU_Double,CRegInfo::RoundDefault);
}
/************************** COP1: L functions ************************/
void Compile_R4300i_COP1_L_CVT_S (CCodeSection * Section) {
CPU_Message(" %X %s",Section->m_CompilePC,R4300iOpcodeName(m_CompileOpcode.Hex,Section->m_CompilePC));
CompileCop1Test(Section);
if (m_CompileOpcode.fd != m_CompileOpcode.fs || !RegInStack(Section,m_CompileOpcode.fd,CRegInfo::FPU_Qword)) {
Load_FPR_ToTop(Section,m_CompileOpcode.fd,m_CompileOpcode.fs,CRegInfo::FPU_Qword);
}
ChangeFPURegFormat(Section,m_CompileOpcode.fd,CRegInfo::FPU_Qword,CRegInfo::FPU_Float,CRegInfo::RoundDefault);
}
void Compile_R4300i_COP1_L_CVT_D (CCodeSection * Section) {
CPU_Message(" %X %s",Section->m_CompilePC,R4300iOpcodeName(m_CompileOpcode.Hex,Section->m_CompilePC));
CompileCop1Test(Section);
if (m_CompileOpcode.fd != m_CompileOpcode.fs || !RegInStack(Section,m_CompileOpcode.fd,CRegInfo::FPU_Qword)) {
Load_FPR_ToTop(Section,m_CompileOpcode.fd,m_CompileOpcode.fs,CRegInfo::FPU_Qword);
}
ChangeFPURegFormat(Section,m_CompileOpcode.fd,CRegInfo::FPU_Qword,CRegInfo::FPU_Double,CRegInfo::RoundDefault);
}
#endif