2016-08-11 11:09:21 +00:00
|
|
|
#include "stdafx.h"
|
|
|
|
|
|
|
|
#if defined(__arm__) || defined(_M_ARM)
|
2016-09-30 13:33:07 +00:00
|
|
|
#include <Project64-core/N64System/SystemGlobals.h>
|
2021-06-28 01:57:35 +00:00
|
|
|
#include <Project64-core/N64System/N64System.h>
|
2022-09-12 13:14:42 +00:00
|
|
|
#include <Project64-core/N64System/Recompiler/Recompiler.h>
|
2016-08-11 11:09:21 +00:00
|
|
|
#include <Project64-core/N64System/Recompiler/Arm/ArmRegInfo.h>
|
|
|
|
|
2022-09-12 13:14:42 +00:00
|
|
|
CArmRegInfo::CArmRegInfo(CCodeBlock & CodeBlock, CArmOps & Assembler) :
|
|
|
|
m_CodeBlock(CodeBlock),
|
|
|
|
m_Assembler(Assembler),
|
2016-12-01 10:22:14 +00:00
|
|
|
m_InCallDirect(false)
|
2016-08-11 11:09:21 +00:00
|
|
|
{
|
2016-10-01 03:21:02 +00:00
|
|
|
for (int32_t i = 0; i < 32; i++)
|
|
|
|
{
|
2022-09-12 13:14:42 +00:00
|
|
|
m_RegMapLo[i] = CArmOps::Arm_Unknown;
|
|
|
|
m_RegMapHi[i] = CArmOps::Arm_Unknown;
|
2016-10-01 03:21:02 +00:00
|
|
|
}
|
|
|
|
|
2016-09-30 13:33:07 +00:00
|
|
|
for (int32_t i = 0, n = sizeof(m_ArmReg_MappedTo) / sizeof(m_ArmReg_MappedTo[0]); i < n; i++)
|
|
|
|
{
|
2016-09-30 19:58:04 +00:00
|
|
|
m_ArmReg_MapOrder[i] = 0;
|
2016-09-30 13:33:07 +00:00
|
|
|
m_ArmReg_Protected[i] = false;
|
|
|
|
m_ArmReg_MappedTo[i] = NotMapped;
|
|
|
|
m_Variable_MappedTo[i] = VARIABLE_UNKNOWN;
|
|
|
|
}
|
2016-08-11 11:09:21 +00:00
|
|
|
}
|
|
|
|
|
2022-09-12 13:14:42 +00:00
|
|
|
CArmRegInfo::CArmRegInfo(const CArmRegInfo& rhs) :
|
|
|
|
m_CodeBlock(rhs.m_CodeBlock),
|
|
|
|
m_Assembler(rhs.m_CodeBlock.RecompilerOps()->Assembler())
|
2016-08-11 11:09:21 +00:00
|
|
|
{
|
|
|
|
*this = rhs;
|
|
|
|
}
|
|
|
|
|
|
|
|
CArmRegInfo::~CArmRegInfo()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
CArmRegInfo& CArmRegInfo::operator=(const CArmRegInfo& right)
|
|
|
|
{
|
|
|
|
CRegBase::operator=(right);
|
2016-09-29 12:17:54 +00:00
|
|
|
|
|
|
|
m_InCallDirect = right.m_InCallDirect;
|
2016-10-01 03:21:02 +00:00
|
|
|
memcpy(&m_RegMapLo, &right.m_RegMapLo, sizeof(m_RegMapLo));
|
|
|
|
memcpy(&m_RegMapHi, &right.m_RegMapHi, sizeof(m_RegMapHi));
|
2016-09-30 19:58:04 +00:00
|
|
|
memcpy(&m_ArmReg_MapOrder, &right.m_ArmReg_MapOrder, sizeof(m_ArmReg_MapOrder));
|
2016-09-30 13:33:07 +00:00
|
|
|
memcpy(&m_ArmReg_Protected, &right.m_ArmReg_Protected, sizeof(m_ArmReg_Protected));
|
|
|
|
memcpy(&m_ArmReg_MappedTo, &right.m_ArmReg_MappedTo, sizeof(m_ArmReg_MappedTo));
|
|
|
|
memcpy(&m_Variable_MappedTo, &right.m_Variable_MappedTo, sizeof(m_Variable_MappedTo));
|
2016-08-11 11:09:21 +00:00
|
|
|
#ifdef _DEBUG
|
|
|
|
if (*this != right)
|
|
|
|
{
|
|
|
|
g_Notify->BreakPoint(__FILE__, __LINE__);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
2016-11-22 21:52:05 +00:00
|
|
|
bool CArmRegInfo::operator==(const CArmRegInfo& right) const
|
|
|
|
{
|
|
|
|
if (!CRegBase::operator==(right))
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (int32_t count = 0; count < 32; count++)
|
|
|
|
{
|
|
|
|
if (m_RegMapHi[count] != right.m_RegMapHi[count]) { return false; }
|
|
|
|
if (m_RegMapLo[count] != right.m_RegMapLo[count]) { return false; }
|
|
|
|
}
|
|
|
|
|
|
|
|
for (int32_t count = 0; count < 16; count++)
|
|
|
|
{
|
|
|
|
if (m_ArmReg_MapOrder[count] != right.m_ArmReg_MapOrder[count]) { return false; }
|
|
|
|
if (m_ArmReg_Protected[count] != right.m_ArmReg_Protected[count]) { return false; }
|
|
|
|
if (m_ArmReg_MappedTo[count] != right.m_ArmReg_MappedTo[count]) { return false; }
|
|
|
|
if (m_Variable_MappedTo[count] != right.m_Variable_MappedTo[count]) { return false; }
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2022-09-12 13:14:42 +00:00
|
|
|
bool CArmRegInfo::ShouldPushPopReg(CArmOps::ArmReg Reg)
|
2016-10-01 04:38:45 +00:00
|
|
|
{
|
|
|
|
if (m_ArmReg_MappedTo[Reg] == NotMapped)
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
if (m_ArmReg_MappedTo[Reg] == Temp_Mapped && !GetArmRegProtected(Reg))
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2016-08-11 11:09:21 +00:00
|
|
|
void CArmRegInfo::BeforeCallDirect(void)
|
|
|
|
{
|
2017-01-19 21:43:38 +00:00
|
|
|
static uint32_t PushPopRegisterList[] =
|
|
|
|
{
|
2022-09-12 13:14:42 +00:00
|
|
|
CArmOps::ArmPushPop_R0, CArmOps::ArmPushPop_R1, CArmOps::ArmPushPop_R2, CArmOps::ArmPushPop_R3, CArmOps::ArmPushPop_R4,
|
|
|
|
CArmOps::ArmPushPop_R5, CArmOps::ArmPushPop_R6, CArmOps::ArmPushPop_R7, CArmOps::ArmPushPop_R8, CArmOps::ArmPushPop_R9,
|
|
|
|
CArmOps::ArmPushPop_R10, CArmOps::ArmPushPop_R11, CArmOps::ArmPushPop_R12
|
2017-01-19 21:43:38 +00:00
|
|
|
};
|
2017-05-06 09:27:06 +00:00
|
|
|
|
2022-09-12 13:14:42 +00:00
|
|
|
static CArmOps::ArmReg RegisterList[] =
|
2017-01-19 21:43:38 +00:00
|
|
|
{
|
2022-09-12 13:14:42 +00:00
|
|
|
CArmOps::Arm_R0, CArmOps::Arm_R1, CArmOps::Arm_R2, CArmOps::Arm_R3, CArmOps::Arm_R4,
|
|
|
|
CArmOps::Arm_R5, CArmOps::Arm_R6, CArmOps::Arm_R7, CArmOps::Arm_R8, CArmOps::Arm_R9,
|
|
|
|
CArmOps::Arm_R10, CArmOps::Arm_R11, CArmOps::Arm_R12
|
2017-01-19 21:43:38 +00:00
|
|
|
};
|
|
|
|
|
2016-09-29 12:17:54 +00:00
|
|
|
if (m_InCallDirect)
|
|
|
|
{
|
2022-09-12 13:14:42 +00:00
|
|
|
m_CodeBlock.Log("%s: in CallDirect", __FUNCTION__);
|
2016-09-29 12:17:54 +00:00
|
|
|
g_Notify->BreakPoint(__FILE__, __LINE__);
|
|
|
|
return;
|
|
|
|
}
|
2016-10-01 04:38:45 +00:00
|
|
|
UnMap_AllFPRs();
|
|
|
|
int PushPopRegisters = 0;
|
2017-01-19 21:43:38 +00:00
|
|
|
for (int i = 0; i < (sizeof(RegisterList) / sizeof(RegisterList[0])); i++)
|
|
|
|
{
|
|
|
|
if (ShouldPushPopReg(RegisterList[i])) { PushPopRegisters |= PushPopRegisterList[i]; }
|
|
|
|
}
|
2016-10-01 04:38:45 +00:00
|
|
|
|
2017-01-19 21:43:38 +00:00
|
|
|
if (PushPopRegisters == 0)
|
|
|
|
{
|
|
|
|
m_InCallDirect = true;
|
|
|
|
return;
|
|
|
|
}
|
2017-05-06 09:27:06 +00:00
|
|
|
|
2022-09-12 13:14:42 +00:00
|
|
|
if ((m_Assembler.PushPopRegisterSize(PushPopRegisters) % 8) != 0)
|
2016-10-01 04:38:45 +00:00
|
|
|
{
|
2017-01-19 21:43:38 +00:00
|
|
|
bool Added = false;
|
|
|
|
for (int i = 0; i < (sizeof(RegisterList) / sizeof(RegisterList[0])); i++)
|
|
|
|
{
|
2017-05-06 09:27:06 +00:00
|
|
|
if (ShouldPushPopReg(RegisterList[i]))
|
2017-01-19 21:43:38 +00:00
|
|
|
{
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
PushPopRegisters |= PushPopRegisterList[i];
|
|
|
|
Added = true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (!Added)
|
|
|
|
{
|
2022-09-12 13:14:42 +00:00
|
|
|
CArmOps::ArmReg reg = FreeArmReg(false);
|
|
|
|
m_CodeBlock.Log(" Freed %s", m_Assembler.ArmRegName(reg));
|
2017-01-19 21:43:38 +00:00
|
|
|
PushPopRegisters = 0;
|
|
|
|
for (int i = 0; i < (sizeof(RegisterList) / sizeof(RegisterList[0])); i++)
|
|
|
|
{
|
|
|
|
if (ShouldPushPopReg(RegisterList[i])) { PushPopRegisters |= PushPopRegisterList[i]; }
|
|
|
|
}
|
|
|
|
}
|
2022-09-12 13:14:42 +00:00
|
|
|
if ((m_Assembler.PushPopRegisterSize(PushPopRegisters) % 8) != 0)
|
2017-01-19 21:43:38 +00:00
|
|
|
{
|
|
|
|
g_Notify->BreakPoint(__FILE__, __LINE__);
|
|
|
|
}
|
2016-10-01 04:38:45 +00:00
|
|
|
}
|
2017-01-19 21:43:38 +00:00
|
|
|
m_InCallDirect = true;
|
2022-09-12 13:14:42 +00:00
|
|
|
m_Assembler.PushArmReg(PushPopRegisters);
|
2016-08-11 11:09:21 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void CArmRegInfo::AfterCallDirect(void)
|
|
|
|
{
|
2017-01-19 21:43:38 +00:00
|
|
|
static uint32_t PushPopRegisterList[] =
|
|
|
|
{
|
2022-09-12 13:14:42 +00:00
|
|
|
CArmOps::ArmPushPop_R0, CArmOps::ArmPushPop_R1, CArmOps::ArmPushPop_R2, CArmOps::ArmPushPop_R3, CArmOps::ArmPushPop_R4,
|
|
|
|
CArmOps::ArmPushPop_R5, CArmOps::ArmPushPop_R6, CArmOps::ArmPushPop_R7, CArmOps::ArmPushPop_R8, CArmOps::ArmPushPop_R9,
|
|
|
|
CArmOps::ArmPushPop_R10, CArmOps::ArmPushPop_R11, CArmOps::ArmPushPop_R12, CArmOps::ArmPushPop_LR, CArmOps::ArmPushPop_PC
|
2017-01-19 21:43:38 +00:00
|
|
|
};
|
|
|
|
|
2022-09-12 13:14:42 +00:00
|
|
|
static CArmOps::ArmReg RegisterList[] =
|
2017-01-19 21:43:38 +00:00
|
|
|
{
|
2022-09-12 13:14:42 +00:00
|
|
|
CArmOps::Arm_R0, CArmOps::Arm_R1, CArmOps::Arm_R2, CArmOps::Arm_R3, CArmOps::Arm_R4,
|
|
|
|
CArmOps::Arm_R5, CArmOps::Arm_R6, CArmOps::Arm_R7, CArmOps::Arm_R8, CArmOps::Arm_R9,
|
|
|
|
CArmOps::Arm_R10, CArmOps::Arm_R11, CArmOps::Arm_R12, CArmOps::ArmRegLR, CArmOps::ArmRegPC,
|
2017-01-19 21:43:38 +00:00
|
|
|
};
|
|
|
|
|
2016-09-29 12:17:54 +00:00
|
|
|
if (!m_InCallDirect)
|
|
|
|
{
|
2022-09-12 13:14:42 +00:00
|
|
|
m_CodeBlock.Log("%s: Not in CallDirect", __FUNCTION__);
|
2016-09-29 12:17:54 +00:00
|
|
|
g_Notify->BreakPoint(__FILE__, __LINE__);
|
|
|
|
return;
|
|
|
|
}
|
2017-01-19 21:43:38 +00:00
|
|
|
|
2016-10-01 04:38:45 +00:00
|
|
|
int PushPopRegisters = 0;
|
2017-01-19 21:43:38 +00:00
|
|
|
for (int i = 0; i < (sizeof(RegisterList) / sizeof(RegisterList[0])); i++)
|
|
|
|
{
|
|
|
|
if (ShouldPushPopReg(RegisterList[i])) { PushPopRegisters |= PushPopRegisterList[i]; }
|
|
|
|
}
|
2016-10-01 04:38:45 +00:00
|
|
|
|
|
|
|
if (PushPopRegisters != 0)
|
|
|
|
{
|
2022-09-12 13:14:42 +00:00
|
|
|
if ((m_Assembler.PushPopRegisterSize(PushPopRegisters) % 8) != 0)
|
2017-01-19 21:43:38 +00:00
|
|
|
{
|
|
|
|
for (int i = 0; i < (sizeof(RegisterList) / sizeof(RegisterList[0])); i++)
|
|
|
|
{
|
|
|
|
if (ShouldPushPopReg(RegisterList[i]))
|
|
|
|
{
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
PushPopRegisters |= PushPopRegisterList[i];
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2022-09-12 13:14:42 +00:00
|
|
|
m_Assembler.PopArmReg(PushPopRegisters);
|
2016-10-01 04:38:45 +00:00
|
|
|
}
|
2017-01-19 21:43:38 +00:00
|
|
|
|
2016-10-01 04:38:45 +00:00
|
|
|
SetRoundingModel(CRegInfo::RoundUnknown);
|
2016-09-29 12:17:54 +00:00
|
|
|
m_InCallDirect = false;
|
2016-08-11 11:09:21 +00:00
|
|
|
}
|
|
|
|
|
2016-10-01 02:35:00 +00:00
|
|
|
void CArmRegInfo::FixRoundModel(FPU_ROUND RoundMethod)
|
|
|
|
{
|
|
|
|
if (m_InCallDirect)
|
|
|
|
{
|
2022-09-12 13:14:42 +00:00
|
|
|
m_CodeBlock.Log("%s: in CallDirect", __FUNCTION__);
|
2016-10-01 02:35:00 +00:00
|
|
|
g_Notify->BreakPoint(__FILE__, __LINE__);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (GetRoundingModel() == RoundMethod)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
2022-09-12 13:14:42 +00:00
|
|
|
m_CodeBlock.Log(" FixRoundModel: CurrentRoundingModel: %s targetRoundModel: %s", RoundingModelName(GetRoundingModel()), RoundingModelName(RoundMethod));
|
2016-10-01 02:35:00 +00:00
|
|
|
if (RoundMethod == RoundDefault)
|
|
|
|
{
|
2022-09-12 13:14:42 +00:00
|
|
|
BeforeCallDirect();
|
|
|
|
m_Assembler.MoveVariableToArmReg(_RoundingModel, "_RoundingModel", CArmOps::Arm_R0);
|
|
|
|
m_Assembler.CallFunction((void *)fesetround, "fesetround");
|
|
|
|
AfterCallDirect();
|
2016-10-01 02:35:00 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
g_Notify->BreakPoint(__FILE__, __LINE__);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-10-01 03:21:02 +00:00
|
|
|
void CArmRegInfo::Map_GPR_32bit(int32_t MipsReg, bool SignValue, int32_t MipsRegToLoad)
|
|
|
|
{
|
|
|
|
if (m_InCallDirect)
|
|
|
|
{
|
2022-09-12 13:14:42 +00:00
|
|
|
m_CodeBlock.Log("%s: in CallDirect", __FUNCTION__);
|
2016-10-01 03:21:02 +00:00
|
|
|
g_Notify->BreakPoint(__FILE__, __LINE__);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2022-09-12 13:14:42 +00:00
|
|
|
CArmOps::ArmReg Reg;
|
2016-10-01 03:21:02 +00:00
|
|
|
if (MipsReg == 0)
|
|
|
|
{
|
|
|
|
g_Notify->BreakPoint(__FILE__, __LINE__);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (IsUnknown(MipsReg) || IsConst(MipsReg))
|
|
|
|
{
|
2016-11-22 21:39:40 +00:00
|
|
|
Reg = FreeArmReg(false);
|
2016-10-01 03:21:02 +00:00
|
|
|
if (Reg < 0)
|
|
|
|
{
|
2018-01-15 21:23:21 +00:00
|
|
|
if (HaveDebugger()) { g_Notify->DisplayError("Map_GPR_32bit\n\nOut of registers"); }
|
2016-10-01 03:21:02 +00:00
|
|
|
g_Notify->BreakPoint(__FILE__, __LINE__);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
SetArmRegProtected(Reg, true);
|
2022-09-12 13:14:42 +00:00
|
|
|
m_CodeBlock.Log(" regcache: allocate %s to %s", m_Assembler.ArmRegName(Reg), CRegName::GPR[MipsReg]);
|
2016-10-01 03:21:02 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (Is64Bit(MipsReg))
|
|
|
|
{
|
2022-09-12 13:14:42 +00:00
|
|
|
m_CodeBlock.Log(" regcache: unallocate %s from high 32-bit of %s", m_Assembler.ArmRegName(GetMipsRegMapHi(MipsReg)), CRegName::GPR_Hi[MipsReg]);
|
2016-10-01 03:21:02 +00:00
|
|
|
SetArmRegMapOrder(GetMipsRegMapHi(MipsReg), 0);
|
|
|
|
SetArmRegMapped(GetMipsRegMapHi(MipsReg), NotMapped);
|
|
|
|
SetArmRegProtected(GetMipsRegMapHi(MipsReg), false);
|
|
|
|
SetMipsRegHi(MipsReg, 0);
|
|
|
|
}
|
|
|
|
Reg = GetMipsRegMapLo(MipsReg);
|
|
|
|
}
|
2022-09-12 13:14:42 +00:00
|
|
|
for (int32_t count = 0; count <= CArmOps::Arm_R15; count++)
|
2016-10-01 03:21:02 +00:00
|
|
|
{
|
2022-09-12 13:14:42 +00:00
|
|
|
uint32_t Count = GetArmRegMapOrder((CArmOps::ArmReg)count);
|
2016-10-01 03:21:02 +00:00
|
|
|
if (Count > 0)
|
|
|
|
{
|
2022-09-12 13:14:42 +00:00
|
|
|
SetArmRegMapOrder((CArmOps::ArmReg)count, Count + 1);
|
2016-10-01 03:21:02 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
SetArmRegMapOrder(Reg, 1);
|
|
|
|
|
|
|
|
if (MipsRegToLoad > 0)
|
|
|
|
{
|
|
|
|
if (IsUnknown(MipsRegToLoad))
|
|
|
|
{
|
2022-09-12 13:14:42 +00:00
|
|
|
CArmOps::ArmReg GprReg = Map_Variable(VARIABLE_GPR);
|
|
|
|
m_Assembler.LoadArmRegPointerToArmReg(Reg, GprReg, (uint8_t)(MipsRegToLoad << 3), CRegName::GPR_Lo[MipsRegToLoad]);
|
2016-10-01 03:21:02 +00:00
|
|
|
SetArmRegProtected(GprReg, false);
|
|
|
|
}
|
|
|
|
else if (IsMapped(MipsRegToLoad))
|
|
|
|
{
|
|
|
|
if (MipsReg != MipsRegToLoad)
|
|
|
|
{
|
2022-09-12 13:14:42 +00:00
|
|
|
m_Assembler.AddConstToArmReg(Reg, GetMipsRegMapLo(MipsRegToLoad), 0);
|
2016-10-01 03:21:02 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2022-09-12 13:14:42 +00:00
|
|
|
m_Assembler.MoveConstToArmReg(Reg, GetMipsRegLo(MipsRegToLoad));
|
2016-10-01 03:21:02 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (MipsRegToLoad == 0)
|
|
|
|
{
|
2022-09-12 13:14:42 +00:00
|
|
|
m_Assembler.MoveConstToArmReg(Reg, (uint32_t)0);
|
2016-10-01 03:21:02 +00:00
|
|
|
}
|
|
|
|
SetArmRegMapped(Reg, GPR_Mapped);
|
|
|
|
SetArmRegProtected(Reg, true);
|
|
|
|
SetMipsRegMapLo(MipsReg, Reg);
|
|
|
|
SetMipsRegState(MipsReg, SignValue ? STATE_MAPPED_32_SIGN : STATE_MAPPED_32_ZERO);
|
|
|
|
}
|
|
|
|
|
2016-10-01 04:22:23 +00:00
|
|
|
void CArmRegInfo::Map_GPR_64bit(int32_t MipsReg, int32_t MipsRegToLoad)
|
|
|
|
{
|
|
|
|
if (m_InCallDirect)
|
|
|
|
{
|
2022-09-12 13:14:42 +00:00
|
|
|
m_CodeBlock.Log("%s: in CallDirect", __FUNCTION__);
|
2016-10-01 04:22:23 +00:00
|
|
|
g_Notify->BreakPoint(__FILE__, __LINE__);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2022-09-12 13:14:42 +00:00
|
|
|
CArmOps::ArmReg regHi, reglo;
|
2016-10-01 04:22:23 +00:00
|
|
|
int32_t count;
|
|
|
|
|
|
|
|
if (MipsReg == 0)
|
|
|
|
{
|
2021-05-18 11:51:36 +00:00
|
|
|
if (HaveDebugger()) { g_Notify->DisplayError("Map_GPR_64bit\n\nWhy are you trying to map register 0?"); }
|
2016-10-01 04:22:23 +00:00
|
|
|
g_Notify->BreakPoint(__FILE__, __LINE__);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
ProtectGPR(MipsReg);
|
|
|
|
if (IsUnknown(MipsReg) || IsConst(MipsReg))
|
|
|
|
{
|
2016-11-22 21:39:40 +00:00
|
|
|
regHi = FreeArmReg(false);
|
2016-10-01 04:22:23 +00:00
|
|
|
if (regHi < 0)
|
|
|
|
{
|
2018-01-15 21:23:21 +00:00
|
|
|
if (HaveDebugger()) { g_Notify->DisplayError("Map_GPR_64bit\n\nOut of registers"); }
|
2016-10-01 04:22:23 +00:00
|
|
|
g_Notify->BreakPoint(__FILE__, __LINE__);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
SetArmRegProtected(regHi, true);
|
|
|
|
|
2016-11-22 21:39:40 +00:00
|
|
|
reglo = FreeArmReg(false);
|
2016-10-06 11:59:03 +00:00
|
|
|
if (reglo < 0)
|
2016-10-01 04:22:23 +00:00
|
|
|
{
|
2018-01-15 21:23:21 +00:00
|
|
|
if (HaveDebugger()) { g_Notify->DisplayError("Map_GPR_64bit\n\nOut of registers"); }
|
2016-10-01 04:22:23 +00:00
|
|
|
g_Notify->BreakPoint(__FILE__, __LINE__);
|
2016-10-06 11:59:03 +00:00
|
|
|
return;
|
2016-10-01 04:22:23 +00:00
|
|
|
}
|
|
|
|
SetArmRegProtected(reglo, true);
|
|
|
|
|
2022-09-12 13:14:42 +00:00
|
|
|
m_CodeBlock.Log(" regcache: allocate %s to hi word of %s", m_Assembler.ArmRegName(regHi), CRegName::GPR[MipsReg]);
|
|
|
|
m_CodeBlock.Log(" regcache: allocate %s to low word of %s", m_Assembler.ArmRegName(reglo), CRegName::GPR[MipsReg]);
|
2016-10-01 04:22:23 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
reglo = GetMipsRegMapLo(MipsReg);
|
|
|
|
if (Is32Bit(MipsReg))
|
|
|
|
{
|
|
|
|
SetArmRegProtected(reglo, true);
|
2016-11-22 21:39:40 +00:00
|
|
|
regHi = FreeArmReg(false);
|
2016-10-06 11:59:03 +00:00
|
|
|
if (regHi < 0)
|
2016-10-01 04:22:23 +00:00
|
|
|
{
|
2018-01-15 21:23:21 +00:00
|
|
|
if (HaveDebugger()) { g_Notify->DisplayError("Map_GPR_64bit\n\nOut of registers"); }
|
2016-10-01 04:22:23 +00:00
|
|
|
g_Notify->BreakPoint(__FILE__, __LINE__);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
SetArmRegProtected(regHi, true);
|
|
|
|
|
2022-09-12 13:14:42 +00:00
|
|
|
m_CodeBlock.Log(" regcache: allocate %s to hi word of %s", m_Assembler.ArmRegName(regHi), CRegName::GPR[MipsReg]);
|
2016-10-01 04:22:23 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
regHi = GetMipsRegMapHi(MipsReg);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-09-12 13:14:42 +00:00
|
|
|
for (int32_t count = 0; count <= CArmOps::Arm_R15; count++)
|
2016-10-01 04:22:23 +00:00
|
|
|
{
|
2022-09-12 13:14:42 +00:00
|
|
|
uint32_t Count = GetArmRegMapOrder((CArmOps::ArmReg)count);
|
2016-10-01 04:22:23 +00:00
|
|
|
if (Count > 0)
|
|
|
|
{
|
2022-09-12 13:14:42 +00:00
|
|
|
SetArmRegMapOrder((CArmOps::ArmReg)count, Count + 1);
|
2016-10-01 04:22:23 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
SetArmRegMapOrder(regHi, 1);
|
|
|
|
SetArmRegMapOrder(reglo, 1);
|
|
|
|
|
|
|
|
if (MipsRegToLoad > 0)
|
|
|
|
{
|
|
|
|
if (IsUnknown(MipsRegToLoad))
|
|
|
|
{
|
2022-09-12 13:14:42 +00:00
|
|
|
CArmOps::ArmReg GprReg = Map_Variable(VARIABLE_GPR);
|
|
|
|
m_Assembler.LoadArmRegPointerToArmReg(regHi, GprReg, (uint8_t)(MipsRegToLoad << 3) + 4, CRegName::GPR_Hi[MipsRegToLoad]);
|
|
|
|
m_Assembler.LoadArmRegPointerToArmReg(reglo, GprReg, (uint8_t)(MipsRegToLoad << 3), CRegName::GPR_Lo[MipsRegToLoad]);
|
2016-10-01 04:22:23 +00:00
|
|
|
SetArmRegProtected(GprReg, false);
|
|
|
|
}
|
|
|
|
else if (IsMapped(MipsRegToLoad))
|
|
|
|
{
|
|
|
|
if (Is32Bit(MipsRegToLoad))
|
|
|
|
{
|
2016-11-22 22:02:55 +00:00
|
|
|
if (IsSigned(MipsRegToLoad))
|
2016-10-01 04:22:23 +00:00
|
|
|
{
|
2022-09-12 13:14:42 +00:00
|
|
|
m_Assembler.ShiftRightSignImmed(regHi, GetMipsRegMapLo(MipsRegToLoad), 31);
|
2016-10-01 04:22:23 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2022-09-12 13:14:42 +00:00
|
|
|
m_Assembler.MoveConstToArmReg(regHi, (uint32_t)0);
|
2016-10-01 04:22:23 +00:00
|
|
|
}
|
|
|
|
if (MipsReg != MipsRegToLoad)
|
|
|
|
{
|
2022-09-12 13:14:42 +00:00
|
|
|
m_Assembler.AddConstToArmReg(reglo, GetMipsRegMapLo(MipsRegToLoad), 0);
|
2016-11-22 22:02:55 +00:00
|
|
|
}
|
2016-10-01 04:22:23 +00:00
|
|
|
}
|
|
|
|
else if (MipsReg != MipsRegToLoad)
|
|
|
|
{
|
2022-09-12 13:14:42 +00:00
|
|
|
m_Assembler.AddConstToArmReg(regHi, GetMipsRegMapHi(MipsRegToLoad), 0);
|
|
|
|
m_Assembler.AddConstToArmReg(reglo, GetMipsRegMapLo(MipsRegToLoad), 0);
|
2016-10-01 04:22:23 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (Is32Bit(MipsRegToLoad))
|
|
|
|
{
|
2022-09-12 13:14:42 +00:00
|
|
|
m_Assembler.MoveConstToArmReg(regHi, (uint32_t)(IsSigned(MipsRegToLoad) ? GetMipsRegLo_S(MipsRegToLoad) >> 31 : 0));
|
2016-10-01 04:22:23 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2022-09-12 13:14:42 +00:00
|
|
|
m_Assembler.MoveConstToArmReg(regHi, GetMipsRegHi(MipsRegToLoad));
|
2016-10-06 11:59:03 +00:00
|
|
|
}
|
2022-09-12 13:14:42 +00:00
|
|
|
m_Assembler.MoveConstToArmReg(reglo, GetMipsRegLo(MipsRegToLoad));
|
2016-10-01 04:22:23 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (MipsRegToLoad == 0)
|
|
|
|
{
|
2022-09-12 13:14:42 +00:00
|
|
|
m_Assembler.MoveConstToArmReg(regHi, (uint32_t)0);
|
|
|
|
m_Assembler.MoveConstToArmReg(reglo, (uint32_t)0);
|
2016-10-01 04:22:23 +00:00
|
|
|
}
|
|
|
|
SetArmRegMapped(regHi, GPR_Mapped);
|
|
|
|
SetArmRegMapped(reglo, GPR_Mapped);
|
|
|
|
SetArmRegProtected(regHi, true);
|
|
|
|
SetArmRegProtected(reglo, true);
|
|
|
|
SetMipsRegMapHi(MipsReg, regHi);
|
|
|
|
SetMipsRegMapLo(MipsReg, reglo);
|
|
|
|
SetMipsRegState(MipsReg, STATE_MAPPED_64);
|
|
|
|
}
|
|
|
|
|
2016-10-01 05:27:34 +00:00
|
|
|
void CArmRegInfo::UnMap_GPR(uint32_t MipsReg, bool WriteBackValue)
|
|
|
|
{
|
|
|
|
if (m_InCallDirect)
|
|
|
|
{
|
2022-09-12 13:14:42 +00:00
|
|
|
m_CodeBlock.Log("%s: in CallDirect", __FUNCTION__);
|
2016-10-01 05:27:34 +00:00
|
|
|
g_Notify->BreakPoint(__FILE__, __LINE__);
|
|
|
|
return;
|
|
|
|
}
|
2016-11-22 11:39:24 +00:00
|
|
|
if (WriteBackValue)
|
|
|
|
{
|
2017-05-06 09:27:06 +00:00
|
|
|
WriteBack_GPR(MipsReg, true);
|
2016-11-22 11:39:24 +00:00
|
|
|
}
|
|
|
|
|
2016-10-01 05:27:34 +00:00
|
|
|
if (MipsReg == 0)
|
|
|
|
{
|
2018-01-15 21:23:21 +00:00
|
|
|
if (HaveDebugger())
|
2016-10-01 05:27:34 +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-10-01 05:27:34 +00:00
|
|
|
}
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (IsUnknown(MipsReg)) { return; }
|
2022-09-12 13:14:42 +00:00
|
|
|
//m_CodeBlock.Log("UnMap_GPR: State: %X\tReg: %s\tWriteBack: %s",State,CRegName::GPR[Reg],WriteBackValue?"true":"false");
|
2016-10-01 05:27:34 +00:00
|
|
|
if (IsConst(MipsReg))
|
|
|
|
{
|
|
|
|
SetMipsRegState(MipsReg, STATE_UNKNOWN);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (Is64Bit(MipsReg))
|
|
|
|
{
|
2022-09-12 13:14:42 +00:00
|
|
|
m_CodeBlock.Log(" regcache: unallocate %s from %s", m_Assembler.ArmRegName(GetMipsRegMapHi(MipsReg)), CRegName::GPR_Hi[MipsReg]);
|
2016-10-01 05:27:34 +00:00
|
|
|
SetArmRegMapped(GetMipsRegMapHi(MipsReg), NotMapped);
|
|
|
|
SetArmRegProtected(GetMipsRegMapHi(MipsReg), false);
|
|
|
|
}
|
2022-09-12 13:14:42 +00:00
|
|
|
m_CodeBlock.Log(" regcache: unallocate %s from %s", m_Assembler.ArmRegName(GetMipsRegMapLo(MipsReg)), CRegName::GPR_Lo[MipsReg]);
|
2016-10-01 05:27:34 +00:00
|
|
|
SetArmRegMapped(GetMipsRegMapLo(MipsReg), NotMapped);
|
|
|
|
SetArmRegProtected(GetMipsRegMapLo(MipsReg), false);
|
2016-11-22 11:39:24 +00:00
|
|
|
SetMipsRegState(MipsReg, STATE_UNKNOWN);
|
|
|
|
}
|
|
|
|
|
|
|
|
void CArmRegInfo::WriteBack_GPR(uint32_t MipsReg, bool Unmapping)
|
|
|
|
{
|
|
|
|
if (m_InCallDirect)
|
2016-10-01 05:27:34 +00:00
|
|
|
{
|
2022-09-12 13:14:42 +00:00
|
|
|
m_CodeBlock.Log("%s: in CallDirect", __FUNCTION__);
|
2016-11-22 11:39:24 +00:00
|
|
|
g_Notify->BreakPoint(__FILE__, __LINE__);
|
2016-10-01 05:27:34 +00:00
|
|
|
return;
|
|
|
|
}
|
2016-11-22 11:39:24 +00:00
|
|
|
if (MipsReg == 0)
|
|
|
|
{
|
2018-01-15 21:23:21 +00:00
|
|
|
if (HaveDebugger())
|
2016-11-22 11:39:24 +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-11-22 11:39:24 +00:00
|
|
|
}
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (IsUnknown(MipsReg))
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2022-09-12 13:14:42 +00:00
|
|
|
CArmOps::ArmReg GprReg = Map_Variable(VARIABLE_GPR);
|
2016-11-22 11:39:24 +00:00
|
|
|
if (IsConst(MipsReg))
|
2016-10-01 05:27:34 +00:00
|
|
|
{
|
2022-09-12 13:14:42 +00:00
|
|
|
CArmOps::ArmReg TempReg = Map_TempReg(CArmOps::Arm_Any, -1, false);
|
2016-11-22 11:39:24 +00:00
|
|
|
|
|
|
|
if (Is64Bit(MipsReg))
|
|
|
|
{
|
2022-09-12 13:14:42 +00:00
|
|
|
m_Assembler.MoveConstToArmReg(TempReg, GetMipsRegHi(MipsReg));
|
|
|
|
m_Assembler.StoreArmRegToArmRegPointer(TempReg, GprReg, (uint8_t)(MipsReg << 3) + 4, CRegName::GPR_Hi[MipsReg]);
|
2016-11-22 11:39:24 +00:00
|
|
|
}
|
|
|
|
else if (!g_System->b32BitCore())
|
|
|
|
{
|
2022-09-12 13:14:42 +00:00
|
|
|
m_Assembler.MoveConstToArmReg(TempReg, (GetMipsRegLo(MipsReg) & 0x80000000) != 0 ? 0xFFFFFFFF : 0);
|
|
|
|
m_Assembler.StoreArmRegToArmRegPointer(TempReg, GprReg, (uint8_t)(MipsReg << 3) + 4, CRegName::GPR_Hi[MipsReg]);
|
2016-11-22 11:39:24 +00:00
|
|
|
}
|
2022-09-12 13:14:42 +00:00
|
|
|
m_Assembler.MoveConstToArmReg(TempReg, GetMipsRegLo(MipsReg));
|
|
|
|
m_Assembler.StoreArmRegToArmRegPointer(TempReg, GprReg, (uint8_t)(MipsReg << 3), CRegName::GPR_Lo[MipsReg]);
|
|
|
|
SetArmRegProtected(TempReg, false);
|
2016-10-01 05:27:34 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2022-09-12 13:14:42 +00:00
|
|
|
m_Assembler.StoreArmRegToArmRegPointer(GetMipsRegMapLo(MipsReg), GprReg, (uint8_t)(MipsReg << 3), CRegName::GPR_Lo[MipsReg]);
|
2016-11-22 11:39:24 +00:00
|
|
|
if (Is64Bit(MipsReg))
|
2016-10-01 05:27:34 +00:00
|
|
|
{
|
2022-09-12 13:14:42 +00:00
|
|
|
m_Assembler.StoreArmRegToArmRegPointer(GetMipsRegMapHi(MipsReg), GprReg, (uint8_t)(MipsReg << 3) + 4, CRegName::GPR_Hi[MipsReg]);
|
2016-11-22 11:39:24 +00:00
|
|
|
}
|
|
|
|
else if (!g_System->b32BitCore())
|
|
|
|
{
|
|
|
|
bool loProtected = GetArmRegProtected(GetMipsRegMapLo(MipsReg));
|
|
|
|
if (!Unmapping)
|
2016-10-01 05:27:34 +00:00
|
|
|
{
|
2016-11-22 11:39:24 +00:00
|
|
|
SetArmRegProtected(GetMipsRegMapLo(MipsReg), true);
|
2022-09-12 13:14:42 +00:00
|
|
|
CArmOps::ArmReg TempReg = Map_TempReg(CArmOps::Arm_Any, -1, false);
|
2016-11-22 11:39:24 +00:00
|
|
|
if (IsSigned(MipsReg))
|
|
|
|
{
|
2022-09-12 13:14:42 +00:00
|
|
|
m_Assembler.ShiftRightSignImmed(TempReg, GetMipsRegMapLo(MipsReg), 31);
|
2016-11-22 11:39:24 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2022-09-12 13:14:42 +00:00
|
|
|
m_Assembler.MoveConstToArmReg(TempReg, (uint32_t)0);
|
2016-11-22 11:39:24 +00:00
|
|
|
}
|
2022-09-12 13:14:42 +00:00
|
|
|
m_Assembler.StoreArmRegToArmRegPointer(TempReg, GprReg, (uint8_t)(MipsReg << 3) + 4, CRegName::GPR_Hi[MipsReg]);
|
|
|
|
SetArmRegProtected(TempReg, false);
|
2016-10-01 05:27:34 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2022-09-12 13:14:42 +00:00
|
|
|
m_Assembler.ShiftRightSignImmed(GetMipsRegMapLo(MipsReg), GetMipsRegMapLo(MipsReg), 31);
|
|
|
|
m_Assembler.StoreArmRegToArmRegPointer(GetMipsRegMapLo(MipsReg), GprReg, (uint8_t)(MipsReg << 3) + 4, CRegName::GPR_Hi[MipsReg]);
|
2016-10-01 05:27:34 +00:00
|
|
|
}
|
2022-09-12 13:14:42 +00:00
|
|
|
SetArmRegProtected(GetMipsRegMapLo(MipsReg), loProtected);
|
2016-10-01 05:27:34 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
SetArmRegProtected(GprReg, false);
|
|
|
|
}
|
|
|
|
|
2016-08-11 11:09:21 +00:00
|
|
|
void CArmRegInfo::WriteBackRegisters()
|
|
|
|
{
|
2016-10-01 05:27:34 +00:00
|
|
|
if (m_InCallDirect)
|
|
|
|
{
|
2022-09-12 13:14:42 +00:00
|
|
|
m_CodeBlock.Log("%s: in CallDirect", __FUNCTION__);
|
2016-10-01 05:27:34 +00:00
|
|
|
g_Notify->BreakPoint(__FILE__, __LINE__);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
UnMap_AllFPRs();
|
|
|
|
|
|
|
|
int32_t ArmRegCount = sizeof(m_ArmReg_MappedTo) / sizeof(m_ArmReg_MappedTo[0]);
|
2017-05-06 09:27:06 +00:00
|
|
|
for (int32_t i = 1; i < 32; i++) { UnMap_GPR(i, true); }
|
2022-09-12 13:14:42 +00:00
|
|
|
for (int32_t i = 0; i < ArmRegCount; i++) { UnMap_ArmReg((CArmOps::ArmReg)i); }
|
|
|
|
for (int32_t i = 0; i < ArmRegCount; i++) { SetArmRegProtected((CArmOps::ArmReg)i, false); }
|
2016-10-01 05:27:34 +00:00
|
|
|
|
|
|
|
for (int32_t count = 1; count < 32; count++)
|
|
|
|
{
|
|
|
|
switch (GetMipsRegState(count))
|
|
|
|
{
|
|
|
|
case STATE_UNKNOWN: break;
|
|
|
|
case STATE_CONST_32_SIGN:
|
|
|
|
g_Notify->BreakPoint(__FILE__, __LINE__);
|
|
|
|
break;
|
|
|
|
case STATE_CONST_32_ZERO:
|
|
|
|
g_Notify->BreakPoint(__FILE__, __LINE__);
|
|
|
|
break;
|
|
|
|
case STATE_CONST_64:
|
|
|
|
g_Notify->BreakPoint(__FILE__, __LINE__);
|
|
|
|
break;
|
|
|
|
default:
|
2022-09-12 13:14:42 +00:00
|
|
|
m_CodeBlock.Log("%s: Unknown state: %d reg %d (%s)", __FUNCTION__, GetMipsRegState(count), count, CRegName::GPR[count]);
|
2016-10-01 05:27:34 +00:00
|
|
|
g_Notify->BreakPoint(__FILE__, __LINE__);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-10-01 05:32:01 +00:00
|
|
|
void CArmRegInfo::UnMap_AllFPRs()
|
|
|
|
{
|
|
|
|
if (m_InCallDirect)
|
|
|
|
{
|
2022-09-12 13:14:42 +00:00
|
|
|
m_CodeBlock.Log("%s: in CallDirect", __FUNCTION__);
|
2016-10-01 05:32:01 +00:00
|
|
|
g_Notify->BreakPoint(__FILE__, __LINE__);
|
|
|
|
return;
|
|
|
|
}
|
2022-09-12 13:14:42 +00:00
|
|
|
m_CodeBlock.Log("%s", __FUNCTION__);
|
2016-10-01 05:32:01 +00:00
|
|
|
}
|
|
|
|
|
2016-11-22 21:39:40 +00:00
|
|
|
CArmOps::ArmReg CArmRegInfo::UnMap_TempReg(bool TempMapping)
|
2016-10-01 06:52:33 +00:00
|
|
|
{
|
|
|
|
if (m_InCallDirect)
|
|
|
|
{
|
2022-09-12 13:14:42 +00:00
|
|
|
m_CodeBlock.Log("%s: in CallDirect", __FUNCTION__);
|
2016-10-01 06:52:33 +00:00
|
|
|
g_Notify->BreakPoint(__FILE__, __LINE__);
|
2022-09-12 13:14:42 +00:00
|
|
|
return CArmOps::Arm_Unknown;
|
|
|
|
}
|
|
|
|
CArmOps::ArmReg Reg = CArmOps::Arm_Unknown;
|
|
|
|
|
|
|
|
if (GetArmRegMapped( CArmOps::Arm_R7) == Temp_Mapped && !GetArmRegProtected( CArmOps::Arm_R7)) { return CArmOps::Arm_R7; }
|
|
|
|
if (GetArmRegMapped( CArmOps::Arm_R6) == Temp_Mapped && !GetArmRegProtected( CArmOps::Arm_R6)) { return CArmOps::Arm_R6; }
|
|
|
|
if (GetArmRegMapped( CArmOps::Arm_R5) == Temp_Mapped && !GetArmRegProtected( CArmOps::Arm_R5)) { return CArmOps::Arm_R5; }
|
|
|
|
if (GetArmRegMapped( CArmOps::Arm_R4) == Temp_Mapped && !GetArmRegProtected( CArmOps::Arm_R4)) { return CArmOps::Arm_R4; }
|
|
|
|
if (GetArmRegMapped( CArmOps::Arm_R3) == Temp_Mapped && !GetArmRegProtected( CArmOps::Arm_R3)) { return CArmOps::Arm_R3; }
|
|
|
|
if (GetArmRegMapped( CArmOps::Arm_R2) == Temp_Mapped && !GetArmRegProtected( CArmOps::Arm_R2)) { return CArmOps::Arm_R2; }
|
|
|
|
if (GetArmRegMapped( CArmOps::Arm_R1) == Temp_Mapped && !GetArmRegProtected( CArmOps::Arm_R1)) { return CArmOps::Arm_R1; }
|
|
|
|
if (GetArmRegMapped( CArmOps::Arm_R0) == Temp_Mapped && !GetArmRegProtected( CArmOps::Arm_R0)) { return CArmOps::Arm_R0; }
|
2016-11-22 21:39:40 +00:00
|
|
|
if (TempMapping)
|
|
|
|
{
|
2022-09-12 13:14:42 +00:00
|
|
|
if (GetArmRegMapped( CArmOps::Arm_R11) == Temp_Mapped && !GetArmRegProtected( CArmOps::Arm_R11)) { return CArmOps::Arm_R11; }
|
|
|
|
if (GetArmRegMapped( CArmOps::Arm_R10) == Temp_Mapped && !GetArmRegProtected( CArmOps::Arm_R10)) { return CArmOps::Arm_R10; }
|
2016-11-22 21:39:40 +00:00
|
|
|
}
|
2022-09-12 13:14:42 +00:00
|
|
|
if (GetArmRegMapped( CArmOps::Arm_R9) == Temp_Mapped && !GetArmRegProtected( CArmOps::Arm_R9)) { return CArmOps::Arm_R9; }
|
|
|
|
if (GetArmRegMapped( CArmOps::Arm_R8) == Temp_Mapped && !GetArmRegProtected( CArmOps::Arm_R8)) { return CArmOps::Arm_R8; }
|
2016-10-01 06:52:33 +00:00
|
|
|
|
2022-09-12 13:14:42 +00:00
|
|
|
if (Reg != CArmOps::Arm_Unknown)
|
2016-10-01 06:52:33 +00:00
|
|
|
{
|
|
|
|
if (GetArmRegMapped(Reg) == Temp_Mapped)
|
|
|
|
{
|
2022-09-12 13:14:42 +00:00
|
|
|
m_CodeBlock.Log(" regcache: unallocate %s from temp storage", m_Assembler.ArmRegName(Reg));
|
2016-10-01 06:52:33 +00:00
|
|
|
}
|
|
|
|
SetArmRegMapped(Reg, NotMapped);
|
|
|
|
}
|
|
|
|
return Reg;
|
|
|
|
}
|
|
|
|
|
2022-09-12 13:14:42 +00:00
|
|
|
bool CArmRegInfo::UnMap_ArmReg(CArmOps::ArmReg Reg)
|
2016-10-01 05:27:34 +00:00
|
|
|
{
|
|
|
|
if (m_InCallDirect)
|
|
|
|
{
|
2022-09-12 13:14:42 +00:00
|
|
|
m_CodeBlock.Log("%s: in CallDirect", __FUNCTION__);
|
2016-10-01 05:27:34 +00:00
|
|
|
g_Notify->BreakPoint(__FILE__, __LINE__);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
if (GetArmRegProtected(Reg))
|
|
|
|
{
|
2022-09-12 13:14:42 +00:00
|
|
|
m_CodeBlock.Log("%s: %s is protected", __FUNCTION__, m_Assembler.ArmRegName(Reg));
|
2016-10-01 05:27:34 +00:00
|
|
|
g_Notify->BreakPoint(__FILE__, __LINE__);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
if (GetArmRegMapped(Reg) == NotMapped)
|
|
|
|
{
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
else if (GetArmRegMapped(Reg) == GPR_Mapped)
|
|
|
|
{
|
|
|
|
for (uint32_t count = 1; count < 32; count++)
|
|
|
|
{
|
|
|
|
if (!IsMapped(count))
|
|
|
|
{
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (Is64Bit(count) && GetMipsRegMapHi(count) == Reg)
|
|
|
|
{
|
|
|
|
if (!GetArmRegProtected(Reg))
|
|
|
|
{
|
|
|
|
UnMap_GPR(count, true);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (GetMipsRegMapLo(count) == Reg)
|
|
|
|
{
|
|
|
|
if (!GetArmRegProtected(Reg))
|
|
|
|
{
|
|
|
|
UnMap_GPR(count, true);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2016-11-22 22:02:55 +00:00
|
|
|
g_Notify->BreakPoint(__FILE__, __LINE__);
|
2016-10-01 05:27:34 +00:00
|
|
|
}
|
|
|
|
else if (GetArmRegMapped(Reg) == Temp_Mapped)
|
|
|
|
{
|
2022-09-12 13:14:42 +00:00
|
|
|
m_CodeBlock.Log(" regcache: unallocate %s from temporary storage", m_Assembler.ArmRegName(Reg));
|
2016-10-01 05:27:34 +00:00
|
|
|
SetArmRegMapped(Reg, NotMapped);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
else if (GetArmRegMapped(Reg) == Variable_Mapped)
|
|
|
|
{
|
2022-09-12 13:14:42 +00:00
|
|
|
m_CodeBlock.Log(" regcache: unallocate %s from variable mapping (%s)", m_Assembler.ArmRegName(Reg), VariableMapName(GetVariableMappedTo(Reg)));
|
2016-10-01 05:27:34 +00:00
|
|
|
SetArmRegMapped(Reg, NotMapped);
|
2016-11-22 19:28:54 +00:00
|
|
|
m_Variable_MappedTo[Reg] = VARIABLE_UNKNOWN;
|
2016-10-01 05:27:34 +00:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
g_Notify->BreakPoint(__FILE__, __LINE__);
|
|
|
|
return false;
|
2016-08-11 11:09:21 +00:00
|
|
|
}
|
2016-09-30 13:33:07 +00:00
|
|
|
|
2016-10-01 07:05:33 +00:00
|
|
|
void CArmRegInfo::ResetRegProtection()
|
|
|
|
{
|
|
|
|
if (m_InCallDirect)
|
|
|
|
{
|
2022-09-12 13:14:42 +00:00
|
|
|
m_CodeBlock.Log("%s: in CallDirect", __FUNCTION__);
|
2016-10-01 07:05:33 +00:00
|
|
|
g_Notify->BreakPoint(__FILE__, __LINE__);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
for (uint32_t i = 0, n = sizeof(m_ArmReg_Protected) / sizeof(m_ArmReg_Protected[0]); i < n; i++)
|
|
|
|
{
|
2022-09-12 13:14:42 +00:00
|
|
|
SetArmRegProtected((CArmOps::ArmReg)i, false);
|
2016-10-01 07:05:33 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-11-22 21:39:40 +00:00
|
|
|
CArmOps::ArmReg CArmRegInfo::FreeArmReg(bool TempMapping)
|
2016-10-01 05:32:01 +00:00
|
|
|
{
|
|
|
|
if (m_InCallDirect)
|
|
|
|
{
|
2022-09-12 13:14:42 +00:00
|
|
|
m_CodeBlock.Log("%s: in CallDirect", __FUNCTION__);
|
2016-10-01 05:32:01 +00:00
|
|
|
g_Notify->BreakPoint(__FILE__, __LINE__);
|
2022-09-12 13:14:42 +00:00
|
|
|
return CArmOps::Arm_Unknown;
|
|
|
|
}
|
|
|
|
if ((GetArmRegMapped( CArmOps::Arm_R7) == NotMapped || GetArmRegMapped( CArmOps::Arm_R7) == Temp_Mapped) && !GetArmRegProtected( CArmOps::Arm_R7)) { return CArmOps::Arm_R7; }
|
|
|
|
if ((GetArmRegMapped( CArmOps::Arm_R6) == NotMapped || GetArmRegMapped( CArmOps::Arm_R6) == Temp_Mapped) && !GetArmRegProtected( CArmOps::Arm_R6)) { return CArmOps::Arm_R6; }
|
|
|
|
if ((GetArmRegMapped( CArmOps::Arm_R5) == NotMapped || GetArmRegMapped( CArmOps::Arm_R5) == Temp_Mapped) && !GetArmRegProtected( CArmOps::Arm_R5)) { return CArmOps::Arm_R5; }
|
|
|
|
if ((GetArmRegMapped( CArmOps::Arm_R4) == NotMapped || GetArmRegMapped( CArmOps::Arm_R4) == Temp_Mapped) && !GetArmRegProtected( CArmOps::Arm_R4)) { return CArmOps::Arm_R4; }
|
|
|
|
if ((GetArmRegMapped( CArmOps::Arm_R3) == NotMapped || GetArmRegMapped( CArmOps::Arm_R3) == Temp_Mapped) && !GetArmRegProtected( CArmOps::Arm_R3)) { return CArmOps::Arm_R3; }
|
|
|
|
if ((GetArmRegMapped( CArmOps::Arm_R2) == NotMapped || GetArmRegMapped( CArmOps::Arm_R2) == Temp_Mapped) && !GetArmRegProtected( CArmOps::Arm_R2)) { return CArmOps::Arm_R2; }
|
|
|
|
if ((GetArmRegMapped( CArmOps::Arm_R1) == NotMapped || GetArmRegMapped( CArmOps::Arm_R1) == Temp_Mapped) && !GetArmRegProtected( CArmOps::Arm_R1)) { return CArmOps::Arm_R1; }
|
|
|
|
if ((GetArmRegMapped( CArmOps::Arm_R0) == NotMapped || GetArmRegMapped( CArmOps::Arm_R0) == Temp_Mapped) && !GetArmRegProtected( CArmOps::Arm_R0)) { return CArmOps::Arm_R0; }
|
2016-11-22 21:39:40 +00:00
|
|
|
if (TempMapping)
|
|
|
|
{
|
2022-09-12 13:14:42 +00:00
|
|
|
if ((GetArmRegMapped( CArmOps::Arm_R11) == NotMapped || GetArmRegMapped( CArmOps::Arm_R11) == Temp_Mapped) && !GetArmRegProtected( CArmOps::Arm_R11)) { return CArmOps::Arm_R11; }
|
|
|
|
if ((GetArmRegMapped( CArmOps::Arm_R10) == NotMapped || GetArmRegMapped( CArmOps::Arm_R10) == Temp_Mapped) && !GetArmRegProtected( CArmOps::Arm_R10)) { return CArmOps::Arm_R10; }
|
2016-11-22 21:39:40 +00:00
|
|
|
}
|
2022-09-12 13:14:42 +00:00
|
|
|
if ((GetArmRegMapped( CArmOps::Arm_R9) == NotMapped || GetArmRegMapped( CArmOps::Arm_R9) == Temp_Mapped) && !GetArmRegProtected( CArmOps::Arm_R9)) { return CArmOps::Arm_R9; }
|
|
|
|
if ((GetArmRegMapped( CArmOps::Arm_R8) == NotMapped || GetArmRegMapped( CArmOps::Arm_R8) == Temp_Mapped) && !GetArmRegProtected( CArmOps::Arm_R8)) { return CArmOps::Arm_R8; }
|
2016-10-01 05:32:01 +00:00
|
|
|
|
2022-09-12 13:14:42 +00:00
|
|
|
CArmOps::ArmReg Reg = UnMap_TempReg(TempMapping);
|
|
|
|
if (Reg != CArmOps::Arm_Unknown) { return Reg; }
|
2016-10-01 06:52:33 +00:00
|
|
|
|
2022-09-12 13:14:42 +00:00
|
|
|
int32_t MapCount[ CArmOps::Arm_R12];
|
|
|
|
CArmOps::ArmReg MapReg[ CArmOps::Arm_R12];
|
2016-10-01 06:52:33 +00:00
|
|
|
|
2022-09-12 13:14:42 +00:00
|
|
|
for (int32_t i = 0, n = TempMapping ? CArmOps::Arm_R12 : CArmOps::Arm_R10; i < n; i++)
|
2016-10-01 06:52:33 +00:00
|
|
|
{
|
2022-09-12 13:14:42 +00:00
|
|
|
MapCount[i] = GetArmRegMapOrder((CArmOps::ArmReg)i);
|
|
|
|
MapReg[i] = (CArmOps::ArmReg)i;
|
2016-10-01 06:52:33 +00:00
|
|
|
}
|
2022-09-12 13:14:42 +00:00
|
|
|
for (int32_t i = 0, n = TempMapping ? CArmOps::Arm_R12 : CArmOps::Arm_R10; i < n; i++)
|
2016-10-01 06:52:33 +00:00
|
|
|
{
|
|
|
|
bool changed = false;
|
|
|
|
for (int32_t z = 0; z < n - 1; z++)
|
|
|
|
{
|
|
|
|
if (MapCount[z] >= MapCount[z + 1])
|
|
|
|
{
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
uint32_t temp = MapCount[z];
|
|
|
|
MapCount[z] = MapCount[z + 1];
|
|
|
|
MapCount[z + 1] = temp;
|
2022-09-12 13:14:42 +00:00
|
|
|
CArmOps::ArmReg tempReg = MapReg[z];
|
2016-10-01 06:52:33 +00:00
|
|
|
MapReg[z] = MapReg[z + 1];
|
|
|
|
MapReg[z + 1] = tempReg;
|
|
|
|
changed = true;
|
|
|
|
}
|
|
|
|
if (!changed)
|
|
|
|
{
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-09-12 13:14:42 +00:00
|
|
|
for (int32_t i = 0, n = TempMapping ? CArmOps::Arm_R12 : CArmOps::Arm_R10; i < n; i++)
|
2016-10-01 06:52:33 +00:00
|
|
|
{
|
2022-09-12 13:14:42 +00:00
|
|
|
if (((MapCount[i] > 0 && GetArmRegMapped(MapReg[i]) == GPR_Mapped) || GetArmRegMapped(MapReg[i]) == Variable_Mapped) && !GetArmRegProtected((CArmOps::ArmReg)MapReg[i]))
|
2016-10-01 06:52:33 +00:00
|
|
|
{
|
2022-09-12 13:14:42 +00:00
|
|
|
if (UnMap_ArmReg((CArmOps::ArmReg)MapReg[i]))
|
2016-10-01 06:52:33 +00:00
|
|
|
{
|
2022-09-12 13:14:42 +00:00
|
|
|
return (CArmOps::ArmReg)MapReg[i];
|
2016-10-01 06:52:33 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2016-11-22 21:47:28 +00:00
|
|
|
|
|
|
|
LogRegisterState();
|
2016-10-01 05:32:01 +00:00
|
|
|
g_Notify->BreakPoint(__FILE__, __LINE__);
|
2022-09-12 13:14:42 +00:00
|
|
|
return CArmOps::Arm_Unknown;
|
2016-10-01 05:32:01 +00:00
|
|
|
}
|
|
|
|
|
2016-11-22 21:47:28 +00:00
|
|
|
void CArmRegInfo::LogRegisterState(void)
|
|
|
|
{
|
2016-12-12 19:11:47 +00:00
|
|
|
if (!CDebugSettings::bRecordRecompilerAsm())
|
2016-11-22 21:47:28 +00:00
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (uint32_t i = 0; i < 16; i++)
|
|
|
|
{
|
|
|
|
stdstr regname;
|
|
|
|
|
2022-09-12 13:14:42 +00:00
|
|
|
if (GetArmRegMapped((CArmOps::ArmReg)i) == CArmRegInfo::GPR_Mapped)
|
2016-11-22 21:47:28 +00:00
|
|
|
{
|
|
|
|
for (uint32_t count = 1; count < 32; count++)
|
|
|
|
{
|
|
|
|
if (!IsMapped(count))
|
|
|
|
{
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2022-09-12 13:14:42 +00:00
|
|
|
if (Is64Bit(count) && GetMipsRegMapHi(count) == (CArmOps::ArmReg)i)
|
2016-11-22 21:47:28 +00:00
|
|
|
{
|
|
|
|
regname = CRegName::GPR_Hi[count];
|
|
|
|
break;
|
|
|
|
}
|
2022-09-12 13:14:42 +00:00
|
|
|
if (GetMipsRegMapLo(count) == (CArmOps::ArmReg)i)
|
2016-11-22 21:47:28 +00:00
|
|
|
{
|
|
|
|
regname = CRegName::GPR_Lo[count];
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-09-12 13:14:42 +00:00
|
|
|
m_CodeBlock.Log("GetArmRegMapped(%s) = %X%s%s Protected: %s MapOrder: %d",
|
|
|
|
m_Assembler.ArmRegName((CArmOps::ArmReg)i),
|
|
|
|
GetArmRegMapped((CArmOps::ArmReg)i),
|
|
|
|
GetArmRegMapped((CArmOps::ArmReg)i) == CArmRegInfo::Variable_Mapped ? stdstr_f(" (%s)", CArmRegInfo::VariableMapName(GetVariableMappedTo((CArmOps::ArmReg)i))).c_str() : "",
|
2016-11-22 21:47:28 +00:00
|
|
|
regname.length() > 0 ? stdstr_f(" (%s)", regname.c_str()).c_str() : "",
|
2022-09-12 13:14:42 +00:00
|
|
|
GetArmRegProtected((CArmOps::ArmReg)i) ? "true" : "false",
|
|
|
|
GetArmRegMapOrder((CArmOps::ArmReg)i)
|
2016-11-22 21:47:28 +00:00
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-09-12 13:14:42 +00:00
|
|
|
CArmOps::ArmReg CArmRegInfo::Map_TempReg(CArmOps::ArmReg Reg, int32_t MipsReg, bool LoadHiWord)
|
2016-09-30 19:58:04 +00:00
|
|
|
{
|
|
|
|
if (m_InCallDirect)
|
|
|
|
{
|
2022-09-12 13:14:42 +00:00
|
|
|
m_CodeBlock.Log("%s: in CallDirect", __FUNCTION__);
|
2016-09-30 19:58:04 +00:00
|
|
|
g_Notify->BreakPoint(__FILE__, __LINE__);
|
2022-09-12 13:14:42 +00:00
|
|
|
return CArmOps::Arm_Unknown;
|
2016-09-30 19:58:04 +00:00
|
|
|
}
|
2022-09-12 13:14:42 +00:00
|
|
|
CArmOps::ArmReg GprReg = MipsReg >= 0 ? Map_Variable(VARIABLE_GPR) : CArmOps::Arm_Unknown;
|
2016-09-30 19:58:04 +00:00
|
|
|
|
|
|
|
if (Reg == CArmOps::Arm_Any)
|
|
|
|
{
|
2022-09-12 13:14:42 +00:00
|
|
|
if (GetArmRegMapped( CArmOps::Arm_R7) == Temp_Mapped && !GetArmRegProtected( CArmOps::Arm_R7)) { Reg = CArmOps::Arm_R7; }
|
|
|
|
else if (GetArmRegMapped( CArmOps::Arm_R6) == Temp_Mapped && !GetArmRegProtected( CArmOps::Arm_R6)) { Reg = CArmOps::Arm_R6; }
|
|
|
|
else if (GetArmRegMapped( CArmOps::Arm_R5) == Temp_Mapped && !GetArmRegProtected( CArmOps::Arm_R5)) { Reg = CArmOps::Arm_R5; }
|
|
|
|
else if (GetArmRegMapped( CArmOps::Arm_R4) == Temp_Mapped && !GetArmRegProtected( CArmOps::Arm_R4)) { Reg = CArmOps::Arm_R4; }
|
|
|
|
else if (GetArmRegMapped( CArmOps::Arm_R3) == Temp_Mapped && !GetArmRegProtected( CArmOps::Arm_R3)) { Reg = CArmOps::Arm_R3; }
|
|
|
|
else if (GetArmRegMapped( CArmOps::Arm_R2) == Temp_Mapped && !GetArmRegProtected( CArmOps::Arm_R2)) { Reg = CArmOps::Arm_R2; }
|
|
|
|
else if (GetArmRegMapped( CArmOps::Arm_R1) == Temp_Mapped && !GetArmRegProtected( CArmOps::Arm_R1)) { Reg = CArmOps::Arm_R1; }
|
|
|
|
else if (GetArmRegMapped( CArmOps::Arm_R0) == Temp_Mapped && !GetArmRegProtected( CArmOps::Arm_R0)) { Reg = CArmOps::Arm_R0; }
|
|
|
|
else if (GetArmRegMapped( CArmOps::Arm_R11) == Temp_Mapped && !GetArmRegProtected( CArmOps::Arm_R11)) { Reg = CArmOps::Arm_R11; }
|
|
|
|
else if (GetArmRegMapped( CArmOps::Arm_R10) == Temp_Mapped && !GetArmRegProtected( CArmOps::Arm_R10)) { Reg = CArmOps::Arm_R10; }
|
|
|
|
else if (GetArmRegMapped( CArmOps::Arm_R9) == Temp_Mapped && !GetArmRegProtected( CArmOps::Arm_R9)) { Reg = CArmOps::Arm_R9; }
|
|
|
|
else if (GetArmRegMapped( CArmOps::Arm_R8) == Temp_Mapped && !GetArmRegProtected( CArmOps::Arm_R8)) { Reg = CArmOps::Arm_R8; }
|
|
|
|
|
|
|
|
if (Reg == CArmOps::Arm_Any)
|
2016-09-30 19:58:04 +00:00
|
|
|
{
|
2016-11-22 21:39:40 +00:00
|
|
|
Reg = FreeArmReg(true);
|
2022-09-12 13:14:42 +00:00
|
|
|
if (Reg == CArmOps::Arm_Unknown)
|
2016-09-30 19:58:04 +00:00
|
|
|
{
|
|
|
|
WriteTrace(TraceRegisterCache, TraceError, "Failed to find a free register");
|
|
|
|
g_Notify->BreakPoint(__FILE__, __LINE__);
|
2022-09-12 13:14:42 +00:00
|
|
|
return CArmOps::Arm_Unknown;
|
2016-09-30 19:58:04 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (GetArmRegMapped(Reg) == NotMapped || GetArmRegMapped(Reg) == Temp_Mapped)
|
|
|
|
{
|
|
|
|
if (GetArmRegProtected(Reg))
|
|
|
|
{
|
|
|
|
g_Notify->BreakPoint(__FILE__, __LINE__);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (GetArmRegMapped(Reg) == GPR_Mapped)
|
|
|
|
{
|
|
|
|
g_Notify->BreakPoint(__FILE__, __LINE__);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
g_Notify->BreakPoint(__FILE__, __LINE__);
|
|
|
|
}
|
|
|
|
if (MipsReg < 0)
|
|
|
|
{
|
2022-09-12 13:14:42 +00:00
|
|
|
m_CodeBlock.Log(" regcache: allocate %s as temporary storage", m_Assembler.ArmRegName(Reg));
|
2016-09-30 19:58:04 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2022-09-12 13:14:42 +00:00
|
|
|
m_CodeBlock.Log(" regcache: allocate %s as temporary storage (%s)", m_Assembler.ArmRegName(Reg), LoadHiWord ? CRegName::GPR_Hi[MipsReg] : CRegName::GPR_Lo[MipsReg]);
|
|
|
|
if (GprReg == CArmOps::Arm_Unknown)
|
2016-09-30 19:58:04 +00:00
|
|
|
{
|
|
|
|
g_Notify->BreakPoint(__FILE__, __LINE__);
|
|
|
|
}
|
|
|
|
if (LoadHiWord)
|
|
|
|
{
|
|
|
|
if (IsUnknown(MipsReg))
|
|
|
|
{
|
2022-09-12 13:14:42 +00:00
|
|
|
m_Assembler.LoadArmRegPointerToArmReg(Reg, GprReg, (uint8_t)(MipsReg << 3) + 4, CRegName::GPR_Hi[MipsReg]);
|
2016-09-30 19:58:04 +00:00
|
|
|
}
|
|
|
|
else if (IsMapped(MipsReg))
|
|
|
|
{
|
2016-10-01 06:55:06 +00:00
|
|
|
if (Is64Bit(MipsReg))
|
|
|
|
{
|
|
|
|
g_Notify->BreakPoint(__FILE__, __LINE__);
|
|
|
|
//MoveArmRegToArmReg(GetMipsRegMapHi(MipsReg), Reg);
|
|
|
|
}
|
|
|
|
else if (IsSigned(MipsReg))
|
|
|
|
{
|
2022-09-12 13:14:42 +00:00
|
|
|
m_Assembler.ShiftRightSignImmed(Reg, GetMipsRegMapLo(MipsReg), 31);
|
2016-10-01 06:55:06 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2022-09-12 13:14:42 +00:00
|
|
|
m_Assembler.MoveConstToArmReg(Reg, (uint32_t)0);
|
2016-10-01 06:55:06 +00:00
|
|
|
}
|
2016-09-30 19:58:04 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (Is64Bit(MipsReg))
|
|
|
|
{
|
|
|
|
g_Notify->BreakPoint(__FILE__, __LINE__);
|
2022-09-12 13:14:42 +00:00
|
|
|
//m_Assembler.MoveConstToArmReg(Reg, GetMipsRegHi(MipsReg));
|
2016-09-30 19:58:04 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
g_Notify->BreakPoint(__FILE__, __LINE__);
|
2022-09-12 13:14:42 +00:00
|
|
|
//m_Assembler.MoveConstToArmReg(Reg, GetMipsRegLo_S(MipsReg) >> 31);
|
2016-09-30 19:58:04 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (IsUnknown(MipsReg))
|
|
|
|
{
|
2022-09-12 13:14:42 +00:00
|
|
|
m_Assembler.LoadArmRegPointerToArmReg(Reg, GprReg, (uint8_t)(MipsReg << 3), CRegName::GPR_Lo[MipsReg]);
|
2016-09-30 19:58:04 +00:00
|
|
|
}
|
|
|
|
else if (IsMapped(MipsReg))
|
|
|
|
{
|
2022-09-12 13:14:42 +00:00
|
|
|
m_Assembler.AddConstToArmReg(Reg, GetMipsRegMapLo(MipsReg), 0);
|
2016-09-30 19:58:04 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2022-09-12 13:14:42 +00:00
|
|
|
m_Assembler.MoveConstToArmReg(Reg, GetMipsRegLo(MipsReg));
|
2016-09-30 19:58:04 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
SetArmRegMapped(Reg, Temp_Mapped);
|
|
|
|
SetArmRegProtected(Reg, true);
|
|
|
|
for (int32_t i = 0, n = sizeof(m_ArmReg_MappedTo) / sizeof(m_ArmReg_MappedTo[0]); i < n; i++)
|
|
|
|
{
|
2022-09-12 13:14:42 +00:00
|
|
|
int32_t MapOrder = GetArmRegMapOrder((CArmOps::ArmReg)i);
|
2016-09-30 19:58:04 +00:00
|
|
|
if (MapOrder > 0)
|
|
|
|
{
|
2022-09-12 13:14:42 +00:00
|
|
|
SetArmRegMapOrder((CArmOps::ArmReg)i, MapOrder + 1);
|
2016-09-30 19:58:04 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
SetArmRegMapOrder(Reg, 1);
|
|
|
|
SetArmRegProtected(GprReg, false);
|
|
|
|
return Reg;
|
|
|
|
}
|
|
|
|
|
2022-09-12 13:14:42 +00:00
|
|
|
CArmOps::ArmReg CArmRegInfo::Map_Variable(VARIABLE_MAPPED variable, CArmOps::ArmReg Reg)
|
2016-09-30 13:33:07 +00:00
|
|
|
{
|
2022-09-12 13:14:42 +00:00
|
|
|
m_CodeBlock.Log("%s: variable: %s Reg: %d", __FUNCTION__, VariableMapName(variable), Reg);
|
2016-11-22 21:29:11 +00:00
|
|
|
|
2016-09-30 13:33:07 +00:00
|
|
|
if (m_InCallDirect)
|
|
|
|
{
|
2022-09-12 13:14:42 +00:00
|
|
|
m_CodeBlock.Log("%s: in CallDirect", __FUNCTION__);
|
2016-09-30 13:33:07 +00:00
|
|
|
g_Notify->BreakPoint(__FILE__, __LINE__);
|
2022-09-12 13:14:42 +00:00
|
|
|
return CArmOps::Arm_Unknown;
|
2016-09-30 13:33:07 +00:00
|
|
|
}
|
2016-11-22 21:29:11 +00:00
|
|
|
|
2022-09-12 13:14:42 +00:00
|
|
|
if (Reg == CArmOps::Arm_Unknown)
|
2016-09-30 13:33:07 +00:00
|
|
|
{
|
2016-11-22 21:29:11 +00:00
|
|
|
g_Notify->BreakPoint(__FILE__, __LINE__);
|
2022-09-12 13:14:42 +00:00
|
|
|
return CArmOps::Arm_Unknown;
|
2016-09-30 13:33:07 +00:00
|
|
|
}
|
|
|
|
|
2022-09-12 13:14:42 +00:00
|
|
|
if (variable == VARIABLE_GPR && Reg != CArmOps::Arm_Any && Reg != CArmOps::Arm_R12)
|
2016-09-30 13:33:07 +00:00
|
|
|
{
|
|
|
|
g_Notify->BreakPoint(__FILE__, __LINE__);
|
2022-09-12 13:14:42 +00:00
|
|
|
return CArmOps::Arm_Unknown;
|
2016-09-30 13:33:07 +00:00
|
|
|
}
|
2016-11-22 21:29:11 +00:00
|
|
|
|
2022-09-12 13:14:42 +00:00
|
|
|
if (Reg == CArmOps::Arm_Any)
|
2016-11-22 21:29:11 +00:00
|
|
|
{
|
|
|
|
Reg = GetVariableReg(variable);
|
2022-09-12 13:14:42 +00:00
|
|
|
if (Reg != CArmOps::Arm_Unknown)
|
2016-11-22 21:29:11 +00:00
|
|
|
{
|
|
|
|
SetArmRegProtected(Reg, true);
|
|
|
|
return Reg;
|
|
|
|
}
|
2017-05-06 09:27:06 +00:00
|
|
|
|
2022-09-12 13:14:42 +00:00
|
|
|
Reg = variable == VARIABLE_GPR ? CArmOps::Arm_R12 : FreeArmReg(false);
|
|
|
|
if (Reg == CArmOps::Arm_Unknown)
|
2016-11-22 21:29:11 +00:00
|
|
|
{
|
|
|
|
WriteTrace(TraceRegisterCache, TraceError, "Failed to find a free register");
|
|
|
|
g_Notify->BreakPoint(__FILE__, __LINE__);
|
2022-09-12 13:14:42 +00:00
|
|
|
return CArmOps::Arm_Unknown;
|
2016-11-22 21:29:11 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (GetArmRegMapped(Reg) == Variable_Mapped && m_Variable_MappedTo[Reg] == variable)
|
|
|
|
{
|
|
|
|
return Reg;
|
|
|
|
}
|
|
|
|
else if (GetArmRegMapped(Reg) != NotMapped)
|
|
|
|
{
|
|
|
|
UnMap_ArmReg(Reg);
|
|
|
|
}
|
|
|
|
|
2016-09-30 13:33:07 +00:00
|
|
|
SetArmRegMapped(Reg, Variable_Mapped);
|
|
|
|
SetArmRegProtected(Reg, true);
|
|
|
|
|
2022-09-12 13:14:42 +00:00
|
|
|
m_CodeBlock.Log(" regcache: allocate %s as pointer to %s", m_Assembler.ArmRegName(Reg), VariableMapName(variable));
|
2016-11-22 21:29:11 +00:00
|
|
|
m_Variable_MappedTo[Reg] = variable;
|
2022-09-12 13:14:42 +00:00
|
|
|
if (variable == VARIABLE_GPR) { m_Assembler.MoveConstToArmReg(Reg, (uint32_t)_GPR, "_GPR"); }
|
|
|
|
else if (variable == VARIABLE_FPR) { m_Assembler.MoveConstToArmReg(Reg, (uint32_t)_FPR_S, "_FPR_S"); }
|
|
|
|
else if (variable == VARIABLE_TLB_READMAP) { m_Assembler.MoveConstToArmReg(Reg, (uint32_t)(g_MMU->m_TLB_ReadMap), "MMU->TLB_ReadMap"); }
|
|
|
|
else if (variable == VARIABLE_TLB_WRITEMAP) { m_Assembler.MoveConstToArmReg(Reg, (uint32_t)(g_MMU->m_TLB_WriteMap), "MMU->m_TLB_WriteMap"); }
|
|
|
|
else if (variable == VARIABLE_TLB_LOAD_ADDRESS) { m_Assembler.MoveConstToArmReg(Reg, (uint32_t)(g_TLBLoadAddress), "g_TLBLoadAddress"); }
|
|
|
|
else if (variable == VARIABLE_TLB_STORE_ADDRESS) { m_Assembler.MoveConstToArmReg(Reg, (uint32_t)(g_TLBStoreAddress), "g_TLBStoreAddress"); }
|
|
|
|
else if (variable == VARIABLE_NEXT_TIMER) { m_Assembler.MoveConstToArmReg(Reg, (uint32_t)(g_NextTimer), "g_NextTimer"); }
|
2016-11-22 21:29:11 +00:00
|
|
|
else
|
2016-09-30 13:33:07 +00:00
|
|
|
{
|
|
|
|
g_Notify->BreakPoint(__FILE__, __LINE__);
|
2022-09-12 13:14:42 +00:00
|
|
|
return CArmOps::Arm_Unknown;
|
2016-09-30 13:33:07 +00:00
|
|
|
}
|
|
|
|
return Reg;
|
|
|
|
}
|
|
|
|
|
2016-11-22 21:29:11 +00:00
|
|
|
CArmOps::ArmReg CArmRegInfo::GetVariableReg(VARIABLE_MAPPED variable) const
|
|
|
|
{
|
|
|
|
for (int32_t i = 0, n = sizeof(m_ArmReg_MappedTo) / sizeof(m_ArmReg_MappedTo[0]); i < n; i++)
|
|
|
|
{
|
|
|
|
if (m_ArmReg_MappedTo[i] == Variable_Mapped && m_Variable_MappedTo[i] == variable)
|
|
|
|
{
|
2022-09-12 13:14:42 +00:00
|
|
|
return (CArmOps::ArmReg)i;
|
2016-11-22 21:29:11 +00:00
|
|
|
}
|
|
|
|
}
|
2022-09-12 13:14:42 +00:00
|
|
|
return CArmOps::Arm_Unknown;
|
2016-11-22 21:29:11 +00:00
|
|
|
}
|
|
|
|
|
2016-10-01 04:38:45 +00:00
|
|
|
void CArmRegInfo::ProtectGPR(uint32_t Reg)
|
|
|
|
{
|
|
|
|
if (m_InCallDirect)
|
|
|
|
{
|
2022-09-12 13:14:42 +00:00
|
|
|
m_CodeBlock.Log("%s: in CallDirect", __FUNCTION__);
|
2016-10-01 04:38:45 +00:00
|
|
|
g_Notify->BreakPoint(__FILE__, __LINE__);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (IsUnknown(Reg) || IsConst(Reg))
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (Is64Bit(Reg))
|
|
|
|
{
|
|
|
|
SetArmRegProtected(GetMipsRegMapHi(Reg), true);
|
|
|
|
}
|
|
|
|
SetArmRegProtected(GetMipsRegMapLo(Reg), true);
|
|
|
|
}
|
|
|
|
|
2016-11-22 21:48:41 +00:00
|
|
|
void CArmRegInfo::UnProtectGPR(uint32_t Reg)
|
|
|
|
{
|
|
|
|
if (m_InCallDirect)
|
|
|
|
{
|
2022-09-12 13:14:42 +00:00
|
|
|
m_CodeBlock.Log("%s: in CallDirect", __FUNCTION__);
|
2016-11-22 21:48:41 +00:00
|
|
|
g_Notify->BreakPoint(__FILE__, __LINE__);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (IsUnknown(Reg) || IsConst(Reg))
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (Is64Bit(Reg))
|
|
|
|
{
|
|
|
|
SetArmRegProtected(GetMipsRegMapHi(Reg), false);
|
|
|
|
}
|
|
|
|
SetArmRegProtected(GetMipsRegMapLo(Reg), false);
|
|
|
|
}
|
|
|
|
|
2016-11-22 19:28:54 +00:00
|
|
|
const char * CArmRegInfo::VariableMapName(VARIABLE_MAPPED variable)
|
|
|
|
{
|
|
|
|
switch (variable)
|
|
|
|
{
|
|
|
|
case VARIABLE_UNKNOWN: return "UNKNOWN";
|
|
|
|
case VARIABLE_GPR: return "_GPR";
|
|
|
|
case VARIABLE_FPR: return "_FPR_S";
|
|
|
|
case VARIABLE_TLB_READMAP: return "m_TLB_ReadMap";
|
2016-11-22 21:29:11 +00:00
|
|
|
case VARIABLE_TLB_WRITEMAP: return "m_TLB_WriteMap";
|
2016-11-22 19:28:54 +00:00
|
|
|
case VARIABLE_TLB_LOAD_ADDRESS: return "g_TLBLoadAddress";
|
2016-11-22 21:29:11 +00:00
|
|
|
case VARIABLE_TLB_STORE_ADDRESS: return "g_TLBStoreAddress";
|
2016-11-22 19:28:54 +00:00
|
|
|
case VARIABLE_NEXT_TIMER: return "g_NextTimer";
|
|
|
|
default:
|
|
|
|
g_Notify->BreakPoint(__FILE__, __LINE__);
|
|
|
|
return "unknown VariableMapName";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-09-29 12:15:33 +00:00
|
|
|
#endif
|