2016-01-27 09:11:59 +00:00
|
|
|
#include "stdafx.h"
|
2016-07-06 20:14:12 +00:00
|
|
|
|
|
|
|
#if defined(__i386__) || defined(_M_IX86)
|
2021-04-14 05:34:15 +00:00
|
|
|
#include <Project64-core/N64System/N64System.h>
|
|
|
|
#include <Project64-core/N64System/Recompiler/Recompiler.h>
|
2016-06-27 11:49:15 +00:00
|
|
|
#include <Project64-core/N64System/Recompiler/x86/x86RegInfo.h>
|
2022-10-10 00:22:17 +00:00
|
|
|
#include <Project64-core/N64System/SystemGlobals.h>
|
2016-01-27 09:11:59 +00:00
|
|
|
|
2022-10-10 00:22:17 +00:00
|
|
|
#include <float.h>
|
2016-01-27 09:11:59 +00:00
|
|
|
#include <stdio.h>
|
|
|
|
#include <string.h>
|
|
|
|
|
2016-06-27 11:49:15 +00:00
|
|
|
uint32_t CX86RegInfo::m_fpuControl = 0;
|
2016-01-27 09:11:59 +00:00
|
|
|
|
2022-10-10 00:22:17 +00:00
|
|
|
const char * Format_Name[] = {"Unknown", "dword", "qword", "float", "double"};
|
2016-01-27 09:11:59 +00:00
|
|
|
|
2022-08-29 02:19:20 +00:00
|
|
|
x86RegIndex GetIndexFromX86Reg(const CX86Ops::x86Reg & Reg)
|
|
|
|
{
|
|
|
|
switch (Reg)
|
|
|
|
{
|
|
|
|
case CX86Ops::x86_EAX: return x86RegIndex_EAX;
|
|
|
|
case CX86Ops::x86_EBX: return x86RegIndex_EBX;
|
|
|
|
case CX86Ops::x86_ECX: return x86RegIndex_ECX;
|
|
|
|
case CX86Ops::x86_EDX: return x86RegIndex_EDX;
|
|
|
|
case CX86Ops::x86_ESI: return x86RegIndex_ESI;
|
|
|
|
case CX86Ops::x86_EDI: return x86RegIndex_EDI;
|
|
|
|
case CX86Ops::x86_EBP: return x86RegIndex_EBP;
|
|
|
|
case CX86Ops::x86_ESP: return x86RegIndex_ESP;
|
|
|
|
}
|
|
|
|
g_Notify->BreakPoint(__FILE__, __LINE__);
|
|
|
|
return x86RegIndex_EAX;
|
|
|
|
}
|
|
|
|
|
|
|
|
CX86Ops::x86Reg GetX86RegFromIndex(x86RegIndex Index)
|
|
|
|
{
|
|
|
|
switch (Index)
|
|
|
|
{
|
|
|
|
case x86RegIndex_EAX: return CX86Ops::x86_EAX;
|
|
|
|
case x86RegIndex_ECX: return CX86Ops::x86_ECX;
|
|
|
|
case x86RegIndex_EDX: return CX86Ops::x86_EDX;
|
|
|
|
case x86RegIndex_EBX: return CX86Ops::x86_EBX;
|
|
|
|
case x86RegIndex_ESP: return CX86Ops::x86_ESP;
|
|
|
|
case x86RegIndex_EBP: return CX86Ops::x86_EBP;
|
|
|
|
case x86RegIndex_ESI: return CX86Ops::x86_ESI;
|
|
|
|
case x86RegIndex_EDI: return CX86Ops::x86_EDI;
|
|
|
|
}
|
|
|
|
g_Notify->BreakPoint(__FILE__, __LINE__);
|
|
|
|
return CX86Ops::x86_Unknown;
|
|
|
|
}
|
|
|
|
|
2022-08-15 03:09:34 +00:00
|
|
|
CX86RegInfo::CX86RegInfo(CCodeBlock & CodeBlock, CX86Ops & Assembler) :
|
2022-08-08 10:52:51 +00:00
|
|
|
m_CodeBlock(CodeBlock),
|
2022-08-15 03:09:34 +00:00
|
|
|
m_Assembler(Assembler),
|
2022-05-30 10:50:25 +00:00
|
|
|
m_Stack_TopPos(0),
|
|
|
|
m_InBeforeCallDirect(false)
|
2016-01-27 09:11:59 +00:00
|
|
|
{
|
2016-09-24 22:29:45 +00:00
|
|
|
for (int32_t i = 0; i < 32; i++)
|
2016-01-27 09:11:59 +00:00
|
|
|
{
|
2022-08-15 03:09:34 +00:00
|
|
|
m_RegMapLo[i] = CX86Ops::x86_Unknown;
|
|
|
|
m_RegMapHi[i] = CX86Ops::x86_Unknown;
|
2016-01-27 09:11:59 +00:00
|
|
|
}
|
2022-08-29 02:19:20 +00:00
|
|
|
for (int32_t i = 0; i < x86RegIndex_Size; i++)
|
2016-01-27 09:11:59 +00:00
|
|
|
{
|
|
|
|
m_x86reg_MappedTo[i] = NotMapped;
|
|
|
|
m_x86reg_Protected[i] = false;
|
|
|
|
m_x86reg_MapOrder[i] = 0;
|
|
|
|
}
|
|
|
|
for (int32_t i = 0, n = sizeof(m_x86fpu_MappedTo) / sizeof(m_x86fpu_MappedTo[0]); i < n; i++)
|
|
|
|
{
|
|
|
|
m_x86fpu_MappedTo[i] = -1;
|
|
|
|
m_x86fpu_State[i] = FPU_Unknown;
|
|
|
|
m_x86fpu_StateChanged[i] = false;
|
|
|
|
m_x86fpu_RoundingModel[i] = RoundDefault;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-10-10 00:22:17 +00:00
|
|
|
CX86RegInfo::CX86RegInfo(const CX86RegInfo & rhs) :
|
2022-08-15 03:09:34 +00:00
|
|
|
m_CodeBlock(rhs.m_CodeBlock),
|
|
|
|
m_Assembler(rhs.m_CodeBlock.RecompilerOps()->Assembler())
|
2016-01-27 09:11:59 +00:00
|
|
|
{
|
|
|
|
*this = rhs;
|
|
|
|
}
|
|
|
|
|
2016-06-27 11:49:15 +00:00
|
|
|
CX86RegInfo::~CX86RegInfo()
|
2016-01-27 09:11:59 +00:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2022-10-10 00:22:17 +00:00
|
|
|
CX86RegInfo & CX86RegInfo::operator=(const CX86RegInfo & right)
|
2016-01-27 09:11:59 +00:00
|
|
|
{
|
2016-07-20 12:22:56 +00:00
|
|
|
CRegBase::operator=(right);
|
2016-01-27 09:11:59 +00:00
|
|
|
m_Stack_TopPos = right.m_Stack_TopPos;
|
2022-05-30 10:50:25 +00:00
|
|
|
m_InBeforeCallDirect = right.m_InBeforeCallDirect;
|
2016-01-27 09:11:59 +00:00
|
|
|
|
|
|
|
memcpy(&m_RegMapLo, &right.m_RegMapLo, sizeof(m_RegMapLo));
|
|
|
|
memcpy(&m_RegMapHi, &right.m_RegMapHi, sizeof(m_RegMapHi));
|
|
|
|
memcpy(&m_x86reg_MappedTo, &right.m_x86reg_MappedTo, sizeof(m_x86reg_MappedTo));
|
|
|
|
memcpy(&m_x86reg_Protected, &right.m_x86reg_Protected, sizeof(m_x86reg_Protected));
|
|
|
|
memcpy(&m_x86reg_MapOrder, &right.m_x86reg_MapOrder, sizeof(m_x86reg_MapOrder));
|
|
|
|
|
|
|
|
memcpy(&m_x86fpu_MappedTo, &right.m_x86fpu_MappedTo, sizeof(m_x86fpu_MappedTo));
|
|
|
|
memcpy(&m_x86fpu_State, &right.m_x86fpu_State, sizeof(m_x86fpu_State));
|
|
|
|
memcpy(&m_x86fpu_StateChanged, &right.m_x86fpu_StateChanged, sizeof(m_x86fpu_StateChanged));
|
|
|
|
memcpy(&m_x86fpu_RoundingModel, &right.m_x86fpu_RoundingModel, sizeof(m_x86fpu_RoundingModel));
|
|
|
|
|
|
|
|
#ifdef _DEBUG
|
|
|
|
if (*this != right)
|
|
|
|
{
|
|
|
|
g_Notify->BreakPoint(__FILE__, __LINE__);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
2022-10-10 00:22:17 +00:00
|
|
|
bool CX86RegInfo::operator==(const CX86RegInfo & right) const
|
2016-01-27 09:11:59 +00:00
|
|
|
{
|
2016-07-20 12:22:56 +00:00
|
|
|
if (!CRegBase::operator==(right))
|
2016-01-27 09:11:59 +00:00
|
|
|
{
|
2016-07-20 12:22:56 +00:00
|
|
|
return false;
|
2016-01-27 09:11:59 +00:00
|
|
|
}
|
2016-07-20 12:22:56 +00:00
|
|
|
|
|
|
|
int32_t count;
|
|
|
|
|
2016-01-27 09:11:59 +00:00
|
|
|
for (count = 0; count < 10; count++)
|
|
|
|
{
|
2022-10-10 00:22:17 +00:00
|
|
|
if (m_x86reg_MappedTo[count] != right.m_x86reg_MappedTo[count])
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
if (m_x86reg_Protected[count] != right.m_x86reg_Protected[count])
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
if (m_x86reg_MapOrder[count] != right.m_x86reg_MapOrder[count])
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (m_Stack_TopPos != right.m_Stack_TopPos)
|
|
|
|
{
|
|
|
|
return false;
|
2016-01-27 09:11:59 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
for (count = 0; count < 8; count++)
|
|
|
|
{
|
2022-10-10 00:22:17 +00:00
|
|
|
if (m_x86fpu_MappedTo[count] != right.m_x86fpu_MappedTo[count])
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
if (m_x86fpu_State[count] != right.m_x86fpu_State[count])
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
if (m_x86fpu_RoundingModel[count] != right.m_x86fpu_RoundingModel[count])
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
2016-01-27 09:11:59 +00:00
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2022-10-10 00:22:17 +00:00
|
|
|
bool CX86RegInfo::operator!=(const CX86RegInfo & right) const
|
2016-01-27 09:11:59 +00:00
|
|
|
{
|
|
|
|
return !(right == *this);
|
|
|
|
}
|
|
|
|
|
2016-06-27 11:49:15 +00:00
|
|
|
CX86RegInfo::REG_STATE CX86RegInfo::ConstantsType(int64_t Value)
|
2016-01-27 09:11:59 +00:00
|
|
|
{
|
2022-10-10 00:22:17 +00:00
|
|
|
if (((Value >> 32) == -1) && ((Value & 0x80000000) != 0))
|
|
|
|
{
|
|
|
|
return STATE_CONST_32_SIGN;
|
|
|
|
}
|
|
|
|
if (((Value >> 32) == 0) && ((Value & 0x80000000) == 0))
|
|
|
|
{
|
|
|
|
return STATE_CONST_32_SIGN;
|
|
|
|
}
|
2016-01-27 09:11:59 +00:00
|
|
|
return STATE_CONST_64;
|
|
|
|
}
|
|
|
|
|
2016-07-05 10:13:21 +00:00
|
|
|
void CX86RegInfo::BeforeCallDirect(void)
|
|
|
|
{
|
2022-05-30 10:50:25 +00:00
|
|
|
if (m_InBeforeCallDirect)
|
|
|
|
{
|
|
|
|
g_Notify->BreakPoint(__FILE__, __LINE__);
|
|
|
|
}
|
|
|
|
m_InBeforeCallDirect = true;
|
2016-07-05 10:13:21 +00:00
|
|
|
UnMap_AllFPRs();
|
2022-08-15 03:09:34 +00:00
|
|
|
m_Assembler.Pushad();
|
2016-07-05 10:13:21 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void CX86RegInfo::AfterCallDirect(void)
|
|
|
|
{
|
2022-05-30 10:50:25 +00:00
|
|
|
if (!m_InBeforeCallDirect)
|
|
|
|
{
|
|
|
|
g_Notify->BreakPoint(__FILE__, __LINE__);
|
|
|
|
}
|
|
|
|
m_InBeforeCallDirect = false;
|
2022-08-15 03:09:34 +00:00
|
|
|
m_Assembler.Popad();
|
2016-07-05 10:13:21 +00:00
|
|
|
SetRoundingModel(CRegInfo::RoundUnknown);
|
|
|
|
}
|
|
|
|
|
2016-06-27 11:49:15 +00:00
|
|
|
void CX86RegInfo::FixRoundModel(FPU_ROUND RoundMethod)
|
2016-01-27 09:11:59 +00:00
|
|
|
{
|
|
|
|
if (GetRoundingModel() == RoundMethod)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
2022-08-08 10:52:51 +00:00
|
|
|
m_CodeBlock.Log(" FixRoundModel: CurrentRoundingModel: %s targetRoundModel: %s", RoundingModelName(GetRoundingModel()), RoundingModelName(RoundMethod));
|
2016-01-27 09:11:59 +00:00
|
|
|
|
|
|
|
m_fpuControl = 0;
|
2022-08-15 03:09:34 +00:00
|
|
|
m_Assembler.fpuStoreControl(&m_fpuControl, "m_fpuControl");
|
2022-09-11 20:31:43 +00:00
|
|
|
CX86Ops::x86Reg reg = Map_TempReg(CX86Ops::x86_Unknown, -1, false, false);
|
2022-08-15 03:09:34 +00:00
|
|
|
m_Assembler.MoveVariableToX86reg(&m_fpuControl, "m_fpuControl", reg);
|
|
|
|
m_Assembler.AndConstToX86Reg(reg, 0xF3FF);
|
2016-01-27 09:11:59 +00:00
|
|
|
|
|
|
|
if (RoundMethod == RoundDefault)
|
|
|
|
{
|
2016-08-07 06:43:26 +00:00
|
|
|
#ifdef _WIN32
|
2016-06-27 11:49:15 +00:00
|
|
|
static const unsigned int msRound[4] =
|
2022-10-10 00:22:17 +00:00
|
|
|
{
|
|
|
|
0x00000000, //_RC_NEAR
|
|
|
|
0x00000300, //_RC_CHOP
|
|
|
|
0x00000200, //_RC_UP
|
|
|
|
0x00000100, //_RC_DOWN
|
|
|
|
};
|
2016-01-27 09:11:59 +00:00
|
|
|
|
2022-09-11 20:31:43 +00:00
|
|
|
CX86Ops::x86Reg RoundReg = Map_TempReg(CX86Ops::x86_Unknown, -1, false, false);
|
2022-08-15 03:09:34 +00:00
|
|
|
m_Assembler.MoveVariableToX86reg(&g_Reg->m_RoundingModel, "m_RoundingModel", RoundReg);
|
|
|
|
m_Assembler.MoveVariableDispToX86Reg((void *)&msRound[0], "msRound", RoundReg, RoundReg, CX86Ops::Multip_x4);
|
2016-01-27 09:11:59 +00:00
|
|
|
|
2022-08-15 03:09:34 +00:00
|
|
|
m_Assembler.ShiftLeftSignImmed(RoundReg, 2);
|
|
|
|
m_Assembler.OrX86RegToX86Reg(reg, RoundReg);
|
2016-08-07 06:43:26 +00:00
|
|
|
#else
|
2022-09-11 20:31:43 +00:00
|
|
|
CX86Ops::x86Reg RoundReg = Map_TempReg(CX86Ops::x86_Unknown, -1, false, false);
|
2022-08-15 03:09:34 +00:00
|
|
|
m_Assembler.MoveVariableToX86reg(_RoundingModel, "_RoundingModel", RoundReg);
|
|
|
|
m_Assembler.OrX86RegToX86Reg(reg, RoundReg);
|
2016-08-07 06:43:26 +00:00
|
|
|
#endif
|
2022-08-29 02:19:20 +00:00
|
|
|
SetX86Protected(GetIndexFromX86Reg(RoundReg), false);
|
2016-01-27 09:11:59 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
switch (RoundMethod)
|
|
|
|
{
|
2022-08-15 03:09:34 +00:00
|
|
|
case RoundTruncate: m_Assembler.OrConstToX86Reg(0x0C00, reg); break;
|
|
|
|
case RoundNearest: m_Assembler.OrConstToX86Reg(0x0000, reg); break;
|
|
|
|
case RoundDown: m_Assembler.OrConstToX86Reg(0x0400, reg); break;
|
|
|
|
case RoundUp: m_Assembler.OrConstToX86Reg(0x0800, reg); break;
|
2016-01-27 09:11:59 +00:00
|
|
|
default:
|
2021-05-18 11:51:36 +00:00
|
|
|
g_Notify->DisplayError("Unknown rounding model");
|
2016-01-27 09:11:59 +00:00
|
|
|
}
|
|
|
|
}
|
2022-08-15 03:09:34 +00:00
|
|
|
m_Assembler.MoveX86regToVariable(reg, &m_fpuControl, "m_fpuControl");
|
2022-08-29 02:19:20 +00:00
|
|
|
SetX86Protected(GetIndexFromX86Reg(reg), false);
|
2022-08-15 03:09:34 +00:00
|
|
|
m_Assembler.fpuLoadControl(&m_fpuControl, "m_fpuControl");
|
2016-01-27 09:11:59 +00:00
|
|
|
SetRoundingModel(RoundMethod);
|
|
|
|
}
|
|
|
|
|
2016-06-27 11:49:15 +00:00
|
|
|
void CX86RegInfo::ChangeFPURegFormat(int32_t Reg, FPU_STATE OldFormat, FPU_STATE NewFormat, FPU_ROUND RoundingModel)
|
2016-01-27 09:11:59 +00:00
|
|
|
{
|
|
|
|
for (uint32_t i = 0; i < 8; i++)
|
|
|
|
{
|
|
|
|
if (m_x86fpu_MappedTo[i] != Reg)
|
|
|
|
{
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
if (m_x86fpu_State[i] != OldFormat || m_x86fpu_StateChanged[i])
|
|
|
|
{
|
|
|
|
UnMap_FPR(Reg, true);
|
|
|
|
Load_FPR_ToTop(Reg, Reg, OldFormat);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2022-08-08 10:52:51 +00:00
|
|
|
m_CodeBlock.Log(" regcache: Changed format of ST(%d) from %s to %s", (i - StackTopPos() + 8) & 7, Format_Name[OldFormat], Format_Name[NewFormat]);
|
2016-01-27 09:11:59 +00:00
|
|
|
}
|
|
|
|
FpuRoundingModel(i) = RoundingModel;
|
|
|
|
m_x86fpu_State[i] = NewFormat;
|
|
|
|
m_x86fpu_StateChanged[i] = true;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2018-01-15 21:23:21 +00:00
|
|
|
if (HaveDebugger())
|
2016-01-27 09:11:59 +00:00
|
|
|
{
|
2021-05-18 11:51:36 +00:00
|
|
|
g_Notify->DisplayError("ChangeFormat: Register not on stack!");
|
2016-01-27 09:11:59 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-06-27 11:49:15 +00:00
|
|
|
void CX86RegInfo::Load_FPR_ToTop(int32_t Reg, int32_t RegToLoad, FPU_STATE Format)
|
2016-01-27 09:11:59 +00:00
|
|
|
{
|
|
|
|
if (GetRoundingModel() != RoundDefault)
|
|
|
|
{
|
|
|
|
FixRoundModel(RoundDefault);
|
|
|
|
}
|
2022-08-08 10:52:51 +00:00
|
|
|
m_CodeBlock.Log("CurrentRoundingModel: %s FpuRoundingModel(StackTopPos()): %s", RoundingModelName(GetRoundingModel()), RoundingModelName(FpuRoundingModel(StackTopPos())));
|
2016-01-27 09:11:59 +00:00
|
|
|
|
2022-10-10 00:22:17 +00:00
|
|
|
if (RegToLoad < 0)
|
|
|
|
{
|
|
|
|
g_Notify->DisplayError("Load_FPR_ToTop\nRegToLoad < 0 ???");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (Reg < 0)
|
|
|
|
{
|
|
|
|
g_Notify->DisplayError("Load_FPR_ToTop\nReg < 0 ???");
|
|
|
|
return;
|
|
|
|
}
|
2016-01-27 09:11:59 +00:00
|
|
|
|
|
|
|
if (Format == FPU_Double || Format == FPU_Qword)
|
|
|
|
{
|
|
|
|
UnMap_FPR(Reg + 1, true);
|
|
|
|
UnMap_FPR(RegToLoad + 1, true);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if ((Reg & 1) != 0)
|
|
|
|
{
|
2022-10-10 03:08:43 +00:00
|
|
|
for (int32_t i = 0; i < 8; i++)
|
2016-01-27 09:11:59 +00:00
|
|
|
{
|
|
|
|
if (m_x86fpu_MappedTo[i] == (Reg - 1))
|
|
|
|
{
|
|
|
|
if (m_x86fpu_State[i] == FPU_Double || m_x86fpu_State[i] == FPU_Qword)
|
|
|
|
{
|
|
|
|
UnMap_FPR(Reg, true);
|
|
|
|
}
|
|
|
|
i = 8;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if ((RegToLoad & 1) != 0)
|
|
|
|
{
|
2022-10-10 03:08:43 +00:00
|
|
|
for (int32_t i = 0; i < 8; i++)
|
2016-01-27 09:11:59 +00:00
|
|
|
{
|
|
|
|
if (m_x86fpu_MappedTo[i] == (RegToLoad - 1))
|
|
|
|
{
|
|
|
|
if (m_x86fpu_State[i] == FPU_Double || m_x86fpu_State[i] == FPU_Qword)
|
|
|
|
{
|
|
|
|
UnMap_FPR(RegToLoad, true);
|
|
|
|
}
|
|
|
|
i = 8;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (Reg == RegToLoad)
|
|
|
|
{
|
2021-05-18 11:51:36 +00:00
|
|
|
// If different format then unmap original register from stack
|
2022-10-10 03:08:43 +00:00
|
|
|
for (int32_t i = 0; i < 8; i++)
|
2016-01-27 09:11:59 +00:00
|
|
|
{
|
|
|
|
if (m_x86fpu_MappedTo[i] != Reg)
|
|
|
|
{
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
if (m_x86fpu_State[i] != Format)
|
|
|
|
{
|
|
|
|
UnMap_FPR(Reg, true);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2021-05-18 11:51:36 +00:00
|
|
|
// If different format then unmap original register from stack
|
2022-10-10 03:08:43 +00:00
|
|
|
for (int32_t i = 0; i < 8; i++)
|
2016-01-27 09:11:59 +00:00
|
|
|
{
|
|
|
|
if (m_x86fpu_MappedTo[i] != Reg)
|
|
|
|
{
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
UnMap_FPR(Reg, m_x86fpu_State[i] != Format);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (RegInStack(RegToLoad, Format))
|
|
|
|
{
|
|
|
|
if (Reg != RegToLoad)
|
|
|
|
{
|
|
|
|
if (m_x86fpu_MappedTo[(StackTopPos() - 1) & 7] != RegToLoad)
|
|
|
|
{
|
|
|
|
UnMap_FPR(m_x86fpu_MappedTo[(StackTopPos() - 1) & 7], true);
|
2022-08-08 10:52:51 +00:00
|
|
|
m_CodeBlock.Log(" regcache: allocate ST(0) to %s", CRegName::FPR[Reg]);
|
2022-08-15 03:09:34 +00:00
|
|
|
m_Assembler.fpuLoadReg(&StackTopPos(), StackPosition(RegToLoad));
|
2016-01-27 09:11:59 +00:00
|
|
|
FpuRoundingModel(StackTopPos()) = RoundDefault;
|
|
|
|
m_x86fpu_MappedTo[StackTopPos()] = Reg;
|
|
|
|
m_x86fpu_State[StackTopPos()] = Format;
|
|
|
|
m_x86fpu_StateChanged[StackTopPos()] = false;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
UnMap_FPR(m_x86fpu_MappedTo[(StackTopPos() - 1) & 7], true);
|
|
|
|
Load_FPR_ToTop(Reg, RegToLoad, Format);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2022-08-15 03:09:34 +00:00
|
|
|
CX86Ops::x86FpuValues RegPos = CX86Ops::x86_ST_Unknown;
|
2021-01-19 05:58:59 +00:00
|
|
|
for (uint32_t z = 0; z < 8; z++)
|
2016-01-27 09:11:59 +00:00
|
|
|
{
|
2022-10-10 03:08:43 +00:00
|
|
|
if (m_x86fpu_MappedTo[z] != Reg)
|
2016-01-27 09:11:59 +00:00
|
|
|
{
|
2022-10-10 03:08:43 +00:00
|
|
|
continue;
|
2016-01-27 09:11:59 +00:00
|
|
|
}
|
2022-10-10 03:08:43 +00:00
|
|
|
RegPos = (CX86Ops::x86FpuValues)z;
|
|
|
|
break;
|
2016-01-27 09:11:59 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (RegPos == StackTopPos())
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
2022-08-15 03:09:34 +00:00
|
|
|
CX86Ops::x86FpuValues StackPos = StackPosition(Reg);
|
2016-01-27 09:11:59 +00:00
|
|
|
|
|
|
|
FpuRoundingModel(RegPos) = FpuRoundingModel(StackTopPos());
|
|
|
|
m_x86fpu_MappedTo[RegPos] = m_x86fpu_MappedTo[StackTopPos()];
|
|
|
|
m_x86fpu_State[RegPos] = m_x86fpu_State[StackTopPos()];
|
|
|
|
m_x86fpu_StateChanged[RegPos] = m_x86fpu_StateChanged[StackTopPos()];
|
2022-08-08 10:52:51 +00:00
|
|
|
m_CodeBlock.Log(" regcache: allocate ST(%d) to %s", StackPos, CRegName::FPR[m_x86fpu_MappedTo[RegPos]]);
|
|
|
|
m_CodeBlock.Log(" regcache: allocate ST(0) to %s", CRegName::FPR[Reg]);
|
2016-01-27 09:11:59 +00:00
|
|
|
|
2022-08-15 03:09:34 +00:00
|
|
|
m_Assembler.fpuExchange(StackPos);
|
2016-01-27 09:11:59 +00:00
|
|
|
|
|
|
|
FpuRoundingModel(StackTopPos()) = RoundDefault;
|
|
|
|
m_x86fpu_MappedTo[StackTopPos()] = Reg;
|
|
|
|
m_x86fpu_State[StackTopPos()] = Format;
|
|
|
|
m_x86fpu_StateChanged[StackTopPos()] = false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2022-08-15 03:09:34 +00:00
|
|
|
CX86Ops::x86Reg TempReg;
|
2016-01-27 09:11:59 +00:00
|
|
|
|
|
|
|
UnMap_FPR(m_x86fpu_MappedTo[(StackTopPos() - 1) & 7], true);
|
2022-10-10 03:08:43 +00:00
|
|
|
for (int32_t i = 0; i < 8; i++)
|
2016-01-27 09:11:59 +00:00
|
|
|
{
|
|
|
|
if (m_x86fpu_MappedTo[i] == RegToLoad)
|
|
|
|
{
|
|
|
|
UnMap_FPR(RegToLoad, true);
|
|
|
|
i = 8;
|
|
|
|
}
|
|
|
|
}
|
2022-08-08 10:52:51 +00:00
|
|
|
m_CodeBlock.Log(" regcache: allocate ST(0) to %s", CRegName::FPR[Reg]);
|
2022-09-11 20:31:43 +00:00
|
|
|
TempReg = Map_TempReg(CX86Ops::x86_Unknown, -1, false, false);
|
2016-01-27 09:11:59 +00:00
|
|
|
switch (Format)
|
|
|
|
{
|
|
|
|
case FPU_Dword:
|
2022-10-10 03:08:43 +00:00
|
|
|
m_Assembler.MoveVariableToX86reg(&g_Reg->m_FPR_S[RegToLoad], stdstr_f("m_FPR_S[%d]", RegToLoad).c_str(), TempReg);
|
2022-08-15 03:09:34 +00:00
|
|
|
m_Assembler.fpuLoadIntegerDwordFromX86Reg(&StackTopPos(), TempReg);
|
2016-01-27 09:11:59 +00:00
|
|
|
break;
|
|
|
|
case FPU_Qword:
|
2022-10-10 03:08:43 +00:00
|
|
|
m_Assembler.MoveVariableToX86reg(&g_Reg->m_FPR_D[RegToLoad], stdstr_f("m_FPR_D[%d]", RegToLoad).c_str(), TempReg);
|
2022-08-15 03:09:34 +00:00
|
|
|
m_Assembler.fpuLoadIntegerQwordFromX86Reg(&StackTopPos(), TempReg);
|
2016-01-27 09:11:59 +00:00
|
|
|
break;
|
|
|
|
case FPU_Float:
|
2022-10-10 03:08:43 +00:00
|
|
|
m_Assembler.MoveVariableToX86reg(&g_Reg->m_FPR_S[RegToLoad], stdstr_f("m_FPR_S[%d]", RegToLoad).c_str(), TempReg);
|
2022-08-15 03:09:34 +00:00
|
|
|
m_Assembler.fpuLoadDwordFromX86Reg(&StackTopPos(), TempReg);
|
2016-01-27 09:11:59 +00:00
|
|
|
break;
|
|
|
|
case FPU_Double:
|
2022-10-10 03:08:43 +00:00
|
|
|
m_Assembler.MoveVariableToX86reg(&g_Reg->m_FPR_D[RegToLoad], stdstr_f("m_FPR_D[%d]", RegToLoad).c_str(), TempReg);
|
2022-08-15 03:09:34 +00:00
|
|
|
m_Assembler.fpuLoadQwordFromX86Reg(&StackTopPos(), TempReg);
|
2016-01-27 09:11:59 +00:00
|
|
|
break;
|
|
|
|
default:
|
2022-10-10 00:22:17 +00:00
|
|
|
if (HaveDebugger())
|
|
|
|
{
|
|
|
|
g_Notify->DisplayError(stdstr_f("Load_FPR_ToTop\nUnkown format to load %d", Format).c_str());
|
|
|
|
}
|
2016-01-27 09:11:59 +00:00
|
|
|
}
|
2022-08-29 02:19:20 +00:00
|
|
|
SetX86Protected(GetIndexFromX86Reg(TempReg), false);
|
2016-01-27 09:11:59 +00:00
|
|
|
FpuRoundingModel(StackTopPos()) = RoundDefault;
|
|
|
|
m_x86fpu_MappedTo[StackTopPos()] = Reg;
|
|
|
|
m_x86fpu_State[StackTopPos()] = Format;
|
|
|
|
m_x86fpu_StateChanged[StackTopPos()] = false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-08-15 03:09:34 +00:00
|
|
|
CX86Ops::x86FpuValues CX86RegInfo::StackPosition(int32_t Reg)
|
2016-01-27 09:11:59 +00:00
|
|
|
{
|
2022-10-10 03:08:43 +00:00
|
|
|
for (int32_t i = 0; i < 8; i++)
|
2016-01-27 09:11:59 +00:00
|
|
|
{
|
|
|
|
if (m_x86fpu_MappedTo[i] == Reg)
|
|
|
|
{
|
2022-08-15 03:09:34 +00:00
|
|
|
return (CX86Ops::x86FpuValues)((i - StackTopPos()) & 7);
|
2016-01-27 09:11:59 +00:00
|
|
|
}
|
|
|
|
}
|
2022-08-15 03:09:34 +00:00
|
|
|
return CX86Ops::x86_ST_Unknown;
|
2016-01-27 09:11:59 +00:00
|
|
|
}
|
|
|
|
|
2022-09-11 20:31:43 +00:00
|
|
|
CX86Ops::x86Reg CX86RegInfo::FreeX86Reg()
|
2016-01-27 09:11:59 +00:00
|
|
|
{
|
2022-10-10 00:22:17 +00:00
|
|
|
if (GetX86Mapped(x86RegIndex_EDI) == NotMapped && !GetX86Protected(x86RegIndex_EDI))
|
|
|
|
{
|
|
|
|
return CX86Ops::x86_EDI;
|
|
|
|
}
|
|
|
|
if (GetX86Mapped(x86RegIndex_ESI) == NotMapped && !GetX86Protected(x86RegIndex_ESI))
|
|
|
|
{
|
|
|
|
return CX86Ops::x86_ESI;
|
|
|
|
}
|
|
|
|
if (GetX86Mapped(x86RegIndex_EBX) == NotMapped && !GetX86Protected(x86RegIndex_EBX))
|
|
|
|
{
|
|
|
|
return CX86Ops::x86_EBX;
|
|
|
|
}
|
|
|
|
if (GetX86Mapped(x86RegIndex_EAX) == NotMapped && !GetX86Protected(x86RegIndex_EAX))
|
|
|
|
{
|
|
|
|
return CX86Ops::x86_EAX;
|
|
|
|
}
|
|
|
|
if (GetX86Mapped(x86RegIndex_EDX) == NotMapped && !GetX86Protected(x86RegIndex_EDX))
|
|
|
|
{
|
|
|
|
return CX86Ops::x86_EDX;
|
|
|
|
}
|
|
|
|
if (GetX86Mapped(x86RegIndex_ECX) == NotMapped && !GetX86Protected(x86RegIndex_ECX))
|
|
|
|
{
|
|
|
|
return CX86Ops::x86_ECX;
|
|
|
|
}
|
2016-01-27 09:11:59 +00:00
|
|
|
|
2022-08-15 03:09:34 +00:00
|
|
|
CX86Ops::x86Reg Reg = UnMap_TempReg();
|
2022-10-10 00:22:17 +00:00
|
|
|
if (Reg != CX86Ops::x86_Unknown)
|
|
|
|
{
|
|
|
|
return Reg;
|
|
|
|
}
|
2016-01-27 09:11:59 +00:00
|
|
|
|
2022-08-29 02:19:20 +00:00
|
|
|
uint32_t MapCount[x86RegIndex_Size];
|
|
|
|
x86RegIndex MapReg[x86RegIndex_Size];
|
2016-01-27 09:11:59 +00:00
|
|
|
|
2022-08-29 02:19:20 +00:00
|
|
|
for (int i = 0; i < x86RegIndex_Size; i++)
|
2016-01-27 09:11:59 +00:00
|
|
|
{
|
2022-08-29 02:19:20 +00:00
|
|
|
MapCount[i] = GetX86MapOrder((x86RegIndex)i);
|
|
|
|
MapReg[i] = (x86RegIndex)i;
|
2016-01-27 09:11:59 +00:00
|
|
|
}
|
2022-08-29 02:19:20 +00:00
|
|
|
for (int i = 0; i < x86RegIndex_Size; i++)
|
2016-01-27 09:11:59 +00:00
|
|
|
{
|
2022-09-05 01:12:49 +00:00
|
|
|
for (int32_t z = 0; z < x86RegIndex_Size - 1; z++)
|
2016-01-27 09:11:59 +00:00
|
|
|
{
|
2022-08-29 02:19:20 +00:00
|
|
|
if (MapCount[z] < MapCount[z + 1])
|
2016-01-27 09:11:59 +00:00
|
|
|
{
|
2022-08-29 02:19:20 +00:00
|
|
|
uint32_t TempCount = MapCount[z];
|
|
|
|
MapCount[z] = MapCount[z + 1];
|
|
|
|
MapCount[z + 1] = TempCount;
|
|
|
|
x86RegIndex tempReg = MapReg[z];
|
|
|
|
MapReg[z] = MapReg[z + 1];
|
|
|
|
MapReg[z + 1] = tempReg;
|
2016-01-27 09:11:59 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-08-15 03:09:34 +00:00
|
|
|
CX86Ops::x86Reg StackReg = CX86Ops::x86_Unknown;
|
2022-08-29 02:19:20 +00:00
|
|
|
for (int i = 0; i < x86RegIndex_Size; i++)
|
2016-01-27 09:11:59 +00:00
|
|
|
{
|
2022-08-29 02:19:20 +00:00
|
|
|
if (MapCount[i] > 0 && GetX86Mapped(MapReg[i]) != Stack_Mapped)
|
2016-01-27 09:11:59 +00:00
|
|
|
{
|
2022-08-29 02:19:20 +00:00
|
|
|
if (UnMap_X86reg((CX86Ops::x86Reg)MapReg[i]))
|
2016-01-27 09:11:59 +00:00
|
|
|
{
|
2022-08-29 02:19:20 +00:00
|
|
|
return (CX86Ops::x86Reg)MapReg[i];
|
2016-01-27 09:11:59 +00:00
|
|
|
}
|
|
|
|
}
|
2022-10-10 00:22:17 +00:00
|
|
|
if (GetX86Mapped(MapReg[i]) == Stack_Mapped)
|
|
|
|
{
|
|
|
|
StackReg = GetX86RegFromIndex(MapReg[i]);
|
|
|
|
}
|
2016-01-27 09:11:59 +00:00
|
|
|
}
|
2022-08-15 03:09:34 +00:00
|
|
|
if (StackReg != CX86Ops::x86_Unknown)
|
2016-01-27 09:11:59 +00:00
|
|
|
{
|
|
|
|
UnMap_X86reg(StackReg);
|
|
|
|
return StackReg;
|
|
|
|
}
|
|
|
|
|
2022-08-15 03:09:34 +00:00
|
|
|
return CX86Ops::x86_Unknown;
|
2016-01-27 09:11:59 +00:00
|
|
|
}
|
|
|
|
|
2022-09-11 20:31:43 +00:00
|
|
|
CX86Ops::x86Reg CX86RegInfo::Free8BitX86Reg()
|
2016-01-27 09:11:59 +00:00
|
|
|
{
|
2022-10-10 00:22:17 +00:00
|
|
|
if (GetX86Mapped(x86RegIndex_EBX) == NotMapped && !GetX86Protected(x86RegIndex_EBX))
|
|
|
|
{
|
|
|
|
return CX86Ops::x86_EBX;
|
|
|
|
}
|
|
|
|
if (GetX86Mapped(x86RegIndex_EAX) == NotMapped && !GetX86Protected(x86RegIndex_EAX))
|
|
|
|
{
|
|
|
|
return CX86Ops::x86_EAX;
|
|
|
|
}
|
|
|
|
if (GetX86Mapped(x86RegIndex_EDX) == NotMapped && !GetX86Protected(x86RegIndex_EDX))
|
|
|
|
{
|
|
|
|
return CX86Ops::x86_EDX;
|
|
|
|
}
|
|
|
|
if (GetX86Mapped(x86RegIndex_ECX) == NotMapped && !GetX86Protected(x86RegIndex_ECX))
|
|
|
|
{
|
|
|
|
return CX86Ops::x86_ECX;
|
|
|
|
}
|
2016-01-27 09:11:59 +00:00
|
|
|
|
2022-08-15 03:09:34 +00:00
|
|
|
CX86Ops::x86Reg Reg = UnMap_8BitTempReg();
|
2022-10-10 00:22:17 +00:00
|
|
|
if (Reg > 0)
|
|
|
|
{
|
|
|
|
return Reg;
|
|
|
|
}
|
2016-01-27 09:11:59 +00:00
|
|
|
|
2022-08-29 02:19:20 +00:00
|
|
|
uint32_t MapCount[10];
|
|
|
|
x86RegIndex MapReg[10];
|
|
|
|
for (uint32_t i = 0; i < x86RegIndex_Size; i++)
|
2016-01-27 09:11:59 +00:00
|
|
|
{
|
2022-08-29 02:19:20 +00:00
|
|
|
MapCount[i] = GetX86MapOrder((x86RegIndex)i);
|
|
|
|
MapReg[i] = (x86RegIndex)i;
|
2016-01-27 09:11:59 +00:00
|
|
|
}
|
2022-08-29 02:19:20 +00:00
|
|
|
for (uint32_t i = 0; i < x86RegIndex_Size; i++)
|
2016-01-27 09:11:59 +00:00
|
|
|
{
|
2022-08-29 02:19:20 +00:00
|
|
|
for (uint32_t z = 0; z < x86RegIndex_Size; z++)
|
2016-01-27 09:11:59 +00:00
|
|
|
{
|
2022-08-29 02:19:20 +00:00
|
|
|
if (MapCount[z] < MapCount[z + 1])
|
2016-01-27 09:11:59 +00:00
|
|
|
{
|
2022-08-29 02:19:20 +00:00
|
|
|
uint32_t TempCount = MapCount[z];
|
|
|
|
MapCount[z] = MapCount[z + 1];
|
|
|
|
MapCount[z + 1] = TempCount;
|
|
|
|
x86RegIndex TempIndex = MapReg[z];
|
|
|
|
MapReg[z] = MapReg[z + 1];
|
|
|
|
MapReg[z + 1] = TempIndex;
|
2016-01-27 09:11:59 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2022-08-29 02:19:20 +00:00
|
|
|
for (uint32_t i = 0; i < x86RegIndex_Size; i++)
|
2016-01-27 09:11:59 +00:00
|
|
|
{
|
2022-08-29 02:19:20 +00:00
|
|
|
if (MapCount[i] > 0)
|
2016-01-27 09:11:59 +00:00
|
|
|
{
|
2022-10-10 00:22:17 +00:00
|
|
|
if (!CX86Ops::Is8BitReg((CX86Ops::x86Reg)i))
|
|
|
|
{
|
|
|
|
continue;
|
|
|
|
}
|
2022-08-29 02:19:20 +00:00
|
|
|
if (UnMap_X86reg((CX86Ops::x86Reg)i))
|
2016-01-27 09:11:59 +00:00
|
|
|
{
|
2022-08-29 02:19:20 +00:00
|
|
|
return (CX86Ops::x86Reg)i;
|
2016-01-27 09:11:59 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2022-08-15 03:09:34 +00:00
|
|
|
return CX86Ops::x86_Unknown;
|
2016-01-27 09:11:59 +00:00
|
|
|
}
|
|
|
|
|
2022-09-11 20:31:43 +00:00
|
|
|
CX86Ops::x86Reg CX86RegInfo::UnMap_8BitTempReg()
|
2016-01-27 09:11:59 +00:00
|
|
|
{
|
2022-08-29 02:19:20 +00:00
|
|
|
for (uint32_t i = 0; i < x86RegIndex_Size; i++)
|
2016-01-27 09:11:59 +00:00
|
|
|
{
|
2022-10-10 00:22:17 +00:00
|
|
|
if (!CX86Ops::Is8BitReg(GetX86RegFromIndex((x86RegIndex)i)))
|
|
|
|
{
|
|
|
|
continue;
|
|
|
|
}
|
2022-08-29 02:19:20 +00:00
|
|
|
if (GetX86Mapped((x86RegIndex)i) == Temp_Mapped)
|
2016-01-27 09:11:59 +00:00
|
|
|
{
|
2022-08-29 02:19:20 +00:00
|
|
|
if (GetX86Protected((x86RegIndex)i) == false)
|
2016-01-27 09:11:59 +00:00
|
|
|
{
|
2022-08-29 02:19:20 +00:00
|
|
|
m_CodeBlock.Log(" regcache: unallocate %s from temp storage", CX86Ops::x86_Name(GetX86RegFromIndex((x86RegIndex)i)));
|
|
|
|
SetX86Mapped((x86RegIndex)i, CX86RegInfo::NotMapped);
|
|
|
|
return GetX86RegFromIndex((x86RegIndex)i);
|
2016-01-27 09:11:59 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2022-08-15 03:09:34 +00:00
|
|
|
return CX86Ops::x86_Unknown;
|
2016-01-27 09:11:59 +00:00
|
|
|
}
|
|
|
|
|
2022-08-15 03:09:34 +00:00
|
|
|
CX86Ops::x86Reg CX86RegInfo::Get_MemoryStack() const
|
2016-01-27 09:11:59 +00:00
|
|
|
{
|
2022-08-29 02:19:20 +00:00
|
|
|
for (int32_t i = 0, n = x86RegIndex_Size; i < n; i++)
|
2016-01-27 09:11:59 +00:00
|
|
|
{
|
2022-08-29 02:19:20 +00:00
|
|
|
if (GetX86Mapped((x86RegIndex)i) == Stack_Mapped)
|
2016-01-27 09:11:59 +00:00
|
|
|
{
|
2022-08-29 02:19:20 +00:00
|
|
|
return GetX86RegFromIndex((x86RegIndex)i);
|
2016-01-27 09:11:59 +00:00
|
|
|
}
|
|
|
|
}
|
2022-08-15 03:09:34 +00:00
|
|
|
return CX86Ops::x86_Unknown;
|
2016-01-27 09:11:59 +00:00
|
|
|
}
|
|
|
|
|
2022-08-15 03:09:34 +00:00
|
|
|
CX86Ops::x86Reg CX86RegInfo::Map_MemoryStack(CX86Ops::x86Reg Reg, bool bMapRegister, bool LoadValue)
|
2016-01-27 09:11:59 +00:00
|
|
|
{
|
2022-08-15 03:09:34 +00:00
|
|
|
CX86Ops::x86Reg CurrentMap = Get_MemoryStack();
|
2016-01-27 09:11:59 +00:00
|
|
|
if (!bMapRegister)
|
|
|
|
{
|
2021-05-18 11:51:36 +00:00
|
|
|
// If not mapping then just return what the current mapping is
|
2016-01-27 09:11:59 +00:00
|
|
|
return CurrentMap;
|
|
|
|
}
|
|
|
|
|
2022-08-15 03:09:34 +00:00
|
|
|
if (CurrentMap != CX86Ops::x86_Unknown && CurrentMap == Reg)
|
2016-01-27 09:11:59 +00:00
|
|
|
{
|
2021-05-18 11:51:36 +00:00
|
|
|
// Already mapped to correct register
|
2016-01-27 09:11:59 +00:00
|
|
|
return CurrentMap;
|
|
|
|
}
|
2021-05-18 11:51:36 +00:00
|
|
|
// Map a register
|
2022-09-11 20:31:43 +00:00
|
|
|
if (Reg == CX86Ops::x86_Unknown)
|
2016-01-27 09:11:59 +00:00
|
|
|
{
|
2022-08-15 03:09:34 +00:00
|
|
|
if (CurrentMap != CX86Ops::x86_Unknown)
|
2016-01-27 09:11:59 +00:00
|
|
|
{
|
|
|
|
return CurrentMap;
|
|
|
|
}
|
|
|
|
Reg = FreeX86Reg();
|
2022-08-15 03:09:34 +00:00
|
|
|
if (Reg == CX86Ops::x86_Unknown)
|
2016-01-27 09:11:59 +00:00
|
|
|
{
|
|
|
|
g_Notify->DisplayError("Map_MemoryStack\n\nOut of registers");
|
|
|
|
g_Notify->BreakPoint(__FILE__, __LINE__);
|
|
|
|
}
|
2022-08-29 02:19:20 +00:00
|
|
|
SetX86Mapped(GetIndexFromX86Reg(Reg), CX86RegInfo::Stack_Mapped);
|
2022-08-15 03:09:34 +00:00
|
|
|
m_CodeBlock.Log(" regcache: allocate %s as Memory Stack", CX86Ops::x86_Name(Reg));
|
2016-01-27 09:11:59 +00:00
|
|
|
if (LoadValue)
|
|
|
|
{
|
2022-08-15 03:09:34 +00:00
|
|
|
m_Assembler.MoveVariableToX86reg(&g_Recompiler->MemoryStackPos(), "MemoryStack", Reg);
|
2016-01-27 09:11:59 +00:00
|
|
|
}
|
|
|
|
return Reg;
|
|
|
|
}
|
|
|
|
|
2021-05-18 11:51:36 +00:00
|
|
|
// Move to a register/allocate register
|
2016-01-27 09:11:59 +00:00
|
|
|
UnMap_X86reg(Reg);
|
2022-08-15 03:09:34 +00:00
|
|
|
if (CurrentMap != CX86Ops::x86_Unknown)
|
2016-01-27 09:11:59 +00:00
|
|
|
{
|
2022-08-15 03:09:34 +00:00
|
|
|
m_CodeBlock.Log(" regcache: change allocation of memory stack from %s to %s", CX86Ops::x86_Name(CurrentMap), CX86Ops::x86_Name(Reg));
|
2022-08-29 02:19:20 +00:00
|
|
|
SetX86Mapped(GetIndexFromX86Reg(Reg), CX86RegInfo::Stack_Mapped);
|
|
|
|
SetX86Mapped(GetIndexFromX86Reg(CurrentMap), CX86RegInfo::NotMapped);
|
2022-08-15 03:09:34 +00:00
|
|
|
m_Assembler.MoveX86RegToX86Reg(CurrentMap, Reg);
|
2016-01-27 09:11:59 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2022-08-29 02:19:20 +00:00
|
|
|
SetX86Mapped(GetIndexFromX86Reg(Reg), CX86RegInfo::Stack_Mapped);
|
2022-08-15 03:09:34 +00:00
|
|
|
m_CodeBlock.Log(" regcache: allocate %s as memory stack", CX86Ops::x86_Name(Reg));
|
2016-01-27 09:11:59 +00:00
|
|
|
if (LoadValue)
|
|
|
|
{
|
2022-08-15 03:09:34 +00:00
|
|
|
m_Assembler.MoveVariableToX86reg(&g_Recompiler->MemoryStackPos(), "MemoryStack", Reg);
|
2016-01-27 09:11:59 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
return Reg;
|
|
|
|
}
|
|
|
|
|
2016-06-27 11:49:15 +00:00
|
|
|
void CX86RegInfo::Map_GPR_32bit(int32_t MipsReg, bool SignValue, int32_t MipsRegToLoad)
|
2016-01-27 09:11:59 +00:00
|
|
|
{
|
2022-08-15 03:09:34 +00:00
|
|
|
CX86Ops::x86Reg Reg;
|
2016-01-27 09:11:59 +00:00
|
|
|
if (MipsReg == 0)
|
|
|
|
{
|
|
|
|
g_Notify->BreakPoint(__FILE__, __LINE__);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (IsUnknown(MipsReg) || IsConst(MipsReg))
|
|
|
|
{
|
|
|
|
Reg = FreeX86Reg();
|
|
|
|
if (Reg < 0)
|
|
|
|
{
|
2022-10-10 00:22:17 +00:00
|
|
|
if (HaveDebugger())
|
|
|
|
{
|
|
|
|
g_Notify->DisplayError("Map_GPR_32bit\n\nOut of registers");
|
|
|
|
}
|
2016-01-27 09:11:59 +00:00
|
|
|
g_Notify->BreakPoint(__FILE__, __LINE__);
|
|
|
|
return;
|
|
|
|
}
|
2022-08-15 03:09:34 +00:00
|
|
|
m_CodeBlock.Log(" regcache: allocate %s to %s", CX86Ops::x86_Name(Reg), CRegName::GPR[MipsReg]);
|
2016-01-27 09:11:59 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (Is64Bit(MipsReg))
|
|
|
|
{
|
2022-08-15 03:09:34 +00:00
|
|
|
m_CodeBlock.Log(" regcache: unallocate %s from high 32-bit of %s", CX86Ops::x86_Name(GetMipsRegMapHi(MipsReg)), CRegName::GPR_Hi[MipsReg]);
|
2022-08-29 02:19:20 +00:00
|
|
|
x86RegIndex RegIndex = GetIndexFromX86Reg(GetMipsRegMapHi(MipsReg));
|
|
|
|
SetX86MapOrder(RegIndex, 0);
|
|
|
|
SetX86Mapped(RegIndex, NotMapped);
|
|
|
|
SetX86Protected(RegIndex, false);
|
2016-01-27 09:11:59 +00:00
|
|
|
SetMipsRegHi(MipsReg, 0);
|
|
|
|
}
|
|
|
|
Reg = GetMipsRegMapLo(MipsReg);
|
|
|
|
}
|
2022-08-29 02:19:20 +00:00
|
|
|
for (uint32_t i = 0; i < x86RegIndex_Size; i++)
|
2016-01-27 09:11:59 +00:00
|
|
|
{
|
2022-08-29 02:19:20 +00:00
|
|
|
uint32_t MapOrder = GetX86MapOrder((x86RegIndex)i);
|
|
|
|
if (MapOrder > 0)
|
2016-01-27 09:11:59 +00:00
|
|
|
{
|
2022-08-29 02:19:20 +00:00
|
|
|
SetX86MapOrder((x86RegIndex)i, MapOrder);
|
2016-01-27 09:11:59 +00:00
|
|
|
}
|
|
|
|
}
|
2022-09-11 20:31:43 +00:00
|
|
|
x86RegIndex RegIndex = GetIndexFromX86Reg(Reg);
|
|
|
|
SetX86MapOrder(RegIndex, 1);
|
2016-01-27 09:11:59 +00:00
|
|
|
|
|
|
|
if (MipsRegToLoad > 0)
|
|
|
|
{
|
|
|
|
if (IsUnknown(MipsRegToLoad))
|
|
|
|
{
|
2022-08-15 03:09:34 +00:00
|
|
|
m_Assembler.MoveVariableToX86reg(&_GPR[MipsRegToLoad].UW[0], CRegName::GPR_Lo[MipsRegToLoad], Reg);
|
2016-01-27 09:11:59 +00:00
|
|
|
}
|
|
|
|
else if (IsMapped(MipsRegToLoad))
|
|
|
|
{
|
|
|
|
if (MipsReg != MipsRegToLoad)
|
|
|
|
{
|
2022-08-15 03:09:34 +00:00
|
|
|
m_Assembler.MoveX86RegToX86Reg(GetMipsRegMapLo(MipsRegToLoad), Reg);
|
2016-01-27 09:11:59 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2022-08-15 03:09:34 +00:00
|
|
|
m_Assembler.MoveConstToX86reg(GetMipsRegLo(MipsRegToLoad), Reg);
|
2016-01-27 09:11:59 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (MipsRegToLoad == 0)
|
|
|
|
{
|
2022-08-15 03:09:34 +00:00
|
|
|
m_Assembler.XorX86RegToX86Reg(Reg, Reg);
|
2016-01-27 09:11:59 +00:00
|
|
|
}
|
2022-09-11 20:31:43 +00:00
|
|
|
SetX86Mapped(RegIndex, GPR_Mapped);
|
|
|
|
SetX86Protected(RegIndex, true);
|
2016-01-27 09:11:59 +00:00
|
|
|
SetMipsRegMapLo(MipsReg, Reg);
|
|
|
|
SetMipsRegState(MipsReg, SignValue ? STATE_MAPPED_32_SIGN : STATE_MAPPED_32_ZERO);
|
|
|
|
}
|
|
|
|
|
2016-06-27 11:49:15 +00:00
|
|
|
void CX86RegInfo::Map_GPR_64bit(int32_t MipsReg, int32_t MipsRegToLoad)
|
2016-01-27 09:11:59 +00:00
|
|
|
{
|
2022-08-29 02:19:20 +00:00
|
|
|
CX86Ops::x86Reg x86Hi = CX86Ops::x86_Unknown, x86lo = CX86Ops::x86_Unknown;
|
2016-01-27 09:11:59 +00:00
|
|
|
if (MipsReg == 0)
|
|
|
|
{
|
2022-10-10 00:22:17 +00:00
|
|
|
if (HaveDebugger())
|
|
|
|
{
|
|
|
|
g_Notify->DisplayError("Map_GPR_32bit\n\nWhy are you trying to map register 0?");
|
|
|
|
}
|
2016-01-27 09:11:59 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
ProtectGPR(MipsReg);
|
|
|
|
if (IsUnknown(MipsReg) || IsConst(MipsReg))
|
|
|
|
{
|
|
|
|
x86Hi = FreeX86Reg();
|
|
|
|
if (x86Hi < 0)
|
|
|
|
{
|
2022-10-10 00:22:17 +00:00
|
|
|
if (HaveDebugger())
|
|
|
|
{
|
|
|
|
g_Notify->DisplayError("Map_GPR_64bit\n\nOut of registers");
|
|
|
|
}
|
2016-01-27 09:11:59 +00:00
|
|
|
return;
|
|
|
|
}
|
2022-08-29 02:19:20 +00:00
|
|
|
SetX86Protected(GetIndexFromX86Reg(x86Hi), true);
|
2016-01-27 09:11:59 +00:00
|
|
|
|
|
|
|
x86lo = FreeX86Reg();
|
2022-10-10 00:22:17 +00:00
|
|
|
if (x86lo < 0)
|
|
|
|
{
|
|
|
|
g_Notify->DisplayError("Map_GPR_64bit\n\nOut of registers");
|
|
|
|
return;
|
|
|
|
}
|
2022-08-29 02:19:20 +00:00
|
|
|
SetX86Protected(GetIndexFromX86Reg(x86lo), true);
|
2016-01-27 09:11:59 +00:00
|
|
|
|
2022-08-15 03:09:34 +00:00
|
|
|
m_CodeBlock.Log(" regcache: allocate %s to hi word of %s", CX86Ops::x86_Name(x86Hi), CRegName::GPR[MipsReg]);
|
|
|
|
m_CodeBlock.Log(" regcache: allocate %s to low word of %s", CX86Ops::x86_Name(x86lo), CRegName::GPR[MipsReg]);
|
2016-01-27 09:11:59 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
x86lo = GetMipsRegMapLo(MipsReg);
|
|
|
|
if (Is32Bit(MipsReg))
|
|
|
|
{
|
2022-08-29 02:19:20 +00:00
|
|
|
SetX86Protected(GetIndexFromX86Reg(x86lo), true);
|
2016-01-27 09:11:59 +00:00
|
|
|
x86Hi = FreeX86Reg();
|
2022-08-15 03:09:34 +00:00
|
|
|
if (x86Hi == CX86Ops::x86_Unknown)
|
2016-01-27 09:11:59 +00:00
|
|
|
{
|
|
|
|
g_Notify->BreakPoint(__FILE__, __LINE__);
|
|
|
|
return;
|
|
|
|
}
|
2022-08-29 02:19:20 +00:00
|
|
|
SetX86Protected(GetIndexFromX86Reg(x86Hi), true);
|
2016-01-27 09:11:59 +00:00
|
|
|
|
2022-08-15 03:09:34 +00:00
|
|
|
m_CodeBlock.Log(" regcache: allocate %s to hi word of %s", CX86Ops::x86_Name(x86Hi), CRegName::GPR[MipsReg]);
|
2016-01-27 09:11:59 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
x86Hi = GetMipsRegMapHi(MipsReg);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-08-29 02:19:20 +00:00
|
|
|
for (uint32_t i = 0; i < x86RegIndex_Size; i++)
|
2016-01-27 09:11:59 +00:00
|
|
|
{
|
2022-08-29 02:19:20 +00:00
|
|
|
uint32_t MapOrder = GetX86MapOrder((x86RegIndex)i);
|
2016-01-27 09:11:59 +00:00
|
|
|
if (MapOrder > 0)
|
|
|
|
{
|
2022-08-29 02:19:20 +00:00
|
|
|
SetX86MapOrder((x86RegIndex)i, MapOrder + 1);
|
2016-01-27 09:11:59 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-08-29 02:19:20 +00:00
|
|
|
SetX86MapOrder(GetIndexFromX86Reg(x86Hi), 1);
|
|
|
|
SetX86MapOrder(GetIndexFromX86Reg(x86lo), 1);
|
2016-01-27 09:11:59 +00:00
|
|
|
if (MipsRegToLoad > 0)
|
|
|
|
{
|
|
|
|
if (IsUnknown(MipsRegToLoad))
|
|
|
|
{
|
2022-08-15 03:09:34 +00:00
|
|
|
m_Assembler.MoveVariableToX86reg(&_GPR[MipsRegToLoad].UW[1], CRegName::GPR_Hi[MipsRegToLoad], x86Hi);
|
|
|
|
m_Assembler.MoveVariableToX86reg(&_GPR[MipsRegToLoad].UW[0], CRegName::GPR_Lo[MipsRegToLoad], x86lo);
|
2016-01-27 09:11:59 +00:00
|
|
|
}
|
|
|
|
else if (IsMapped(MipsRegToLoad))
|
|
|
|
{
|
|
|
|
if (Is32Bit(MipsRegToLoad))
|
|
|
|
{
|
|
|
|
if (IsSigned(MipsRegToLoad))
|
|
|
|
{
|
2022-08-15 03:09:34 +00:00
|
|
|
m_Assembler.MoveX86RegToX86Reg(GetMipsRegMapLo(MipsRegToLoad), x86Hi);
|
|
|
|
m_Assembler.ShiftRightSignImmed(x86Hi, 31);
|
2016-01-27 09:11:59 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2022-08-15 03:09:34 +00:00
|
|
|
m_Assembler.XorX86RegToX86Reg(x86Hi, x86Hi);
|
2016-01-27 09:11:59 +00:00
|
|
|
}
|
|
|
|
if (MipsReg != MipsRegToLoad)
|
|
|
|
{
|
2022-08-15 03:09:34 +00:00
|
|
|
m_Assembler.MoveX86RegToX86Reg(GetMipsRegMapLo(MipsRegToLoad), x86lo);
|
2016-01-27 09:11:59 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (MipsReg != MipsRegToLoad)
|
|
|
|
{
|
2022-08-15 03:09:34 +00:00
|
|
|
m_Assembler.MoveX86RegToX86Reg(GetMipsRegMapHi(MipsRegToLoad), x86Hi);
|
|
|
|
m_Assembler.MoveX86RegToX86Reg(GetMipsRegMapLo(MipsRegToLoad), x86lo);
|
2016-01-27 09:11:59 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2022-08-08 10:52:51 +00:00
|
|
|
m_CodeBlock.Log("Map_GPR_64bit 11");
|
2016-01-27 09:11:59 +00:00
|
|
|
if (Is32Bit(MipsRegToLoad))
|
|
|
|
{
|
|
|
|
if (IsSigned(MipsRegToLoad))
|
|
|
|
{
|
2022-08-15 03:09:34 +00:00
|
|
|
m_Assembler.MoveConstToX86reg(GetMipsRegLo_S(MipsRegToLoad) >> 31, x86Hi);
|
2016-01-27 09:11:59 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2022-08-15 03:09:34 +00:00
|
|
|
m_Assembler.MoveConstToX86reg(0, x86Hi);
|
2016-01-27 09:11:59 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2022-08-15 03:09:34 +00:00
|
|
|
m_Assembler.MoveConstToX86reg(GetMipsRegHi(MipsRegToLoad), x86Hi);
|
2016-01-27 09:11:59 +00:00
|
|
|
}
|
2022-08-15 03:09:34 +00:00
|
|
|
m_Assembler.MoveConstToX86reg(GetMipsRegLo(MipsRegToLoad), x86lo);
|
2016-01-27 09:11:59 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (MipsRegToLoad == 0)
|
|
|
|
{
|
2022-08-15 03:09:34 +00:00
|
|
|
m_Assembler.XorX86RegToX86Reg(x86Hi, x86Hi);
|
|
|
|
m_Assembler.XorX86RegToX86Reg(x86lo, x86lo);
|
2016-01-27 09:11:59 +00:00
|
|
|
}
|
2022-08-29 02:19:20 +00:00
|
|
|
SetX86Mapped(GetIndexFromX86Reg(x86Hi), GPR_Mapped);
|
|
|
|
SetX86Mapped(GetIndexFromX86Reg(x86lo), GPR_Mapped);
|
2016-01-27 09:11:59 +00:00
|
|
|
SetMipsRegMapHi(MipsReg, x86Hi);
|
|
|
|
SetMipsRegMapLo(MipsReg, x86lo);
|
|
|
|
SetMipsRegState(MipsReg, STATE_MAPPED_64);
|
|
|
|
}
|
|
|
|
|
2022-09-11 20:31:43 +00:00
|
|
|
CX86Ops::x86Reg CX86RegInfo::Map_TempReg(CX86Ops::x86Reg Reg, int32_t MipsReg, bool LoadHiWord, bool Reg8Bit)
|
2016-01-27 09:11:59 +00:00
|
|
|
{
|
2022-09-11 20:31:43 +00:00
|
|
|
if (!Reg8Bit && Reg == CX86Ops::x86_Unknown)
|
2016-01-27 09:11:59 +00:00
|
|
|
{
|
2022-10-10 00:22:17 +00:00
|
|
|
if (GetX86Mapped(x86RegIndex_EAX) == Temp_Mapped && !GetX86Protected(x86RegIndex_EAX))
|
|
|
|
{
|
|
|
|
Reg = CX86Ops::x86_EAX;
|
|
|
|
}
|
|
|
|
else if (GetX86Mapped(x86RegIndex_EBX) == Temp_Mapped && !GetX86Protected(x86RegIndex_EBX))
|
|
|
|
{
|
|
|
|
Reg = CX86Ops::x86_EBX;
|
|
|
|
}
|
|
|
|
else if (GetX86Mapped(x86RegIndex_ECX) == Temp_Mapped && !GetX86Protected(x86RegIndex_ECX))
|
|
|
|
{
|
|
|
|
Reg = CX86Ops::x86_ECX;
|
|
|
|
}
|
|
|
|
else if (GetX86Mapped(x86RegIndex_EDX) == Temp_Mapped && !GetX86Protected(x86RegIndex_EDX))
|
|
|
|
{
|
|
|
|
Reg = CX86Ops::x86_EDX;
|
|
|
|
}
|
|
|
|
else if (GetX86Mapped(x86RegIndex_ESI) == Temp_Mapped && !GetX86Protected(x86RegIndex_ESI))
|
|
|
|
{
|
|
|
|
Reg = CX86Ops::x86_ESI;
|
|
|
|
}
|
|
|
|
else if (GetX86Mapped(x86RegIndex_EDI) == Temp_Mapped && !GetX86Protected(x86RegIndex_EDI))
|
|
|
|
{
|
|
|
|
Reg = CX86Ops::x86_EDI;
|
|
|
|
}
|
|
|
|
else if (GetX86Mapped(x86RegIndex_EBP) == Temp_Mapped && !GetX86Protected(x86RegIndex_EBP))
|
|
|
|
{
|
|
|
|
Reg = CX86Ops::x86_EBP;
|
|
|
|
}
|
|
|
|
else if (GetX86Mapped(x86RegIndex_ESP) == Temp_Mapped && !GetX86Protected(x86RegIndex_ESP))
|
|
|
|
{
|
|
|
|
Reg = CX86Ops::x86_ESP;
|
|
|
|
}
|
2016-01-27 09:11:59 +00:00
|
|
|
|
2022-09-11 20:31:43 +00:00
|
|
|
if (Reg == CX86Ops::x86_Unknown)
|
2016-01-27 09:11:59 +00:00
|
|
|
{
|
|
|
|
Reg = FreeX86Reg();
|
2022-08-15 03:09:34 +00:00
|
|
|
if (Reg == CX86Ops::x86_Unknown)
|
2016-01-27 09:11:59 +00:00
|
|
|
{
|
|
|
|
WriteTrace(TraceRegisterCache, TraceError, "Failed to find a free register");
|
|
|
|
g_Notify->BreakPoint(__FILE__, __LINE__);
|
2022-08-15 03:09:34 +00:00
|
|
|
return CX86Ops::x86_Unknown;
|
2016-01-27 09:11:59 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2022-09-11 20:31:43 +00:00
|
|
|
else if (Reg8Bit && Reg == CX86Ops::x86_Unknown)
|
2016-01-27 09:11:59 +00:00
|
|
|
{
|
2022-10-10 00:22:17 +00:00
|
|
|
if (GetX86Mapped(x86RegIndex_EAX) == Temp_Mapped && !GetX86Protected(x86RegIndex_EAX))
|
|
|
|
{
|
|
|
|
Reg = CX86Ops::x86_EAX;
|
|
|
|
}
|
|
|
|
else if (GetX86Mapped(x86RegIndex_EBX) == Temp_Mapped && !GetX86Protected(x86RegIndex_EBX))
|
|
|
|
{
|
|
|
|
Reg = CX86Ops::x86_EBX;
|
|
|
|
}
|
|
|
|
else if (GetX86Mapped(x86RegIndex_ECX) == Temp_Mapped && !GetX86Protected(x86RegIndex_ECX))
|
|
|
|
{
|
|
|
|
Reg = CX86Ops::x86_ECX;
|
|
|
|
}
|
|
|
|
else if (GetX86Mapped(x86RegIndex_EDX) == Temp_Mapped && !GetX86Protected(x86RegIndex_EDX))
|
|
|
|
{
|
|
|
|
Reg = CX86Ops::x86_EDX;
|
|
|
|
}
|
2016-01-27 09:11:59 +00:00
|
|
|
|
2022-09-11 20:31:43 +00:00
|
|
|
if (Reg == CX86Ops::x86_Unknown)
|
2016-01-27 09:11:59 +00:00
|
|
|
{
|
|
|
|
Reg = Free8BitX86Reg();
|
|
|
|
if (Reg < 0)
|
|
|
|
{
|
2021-05-18 11:51:36 +00:00
|
|
|
WriteTrace(TraceRegisterCache, TraceError, "Failed to find a free 8-bit register");
|
2016-01-27 09:11:59 +00:00
|
|
|
g_Notify->BreakPoint(__FILE__, __LINE__);
|
2022-08-15 03:09:34 +00:00
|
|
|
return CX86Ops::x86_Unknown;
|
2016-01-27 09:11:59 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2022-08-29 02:19:20 +00:00
|
|
|
else if (GetX86Mapped(GetIndexFromX86Reg(Reg)) == GPR_Mapped)
|
2016-01-27 09:11:59 +00:00
|
|
|
{
|
2022-08-29 02:19:20 +00:00
|
|
|
if (GetX86Protected(GetIndexFromX86Reg(Reg)))
|
2016-01-27 09:11:59 +00:00
|
|
|
{
|
|
|
|
WriteTrace(TraceRegisterCache, TraceError, "Register is protected");
|
|
|
|
g_Notify->BreakPoint(__FILE__, __LINE__);
|
2022-08-15 03:09:34 +00:00
|
|
|
return CX86Ops::x86_Unknown;
|
2016-01-27 09:11:59 +00:00
|
|
|
}
|
|
|
|
|
2022-08-29 02:19:20 +00:00
|
|
|
SetX86Protected(GetIndexFromX86Reg(Reg), true);
|
2022-08-15 03:09:34 +00:00
|
|
|
CX86Ops::x86Reg NewReg = FreeX86Reg();
|
2022-08-29 02:19:20 +00:00
|
|
|
for (uint32_t i = 1; i < 32; i++)
|
2016-01-27 09:11:59 +00:00
|
|
|
{
|
2022-08-29 02:19:20 +00:00
|
|
|
if (!IsMapped(i))
|
2016-01-27 09:11:59 +00:00
|
|
|
{
|
|
|
|
continue;
|
|
|
|
}
|
2022-08-29 02:19:20 +00:00
|
|
|
if (GetMipsRegMapLo(i) == Reg)
|
2016-01-27 09:11:59 +00:00
|
|
|
{
|
2022-08-15 03:09:34 +00:00
|
|
|
if (NewReg == CX86Ops::x86_Unknown)
|
2016-01-27 09:11:59 +00:00
|
|
|
{
|
2022-08-29 02:19:20 +00:00
|
|
|
UnMap_GPR(i, true);
|
2016-01-27 09:11:59 +00:00
|
|
|
break;
|
|
|
|
}
|
2022-08-29 02:19:20 +00:00
|
|
|
m_CodeBlock.Log(" regcache: change allocation of %s from %s to %s", CRegName::GPR[i], CX86Ops::x86_Name(Reg), CX86Ops::x86_Name(NewReg));
|
|
|
|
SetX86Mapped(GetIndexFromX86Reg(NewReg), GPR_Mapped);
|
|
|
|
SetX86MapOrder(GetIndexFromX86Reg(NewReg), GetX86MapOrder(GetIndexFromX86Reg(Reg)));
|
|
|
|
SetMipsRegMapLo(i, NewReg);
|
2022-08-15 03:09:34 +00:00
|
|
|
m_Assembler.MoveX86RegToX86Reg(Reg, NewReg);
|
2022-08-29 02:19:20 +00:00
|
|
|
if (MipsReg == (int32_t)i && !LoadHiWord)
|
2016-01-27 09:11:59 +00:00
|
|
|
{
|
|
|
|
MipsReg = -1;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
2022-08-29 02:19:20 +00:00
|
|
|
if (Is64Bit(i) && GetMipsRegMapHi(i) == Reg)
|
2016-01-27 09:11:59 +00:00
|
|
|
{
|
2022-08-15 03:09:34 +00:00
|
|
|
if (NewReg == CX86Ops::x86_Unknown)
|
2016-01-27 09:11:59 +00:00
|
|
|
{
|
2022-08-29 02:19:20 +00:00
|
|
|
UnMap_GPR(i, true);
|
2016-01-27 09:11:59 +00:00
|
|
|
break;
|
|
|
|
}
|
2022-08-29 02:19:20 +00:00
|
|
|
m_CodeBlock.Log(" regcache: change allocation of %s from %s to %s", CRegName::GPR_Hi[i], CX86Ops::x86_Name(Reg), CX86Ops::x86_Name(NewReg));
|
|
|
|
SetX86Mapped(GetIndexFromX86Reg(NewReg), GPR_Mapped);
|
|
|
|
SetX86MapOrder(GetIndexFromX86Reg(NewReg), GetX86MapOrder(GetIndexFromX86Reg(Reg)));
|
|
|
|
SetMipsRegMapHi(i, NewReg);
|
2022-08-15 03:09:34 +00:00
|
|
|
m_Assembler.MoveX86RegToX86Reg(Reg, NewReg);
|
2022-08-29 02:19:20 +00:00
|
|
|
if (MipsReg == (int32_t)i && LoadHiWord)
|
2016-01-27 09:11:59 +00:00
|
|
|
{
|
|
|
|
MipsReg = -1;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2022-08-29 02:19:20 +00:00
|
|
|
else if (GetX86Mapped(GetIndexFromX86Reg(Reg)) == Stack_Mapped)
|
2016-01-27 09:11:59 +00:00
|
|
|
{
|
|
|
|
UnMap_X86reg(Reg);
|
|
|
|
}
|
2022-08-15 03:09:34 +00:00
|
|
|
m_CodeBlock.Log(" regcache: allocate %s as temp storage", CX86Ops::x86_Name(Reg));
|
2016-01-27 09:11:59 +00:00
|
|
|
|
|
|
|
if (MipsReg >= 0)
|
|
|
|
{
|
|
|
|
if (LoadHiWord)
|
|
|
|
{
|
|
|
|
if (IsUnknown(MipsReg))
|
|
|
|
{
|
2022-08-15 03:09:34 +00:00
|
|
|
m_Assembler.MoveVariableToX86reg(&_GPR[MipsReg].UW[1], CRegName::GPR_Hi[MipsReg], Reg);
|
2016-01-27 09:11:59 +00:00
|
|
|
}
|
|
|
|
else if (IsMapped(MipsReg))
|
|
|
|
{
|
|
|
|
if (Is64Bit(MipsReg))
|
|
|
|
{
|
2022-08-15 03:09:34 +00:00
|
|
|
m_Assembler.MoveX86RegToX86Reg(GetMipsRegMapHi(MipsReg), Reg);
|
2016-01-27 09:11:59 +00:00
|
|
|
}
|
|
|
|
else if (IsSigned(MipsReg))
|
|
|
|
{
|
2022-08-15 03:09:34 +00:00
|
|
|
m_Assembler.MoveX86RegToX86Reg(GetMipsRegMapLo(MipsReg), Reg);
|
|
|
|
m_Assembler.ShiftRightSignImmed(Reg, 31);
|
2016-01-27 09:11:59 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2022-08-15 03:09:34 +00:00
|
|
|
m_Assembler.MoveConstToX86reg(0, Reg);
|
2016-01-27 09:11:59 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (Is64Bit(MipsReg))
|
|
|
|
{
|
2022-08-15 03:09:34 +00:00
|
|
|
m_Assembler.MoveConstToX86reg(GetMipsRegHi(MipsReg), Reg);
|
2016-01-27 09:11:59 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2022-08-15 03:09:34 +00:00
|
|
|
m_Assembler.MoveConstToX86reg(GetMipsRegLo_S(MipsReg) >> 31, Reg);
|
2016-01-27 09:11:59 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (IsUnknown(MipsReg))
|
|
|
|
{
|
2022-08-15 03:09:34 +00:00
|
|
|
m_Assembler.MoveVariableToX86reg(&_GPR[MipsReg].UW[0], CRegName::GPR_Lo[MipsReg], Reg);
|
2016-01-27 09:11:59 +00:00
|
|
|
}
|
|
|
|
else if (IsMapped(MipsReg))
|
|
|
|
{
|
2022-08-15 03:09:34 +00:00
|
|
|
m_Assembler.MoveX86RegToX86Reg(GetMipsRegMapLo(MipsReg), Reg);
|
2016-01-27 09:11:59 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2022-08-15 03:09:34 +00:00
|
|
|
m_Assembler.MoveConstToX86reg(GetMipsRegLo(MipsReg), Reg);
|
2016-01-27 09:11:59 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2022-08-29 02:19:20 +00:00
|
|
|
SetX86Mapped(GetIndexFromX86Reg(Reg), Temp_Mapped);
|
|
|
|
SetX86Protected(GetIndexFromX86Reg(Reg), true);
|
|
|
|
for (uint32_t i = 0; i < x86RegIndex_Size; i++)
|
2016-01-27 09:11:59 +00:00
|
|
|
{
|
2022-08-29 02:19:20 +00:00
|
|
|
int32_t MapOrder = GetX86MapOrder((x86RegIndex)i);
|
2016-01-27 09:11:59 +00:00
|
|
|
if (MapOrder > 0)
|
|
|
|
{
|
2022-08-29 02:19:20 +00:00
|
|
|
SetX86MapOrder((x86RegIndex)i, MapOrder + 1);
|
2016-01-27 09:11:59 +00:00
|
|
|
}
|
|
|
|
}
|
2022-08-29 02:19:20 +00:00
|
|
|
SetX86MapOrder(GetIndexFromX86Reg(Reg), 1);
|
2016-01-27 09:11:59 +00:00
|
|
|
return Reg;
|
|
|
|
}
|
|
|
|
|
2022-09-11 20:31:43 +00:00
|
|
|
void CX86RegInfo::ProtectGPR(uint32_t MipsReg)
|
2016-01-27 09:11:59 +00:00
|
|
|
{
|
2022-09-11 20:31:43 +00:00
|
|
|
if (IsUnknown(MipsReg) || IsConst(MipsReg))
|
2016-01-27 09:11:59 +00:00
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
2022-09-11 20:31:43 +00:00
|
|
|
if (Is64Bit(MipsReg))
|
2016-01-27 09:11:59 +00:00
|
|
|
{
|
2022-09-11 20:31:43 +00:00
|
|
|
SetX86Protected(GetIndexFromX86Reg(GetMipsRegMapHi(MipsReg)), true);
|
2016-01-27 09:11:59 +00:00
|
|
|
}
|
2022-09-11 20:31:43 +00:00
|
|
|
SetX86Protected(GetIndexFromX86Reg(GetMipsRegMapLo(MipsReg)), true);
|
2016-01-27 09:11:59 +00:00
|
|
|
}
|
|
|
|
|
2016-06-27 11:49:15 +00:00
|
|
|
void CX86RegInfo::UnProtectGPR(uint32_t Reg)
|
2016-01-27 09:11:59 +00:00
|
|
|
{
|
|
|
|
if (IsUnknown(Reg) || IsConst(Reg))
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (Is64Bit(Reg))
|
|
|
|
{
|
2022-08-29 02:19:20 +00:00
|
|
|
SetX86Protected(GetIndexFromX86Reg(GetMipsRegMapHi(Reg)), false);
|
2016-01-27 09:11:59 +00:00
|
|
|
}
|
2022-08-29 02:19:20 +00:00
|
|
|
SetX86Protected(GetIndexFromX86Reg(GetMipsRegMapLo(Reg)), false);
|
2016-01-27 09:11:59 +00:00
|
|
|
}
|
|
|
|
|
2016-06-27 11:49:15 +00:00
|
|
|
void CX86RegInfo::ResetX86Protection()
|
2016-01-27 09:11:59 +00:00
|
|
|
{
|
2022-08-29 02:19:20 +00:00
|
|
|
for (int32_t i = 0; i < x86RegIndex_Size; i++)
|
2016-01-27 09:11:59 +00:00
|
|
|
{
|
2022-08-29 02:19:20 +00:00
|
|
|
SetX86Protected((x86RegIndex)i, false);
|
2016-01-27 09:11:59 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-06-27 11:49:15 +00:00
|
|
|
bool CX86RegInfo::RegInStack(int32_t Reg, FPU_STATE Format)
|
2016-01-27 09:11:59 +00:00
|
|
|
{
|
|
|
|
for (int32_t i = 0; i < 8; i++)
|
|
|
|
{
|
|
|
|
if (m_x86fpu_MappedTo[i] == Reg)
|
|
|
|
{
|
|
|
|
if (m_x86fpu_State[i] == Format || Format == FPU_Any)
|
|
|
|
{
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2016-06-27 11:49:15 +00:00
|
|
|
void CX86RegInfo::UnMap_AllFPRs()
|
2016-01-27 09:11:59 +00:00
|
|
|
{
|
|
|
|
for (;;)
|
|
|
|
{
|
|
|
|
int32_t StackPos = StackTopPos();
|
|
|
|
if (m_x86fpu_MappedTo[StackPos] != -1)
|
|
|
|
{
|
|
|
|
UnMap_FPR(m_x86fpu_MappedTo[StackPos], true);
|
|
|
|
continue;
|
|
|
|
}
|
2021-05-18 11:51:36 +00:00
|
|
|
// See if any more registers mapped
|
2016-01-27 09:11:59 +00:00
|
|
|
int32_t StartPos = StackTopPos();
|
|
|
|
for (int32_t i = 0; i < 8; i++)
|
|
|
|
{
|
2022-10-10 00:22:17 +00:00
|
|
|
if (m_x86fpu_MappedTo[(StartPos + i) & 7] != -1)
|
|
|
|
{
|
|
|
|
m_Assembler.fpuIncStack(&StackTopPos());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (StackPos != StackTopPos())
|
|
|
|
{
|
|
|
|
continue;
|
2016-01-27 09:11:59 +00:00
|
|
|
}
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-06-27 11:49:15 +00:00
|
|
|
void CX86RegInfo::UnMap_FPR(int32_t Reg, bool WriteBackValue)
|
2016-01-27 09:11:59 +00:00
|
|
|
{
|
2022-10-10 00:22:17 +00:00
|
|
|
if (Reg < 0)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
2022-10-10 03:08:43 +00:00
|
|
|
for (int32_t i = 0; i < 8; i++)
|
2016-01-27 09:11:59 +00:00
|
|
|
{
|
2022-10-10 00:22:17 +00:00
|
|
|
if (m_x86fpu_MappedTo[i] != Reg)
|
|
|
|
{
|
|
|
|
continue;
|
|
|
|
}
|
2022-08-08 10:52:51 +00:00
|
|
|
m_CodeBlock.Log(" regcache: unallocate %s from ST(%d)", CRegName::FPR[Reg], (i - StackTopPos() + 8) & 7);
|
2016-01-27 09:11:59 +00:00
|
|
|
if (WriteBackValue)
|
|
|
|
{
|
|
|
|
int32_t RegPos;
|
|
|
|
|
|
|
|
if (((i - StackTopPos() + 8) & 7) != 0)
|
|
|
|
{
|
|
|
|
if (m_x86fpu_MappedTo[StackTopPos()] == -1 && m_x86fpu_MappedTo[(StackTopPos() + 1) & 7] == Reg)
|
|
|
|
{
|
2022-08-15 03:09:34 +00:00
|
|
|
m_Assembler.fpuIncStack(&StackTopPos());
|
2016-01-27 09:11:59 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2016-06-27 11:49:15 +00:00
|
|
|
CX86RegInfo::FPU_ROUND RoundingModel = FpuRoundingModel(StackTopPos());
|
2016-01-27 09:11:59 +00:00
|
|
|
FPU_STATE RegState = m_x86fpu_State[StackTopPos()];
|
|
|
|
bool Changed = m_x86fpu_StateChanged[StackTopPos()];
|
|
|
|
uint32_t MappedTo = m_x86fpu_MappedTo[StackTopPos()];
|
|
|
|
FpuRoundingModel(StackTopPos()) = FpuRoundingModel(i);
|
|
|
|
m_x86fpu_MappedTo[StackTopPos()] = m_x86fpu_MappedTo[i];
|
|
|
|
m_x86fpu_State[StackTopPos()] = m_x86fpu_State[i];
|
|
|
|
m_x86fpu_StateChanged[StackTopPos()] = m_x86fpu_StateChanged[i];
|
|
|
|
FpuRoundingModel(i) = RoundingModel;
|
|
|
|
m_x86fpu_MappedTo[i] = MappedTo;
|
|
|
|
m_x86fpu_State[i] = RegState;
|
|
|
|
m_x86fpu_StateChanged[i] = Changed;
|
2022-08-15 03:09:34 +00:00
|
|
|
m_Assembler.fpuExchange((CX86Ops::x86FpuValues)((i - StackTopPos()) & 7));
|
2016-01-27 09:11:59 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
FixRoundModel(FpuRoundingModel(i));
|
|
|
|
|
|
|
|
RegPos = StackTopPos();
|
2022-09-11 20:31:43 +00:00
|
|
|
CX86Ops::x86Reg TempReg = Map_TempReg(CX86Ops::x86_Unknown, -1, false, false);
|
2016-01-27 09:11:59 +00:00
|
|
|
switch (m_x86fpu_State[StackTopPos()])
|
|
|
|
{
|
|
|
|
case FPU_Dword:
|
2022-10-10 03:08:43 +00:00
|
|
|
m_Assembler.MoveVariableToX86reg(&_FPR_S[m_x86fpu_MappedTo[StackTopPos()]], stdstr_f("_FPR_S[%d]", m_x86fpu_MappedTo[StackTopPos()]).c_str(), TempReg);
|
2022-08-15 03:09:34 +00:00
|
|
|
m_Assembler.fpuStoreIntegerDwordFromX86Reg(&StackTopPos(), TempReg, true);
|
2016-01-27 09:11:59 +00:00
|
|
|
break;
|
|
|
|
case FPU_Qword:
|
2022-10-10 03:08:43 +00:00
|
|
|
m_Assembler.MoveVariableToX86reg(&_FPR_D[m_x86fpu_MappedTo[StackTopPos()]], stdstr_f("_FPR_D[%d]", m_x86fpu_MappedTo[StackTopPos()]).c_str(), TempReg);
|
2022-08-15 03:09:34 +00:00
|
|
|
m_Assembler.fpuStoreIntegerQwordFromX86Reg(&StackTopPos(), TempReg, true);
|
2016-01-27 09:11:59 +00:00
|
|
|
break;
|
|
|
|
case FPU_Float:
|
2022-10-10 03:08:43 +00:00
|
|
|
m_Assembler.MoveVariableToX86reg(&_FPR_S[m_x86fpu_MappedTo[StackTopPos()]], stdstr_f("_FPR_S[%d]", m_x86fpu_MappedTo[StackTopPos()]).c_str(), TempReg);
|
2022-08-15 03:09:34 +00:00
|
|
|
m_Assembler.fpuStoreDwordFromX86Reg(&StackTopPos(), TempReg, true);
|
2016-01-27 09:11:59 +00:00
|
|
|
break;
|
|
|
|
case FPU_Double:
|
2022-10-10 03:08:43 +00:00
|
|
|
m_Assembler.MoveVariableToX86reg(&_FPR_D[m_x86fpu_MappedTo[StackTopPos()]], stdstr_f("_FPR_D[%d]", m_x86fpu_MappedTo[StackTopPos()]).c_str(), TempReg);
|
2022-08-15 03:09:34 +00:00
|
|
|
m_Assembler.fpuStoreQwordFromX86Reg(&StackTopPos(), TempReg, true);
|
2016-01-27 09:11:59 +00:00
|
|
|
break;
|
|
|
|
default:
|
2018-01-15 21:23:21 +00:00
|
|
|
if (HaveDebugger())
|
2016-01-27 09:11:59 +00:00
|
|
|
{
|
|
|
|
g_Notify->DisplayError(stdstr_f("%s\nUnknown format to load %d", __FUNCTION__, m_x86fpu_State[StackTopPos()]).c_str());
|
|
|
|
}
|
|
|
|
}
|
2022-08-29 02:19:20 +00:00
|
|
|
SetX86Protected(GetIndexFromX86Reg(TempReg), false);
|
2016-01-27 09:11:59 +00:00
|
|
|
FpuRoundingModel(RegPos) = RoundDefault;
|
|
|
|
m_x86fpu_MappedTo[RegPos] = -1;
|
|
|
|
m_x86fpu_State[RegPos] = FPU_Unknown;
|
|
|
|
m_x86fpu_StateChanged[RegPos] = false;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2022-08-15 03:09:34 +00:00
|
|
|
m_Assembler.fpuFree((CX86Ops::x86FpuValues)((i - StackTopPos()) & 7));
|
2016-01-27 09:11:59 +00:00
|
|
|
FpuRoundingModel(i) = RoundDefault;
|
|
|
|
m_x86fpu_MappedTo[i] = -1;
|
|
|
|
m_x86fpu_State[i] = FPU_Unknown;
|
|
|
|
m_x86fpu_StateChanged[i] = false;
|
|
|
|
}
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-06-27 11:49:15 +00:00
|
|
|
void CX86RegInfo::UnMap_GPR(uint32_t Reg, bool WriteBackValue)
|
2016-01-27 09:11:59 +00:00
|
|
|
{
|
|
|
|
if (Reg == 0)
|
|
|
|
{
|
2018-01-15 21:23:21 +00:00
|
|
|
if (HaveDebugger())
|
2016-01-27 09:11:59 +00:00
|
|
|
{
|
2021-05-18 11:51:36 +00:00
|
|
|
g_Notify->DisplayError(stdstr_f("%s\n\nWhy are you trying to unmap register 0?", __FUNCTION__).c_str());
|
2016-01-27 09:11:59 +00:00
|
|
|
}
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2022-10-10 00:22:17 +00:00
|
|
|
if (IsUnknown(Reg))
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
2022-08-08 10:52:51 +00:00
|
|
|
//m_CodeBlock.Log("UnMap_GPR: State: %X\tReg: %s\tWriteBack: %s",State,CRegName::GPR[Reg],WriteBackValue?"true":"false");
|
2016-01-27 09:11:59 +00:00
|
|
|
if (IsConst(Reg))
|
|
|
|
{
|
|
|
|
if (!WriteBackValue)
|
|
|
|
{
|
|
|
|
SetMipsRegState(Reg, STATE_UNKNOWN);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (Is64Bit(Reg))
|
|
|
|
{
|
2022-08-15 03:09:34 +00:00
|
|
|
m_Assembler.MoveConstToVariable(GetMipsRegHi(Reg), &_GPR[Reg].UW[1], CRegName::GPR_Hi[Reg]);
|
|
|
|
m_Assembler.MoveConstToVariable(GetMipsRegLo(Reg), &_GPR[Reg].UW[0], CRegName::GPR_Lo[Reg]);
|
2016-01-27 09:11:59 +00:00
|
|
|
SetMipsRegState(Reg, STATE_UNKNOWN);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if ((GetMipsRegLo(Reg) & 0x80000000) != 0)
|
|
|
|
{
|
2022-08-15 03:09:34 +00:00
|
|
|
m_Assembler.MoveConstToVariable(0xFFFFFFFF, &_GPR[Reg].UW[1], CRegName::GPR_Hi[Reg]);
|
2016-01-27 09:11:59 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2022-08-15 03:09:34 +00:00
|
|
|
m_Assembler.MoveConstToVariable(0, &_GPR[Reg].UW[1], CRegName::GPR_Hi[Reg]);
|
2016-01-27 09:11:59 +00:00
|
|
|
}
|
2022-08-15 03:09:34 +00:00
|
|
|
m_Assembler.MoveConstToVariable(GetMipsRegLo(Reg), &_GPR[Reg].UW[0], CRegName::GPR_Lo[Reg]);
|
2016-01-27 09:11:59 +00:00
|
|
|
SetMipsRegState(Reg, STATE_UNKNOWN);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (Is64Bit(Reg))
|
|
|
|
{
|
2022-08-15 03:09:34 +00:00
|
|
|
m_CodeBlock.Log(" regcache: unallocate %s from %s", CX86Ops::x86_Name(GetMipsRegMapHi(Reg)), CRegName::GPR_Hi[Reg]);
|
2022-08-29 02:19:20 +00:00
|
|
|
SetX86Mapped(GetIndexFromX86Reg(GetMipsRegMapHi(Reg)), NotMapped);
|
|
|
|
SetX86Protected(GetIndexFromX86Reg(GetMipsRegMapHi(Reg)), false);
|
2016-01-27 09:11:59 +00:00
|
|
|
}
|
2022-08-15 03:09:34 +00:00
|
|
|
m_CodeBlock.Log(" regcache: unallocate %s from %s", CX86Ops::x86_Name(GetMipsRegMapLo(Reg)), CRegName::GPR_Lo[Reg]);
|
2022-09-11 20:31:43 +00:00
|
|
|
x86RegIndex RegIndex = GetIndexFromX86Reg(GetMipsRegMapLo(Reg));
|
|
|
|
SetX86Mapped(RegIndex, NotMapped);
|
|
|
|
SetX86Protected(RegIndex, false);
|
2016-01-27 09:11:59 +00:00
|
|
|
if (!WriteBackValue)
|
|
|
|
{
|
|
|
|
SetMipsRegState(Reg, STATE_UNKNOWN);
|
|
|
|
return;
|
|
|
|
}
|
2022-08-15 03:09:34 +00:00
|
|
|
m_Assembler.MoveX86regToVariable(GetMipsRegMapLo(Reg), &_GPR[Reg].UW[0], CRegName::GPR_Lo[Reg]);
|
2016-01-27 09:11:59 +00:00
|
|
|
if (Is64Bit(Reg))
|
|
|
|
{
|
2022-08-15 03:09:34 +00:00
|
|
|
SetMipsRegMapLo(Reg, CX86Ops::x86_Unknown);
|
|
|
|
m_Assembler.MoveX86regToVariable(GetMipsRegMapHi(Reg), &_GPR[Reg].UW[1], CRegName::GPR_Hi[Reg]);
|
|
|
|
SetMipsRegMapHi(Reg, CX86Ops::x86_Unknown);
|
2016-01-27 09:11:59 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (!g_System->b32BitCore())
|
|
|
|
{
|
|
|
|
if (IsSigned(Reg))
|
|
|
|
{
|
2022-08-15 03:09:34 +00:00
|
|
|
m_Assembler.ShiftRightSignImmed(GetMipsRegMapLo(Reg), 31);
|
|
|
|
m_Assembler.MoveX86regToVariable(GetMipsRegMapLo(Reg), &_GPR[Reg].UW[1], CRegName::GPR_Hi[Reg]);
|
2016-01-27 09:11:59 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2022-08-15 03:09:34 +00:00
|
|
|
m_Assembler.MoveConstToVariable(0, &_GPR[Reg].UW[1], CRegName::GPR_Hi[Reg]);
|
2016-01-27 09:11:59 +00:00
|
|
|
}
|
|
|
|
}
|
2022-08-15 03:09:34 +00:00
|
|
|
SetMipsRegMapLo(Reg, CX86Ops::x86_Unknown);
|
2016-01-27 09:11:59 +00:00
|
|
|
}
|
|
|
|
SetMipsRegState(Reg, STATE_UNKNOWN);
|
|
|
|
}
|
|
|
|
|
2022-09-11 20:31:43 +00:00
|
|
|
CX86Ops::x86Reg CX86RegInfo::UnMap_TempReg()
|
2016-01-27 09:11:59 +00:00
|
|
|
{
|
2022-09-11 20:31:43 +00:00
|
|
|
CX86Ops::x86Reg Reg = CX86Ops::x86_Unknown;
|
2016-01-27 09:11:59 +00:00
|
|
|
|
2022-10-10 00:22:17 +00:00
|
|
|
if (GetX86Mapped(x86RegIndex_EAX) == Temp_Mapped && !GetX86Protected(x86RegIndex_EAX))
|
|
|
|
{
|
|
|
|
Reg = CX86Ops::x86_EAX;
|
|
|
|
}
|
|
|
|
else if (GetX86Mapped(x86RegIndex_EBX) == Temp_Mapped && !GetX86Protected(x86RegIndex_EBX))
|
|
|
|
{
|
|
|
|
Reg = CX86Ops::x86_EBX;
|
|
|
|
}
|
|
|
|
else if (GetX86Mapped(x86RegIndex_ECX) == Temp_Mapped && !GetX86Protected(x86RegIndex_ECX))
|
|
|
|
{
|
|
|
|
Reg = CX86Ops::x86_ECX;
|
|
|
|
}
|
|
|
|
else if (GetX86Mapped(x86RegIndex_EDX) == Temp_Mapped && !GetX86Protected(x86RegIndex_EDX))
|
|
|
|
{
|
|
|
|
Reg = CX86Ops::x86_EDX;
|
|
|
|
}
|
|
|
|
else if (GetX86Mapped(x86RegIndex_ESI) == Temp_Mapped && !GetX86Protected(x86RegIndex_ESI))
|
|
|
|
{
|
|
|
|
Reg = CX86Ops::x86_ESI;
|
|
|
|
}
|
|
|
|
else if (GetX86Mapped(x86RegIndex_EDI) == Temp_Mapped && !GetX86Protected(x86RegIndex_EDI))
|
|
|
|
{
|
|
|
|
Reg = CX86Ops::x86_EDI;
|
|
|
|
}
|
|
|
|
else if (GetX86Mapped(x86RegIndex_EBP) == Temp_Mapped && !GetX86Protected(x86RegIndex_EBP))
|
|
|
|
{
|
|
|
|
Reg = CX86Ops::x86_EBP;
|
|
|
|
}
|
|
|
|
else if (GetX86Mapped(x86RegIndex_ESP) == Temp_Mapped && !GetX86Protected(x86RegIndex_ESP))
|
|
|
|
{
|
|
|
|
Reg = CX86Ops::x86_ESP;
|
|
|
|
}
|
2016-01-27 09:11:59 +00:00
|
|
|
|
2022-08-15 03:09:34 +00:00
|
|
|
if (Reg != CX86Ops::x86_Unknown)
|
2016-01-27 09:11:59 +00:00
|
|
|
{
|
2022-08-29 02:19:20 +00:00
|
|
|
if (GetX86Mapped(GetIndexFromX86Reg(Reg)) == Temp_Mapped)
|
2016-01-27 09:11:59 +00:00
|
|
|
{
|
2022-08-15 03:09:34 +00:00
|
|
|
m_CodeBlock.Log(" regcache: unallocate %s from temp storage", CX86Ops::x86_Name(Reg));
|
2016-01-27 09:11:59 +00:00
|
|
|
}
|
2022-08-29 02:19:20 +00:00
|
|
|
SetX86Mapped(GetIndexFromX86Reg(Reg), NotMapped);
|
2016-01-27 09:11:59 +00:00
|
|
|
}
|
|
|
|
return Reg;
|
|
|
|
}
|
|
|
|
|
2022-08-29 02:19:20 +00:00
|
|
|
bool CX86RegInfo::UnMap_X86reg(CX86Ops::x86Reg Reg)
|
2016-01-27 09:11:59 +00:00
|
|
|
{
|
2022-09-11 20:31:43 +00:00
|
|
|
x86RegIndex RegIndex = GetIndexFromX86Reg(Reg);
|
|
|
|
if (GetX86Mapped(RegIndex) == NotMapped)
|
2016-01-27 09:11:59 +00:00
|
|
|
{
|
2022-09-11 20:31:43 +00:00
|
|
|
if (!GetX86Protected(RegIndex))
|
2016-01-27 09:11:59 +00:00
|
|
|
{
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
2022-09-11 20:31:43 +00:00
|
|
|
else if (GetX86Mapped(RegIndex) == CX86RegInfo::GPR_Mapped)
|
2016-01-27 09:11:59 +00:00
|
|
|
{
|
2022-09-11 20:31:43 +00:00
|
|
|
for (int i = 1; i < 32; i++)
|
2016-01-27 09:11:59 +00:00
|
|
|
{
|
2022-09-11 20:31:43 +00:00
|
|
|
if (!IsMapped(i))
|
2016-01-27 09:11:59 +00:00
|
|
|
{
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2022-09-11 20:31:43 +00:00
|
|
|
if (Is64Bit(i) && GetMipsRegMapHi(i) == Reg)
|
2016-01-27 09:11:59 +00:00
|
|
|
{
|
2022-09-11 20:31:43 +00:00
|
|
|
if (!GetX86Protected(RegIndex))
|
2016-01-27 09:11:59 +00:00
|
|
|
{
|
2022-09-11 20:31:43 +00:00
|
|
|
UnMap_GPR(i, true);
|
2016-01-27 09:11:59 +00:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
2022-09-11 20:31:43 +00:00
|
|
|
if (GetMipsRegMapLo(i) == Reg)
|
2016-01-27 09:11:59 +00:00
|
|
|
{
|
2022-09-11 20:31:43 +00:00
|
|
|
if (!GetX86Protected(RegIndex))
|
2016-01-27 09:11:59 +00:00
|
|
|
{
|
2022-09-11 20:31:43 +00:00
|
|
|
UnMap_GPR(i, true);
|
2016-01-27 09:11:59 +00:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2022-09-11 20:31:43 +00:00
|
|
|
else if (GetX86Mapped(RegIndex) == CX86RegInfo::Temp_Mapped)
|
2016-01-27 09:11:59 +00:00
|
|
|
{
|
2022-09-11 20:31:43 +00:00
|
|
|
if (!GetX86Protected(RegIndex))
|
2016-01-27 09:11:59 +00:00
|
|
|
{
|
2022-08-15 03:09:34 +00:00
|
|
|
m_CodeBlock.Log(" regcache: unallocate %s from temp storage", CX86Ops::x86_Name(Reg));
|
2022-09-11 20:31:43 +00:00
|
|
|
SetX86Mapped(RegIndex, NotMapped);
|
2016-01-27 09:11:59 +00:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
2022-09-11 20:31:43 +00:00
|
|
|
else if (GetX86Mapped(RegIndex) == CX86RegInfo::Stack_Mapped)
|
2016-01-27 09:11:59 +00:00
|
|
|
{
|
2022-08-15 03:09:34 +00:00
|
|
|
m_CodeBlock.Log(" regcache: unallocate %s from memory stack", CX86Ops::x86_Name(Reg));
|
|
|
|
m_Assembler.MoveX86regToVariable(Reg, &(g_Recompiler->MemoryStackPos()), "MemoryStack");
|
2022-09-11 20:31:43 +00:00
|
|
|
SetX86Mapped(RegIndex, NotMapped);
|
2016-01-27 09:11:59 +00:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2016-06-27 11:49:15 +00:00
|
|
|
void CX86RegInfo::WriteBackRegisters()
|
2016-01-27 09:11:59 +00:00
|
|
|
{
|
|
|
|
UnMap_AllFPRs();
|
|
|
|
|
|
|
|
int32_t count;
|
|
|
|
bool bEdiZero = false;
|
|
|
|
bool bEsiSign = false;
|
|
|
|
|
2022-10-10 00:22:17 +00:00
|
|
|
for (uint32_t i = 0; i < x86RegIndex_Size; i++)
|
|
|
|
{
|
|
|
|
SetX86Protected((x86RegIndex)i, false);
|
|
|
|
}
|
|
|
|
for (uint32_t i = 0; i < x86RegIndex_Size; i++)
|
|
|
|
{
|
|
|
|
UnMap_X86reg(GetX86RegFromIndex((x86RegIndex)i));
|
|
|
|
}
|
2016-01-27 09:11:59 +00:00
|
|
|
|
|
|
|
for (count = 1; count < 32; count++)
|
|
|
|
{
|
|
|
|
switch (GetMipsRegState(count))
|
|
|
|
{
|
2016-06-27 11:49:15 +00:00
|
|
|
case CX86RegInfo::STATE_UNKNOWN: break;
|
|
|
|
case CX86RegInfo::STATE_CONST_32_SIGN:
|
2016-01-27 09:11:59 +00:00
|
|
|
if (!g_System->b32BitCore())
|
|
|
|
{
|
|
|
|
if (!bEdiZero && (!GetMipsRegLo(count) || !(GetMipsRegLo(count) & 0x80000000)))
|
|
|
|
{
|
2022-08-15 03:09:34 +00:00
|
|
|
m_Assembler.XorX86RegToX86Reg(CX86Ops::x86_EDI, CX86Ops::x86_EDI);
|
2016-01-27 09:11:59 +00:00
|
|
|
bEdiZero = true;
|
|
|
|
}
|
|
|
|
if (!bEsiSign && (GetMipsRegLo(count) & 0x80000000))
|
|
|
|
{
|
2022-08-15 03:09:34 +00:00
|
|
|
m_Assembler.MoveConstToX86reg(0xFFFFFFFF, CX86Ops::x86_ESI);
|
2016-01-27 09:11:59 +00:00
|
|
|
bEsiSign = true;
|
|
|
|
}
|
|
|
|
if ((GetMipsRegLo(count) & 0x80000000) != 0)
|
|
|
|
{
|
2022-08-15 03:09:34 +00:00
|
|
|
m_Assembler.MoveX86regToVariable(CX86Ops::x86_ESI, &_GPR[count].UW[1], CRegName::GPR_Hi[count]);
|
2016-01-27 09:11:59 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2022-08-15 03:09:34 +00:00
|
|
|
m_Assembler.MoveX86regToVariable(CX86Ops::x86_EDI, &_GPR[count].UW[1], CRegName::GPR_Hi[count]);
|
2016-01-27 09:11:59 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (GetMipsRegLo(count) == 0)
|
|
|
|
{
|
|
|
|
if (g_System->b32BitCore())
|
|
|
|
{
|
|
|
|
if (!bEdiZero)
|
|
|
|
{
|
2022-08-15 03:09:34 +00:00
|
|
|
m_Assembler.XorX86RegToX86Reg(CX86Ops::x86_EDI, CX86Ops::x86_EDI);
|
2016-01-27 09:11:59 +00:00
|
|
|
bEdiZero = true;
|
|
|
|
}
|
|
|
|
}
|
2022-08-15 03:09:34 +00:00
|
|
|
m_Assembler.MoveX86regToVariable(CX86Ops::x86_EDI, &_GPR[count].UW[0], CRegName::GPR_Lo[count]);
|
2016-01-27 09:11:59 +00:00
|
|
|
}
|
|
|
|
else if (GetMipsRegLo(count) == 0xFFFFFFFF)
|
|
|
|
{
|
|
|
|
if (g_System->b32BitCore())
|
|
|
|
{
|
|
|
|
if (!bEsiSign)
|
|
|
|
{
|
2022-08-15 03:09:34 +00:00
|
|
|
m_Assembler.MoveConstToX86reg(0xFFFFFFFF, CX86Ops::x86_ESI);
|
2016-01-27 09:11:59 +00:00
|
|
|
bEsiSign = true;
|
|
|
|
}
|
|
|
|
}
|
2022-08-15 03:09:34 +00:00
|
|
|
m_Assembler.MoveX86regToVariable(CX86Ops::x86_ESI, &_GPR[count].UW[0], CRegName::GPR_Lo[count]);
|
2016-01-27 09:11:59 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2022-08-15 03:09:34 +00:00
|
|
|
m_Assembler.MoveConstToVariable(GetMipsRegLo(count), &_GPR[count].UW[0], CRegName::GPR_Lo[count]);
|
2016-01-27 09:11:59 +00:00
|
|
|
}
|
|
|
|
|
2016-06-27 11:49:15 +00:00
|
|
|
SetMipsRegState(count, CX86RegInfo::STATE_UNKNOWN);
|
2016-01-27 09:11:59 +00:00
|
|
|
break;
|
2016-06-27 11:49:15 +00:00
|
|
|
case CX86RegInfo::STATE_CONST_32_ZERO:
|
2016-01-27 09:11:59 +00:00
|
|
|
if (!g_System->b32BitCore())
|
|
|
|
{
|
|
|
|
if (!bEdiZero)
|
|
|
|
{
|
2022-08-15 03:09:34 +00:00
|
|
|
m_Assembler.XorX86RegToX86Reg(CX86Ops::x86_EDI, CX86Ops::x86_EDI);
|
2016-01-27 09:11:59 +00:00
|
|
|
bEdiZero = true;
|
|
|
|
}
|
2022-08-15 03:09:34 +00:00
|
|
|
m_Assembler.MoveX86regToVariable(CX86Ops::x86_EDI, &_GPR[count].UW[1], CRegName::GPR_Hi[count]);
|
2016-01-27 09:11:59 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (GetMipsRegLo(count) == 0)
|
|
|
|
{
|
|
|
|
if (g_System->b32BitCore())
|
|
|
|
{
|
|
|
|
if (!bEdiZero)
|
|
|
|
{
|
2022-08-15 03:09:34 +00:00
|
|
|
m_Assembler.XorX86RegToX86Reg(CX86Ops::x86_EDI, CX86Ops::x86_EDI);
|
2016-01-27 09:11:59 +00:00
|
|
|
bEdiZero = true;
|
|
|
|
}
|
|
|
|
}
|
2022-08-15 03:09:34 +00:00
|
|
|
m_Assembler.MoveX86regToVariable(CX86Ops::x86_EDI, &_GPR[count].UW[0], CRegName::GPR_Lo[count]);
|
2016-01-27 09:11:59 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2022-08-15 03:09:34 +00:00
|
|
|
m_Assembler.MoveConstToVariable(GetMipsRegLo(count), &_GPR[count].UW[0], CRegName::GPR_Lo[count]);
|
2016-01-27 09:11:59 +00:00
|
|
|
}
|
2016-06-27 11:49:15 +00:00
|
|
|
SetMipsRegState(count, CX86RegInfo::STATE_UNKNOWN);
|
2016-01-27 09:11:59 +00:00
|
|
|
break;
|
2016-06-27 11:49:15 +00:00
|
|
|
case CX86RegInfo::STATE_CONST_64:
|
2016-01-27 09:11:59 +00:00
|
|
|
if (GetMipsRegLo(count) == 0 || GetMipsRegHi(count) == 0)
|
|
|
|
{
|
2022-08-15 03:09:34 +00:00
|
|
|
m_Assembler.XorX86RegToX86Reg(CX86Ops::x86_EDI, CX86Ops::x86_EDI);
|
2016-01-27 09:11:59 +00:00
|
|
|
bEdiZero = true;
|
|
|
|
}
|
|
|
|
if (GetMipsRegLo(count) == 0xFFFFFFFF || GetMipsRegHi(count) == 0xFFFFFFFF)
|
|
|
|
{
|
2022-08-15 03:09:34 +00:00
|
|
|
m_Assembler.MoveConstToX86reg(0xFFFFFFFF, CX86Ops::x86_ESI);
|
2016-01-27 09:11:59 +00:00
|
|
|
bEsiSign = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (GetMipsRegHi(count) == 0)
|
|
|
|
{
|
2022-08-15 03:09:34 +00:00
|
|
|
m_Assembler.MoveX86regToVariable(CX86Ops::x86_EDI, &_GPR[count].UW[1], CRegName::GPR_Hi[count]);
|
2016-01-27 09:11:59 +00:00
|
|
|
}
|
|
|
|
else if (GetMipsRegLo(count) == 0xFFFFFFFF)
|
|
|
|
{
|
2022-08-15 03:09:34 +00:00
|
|
|
m_Assembler.MoveX86regToVariable(CX86Ops::x86_ESI, &_GPR[count].UW[1], CRegName::GPR_Hi[count]);
|
2016-01-27 09:11:59 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2022-08-15 03:09:34 +00:00
|
|
|
m_Assembler.MoveConstToVariable(GetMipsRegHi(count), &_GPR[count].UW[1], CRegName::GPR_Hi[count]);
|
2016-01-27 09:11:59 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (GetMipsRegLo(count) == 0)
|
|
|
|
{
|
2022-08-15 03:09:34 +00:00
|
|
|
m_Assembler.MoveX86regToVariable(CX86Ops::x86_EDI, &_GPR[count].UW[0], CRegName::GPR_Lo[count]);
|
2016-01-27 09:11:59 +00:00
|
|
|
}
|
|
|
|
else if (GetMipsRegLo(count) == 0xFFFFFFFF)
|
|
|
|
{
|
2022-08-15 03:09:34 +00:00
|
|
|
m_Assembler.MoveX86regToVariable(CX86Ops::x86_ESI, &_GPR[count].UW[0], CRegName::GPR_Lo[count]);
|
2016-01-27 09:11:59 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2022-08-15 03:09:34 +00:00
|
|
|
m_Assembler.MoveConstToVariable(GetMipsRegLo(count), &_GPR[count].UW[0], CRegName::GPR_Lo[count]);
|
2016-01-27 09:11:59 +00:00
|
|
|
}
|
2016-06-27 11:49:15 +00:00
|
|
|
SetMipsRegState(count, CX86RegInfo::STATE_UNKNOWN);
|
2016-01-27 09:11:59 +00:00
|
|
|
break;
|
|
|
|
default:
|
2022-08-08 10:52:51 +00:00
|
|
|
m_CodeBlock.Log("%s: Unknown State: %d reg %d (%s)", __FUNCTION__, GetMipsRegState(count), count, CRegName::GPR[count]);
|
2016-01-27 09:11:59 +00:00
|
|
|
g_Notify->BreakPoint(__FILE__, __LINE__);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-07-06 20:14:12 +00:00
|
|
|
#endif
|