mirror of
https://github.com/izzy2lost/WeeU.git
synced 2026-07-06 00:19:59 -07:00
PPCRec: Initial support for typed registers
This commit is contained in:
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -26,7 +26,7 @@ bool IMLAnalyzer_IsTightFiniteLoop(IMLSegment* imlSegment)
|
||||
// for non-BDNZ loops, check for common patterns
|
||||
// risky approach, look for ADD/SUB operations and assume that potential overflow means finite (does not include r_r_s32 ADD/SUB)
|
||||
// this catches most loops with load-update and store-update instructions, but also those with decrementing counters
|
||||
FixedSizeList<sint32, 64, true> list_modifiedRegisters;
|
||||
FixedSizeList<IMLReg, 64, true> list_modifiedRegisters;
|
||||
for (const IMLInstruction& instIt : imlSegment->imlList)
|
||||
{
|
||||
if (instIt.type == PPCREC_IML_TYPE_R_S32 && (instIt.operation == PPCREC_IML_OP_ADD || instIt.operation == PPCREC_IML_OP_SUB) )
|
||||
|
||||
@@ -41,20 +41,22 @@ const char* IMLDebug_GetOpcodeName(const IMLInstruction* iml)
|
||||
return _tempOpcodename;
|
||||
}
|
||||
|
||||
void IMLDebug_AppendRegisterParam(StringBuf& strOutput, sint32 virtualRegister, bool isLast = false)
|
||||
void IMLDebug_AppendRegisterParam(StringBuf& strOutput, IMLReg virtualRegister, bool isLast = false)
|
||||
{
|
||||
uint32 regId = virtualRegister.GetRegID();
|
||||
DEBUG_BREAK; // todo (print type)
|
||||
if (isLast)
|
||||
{
|
||||
if (virtualRegister < 10)
|
||||
strOutput.addFmt("t{} ", virtualRegister);
|
||||
if (regId < 10)
|
||||
strOutput.addFmt("t{} ", regId);
|
||||
else
|
||||
strOutput.addFmt("t{}", virtualRegister);
|
||||
strOutput.addFmt("t{}", regId);
|
||||
return;
|
||||
}
|
||||
if (virtualRegister < 10)
|
||||
strOutput.addFmt("t{} , ", virtualRegister);
|
||||
if (regId < 10)
|
||||
strOutput.addFmt("t{} , ", regId);
|
||||
else
|
||||
strOutput.addFmt("t{}, ", virtualRegister);
|
||||
strOutput.addFmt("t{}, ", regId);
|
||||
}
|
||||
|
||||
void IMLDebug_AppendS32Param(StringBuf& strOutput, sint32 val, bool isLast = false)
|
||||
@@ -147,6 +149,12 @@ std::string IMLDebug_GetConditionName(IMLCondition cond)
|
||||
return "ukn";
|
||||
}
|
||||
|
||||
std::string IMLDebug_GetRegName(IMLReg r)
|
||||
{
|
||||
cemu_assert_unimplemented();
|
||||
return "";
|
||||
}
|
||||
|
||||
void IMLDebug_DumpSegment(ppcImlGenContext_t* ctx, IMLSegment* imlSegment, bool printLivenessRangeInfo)
|
||||
{
|
||||
StringBuf strOutput(1024);
|
||||
@@ -197,7 +205,7 @@ void IMLDebug_DumpSegment(ppcImlGenContext_t* ctx, IMLSegment* imlSegment, bool
|
||||
|
||||
IMLDebug_AppendRegisterParam(strOutput, inst.op_r_name.regR);
|
||||
|
||||
strOutput.addFmt("name_{} (", inst.op_r_name.regR, inst.op_r_name.name);
|
||||
strOutput.addFmt("name_{} (", inst.op_r_name.regR.GetRegID());
|
||||
if (inst.op_r_name.name >= PPCREC_NAME_R0 && inst.op_r_name.name < (PPCREC_NAME_R0 + 999))
|
||||
{
|
||||
strOutput.addFmt("r{}", inst.op_r_name.name - PPCREC_NAME_R0);
|
||||
@@ -334,9 +342,9 @@ void IMLDebug_DumpSegment(ppcImlGenContext_t* ctx, IMLSegment* imlSegment, bool
|
||||
IMLDebug_AppendRegisterParam(strOutput, inst.op_storeLoad.registerData);
|
||||
|
||||
if (inst.type == PPCREC_IML_TYPE_LOAD_INDEXED || inst.type == PPCREC_IML_TYPE_STORE_INDEXED)
|
||||
strOutput.addFmt("[t{}+t{}]", inst.op_storeLoad.registerMem, inst.op_storeLoad.registerMem2);
|
||||
strOutput.addFmt("[t{}+t{}]", inst.op_storeLoad.registerMem.GetRegID(), inst.op_storeLoad.registerMem2.GetRegID());
|
||||
else
|
||||
strOutput.addFmt("[t{}+{}]", inst.op_storeLoad.registerMem, inst.op_storeLoad.immS32);
|
||||
strOutput.addFmt("[t{}+{}]", inst.op_storeLoad.registerMem.GetRegID(), inst.op_storeLoad.immS32);
|
||||
}
|
||||
else if (inst.type == PPCREC_IML_TYPE_ATOMIC_CMP_STORE)
|
||||
{
|
||||
@@ -391,7 +399,7 @@ void IMLDebug_DumpSegment(ppcImlGenContext_t* ctx, IMLSegment* imlSegment, bool
|
||||
}
|
||||
else if (inst.type == PPCREC_IML_TYPE_FPR_R_NAME)
|
||||
{
|
||||
strOutput.addFmt("fpr_t{} = name_{} (", inst.op_r_name.regR, inst.op_r_name.name);
|
||||
strOutput.addFmt("fpr_t{} = name_{} (", inst.op_r_name.regR.GetRegID(), inst.op_r_name.name);
|
||||
if (inst.op_r_name.name >= PPCREC_NAME_FPR0 && inst.op_r_name.name < (PPCREC_NAME_FPR0 + 999))
|
||||
{
|
||||
strOutput.addFmt("fpr{}", inst.op_r_name.name - PPCREC_NAME_FPR0);
|
||||
@@ -417,16 +425,16 @@ void IMLDebug_DumpSegment(ppcImlGenContext_t* ctx, IMLSegment* imlSegment, bool
|
||||
}
|
||||
else
|
||||
strOutput.add("ukn");
|
||||
strOutput.addFmt(") = fpr_t{}", inst.op_r_name.regR);
|
||||
strOutput.addFmt(") = {}", IMLDebug_GetRegName(inst.op_r_name.regR));
|
||||
}
|
||||
else if (inst.type == PPCREC_IML_TYPE_FPR_LOAD)
|
||||
{
|
||||
strOutput.addFmt("fpr_t{} = ", inst.op_storeLoad.registerData);
|
||||
strOutput.addFmt("{} = ", IMLDebug_GetRegName(inst.op_storeLoad.registerData));
|
||||
if (inst.op_storeLoad.flags2.signExtend)
|
||||
strOutput.add("S");
|
||||
else
|
||||
strOutput.add("U");
|
||||
strOutput.addFmt("{} [t{}+{}] mode {}", inst.op_storeLoad.copyWidth / 8, inst.op_storeLoad.registerMem, inst.op_storeLoad.immS32, inst.op_storeLoad.mode);
|
||||
strOutput.addFmt("{} [{}+{}] mode {}", inst.op_storeLoad.copyWidth / 8, IMLDebug_GetRegName(inst.op_storeLoad.registerMem), inst.op_storeLoad.immS32, inst.op_storeLoad.mode);
|
||||
if (inst.op_storeLoad.flags2.notExpanded)
|
||||
{
|
||||
strOutput.addFmt(" <No expand>");
|
||||
@@ -438,23 +446,23 @@ void IMLDebug_DumpSegment(ppcImlGenContext_t* ctx, IMLSegment* imlSegment, bool
|
||||
strOutput.add("S");
|
||||
else
|
||||
strOutput.add("U");
|
||||
strOutput.addFmt("{} [t{}+{}]", inst.op_storeLoad.copyWidth / 8, inst.op_storeLoad.registerMem, inst.op_storeLoad.immS32);
|
||||
strOutput.addFmt(" = fpr_t{} mode {}", inst.op_storeLoad.registerData, inst.op_storeLoad.mode);
|
||||
strOutput.addFmt("{} [t{}+{}]", inst.op_storeLoad.copyWidth / 8, inst.op_storeLoad.registerMem.GetRegID(), inst.op_storeLoad.immS32);
|
||||
strOutput.addFmt(" = {} mode {}", IMLDebug_GetRegName(inst.op_storeLoad.registerData), inst.op_storeLoad.mode);
|
||||
}
|
||||
else if (inst.type == PPCREC_IML_TYPE_FPR_R_R)
|
||||
{
|
||||
strOutput.addFmt("{:>6} ", IMLDebug_GetOpcodeName(&inst));
|
||||
strOutput.addFmt("fpr{:02}, fpr{:02}", inst.op_fpr_r_r.regR, inst.op_fpr_r_r.regA);
|
||||
strOutput.addFmt("{}, {}", IMLDebug_GetRegName(inst.op_fpr_r_r.regR), IMLDebug_GetRegName(inst.op_fpr_r_r.regA));
|
||||
}
|
||||
else if (inst.type == PPCREC_IML_TYPE_FPR_R_R_R_R)
|
||||
{
|
||||
strOutput.addFmt("{:>6} ", IMLDebug_GetOpcodeName(&inst));
|
||||
strOutput.addFmt("fpr{:02}, fpr{:02}, fpr{:02}, fpr{:02}", inst.op_fpr_r_r_r_r.regR, inst.op_fpr_r_r_r_r.regA, inst.op_fpr_r_r_r_r.regB, inst.op_fpr_r_r_r_r.regC);
|
||||
strOutput.addFmt("{}, {}, {}, {}", IMLDebug_GetRegName(inst.op_fpr_r_r_r_r.regR), IMLDebug_GetRegName(inst.op_fpr_r_r_r_r.regA), IMLDebug_GetRegName(inst.op_fpr_r_r_r_r.regB), IMLDebug_GetRegName(inst.op_fpr_r_r_r_r.regC));
|
||||
}
|
||||
else if (inst.type == PPCREC_IML_TYPE_FPR_R_R_R)
|
||||
{
|
||||
strOutput.addFmt("{:>6} ", IMLDebug_GetOpcodeName(&inst));
|
||||
strOutput.addFmt("fpr{:02}, fpr{:02}, fpr{:02}", inst.op_fpr_r_r_r.regR, inst.op_fpr_r_r_r.regA, inst.op_fpr_r_r_r.regB);
|
||||
strOutput.addFmt("{}, {}, {}", IMLDebug_GetRegName(inst.op_fpr_r_r_r.regR), IMLDebug_GetRegName(inst.op_fpr_r_r_r.regA), IMLDebug_GetRegName(inst.op_fpr_r_r_r.regB));
|
||||
}
|
||||
else if (inst.type == PPCREC_IML_TYPE_CJUMP_CYCLE_CHECK)
|
||||
{
|
||||
@@ -462,7 +470,7 @@ void IMLDebug_DumpSegment(ppcImlGenContext_t* ctx, IMLSegment* imlSegment, bool
|
||||
}
|
||||
else if (inst.type == PPCREC_IML_TYPE_CONDITIONAL_R_S32)
|
||||
{
|
||||
strOutput.addFmt("t{} ", inst.op_conditional_r_s32.regR);
|
||||
strOutput.addFmt("{} ", IMLDebug_GetRegName(inst.op_conditional_r_s32.regR));
|
||||
bool displayAsHex = false;
|
||||
if (inst.operation == PPCREC_IML_OP_ASSIGN)
|
||||
{
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,7 +1,103 @@
|
||||
#pragma once
|
||||
|
||||
using IMLReg = uint8;
|
||||
inline constexpr IMLReg IMLREG_INVALID = (IMLReg)-1;
|
||||
using IMLRegID = uint16; // 16 bit ID
|
||||
|
||||
// format of IMLReg:
|
||||
// 0-15 (16 bit) IMLRegID
|
||||
// 19-23 (5 bit) Offset In elements, for SIMD registers
|
||||
// 24-27 (4 bit) IMLRegFormat RegFormat
|
||||
// 28-31 (4 bit) IMLRegFormat BaseFormat
|
||||
|
||||
enum class IMLRegFormat : uint8
|
||||
{
|
||||
INVALID_FORMAT,
|
||||
I64,
|
||||
I32,
|
||||
I16,
|
||||
I8,
|
||||
// I1 ?
|
||||
F64,
|
||||
F32
|
||||
};
|
||||
|
||||
class IMLReg
|
||||
{
|
||||
public:
|
||||
IMLReg()
|
||||
{
|
||||
m_raw = 0; // 0 is invalid
|
||||
}
|
||||
|
||||
IMLReg(IMLRegFormat baseRegFormat, IMLRegFormat regFormat, uint8 viewOffset, IMLRegID regId)
|
||||
{
|
||||
m_raw = 0;
|
||||
m_raw |= ((uint8)baseRegFormat << 28);
|
||||
m_raw |= ((uint8)regFormat << 24);
|
||||
m_raw |= (uint32)regId;
|
||||
}
|
||||
|
||||
IMLReg(IMLReg&& baseReg, IMLRegFormat viewFormat, uint8 viewOffset, IMLRegID regId)
|
||||
{
|
||||
DEBUG_BREAK;
|
||||
//m_raw = 0;
|
||||
//m_raw |= ((uint8)baseRegFormat << 28);
|
||||
//m_raw |= ((uint8)viewFormat << 24);
|
||||
//m_raw |= (uint32)regId;
|
||||
}
|
||||
|
||||
IMLReg(const IMLReg& other) : m_raw(other.m_raw) {}
|
||||
|
||||
IMLRegFormat GetBaseFormat() const
|
||||
{
|
||||
return (IMLRegFormat)((m_raw >> 28) & 0xF);
|
||||
}
|
||||
|
||||
IMLRegFormat GetRegFormat() const
|
||||
{
|
||||
return (IMLRegFormat)((m_raw >> 24) & 0xF);
|
||||
}
|
||||
|
||||
IMLRegID GetRegID() const
|
||||
{
|
||||
cemu_assert_debug(GetBaseFormat() != IMLRegFormat::INVALID_FORMAT);
|
||||
cemu_assert_debug(GetRegFormat() != IMLRegFormat::INVALID_FORMAT);
|
||||
return (IMLRegID)(m_raw & 0xFFFF);
|
||||
}
|
||||
|
||||
void SetRegID(IMLRegID regId)
|
||||
{
|
||||
cemu_assert_debug(regId <= 0xFFFF);
|
||||
m_raw &= ~0xFFFF;
|
||||
m_raw |= (uint32)regId;
|
||||
}
|
||||
|
||||
bool IsInvalid() const
|
||||
{
|
||||
return GetBaseFormat() == IMLRegFormat::INVALID_FORMAT;
|
||||
}
|
||||
|
||||
bool IsValid() const
|
||||
{
|
||||
return GetBaseFormat() != IMLRegFormat::INVALID_FORMAT;
|
||||
}
|
||||
|
||||
bool IsValidAndSameRegID(IMLRegID regId) const
|
||||
{
|
||||
return IsValid() && GetRegID() == regId;
|
||||
}
|
||||
|
||||
// risky
|
||||
bool operator==(const IMLReg& other) const
|
||||
{
|
||||
//__debugbreak();
|
||||
return m_raw == other.m_raw;
|
||||
}
|
||||
|
||||
private:
|
||||
uint32 m_raw;
|
||||
};
|
||||
|
||||
static const IMLReg IMLREG_INVALID(IMLRegFormat::INVALID_FORMAT, IMLRegFormat::INVALID_FORMAT, 0, 0);
|
||||
|
||||
using IMLName = uint32;
|
||||
|
||||
@@ -230,6 +326,8 @@ enum
|
||||
|
||||
struct IMLUsedRegisters
|
||||
{
|
||||
IMLUsedRegisters() {};
|
||||
|
||||
// GPR
|
||||
union
|
||||
{
|
||||
@@ -256,59 +354,63 @@ struct IMLUsedRegisters
|
||||
};
|
||||
};
|
||||
|
||||
bool IsGPRWritten(IMLReg imlReg) const
|
||||
bool IsBaseGPRWritten(IMLReg imlReg) const
|
||||
{
|
||||
cemu_assert_debug(imlReg != IMLREG_INVALID);
|
||||
return writtenGPR1 == imlReg || writtenGPR2 == imlReg;
|
||||
cemu_assert_debug(imlReg.IsValid());
|
||||
auto regId = imlReg.GetRegID();
|
||||
if (writtenGPR1.IsValid() && writtenGPR1.GetRegID() == regId)
|
||||
return true;
|
||||
if (writtenGPR2.IsValid() && writtenGPR2.GetRegID() == regId)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
template<typename Fn>
|
||||
void ForEachWrittenGPR(Fn F) const
|
||||
{
|
||||
if (writtenGPR1 != IMLREG_INVALID)
|
||||
if (writtenGPR1.IsValid())
|
||||
F(writtenGPR1);
|
||||
if (writtenGPR2 != IMLREG_INVALID)
|
||||
if (writtenGPR2.IsValid())
|
||||
F(writtenGPR2);
|
||||
}
|
||||
|
||||
template<typename Fn>
|
||||
void ForEachReadGPR(Fn F) const
|
||||
{
|
||||
if (readGPR1 != IMLREG_INVALID)
|
||||
if (readGPR1.IsValid())
|
||||
F(readGPR1);
|
||||
if (readGPR2 != IMLREG_INVALID)
|
||||
if (readGPR2.IsValid())
|
||||
F(readGPR2);
|
||||
if (readGPR3 != IMLREG_INVALID)
|
||||
if (readGPR3.IsValid())
|
||||
F(readGPR3);
|
||||
}
|
||||
|
||||
template<typename Fn>
|
||||
void ForEachAccessedGPR(Fn F) const
|
||||
{
|
||||
if (readGPR1 != IMLREG_INVALID)
|
||||
if (readGPR1.IsValid())
|
||||
F(readGPR1, false);
|
||||
if (readGPR2 != IMLREG_INVALID)
|
||||
if (readGPR2.IsValid())
|
||||
F(readGPR2, false);
|
||||
if (readGPR3 != IMLREG_INVALID)
|
||||
if (readGPR3.IsValid())
|
||||
F(readGPR3, false);
|
||||
if (writtenGPR1 != IMLREG_INVALID)
|
||||
if (writtenGPR1.IsValid())
|
||||
F(writtenGPR1, true);
|
||||
if (writtenGPR2 != IMLREG_INVALID)
|
||||
if (writtenGPR2.IsValid())
|
||||
F(writtenGPR2, true);
|
||||
}
|
||||
|
||||
bool HasFPRReg(sint16 imlReg) const
|
||||
bool HasSameBaseFPRRegId(IMLRegID regId) const
|
||||
{
|
||||
cemu_assert_debug(imlReg != IMLREG_INVALID);
|
||||
if (readFPR1 == imlReg)
|
||||
if (readFPR1.IsValid() && readFPR1.GetRegID() == regId)
|
||||
return true;
|
||||
if (readFPR2 == imlReg)
|
||||
if (readFPR2.IsValid() && readFPR2.GetRegID() == regId)
|
||||
return true;
|
||||
if (readFPR3 == imlReg)
|
||||
if (readFPR3.IsValid() && readFPR3.GetRegID() == regId)
|
||||
return true;
|
||||
if (readFPR4 == imlReg)
|
||||
if (readFPR4.IsValid() && readFPR4.GetRegID() == regId)
|
||||
return true;
|
||||
if (writtenFPR1 == imlReg)
|
||||
if (writtenFPR1.IsValid() && writtenFPR1.GetRegID() == regId)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
@@ -316,6 +418,12 @@ struct IMLUsedRegisters
|
||||
|
||||
struct IMLInstruction
|
||||
{
|
||||
IMLInstruction() {}
|
||||
IMLInstruction(const IMLInstruction& other)
|
||||
{
|
||||
memcpy(this, &other, sizeof(IMLInstruction));
|
||||
}
|
||||
|
||||
uint8 type;
|
||||
uint8 operation;
|
||||
union
|
||||
@@ -370,6 +478,7 @@ struct IMLInstruction
|
||||
uint32 param;
|
||||
uint32 param2;
|
||||
uint16 paramU16;
|
||||
IMLReg paramReg;
|
||||
}op_macro;
|
||||
struct
|
||||
{
|
||||
@@ -446,7 +555,7 @@ struct IMLInstruction
|
||||
struct
|
||||
{
|
||||
// r_s32
|
||||
uint8 regR;
|
||||
IMLReg regR;
|
||||
sint32 immS32;
|
||||
// condition
|
||||
uint8 crRegisterIndex;
|
||||
@@ -479,16 +588,17 @@ struct IMLInstruction
|
||||
|
||||
void make_debugbreak(uint32 currentPPCAddress = 0)
|
||||
{
|
||||
make_macro(PPCREC_IML_MACRO_DEBUGBREAK, 0, currentPPCAddress, 0);
|
||||
make_macro(PPCREC_IML_MACRO_DEBUGBREAK, 0, currentPPCAddress, 0, IMLREG_INVALID);
|
||||
}
|
||||
|
||||
void make_macro(uint32 macroId, uint32 param, uint32 param2, uint16 paramU16)
|
||||
void make_macro(uint32 macroId, uint32 param, uint32 param2, uint16 paramU16, IMLReg regParam)
|
||||
{
|
||||
this->type = PPCREC_IML_TYPE_MACRO;
|
||||
this->operation = macroId;
|
||||
this->op_macro.param = param;
|
||||
this->op_macro.param2 = param2;
|
||||
this->op_macro.paramU16 = paramU16;
|
||||
this->op_macro.paramReg = regParam;
|
||||
}
|
||||
|
||||
void make_cjump_cycle_check()
|
||||
@@ -497,85 +607,85 @@ struct IMLInstruction
|
||||
this->operation = 0;
|
||||
}
|
||||
|
||||
void make_r_r(uint32 operation, uint8 registerResult, uint8 registerA)
|
||||
void make_r_r(uint32 operation, IMLReg regR, IMLReg regA)
|
||||
{
|
||||
this->type = PPCREC_IML_TYPE_R_R;
|
||||
this->operation = operation;
|
||||
this->op_r_r.regR = registerResult;
|
||||
this->op_r_r.regA = registerA;
|
||||
this->op_r_r.regR = regR;
|
||||
this->op_r_r.regA = regA;
|
||||
}
|
||||
|
||||
void make_r_s32(uint32 operation, uint8 registerIndex, sint32 immS32)
|
||||
void make_r_s32(uint32 operation, IMLReg regR, sint32 immS32)
|
||||
{
|
||||
this->type = PPCREC_IML_TYPE_R_S32;
|
||||
this->operation = operation;
|
||||
this->op_r_immS32.regR = registerIndex;
|
||||
this->op_r_immS32.regR = regR;
|
||||
this->op_r_immS32.immS32 = immS32;
|
||||
}
|
||||
|
||||
void make_r_r_r(uint32 operation, uint8 registerResult, uint8 registerA, uint8 registerB)
|
||||
void make_r_r_r(uint32 operation, IMLReg regR, IMLReg regA, IMLReg regB)
|
||||
{
|
||||
this->type = PPCREC_IML_TYPE_R_R_R;
|
||||
this->operation = operation;
|
||||
this->op_r_r_r.regR = registerResult;
|
||||
this->op_r_r_r.regA = registerA;
|
||||
this->op_r_r_r.regB = registerB;
|
||||
this->op_r_r_r.regR = regR;
|
||||
this->op_r_r_r.regA = regA;
|
||||
this->op_r_r_r.regB = regB;
|
||||
}
|
||||
|
||||
void make_r_r_r_carry(uint32 operation, uint8 registerResult, uint8 registerA, uint8 registerB, uint8 registerCarry)
|
||||
void make_r_r_r_carry(uint32 operation, IMLReg regR, IMLReg regA, IMLReg regB, IMLReg regCarry)
|
||||
{
|
||||
this->type = PPCREC_IML_TYPE_R_R_R_CARRY;
|
||||
this->operation = operation;
|
||||
this->op_r_r_r_carry.regR = registerResult;
|
||||
this->op_r_r_r_carry.regA = registerA;
|
||||
this->op_r_r_r_carry.regB = registerB;
|
||||
this->op_r_r_r_carry.regCarry = registerCarry;
|
||||
this->op_r_r_r_carry.regR = regR;
|
||||
this->op_r_r_r_carry.regA = regA;
|
||||
this->op_r_r_r_carry.regB = regB;
|
||||
this->op_r_r_r_carry.regCarry = regCarry;
|
||||
}
|
||||
|
||||
void make_r_r_s32(uint32 operation, uint8 registerResult, uint8 registerA, sint32 immS32)
|
||||
void make_r_r_s32(uint32 operation, IMLReg regR, IMLReg regA, sint32 immS32)
|
||||
{
|
||||
this->type = PPCREC_IML_TYPE_R_R_S32;
|
||||
this->operation = operation;
|
||||
this->op_r_r_s32.regR = registerResult;
|
||||
this->op_r_r_s32.regA = registerA;
|
||||
this->op_r_r_s32.regR = regR;
|
||||
this->op_r_r_s32.regA = regA;
|
||||
this->op_r_r_s32.immS32 = immS32;
|
||||
}
|
||||
|
||||
void make_r_r_s32_carry(uint32 operation, uint8 registerResult, uint8 registerA, sint32 immS32, uint8 registerCarry)
|
||||
void make_r_r_s32_carry(uint32 operation, IMLReg regR, IMLReg regA, sint32 immS32, IMLReg regCarry)
|
||||
{
|
||||
this->type = PPCREC_IML_TYPE_R_R_S32_CARRY;
|
||||
this->operation = operation;
|
||||
this->op_r_r_s32_carry.regR = registerResult;
|
||||
this->op_r_r_s32_carry.regA = registerA;
|
||||
this->op_r_r_s32_carry.regR = regR;
|
||||
this->op_r_r_s32_carry.regA = regA;
|
||||
this->op_r_r_s32_carry.immS32 = immS32;
|
||||
this->op_r_r_s32_carry.regCarry = registerCarry;
|
||||
this->op_r_r_s32_carry.regCarry = regCarry;
|
||||
}
|
||||
|
||||
void make_compare(uint8 registerA, uint8 registerB, uint8 registerResult, IMLCondition cond)
|
||||
void make_compare(IMLReg regA, IMLReg regB, IMLReg regR, IMLCondition cond)
|
||||
{
|
||||
this->type = PPCREC_IML_TYPE_COMPARE;
|
||||
this->operation = -999;
|
||||
this->op_compare.regR = registerResult;
|
||||
this->op_compare.regA = registerA;
|
||||
this->op_compare.regB = registerB;
|
||||
this->op_compare.regR = regR;
|
||||
this->op_compare.regA = regA;
|
||||
this->op_compare.regB = regB;
|
||||
this->op_compare.cond = cond;
|
||||
}
|
||||
|
||||
void make_compare_s32(uint8 registerA, sint32 immS32, uint8 registerResult, IMLCondition cond)
|
||||
void make_compare_s32(IMLReg regA, sint32 immS32, IMLReg regR, IMLCondition cond)
|
||||
{
|
||||
this->type = PPCREC_IML_TYPE_COMPARE_S32;
|
||||
this->operation = -999;
|
||||
this->op_compare_s32.regR = registerResult;
|
||||
this->op_compare_s32.regA = registerA;
|
||||
this->op_compare_s32.regR = regR;
|
||||
this->op_compare_s32.regA = regA;
|
||||
this->op_compare_s32.immS32 = immS32;
|
||||
this->op_compare_s32.cond = cond;
|
||||
}
|
||||
|
||||
void make_conditional_jump(uint8 registerBool, bool mustBeTrue)
|
||||
void make_conditional_jump(IMLReg regBool, bool mustBeTrue)
|
||||
{
|
||||
this->type = PPCREC_IML_TYPE_CONDITIONAL_JUMP;
|
||||
this->operation = -999;
|
||||
this->op_conditional_jump.registerBool = registerBool;
|
||||
this->op_conditional_jump.registerBool = regBool;
|
||||
this->op_conditional_jump.mustBeTrue = mustBeTrue;
|
||||
}
|
||||
|
||||
@@ -586,12 +696,12 @@ struct IMLInstruction
|
||||
}
|
||||
|
||||
// load from memory
|
||||
void make_r_memory(uint8 registerDestination, uint8 registerMemory, sint32 immS32, uint32 copyWidth, bool signExtend, bool switchEndian)
|
||||
void make_r_memory(IMLReg regD, IMLReg regMem, sint32 immS32, uint32 copyWidth, bool signExtend, bool switchEndian)
|
||||
{
|
||||
this->type = PPCREC_IML_TYPE_LOAD;
|
||||
this->operation = 0;
|
||||
this->op_storeLoad.registerData = registerDestination;
|
||||
this->op_storeLoad.registerMem = registerMemory;
|
||||
this->op_storeLoad.registerData = regD;
|
||||
this->op_storeLoad.registerMem = regMem;
|
||||
this->op_storeLoad.immS32 = immS32;
|
||||
this->op_storeLoad.copyWidth = copyWidth;
|
||||
this->op_storeLoad.flags2.swapEndian = switchEndian;
|
||||
@@ -599,12 +709,12 @@ struct IMLInstruction
|
||||
}
|
||||
|
||||
// store to memory
|
||||
void make_memory_r(uint8 registerSource, uint8 registerMemory, sint32 immS32, uint32 copyWidth, bool switchEndian)
|
||||
void make_memory_r(IMLReg regS, IMLReg regMem, sint32 immS32, uint32 copyWidth, bool switchEndian)
|
||||
{
|
||||
this->type = PPCREC_IML_TYPE_STORE;
|
||||
this->operation = 0;
|
||||
this->op_storeLoad.registerData = registerSource;
|
||||
this->op_storeLoad.registerMem = registerMemory;
|
||||
this->op_storeLoad.registerData = regS;
|
||||
this->op_storeLoad.registerMem = regMem;
|
||||
this->op_storeLoad.immS32 = immS32;
|
||||
this->op_storeLoad.copyWidth = copyWidth;
|
||||
this->op_storeLoad.flags2.swapEndian = switchEndian;
|
||||
@@ -633,7 +743,8 @@ struct IMLInstruction
|
||||
|
||||
void CheckRegisterUsage(IMLUsedRegisters* registersUsed) const;
|
||||
|
||||
void RewriteGPR(const std::unordered_map<IMLReg, IMLReg>& translationTable);
|
||||
void ReplaceFPRs(sint32 fprRegisterSearched[4], sint32 fprRegisterReplaced[4]);
|
||||
void ReplaceFPR(sint32 fprRegisterSearched, sint32 fprRegisterReplaced);
|
||||
void RewriteGPR(const std::unordered_map<IMLRegID, IMLRegID>& translationTable);
|
||||
void ReplaceFPRs(IMLReg fprRegisterSearched[4], IMLReg fprRegisterReplaced[4]);
|
||||
void ReplaceFPR(IMLRegID fprRegisterSearched, IMLRegID fprRegisterReplaced);
|
||||
|
||||
};
|
||||
@@ -8,13 +8,18 @@
|
||||
|
||||
bool _RegExceedsFPRSpace(IMLReg r)
|
||||
{
|
||||
if (r == IMLREG_INVALID)
|
||||
if (r.IsInvalid())
|
||||
return false;
|
||||
if ((uint32)r >= PPC_X64_FPR_USABLE_REGISTERS)
|
||||
if (r.GetRegID() >= PPC_X64_FPR_USABLE_REGISTERS)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
IMLReg _FPRRegFromID(IMLRegID regId)
|
||||
{
|
||||
return IMLReg(IMLRegFormat::F64, IMLRegFormat::F64, 0, regId);
|
||||
}
|
||||
|
||||
bool PPCRecompiler_reduceNumberOfFPRRegisters(ppcImlGenContext_t* ppcImlGenContext)
|
||||
{
|
||||
// only xmm0 to xmm14 may be used, xmm15 is reserved
|
||||
@@ -48,34 +53,34 @@ bool PPCRecompiler_reduceNumberOfFPRRegisters(ppcImlGenContext_t* ppcImlGenConte
|
||||
while( true )
|
||||
{
|
||||
segIt->imlList[imlIndex].CheckRegisterUsage(®istersUsed);
|
||||
if(registersUsed.readFPR1 >= PPC_X64_FPR_USABLE_REGISTERS || registersUsed.readFPR2 >= PPC_X64_FPR_USABLE_REGISTERS || registersUsed.readFPR3 >= PPC_X64_FPR_USABLE_REGISTERS || registersUsed.readFPR4 >= PPC_X64_FPR_USABLE_REGISTERS || registersUsed.writtenFPR1 >= PPC_X64_FPR_USABLE_REGISTERS)
|
||||
if(_RegExceedsFPRSpace(registersUsed.readFPR1) || _RegExceedsFPRSpace(registersUsed.readFPR2) || _RegExceedsFPRSpace(registersUsed.readFPR3) || _RegExceedsFPRSpace(registersUsed.readFPR4) || _RegExceedsFPRSpace(registersUsed.writtenFPR1) )
|
||||
{
|
||||
// get index of register to replace
|
||||
sint32 fprToReplace = -1;
|
||||
if(_RegExceedsFPRSpace(registersUsed.readFPR1) )
|
||||
fprToReplace = registersUsed.readFPR1;
|
||||
fprToReplace = registersUsed.readFPR1.GetRegID();
|
||||
else if(_RegExceedsFPRSpace(registersUsed.readFPR2) )
|
||||
fprToReplace = registersUsed.readFPR2;
|
||||
fprToReplace = registersUsed.readFPR2.GetRegID();
|
||||
else if (_RegExceedsFPRSpace(registersUsed.readFPR3))
|
||||
fprToReplace = registersUsed.readFPR3;
|
||||
fprToReplace = registersUsed.readFPR3.GetRegID();
|
||||
else if (_RegExceedsFPRSpace(registersUsed.readFPR4))
|
||||
fprToReplace = registersUsed.readFPR4;
|
||||
fprToReplace = registersUsed.readFPR4.GetRegID();
|
||||
else if(_RegExceedsFPRSpace(registersUsed.writtenFPR1) )
|
||||
fprToReplace = registersUsed.writtenFPR1;
|
||||
fprToReplace = registersUsed.writtenFPR1.GetRegID();
|
||||
if (fprToReplace >= 0)
|
||||
{
|
||||
// generate mask of useable registers
|
||||
uint8 useableRegisterMask = 0x7F; // lowest bit is fpr register 0
|
||||
if (registersUsed.readFPR1 != -1)
|
||||
useableRegisterMask &= ~(1 << (registersUsed.readFPR1));
|
||||
if (registersUsed.readFPR2 != -1)
|
||||
useableRegisterMask &= ~(1 << (registersUsed.readFPR2));
|
||||
if (registersUsed.readFPR3 != -1)
|
||||
useableRegisterMask &= ~(1 << (registersUsed.readFPR3));
|
||||
if (registersUsed.readFPR4 != -1)
|
||||
useableRegisterMask &= ~(1 << (registersUsed.readFPR4));
|
||||
if (registersUsed.writtenFPR1 != -1)
|
||||
useableRegisterMask &= ~(1 << (registersUsed.writtenFPR1));
|
||||
if (registersUsed.readFPR1.IsValid())
|
||||
useableRegisterMask &= ~(1 << (registersUsed.readFPR1.GetRegID()));
|
||||
if (registersUsed.readFPR2.IsValid())
|
||||
useableRegisterMask &= ~(1 << (registersUsed.readFPR2.GetRegID()));
|
||||
if (registersUsed.readFPR3.IsValid())
|
||||
useableRegisterMask &= ~(1 << (registersUsed.readFPR3.GetRegID()));
|
||||
if (registersUsed.readFPR4.IsValid())
|
||||
useableRegisterMask &= ~(1 << (registersUsed.readFPR4.GetRegID()));
|
||||
if (registersUsed.writtenFPR1.IsValid())
|
||||
useableRegisterMask &= ~(1 << (registersUsed.writtenFPR1.GetRegID()));
|
||||
// get highest unused register index (0-6 range)
|
||||
sint32 unusedRegisterIndex = -1;
|
||||
for (sint32 f = 0; f < PPC_X64_FPR_USABLE_REGISTERS; f++)
|
||||
@@ -107,7 +112,7 @@ bool PPCRecompiler_reduceNumberOfFPRRegisters(ppcImlGenContext_t* ppcImlGenConte
|
||||
{
|
||||
imlInstructionItr->type = PPCREC_IML_TYPE_FPR_NAME_R;
|
||||
imlInstructionItr->operation = PPCREC_IML_OP_ASSIGN;
|
||||
imlInstructionItr->op_r_name.regR = unusedRegisterIndex;
|
||||
imlInstructionItr->op_r_name.regR = _FPRRegFromID(unusedRegisterIndex);
|
||||
imlInstructionItr->op_r_name.name = ppcImlGenContext->mappedFPRRegister[unusedRegisterIndex];
|
||||
}
|
||||
else
|
||||
@@ -116,14 +121,14 @@ bool PPCRecompiler_reduceNumberOfFPRRegisters(ppcImlGenContext_t* ppcImlGenConte
|
||||
memset(imlInstructionItr, 0x00, sizeof(IMLInstruction));
|
||||
imlInstructionItr->type = PPCREC_IML_TYPE_FPR_R_NAME;
|
||||
imlInstructionItr->operation = PPCREC_IML_OP_ASSIGN;
|
||||
imlInstructionItr->op_r_name.regR = unusedRegisterIndex;
|
||||
imlInstructionItr->op_r_name.regR = _FPRRegFromID(unusedRegisterIndex);
|
||||
imlInstructionItr->op_r_name.name = ppcImlGenContext->mappedFPRRegister[fprToReplace];
|
||||
// name_gprToReplace = unusedRegister
|
||||
imlInstructionItr = segIt->imlList.data() + (imlIndex + 3);
|
||||
memset(imlInstructionItr, 0x00, sizeof(IMLInstruction));
|
||||
imlInstructionItr->type = PPCREC_IML_TYPE_FPR_NAME_R;
|
||||
imlInstructionItr->operation = PPCREC_IML_OP_ASSIGN;
|
||||
imlInstructionItr->op_r_name.regR = unusedRegisterIndex;
|
||||
imlInstructionItr->op_r_name.regR = _FPRRegFromID(unusedRegisterIndex);
|
||||
imlInstructionItr->op_r_name.name = ppcImlGenContext->mappedFPRRegister[fprToReplace];
|
||||
// unusedRegister = name_unusedRegister
|
||||
imlInstructionItr = segIt->imlList.data() + (imlIndex + 4);
|
||||
@@ -132,7 +137,7 @@ bool PPCRecompiler_reduceNumberOfFPRRegisters(ppcImlGenContext_t* ppcImlGenConte
|
||||
{
|
||||
imlInstructionItr->type = PPCREC_IML_TYPE_FPR_R_NAME;
|
||||
imlInstructionItr->operation = PPCREC_IML_OP_ASSIGN;
|
||||
imlInstructionItr->op_r_name.regR = unusedRegisterIndex;
|
||||
imlInstructionItr->op_r_name.regR = _FPRRegFromID(unusedRegisterIndex);
|
||||
imlInstructionItr->op_r_name.name = ppcImlGenContext->mappedFPRRegister[unusedRegisterIndex];
|
||||
}
|
||||
else
|
||||
@@ -190,8 +195,8 @@ ppcRecRegisterMapping_t* PPCRecompiler_findUnloadableRegister(ppcRecManageRegist
|
||||
continue;
|
||||
if( (unloadLockedMask&(1<<i)) != 0 )
|
||||
continue;
|
||||
uint32 virtualReg = rCtx->currentMapping[i].virtualReg;
|
||||
bool isReserved = instructionUsedRegisters->HasFPRReg(virtualReg);
|
||||
IMLRegID virtualReg = rCtx->currentMapping[i].virtualReg;
|
||||
bool isReserved = instructionUsedRegisters->HasSameBaseFPRRegId(virtualReg);
|
||||
if (isReserved)
|
||||
continue;
|
||||
if (rCtx->currentMapping[i].lastUseIndex < unloadIndexLastUse)
|
||||
@@ -219,22 +224,22 @@ bool PPCRecompiler_manageFPRRegistersForSegment(ppcImlGenContext_t* ppcImlGenCon
|
||||
if (idxInst.IsSuffixInstruction())
|
||||
break;
|
||||
idxInst.CheckRegisterUsage(®istersUsed);
|
||||
sint32 fprMatch[4]; // should be IMLReg, but this code is being dropped soon anyway
|
||||
sint32 fprReplace[4];
|
||||
fprMatch[0] = -1; // should be IMLREG_INVALID
|
||||
fprMatch[1] = -1;
|
||||
fprMatch[2] = -1;
|
||||
fprMatch[3] = -1;
|
||||
fprReplace[0] = -1;
|
||||
fprReplace[1] = -1;
|
||||
fprReplace[2] = -1;
|
||||
fprReplace[3] = -1;
|
||||
IMLReg fprMatch[4];
|
||||
IMLReg fprReplace[4];
|
||||
fprMatch[0] = IMLREG_INVALID;
|
||||
fprMatch[1] = IMLREG_INVALID;
|
||||
fprMatch[2] = IMLREG_INVALID;
|
||||
fprMatch[3] = IMLREG_INVALID;
|
||||
fprReplace[0] = IMLREG_INVALID;
|
||||
fprReplace[1] = IMLREG_INVALID;
|
||||
fprReplace[2] = IMLREG_INVALID;
|
||||
fprReplace[3] = IMLREG_INVALID;
|
||||
// generate a mask of registers that we may not free
|
||||
sint32 numReplacedOperands = 0;
|
||||
uint32 unloadLockedMask = 0;
|
||||
for (sint32 f = 0; f < 5; f++)
|
||||
{
|
||||
sint32 virtualFpr;
|
||||
IMLReg virtualFpr;
|
||||
if (f == 0)
|
||||
virtualFpr = registersUsed.readFPR1;
|
||||
else if (f == 1)
|
||||
@@ -245,12 +250,14 @@ bool PPCRecompiler_manageFPRRegistersForSegment(ppcImlGenContext_t* ppcImlGenCon
|
||||
virtualFpr = registersUsed.readFPR4;
|
||||
else if (f == 4)
|
||||
virtualFpr = registersUsed.writtenFPR1;
|
||||
if(virtualFpr == IMLREG_INVALID)
|
||||
if(virtualFpr.IsInvalid())
|
||||
continue;
|
||||
cemu_assert_debug(virtualFpr < 64);
|
||||
cemu_assert_debug(virtualFpr.GetBaseFormat() == IMLRegFormat::F64);
|
||||
cemu_assert_debug(virtualFpr.GetRegFormat() == IMLRegFormat::F64);
|
||||
cemu_assert_debug(virtualFpr.GetRegID() < 64);
|
||||
// check if this virtual FPR is already loaded in any real register
|
||||
ppcRecRegisterMapping_t* regMapping;
|
||||
if (rCtx.ppcRegToMapping[virtualFpr] == -1)
|
||||
if (rCtx.ppcRegToMapping[virtualFpr.GetRegID()] == -1)
|
||||
{
|
||||
// not loaded
|
||||
// find available register
|
||||
@@ -269,7 +276,7 @@ bool PPCRecompiler_manageFPRRegistersForSegment(ppcImlGenContext_t* ppcImlGenCon
|
||||
memset(imlInstructionTemp, 0x00, sizeof(IMLInstruction));
|
||||
imlInstructionTemp->type = PPCREC_IML_TYPE_FPR_NAME_R;
|
||||
imlInstructionTemp->operation = PPCREC_IML_OP_ASSIGN;
|
||||
imlInstructionTemp->op_r_name.regR = (uint8)(unloadRegMapping - rCtx.currentMapping);
|
||||
imlInstructionTemp->op_r_name.regR = _FPRRegFromID((uint8)(unloadRegMapping - rCtx.currentMapping));
|
||||
imlInstructionTemp->op_r_name.name = ppcImlGenContext->mappedFPRRegister[unloadRegMapping->virtualReg];
|
||||
idx++;
|
||||
// update mapping
|
||||
@@ -285,18 +292,18 @@ bool PPCRecompiler_manageFPRRegistersForSegment(ppcImlGenContext_t* ppcImlGenCon
|
||||
memset(imlInstructionTemp, 0x00, sizeof(IMLInstruction));
|
||||
imlInstructionTemp->type = PPCREC_IML_TYPE_FPR_R_NAME;
|
||||
imlInstructionTemp->operation = PPCREC_IML_OP_ASSIGN;
|
||||
imlInstructionTemp->op_r_name.regR = (uint8)(regMapping-rCtx.currentMapping);
|
||||
imlInstructionTemp->op_r_name.name = ppcImlGenContext->mappedFPRRegister[virtualFpr];
|
||||
imlInstructionTemp->op_r_name.regR = _FPRRegFromID((uint8)(regMapping-rCtx.currentMapping));
|
||||
imlInstructionTemp->op_r_name.name = ppcImlGenContext->mappedFPRRegister[virtualFpr.GetRegID()];
|
||||
idx++;
|
||||
// update mapping
|
||||
regMapping->virtualReg = virtualFpr;
|
||||
rCtx.ppcRegToMapping[virtualFpr] = (sint32)(regMapping - rCtx.currentMapping);
|
||||
regMapping->virtualReg = virtualFpr.GetRegID();
|
||||
rCtx.ppcRegToMapping[virtualFpr.GetRegID()] = (sint32)(regMapping - rCtx.currentMapping);
|
||||
regMapping->lastUseIndex = rCtx.currentUseIndex;
|
||||
rCtx.currentUseIndex++;
|
||||
}
|
||||
else
|
||||
{
|
||||
regMapping = rCtx.currentMapping + rCtx.ppcRegToMapping[virtualFpr];
|
||||
regMapping = rCtx.currentMapping + rCtx.ppcRegToMapping[virtualFpr.GetRegID()];
|
||||
regMapping->lastUseIndex = rCtx.currentUseIndex;
|
||||
rCtx.currentUseIndex++;
|
||||
}
|
||||
@@ -304,9 +311,9 @@ bool PPCRecompiler_manageFPRRegistersForSegment(ppcImlGenContext_t* ppcImlGenCon
|
||||
bool entryFound = false;
|
||||
for (sint32 t = 0; t < numReplacedOperands; t++)
|
||||
{
|
||||
if (fprMatch[t] == virtualFpr)
|
||||
if (fprMatch[t].IsValid() && fprMatch[t].GetRegID() == virtualFpr.GetRegID())
|
||||
{
|
||||
cemu_assert_debug(fprReplace[t] == (regMapping - rCtx.currentMapping));
|
||||
cemu_assert_debug(fprReplace[t] == _FPRRegFromID(regMapping - rCtx.currentMapping));
|
||||
entryFound = true;
|
||||
break;
|
||||
}
|
||||
@@ -315,7 +322,7 @@ bool PPCRecompiler_manageFPRRegistersForSegment(ppcImlGenContext_t* ppcImlGenCon
|
||||
{
|
||||
cemu_assert_debug(numReplacedOperands != 4);
|
||||
fprMatch[numReplacedOperands] = virtualFpr;
|
||||
fprReplace[numReplacedOperands] = (sint32)(regMapping - rCtx.currentMapping);
|
||||
fprReplace[numReplacedOperands] = _FPRRegFromID(regMapping - rCtx.currentMapping);
|
||||
numReplacedOperands++;
|
||||
}
|
||||
}
|
||||
@@ -345,7 +352,7 @@ bool PPCRecompiler_manageFPRRegistersForSegment(ppcImlGenContext_t* ppcImlGenCon
|
||||
memset(imlInstructionTemp, 0x00, sizeof(IMLInstruction));
|
||||
imlInstructionTemp->type = PPCREC_IML_TYPE_FPR_NAME_R;
|
||||
imlInstructionTemp->operation = PPCREC_IML_OP_ASSIGN;
|
||||
imlInstructionTemp->op_r_name.regR = i;
|
||||
imlInstructionTemp->op_r_name.regR = _FPRRegFromID(i);
|
||||
imlInstructionTemp->op_r_name.name = ppcImlGenContext->mappedFPRRegister[rCtx.currentMapping[i].virtualReg];
|
||||
idx++;
|
||||
}
|
||||
@@ -377,7 +384,7 @@ bool PPCRecompiler_trackRedundantNameLoadInstruction(ppcImlGenContext_t* ppcImlG
|
||||
imlInstruction->CheckRegisterUsage(®istersUsed);
|
||||
if( registersUsed.readGPR1 == registerIndex || registersUsed.readGPR2 == registerIndex || registersUsed.readGPR3 == registerIndex )
|
||||
return false;
|
||||
if (registersUsed.IsGPRWritten(registerIndex))
|
||||
if (registersUsed.IsBaseGPRWritten(registerIndex))
|
||||
return true;
|
||||
}
|
||||
// todo: Scan next segment(s)
|
||||
@@ -389,15 +396,15 @@ bool PPCRecompiler_trackRedundantNameLoadInstruction(ppcImlGenContext_t* ppcImlG
|
||||
*/
|
||||
bool PPCRecompiler_trackRedundantFPRNameLoadInstruction(ppcImlGenContext_t* ppcImlGenContext, IMLSegment* imlSegment, sint32 startIndex, IMLInstruction* nameStoreInstruction, sint32 scanDepth)
|
||||
{
|
||||
sint16 registerIndex = nameStoreInstruction->op_r_name.regR;
|
||||
IMLRegID regId = nameStoreInstruction->op_r_name.regR.GetRegID();
|
||||
for(size_t i=startIndex; i<imlSegment->imlList.size(); i++)
|
||||
{
|
||||
IMLInstruction* imlInstruction = imlSegment->imlList.data() + i;
|
||||
IMLUsedRegisters registersUsed;
|
||||
imlInstruction->CheckRegisterUsage(®istersUsed);
|
||||
if( registersUsed.readFPR1 == registerIndex || registersUsed.readFPR2 == registerIndex || registersUsed.readFPR3 == registerIndex || registersUsed.readFPR4 == registerIndex)
|
||||
if( registersUsed.readFPR1.IsValidAndSameRegID(regId) || registersUsed.readFPR2.IsValidAndSameRegID(regId) || registersUsed.readFPR3.IsValidAndSameRegID(regId) || registersUsed.readFPR4.IsValidAndSameRegID(regId))
|
||||
return false;
|
||||
if( registersUsed.writtenFPR1 == registerIndex )
|
||||
if( registersUsed.writtenFPR1.IsValidAndSameRegID(regId) )
|
||||
return true;
|
||||
}
|
||||
// todo: Scan next segment(s)
|
||||
@@ -409,13 +416,13 @@ bool PPCRecompiler_trackRedundantFPRNameLoadInstruction(ppcImlGenContext_t* ppcI
|
||||
*/
|
||||
bool PPCRecompiler_trackRedundantNameStoreInstruction(ppcImlGenContext_t* ppcImlGenContext, IMLSegment* imlSegment, sint32 startIndex, IMLInstruction* nameStoreInstruction, sint32 scanDepth)
|
||||
{
|
||||
sint16 registerIndex = nameStoreInstruction->op_r_name.regR;
|
||||
IMLReg regR = nameStoreInstruction->op_r_name.regR;
|
||||
for(sint32 i=startIndex; i>=0; i--)
|
||||
{
|
||||
IMLInstruction* imlInstruction = imlSegment->imlList.data() + i;
|
||||
IMLUsedRegisters registersUsed;
|
||||
imlInstruction->CheckRegisterUsage(®istersUsed);
|
||||
if( registersUsed.IsGPRWritten(registerIndex) )
|
||||
if( registersUsed.IsBaseGPRWritten(regR) )
|
||||
{
|
||||
if( imlSegment->imlList[i].type == PPCREC_IML_TYPE_R_NAME )
|
||||
return true;
|
||||
@@ -468,13 +475,13 @@ bool PPCRecompiler_trackOverwrittenNameStoreInstruction(ppcImlGenContext_t* ppcI
|
||||
*/
|
||||
bool PPCRecompiler_trackRedundantFPRNameStoreInstruction(ppcImlGenContext_t* ppcImlGenContext, IMLSegment* imlSegment, sint32 startIndex, IMLInstruction* nameStoreInstruction, sint32 scanDepth)
|
||||
{
|
||||
sint16 registerIndex = nameStoreInstruction->op_r_name.regR;
|
||||
IMLRegID regId = nameStoreInstruction->op_r_name.regR.GetRegID();
|
||||
for(sint32 i=startIndex; i>=0; i--)
|
||||
{
|
||||
IMLInstruction* imlInstruction = imlSegment->imlList.data() + i;
|
||||
IMLUsedRegisters registersUsed;
|
||||
imlInstruction->CheckRegisterUsage(®istersUsed);
|
||||
if( registersUsed.writtenFPR1 == registerIndex )
|
||||
if( registersUsed.writtenFPR1.IsValidAndSameRegID(regId))
|
||||
{
|
||||
if(imlInstruction->type == PPCREC_IML_TYPE_FPR_R_NAME )
|
||||
return true;
|
||||
@@ -485,8 +492,10 @@ bool PPCRecompiler_trackRedundantFPRNameStoreInstruction(ppcImlGenContext_t* ppc
|
||||
return false;
|
||||
}
|
||||
|
||||
void PPCRecompiler_optimizeDirectFloatCopiesScanForward(ppcImlGenContext_t* ppcImlGenContext, IMLSegment* imlSegment, sint32 imlIndexLoad, sint32 fprIndex)
|
||||
void PPCRecompiler_optimizeDirectFloatCopiesScanForward(ppcImlGenContext_t* ppcImlGenContext, IMLSegment* imlSegment, sint32 imlIndexLoad, IMLReg fprReg)
|
||||
{
|
||||
IMLRegID fprIndex = fprReg.GetRegID();
|
||||
|
||||
IMLInstruction* imlInstructionLoad = imlSegment->imlList.data() + imlIndexLoad;
|
||||
if (imlInstructionLoad->op_storeLoad.flags2.notExpanded)
|
||||
return;
|
||||
@@ -504,7 +513,7 @@ void PPCRecompiler_optimizeDirectFloatCopiesScanForward(ppcImlGenContext_t* ppcI
|
||||
if ((imlInstruction->type == PPCREC_IML_TYPE_FPR_STORE && imlInstruction->op_storeLoad.mode == PPCREC_FPR_ST_MODE_SINGLE_FROM_PS0) ||
|
||||
(imlInstruction->type == PPCREC_IML_TYPE_FPR_STORE_INDEXED && imlInstruction->op_storeLoad.mode == PPCREC_FPR_ST_MODE_SINGLE_FROM_PS0))
|
||||
{
|
||||
if (imlInstruction->op_storeLoad.registerData == fprIndex)
|
||||
if (imlInstruction->op_storeLoad.registerData.GetRegID() == fprIndex)
|
||||
{
|
||||
if (foundMatch == false)
|
||||
{
|
||||
@@ -524,15 +533,15 @@ void PPCRecompiler_optimizeDirectFloatCopiesScanForward(ppcImlGenContext_t* ppcI
|
||||
|
||||
// check if FPR is overwritten (we can actually ignore read operations?)
|
||||
imlInstruction->CheckRegisterUsage(®istersUsed);
|
||||
if (registersUsed.writtenFPR1 == fprIndex)
|
||||
if (registersUsed.writtenFPR1.IsValidAndSameRegID(fprIndex))
|
||||
break;
|
||||
if (registersUsed.readFPR1 == fprIndex)
|
||||
if (registersUsed.readFPR1.IsValidAndSameRegID(fprIndex))
|
||||
break;
|
||||
if (registersUsed.readFPR2 == fprIndex)
|
||||
if (registersUsed.readFPR2.IsValidAndSameRegID(fprIndex))
|
||||
break;
|
||||
if (registersUsed.readFPR3 == fprIndex)
|
||||
if (registersUsed.readFPR3.IsValidAndSameRegID(fprIndex))
|
||||
break;
|
||||
if (registersUsed.readFPR4 == fprIndex)
|
||||
if (registersUsed.readFPR4.IsValidAndSameRegID(fprIndex))
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -540,7 +549,7 @@ void PPCRecompiler_optimizeDirectFloatCopiesScanForward(ppcImlGenContext_t* ppcI
|
||||
{
|
||||
// insert expand instruction after store
|
||||
IMLInstruction* newExpand = PPCRecompiler_insertInstruction(imlSegment, lastStore);
|
||||
PPCRecompilerImlGen_generateNewInstruction_fpr_r(ppcImlGenContext, newExpand, PPCREC_IML_OP_FPR_EXPAND_BOTTOM32_TO_BOTTOM64_AND_TOP64, fprIndex);
|
||||
PPCRecompilerImlGen_generateNewInstruction_fpr_r(ppcImlGenContext, newExpand, PPCREC_IML_OP_FPR_EXPAND_BOTTOM32_TO_BOTTOM64_AND_TOP64, _FPRRegFromID(fprIndex));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -574,8 +583,12 @@ void PPCRecompiler_optimizeDirectFloatCopies(ppcImlGenContext_t* ppcImlGenContex
|
||||
}
|
||||
}
|
||||
|
||||
void PPCRecompiler_optimizeDirectIntegerCopiesScanForward(ppcImlGenContext_t* ppcImlGenContext, IMLSegment* imlSegment, sint32 imlIndexLoad, sint32 gprIndex)
|
||||
void PPCRecompiler_optimizeDirectIntegerCopiesScanForward(ppcImlGenContext_t* ppcImlGenContext, IMLSegment* imlSegment, sint32 imlIndexLoad, IMLReg gprReg)
|
||||
{
|
||||
cemu_assert_debug(gprReg.GetBaseFormat() == IMLRegFormat::I64); // todo - proper handling required for non-standard sizes
|
||||
cemu_assert_debug(gprReg.GetRegFormat() == IMLRegFormat::I32);
|
||||
|
||||
IMLRegID gprIndex = gprReg.GetRegID();
|
||||
IMLInstruction* imlInstructionLoad = imlSegment->imlList.data() + imlIndexLoad;
|
||||
if ( imlInstructionLoad->op_storeLoad.flags2.swapEndian == false )
|
||||
return;
|
||||
@@ -591,9 +604,9 @@ void PPCRecompiler_optimizeDirectIntegerCopiesScanForward(ppcImlGenContext_t* pp
|
||||
// check if GPR is stored
|
||||
if ((imlInstruction->type == PPCREC_IML_TYPE_STORE && imlInstruction->op_storeLoad.copyWidth == 32 ) )
|
||||
{
|
||||
if (imlInstruction->op_storeLoad.registerMem == gprIndex)
|
||||
if (imlInstruction->op_storeLoad.registerMem.GetRegID() == gprIndex)
|
||||
break;
|
||||
if (imlInstruction->op_storeLoad.registerData == gprIndex)
|
||||
if (imlInstruction->op_storeLoad.registerData.GetRegID() == gprIndex)
|
||||
{
|
||||
IMLInstruction* imlInstructionStore = imlInstruction;
|
||||
if (foundMatch == false)
|
||||
@@ -610,18 +623,18 @@ void PPCRecompiler_optimizeDirectIntegerCopiesScanForward(ppcImlGenContext_t* pp
|
||||
}
|
||||
// check if GPR is accessed
|
||||
imlInstruction->CheckRegisterUsage(®istersUsed);
|
||||
if (registersUsed.readGPR1 == gprIndex ||
|
||||
registersUsed.readGPR2 == gprIndex ||
|
||||
registersUsed.readGPR3 == gprIndex)
|
||||
if (registersUsed.readGPR1.IsValidAndSameRegID(gprIndex) ||
|
||||
registersUsed.readGPR2.IsValidAndSameRegID(gprIndex) ||
|
||||
registersUsed.readGPR3.IsValidAndSameRegID(gprIndex))
|
||||
{
|
||||
break;
|
||||
}
|
||||
if (registersUsed.IsGPRWritten(gprIndex))
|
||||
if (registersUsed.IsBaseGPRWritten(gprReg))
|
||||
return; // GPR overwritten, we don't need to byte swap anymore
|
||||
}
|
||||
if (foundMatch)
|
||||
{
|
||||
PPCRecompiler_insertInstruction(imlSegment, i)->make_r_r(PPCREC_IML_OP_ENDIAN_SWAP, gprIndex, gprIndex);
|
||||
PPCRecompiler_insertInstruction(imlSegment, i)->make_r_r(PPCREC_IML_OP_ENDIAN_SWAP, gprReg, gprReg);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -650,15 +663,19 @@ void PPCRecompiler_optimizeDirectIntegerCopies(ppcImlGenContext_t* ppcImlGenCont
|
||||
}
|
||||
}
|
||||
|
||||
sint32 _getGQRIndexFromRegister(ppcImlGenContext_t* ppcImlGenContext, sint32 registerIndex)
|
||||
sint32 _getGQRIndexFromRegister(ppcImlGenContext_t* ppcImlGenContext, IMLReg gqrReg)
|
||||
{
|
||||
if (registerIndex == PPC_REC_INVALID_REGISTER)
|
||||
if (gqrReg.IsInvalid())
|
||||
return -1;
|
||||
sint32 namedReg = ppcImlGenContext->mappedRegister[registerIndex];
|
||||
sint32 namedReg = ppcImlGenContext->mappedRegister[gqrReg.GetRegID()];
|
||||
if (namedReg >= (PPCREC_NAME_SPR0 + SPR_UGQR0) && namedReg <= (PPCREC_NAME_SPR0 + SPR_UGQR7))
|
||||
{
|
||||
return namedReg - (PPCREC_NAME_SPR0 + SPR_UGQR0);
|
||||
}
|
||||
else
|
||||
{
|
||||
cemu_assert_suspicious();
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -694,7 +711,7 @@ void PPCRecompiler_optimizePSQLoadAndStore(ppcImlGenContext_t* ppcImlGenContext)
|
||||
instIt.op_storeLoad.mode != PPCREC_FPR_LD_MODE_PSQ_GENERIC_PS0_PS1 )
|
||||
continue;
|
||||
// get GQR value
|
||||
cemu_assert_debug(instIt.op_storeLoad.registerGQR != PPC_REC_INVALID_REGISTER);
|
||||
cemu_assert_debug(instIt.op_storeLoad.registerGQR.IsValid());
|
||||
sint32 gqrIndex = _getGQRIndexFromRegister(ppcImlGenContext, instIt.op_storeLoad.registerGQR);
|
||||
cemu_assert(gqrIndex >= 0);
|
||||
if (ppcImlGenContext->tracking.modifiesGQR[gqrIndex])
|
||||
@@ -720,7 +737,7 @@ void PPCRecompiler_optimizePSQLoadAndStore(ppcImlGenContext_t* ppcImlGenContext)
|
||||
else if (formatType == 7)
|
||||
instIt.op_storeLoad.mode = PPCREC_FPR_LD_MODE_PSQ_S16_PS0;
|
||||
if (instIt.op_storeLoad.mode != PPCREC_FPR_LD_MODE_PSQ_GENERIC_PS0)
|
||||
instIt.op_storeLoad.registerGQR = PPC_REC_INVALID_REGISTER;
|
||||
instIt.op_storeLoad.registerGQR = IMLREG_INVALID;
|
||||
}
|
||||
else if (instIt.op_storeLoad.mode == PPCREC_FPR_LD_MODE_PSQ_GENERIC_PS0_PS1)
|
||||
{
|
||||
@@ -735,7 +752,7 @@ void PPCRecompiler_optimizePSQLoadAndStore(ppcImlGenContext_t* ppcImlGenContext)
|
||||
else if (formatType == 7)
|
||||
instIt.op_storeLoad.mode = PPCREC_FPR_LD_MODE_PSQ_S16_PS0_PS1;
|
||||
if (instIt.op_storeLoad.mode != PPCREC_FPR_LD_MODE_PSQ_GENERIC_PS0_PS1)
|
||||
instIt.op_storeLoad.registerGQR = PPC_REC_INVALID_REGISTER;
|
||||
instIt.op_storeLoad.registerGQR = IMLREG_INVALID;
|
||||
}
|
||||
}
|
||||
else if (instIt.type == PPCREC_IML_TYPE_FPR_STORE || instIt.type == PPCREC_IML_TYPE_FPR_STORE_INDEXED)
|
||||
@@ -744,7 +761,7 @@ void PPCRecompiler_optimizePSQLoadAndStore(ppcImlGenContext_t* ppcImlGenContext)
|
||||
instIt.op_storeLoad.mode != PPCREC_FPR_ST_MODE_PSQ_GENERIC_PS0_PS1)
|
||||
continue;
|
||||
// get GQR value
|
||||
cemu_assert_debug(instIt.op_storeLoad.registerGQR != PPC_REC_INVALID_REGISTER);
|
||||
cemu_assert_debug(instIt.op_storeLoad.registerGQR.IsValid());
|
||||
sint32 gqrIndex = _getGQRIndexFromRegister(ppcImlGenContext, instIt.op_storeLoad.registerGQR);
|
||||
cemu_assert(gqrIndex >= 0 && gqrIndex < 8);
|
||||
if (ppcImlGenContext->tracking.modifiesGQR[gqrIndex])
|
||||
@@ -769,7 +786,7 @@ void PPCRecompiler_optimizePSQLoadAndStore(ppcImlGenContext_t* ppcImlGenContext)
|
||||
else if (formatType == 7)
|
||||
instIt.op_storeLoad.mode = PPCREC_FPR_ST_MODE_PSQ_S16_PS0;
|
||||
if (instIt.op_storeLoad.mode != PPCREC_FPR_ST_MODE_PSQ_GENERIC_PS0)
|
||||
instIt.op_storeLoad.registerGQR = PPC_REC_INVALID_REGISTER;
|
||||
instIt.op_storeLoad.registerGQR = IMLREG_INVALID;
|
||||
}
|
||||
else if (instIt.op_storeLoad.mode == PPCREC_FPR_ST_MODE_PSQ_GENERIC_PS0_PS1)
|
||||
{
|
||||
@@ -784,7 +801,7 @@ void PPCRecompiler_optimizePSQLoadAndStore(ppcImlGenContext_t* ppcImlGenContext)
|
||||
else if (formatType == 7)
|
||||
instIt.op_storeLoad.mode = PPCREC_FPR_ST_MODE_PSQ_S16_PS0_PS1;
|
||||
if (instIt.op_storeLoad.mode != PPCREC_FPR_ST_MODE_PSQ_GENERIC_PS0_PS1)
|
||||
instIt.op_storeLoad.registerGQR = PPC_REC_INVALID_REGISTER;
|
||||
instIt.op_storeLoad.registerGQR = IMLREG_INVALID;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -123,18 +123,23 @@ void PPCRecRA_identifyLoop(ppcImlGenContext_t* ppcImlGenContext, IMLSegment* iml
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint16 registerIndex;
|
||||
IMLRegID registerIndex;
|
||||
uint16 registerName;
|
||||
}raLoadStoreInfo_t;
|
||||
|
||||
void PPCRecRA_insertGPRLoadInstruction(IMLSegment* imlSegment, sint32 insertIndex, sint32 registerIndex, sint32 registerName)
|
||||
IMLReg _MakeNativeGPR(IMLRegID regId)
|
||||
{
|
||||
return IMLReg(IMLRegFormat::I64, IMLRegFormat::I64, 0, regId);
|
||||
}
|
||||
|
||||
void PPCRecRA_insertGPRLoadInstruction(IMLSegment* imlSegment, sint32 insertIndex, IMLRegID registerIndex, sint32 registerName)
|
||||
{
|
||||
PPCRecompiler_pushBackIMLInstructions(imlSegment, insertIndex, 1);
|
||||
IMLInstruction* imlInstructionItr = imlSegment->imlList.data() + (insertIndex + 0);
|
||||
memset(imlInstructionItr, 0x00, sizeof(IMLInstruction));
|
||||
imlInstructionItr->type = PPCREC_IML_TYPE_R_NAME;
|
||||
imlInstructionItr->operation = PPCREC_IML_OP_ASSIGN;
|
||||
imlInstructionItr->op_r_name.regR = registerIndex;
|
||||
imlInstructionItr->op_r_name.regR = _MakeNativeGPR(registerIndex);
|
||||
imlInstructionItr->op_r_name.name = registerName;
|
||||
}
|
||||
|
||||
@@ -147,19 +152,19 @@ void PPCRecRA_insertGPRLoadInstructions(IMLSegment* imlSegment, sint32 insertInd
|
||||
IMLInstruction* imlInstructionItr = imlSegment->imlList.data() + (insertIndex + i);
|
||||
imlInstructionItr->type = PPCREC_IML_TYPE_R_NAME;
|
||||
imlInstructionItr->operation = PPCREC_IML_OP_ASSIGN;
|
||||
imlInstructionItr->op_r_name.regR = (uint8)loadList[i].registerIndex;
|
||||
imlInstructionItr->op_r_name.regR = _MakeNativeGPR(loadList[i].registerIndex);
|
||||
imlInstructionItr->op_r_name.name = (uint32)loadList[i].registerName;
|
||||
}
|
||||
}
|
||||
|
||||
void PPCRecRA_insertGPRStoreInstruction(IMLSegment* imlSegment, sint32 insertIndex, sint32 registerIndex, sint32 registerName)
|
||||
void PPCRecRA_insertGPRStoreInstruction(IMLSegment* imlSegment, sint32 insertIndex, IMLRegID registerIndex, sint32 registerName)
|
||||
{
|
||||
PPCRecompiler_pushBackIMLInstructions(imlSegment, insertIndex, 1);
|
||||
IMLInstruction* imlInstructionItr = imlSegment->imlList.data() + (insertIndex + 0);
|
||||
memset(imlInstructionItr, 0x00, sizeof(IMLInstruction));
|
||||
imlInstructionItr->type = PPCREC_IML_TYPE_NAME_R;
|
||||
imlInstructionItr->operation = PPCREC_IML_OP_ASSIGN;
|
||||
imlInstructionItr->op_r_name.regR = registerIndex;
|
||||
imlInstructionItr->op_r_name.regR = _MakeNativeGPR(registerIndex);
|
||||
imlInstructionItr->op_r_name.name = registerName;
|
||||
}
|
||||
|
||||
@@ -173,7 +178,7 @@ void PPCRecRA_insertGPRStoreInstructions(IMLSegment* imlSegment, sint32 insertIn
|
||||
memset(imlInstructionItr, 0x00, sizeof(IMLInstruction));
|
||||
imlInstructionItr->type = PPCREC_IML_TYPE_NAME_R;
|
||||
imlInstructionItr->operation = PPCREC_IML_OP_ASSIGN;
|
||||
imlInstructionItr->op_r_name.regR = (uint8)storeList[i].registerIndex;
|
||||
imlInstructionItr->op_r_name.regR = _MakeNativeGPR(storeList[i].registerIndex);
|
||||
imlInstructionItr->op_r_name.name = (uint32)storeList[i].registerName;
|
||||
}
|
||||
}
|
||||
@@ -368,7 +373,7 @@ void _sortSegmentAllSubrangesLinkedList(IMLSegment* imlSegment)
|
||||
|
||||
raLivenessSubrange_t* _GetSubrangeByInstructionIndexAndVirtualReg(IMLSegment* imlSegment, IMLReg regToSearch, sint32 instructionIndex)
|
||||
{
|
||||
uint32 regId = regToSearch & 0xFF;
|
||||
uint32 regId = regToSearch.GetRegID();
|
||||
raLivenessSubrange_t* subrangeItr = imlSegment->raInfo.linkedList_perVirtualGPR[regId];
|
||||
while (subrangeItr)
|
||||
{
|
||||
@@ -828,7 +833,7 @@ void IMLRA_GenerateSegmentInstructions(ppcImlGenContext_t* ppcImlGenContext, IML
|
||||
sint16 virtualReg2PhysReg[IML_RA_VIRT_REG_COUNT_MAX];
|
||||
for (sint32 i = 0; i < IML_RA_VIRT_REG_COUNT_MAX; i++)
|
||||
virtualReg2PhysReg[i] = -1;
|
||||
std::unordered_map<IMLReg, IMLReg> virt2PhysRegMap; // key = virtual register, value = physical register
|
||||
std::unordered_map<IMLRegID, IMLRegID> virtId2PhysRegIdMap; // key = virtual register, value = physical register
|
||||
IMLRALivenessTimeline livenessTimeline;
|
||||
sint32 index = 0;
|
||||
sint32 suffixInstructionCount = imlSegment->HasSuffixInstruction() ? 1 : 0;
|
||||
@@ -850,7 +855,7 @@ void IMLRA_GenerateSegmentInstructions(ppcImlGenContext_t* ppcImlGenContext, IML
|
||||
assert_dbg();
|
||||
#endif
|
||||
virtualReg2PhysReg[subrangeItr->range->virtualRegister] = subrangeItr->range->physicalRegister;
|
||||
virt2PhysRegMap.insert_or_assign(subrangeItr->range->virtualRegister, subrangeItr->range->physicalRegister);
|
||||
virtId2PhysRegIdMap.insert_or_assign(subrangeItr->range->virtualRegister, subrangeItr->range->physicalRegister);
|
||||
}
|
||||
// next
|
||||
subrangeItr = subrangeItr->link_segmentSubrangesGPR.next;
|
||||
@@ -866,7 +871,7 @@ void IMLRA_GenerateSegmentInstructions(ppcImlGenContext_t* ppcImlGenContext, IML
|
||||
if (virtualReg2PhysReg[expiredRange->range->virtualRegister] == -1)
|
||||
assert_dbg();
|
||||
virtualReg2PhysReg[expiredRange->range->virtualRegister] = -1;
|
||||
virt2PhysRegMap.erase(expiredRange->range->virtualRegister);
|
||||
virtId2PhysRegIdMap.erase(expiredRange->range->virtualRegister);
|
||||
// store GPR if required
|
||||
// special care has to be taken to execute any stores before the suffix instruction since trailing instructions may not get executed
|
||||
if (expiredRange->hasStore)
|
||||
@@ -900,13 +905,13 @@ void IMLRA_GenerateSegmentInstructions(ppcImlGenContext_t* ppcImlGenContext, IML
|
||||
// update translation table
|
||||
cemu_assert_debug(virtualReg2PhysReg[subrangeItr->range->virtualRegister] == -1);
|
||||
virtualReg2PhysReg[subrangeItr->range->virtualRegister] = subrangeItr->range->physicalRegister;
|
||||
virt2PhysRegMap.insert_or_assign(subrangeItr->range->virtualRegister, subrangeItr->range->physicalRegister);
|
||||
virtId2PhysRegIdMap.insert_or_assign(subrangeItr->range->virtualRegister, subrangeItr->range->physicalRegister);
|
||||
}
|
||||
subrangeItr = subrangeItr->link_segmentSubrangesGPR.next;
|
||||
}
|
||||
// rewrite registers
|
||||
if (index < imlSegment->imlList.size())
|
||||
imlSegment->imlList[index].RewriteGPR(virt2PhysRegMap);
|
||||
imlSegment->imlList[index].RewriteGPR(virtId2PhysRegIdMap);
|
||||
// next iml instruction
|
||||
index++;
|
||||
}
|
||||
@@ -919,7 +924,7 @@ void IMLRA_GenerateSegmentInstructions(ppcImlGenContext_t* ppcImlGenContext, IML
|
||||
// update translation table
|
||||
cemu_assert_debug(virtualReg2PhysReg[liverange->range->virtualRegister] != -1);
|
||||
virtualReg2PhysReg[liverange->range->virtualRegister] = -1;
|
||||
virt2PhysRegMap.erase(liverange->range->virtualRegister);
|
||||
virtId2PhysRegIdMap.erase(liverange->range->virtualRegister);
|
||||
// store GPR
|
||||
if (liverange->hasStore)
|
||||
{
|
||||
@@ -951,7 +956,7 @@ void IMLRA_GenerateSegmentInstructions(ppcImlGenContext_t* ppcImlGenContext, IML
|
||||
// update translation table
|
||||
cemu_assert_debug(virtualReg2PhysReg[subrangeItr->range->virtualRegister] == -1);
|
||||
virtualReg2PhysReg[subrangeItr->range->virtualRegister] = subrangeItr->range->physicalRegister;
|
||||
virt2PhysRegMap.insert_or_assign(subrangeItr->range->virtualRegister, subrangeItr->range->physicalRegister);
|
||||
virtId2PhysRegIdMap.insert_or_assign(subrangeItr->range->virtualRegister, subrangeItr->range->physicalRegister);
|
||||
}
|
||||
// next
|
||||
subrangeItr = subrangeItr->link_segmentSubrangesGPR.next;
|
||||
@@ -1063,7 +1068,8 @@ void PPCRecRA_calculateSegmentMinMaxRanges(ppcImlGenContext_t* ppcImlGenContext,
|
||||
while (index < imlSegment->imlList.size())
|
||||
{
|
||||
imlSegment->imlList[index].CheckRegisterUsage(&gprTracking);
|
||||
gprTracking.ForEachAccessedGPR([&](IMLReg gprId, bool isWritten) {
|
||||
gprTracking.ForEachAccessedGPR([&](IMLReg gprReg, bool isWritten) {
|
||||
IMLRegID gprId = gprReg.GetRegID();
|
||||
cemu_assert_debug(gprId < IML_RA_VIRT_REG_COUNT_MAX);
|
||||
imlSegment->raDistances.reg[gprId].usageStart = std::min<sint32>(imlSegment->raDistances.reg[gprId].usageStart, index); // index before/at instruction
|
||||
imlSegment->raDistances.reg[gprId].usageEnd = std::max<sint32>(imlSegment->raDistances.reg[gprId].usageEnd, index + 1); // index after instruction
|
||||
@@ -1156,7 +1162,8 @@ void PPCRecRA_createSegmentLivenessRanges(ppcImlGenContext_t* ppcImlGenContext,
|
||||
while (index < imlSegment->imlList.size())
|
||||
{
|
||||
imlSegment->imlList[index].CheckRegisterUsage(&gprTracking);
|
||||
gprTracking.ForEachAccessedGPR([&](IMLReg gprId, bool isWritten) {
|
||||
gprTracking.ForEachAccessedGPR([&](IMLReg gprReg, bool isWritten) {
|
||||
IMLRegID gprId = gprReg.GetRegID();
|
||||
// add location
|
||||
PPCRecRA_updateOrAddSubrangeLocation(vGPR2Subrange[gprId], index, !isWritten, isWritten);
|
||||
#ifdef CEMU_DEBUG_ASSERT
|
||||
|
||||
@@ -270,9 +270,9 @@ bool PPCRecompiler_ApplyIMLPasses(ppcImlGenContext_t& ppcImlGenContext)
|
||||
accessedTempReg[4] = registersUsed.writtenFPR1;
|
||||
for (sint32 f = 0; f < 5; f++)
|
||||
{
|
||||
if (accessedTempReg[f] == IMLREG_INVALID)
|
||||
if (accessedTempReg[f].IsInvalid())
|
||||
continue;
|
||||
uint32 regName = ppcImlGenContext.mappedFPRRegister[accessedTempReg[f]];
|
||||
uint32 regName = ppcImlGenContext.mappedFPRRegister[accessedTempReg[f].GetRegID()];
|
||||
if (regName >= PPCREC_NAME_FPR0 && regName < PPCREC_NAME_FPR0 + 32)
|
||||
{
|
||||
segIt->ppcFPRUsed[regName - PPCREC_NAME_FPR0] = true;
|
||||
|
||||
@@ -15,15 +15,15 @@ void PPCRecompilerIml_setSegmentPoint(IMLSegmentPoint* segmentPoint, IMLSegment*
|
||||
void PPCRecompilerIml_removeSegmentPoint(IMLSegmentPoint* segmentPoint);
|
||||
|
||||
// GPR register management
|
||||
uint32 PPCRecompilerImlGen_loadRegister(ppcImlGenContext_t* ppcImlGenContext, uint32 mappedName);
|
||||
IMLReg PPCRecompilerImlGen_loadRegister(ppcImlGenContext_t* ppcImlGenContext, uint32 mappedName);
|
||||
|
||||
// FPR register management
|
||||
uint32 PPCRecompilerImlGen_loadFPRRegister(ppcImlGenContext_t* ppcImlGenContext, uint32 mappedName, bool loadNew = false);
|
||||
uint32 PPCRecompilerImlGen_loadOverwriteFPRRegister(ppcImlGenContext_t* ppcImlGenContext, uint32 mappedName);
|
||||
IMLReg PPCRecompilerImlGen_loadFPRRegister(ppcImlGenContext_t* ppcImlGenContext, uint32 mappedName, bool loadNew = false);
|
||||
IMLReg PPCRecompilerImlGen_loadOverwriteFPRRegister(ppcImlGenContext_t* ppcImlGenContext, uint32 mappedName);
|
||||
|
||||
// IML instruction generation
|
||||
void PPCRecompilerImlGen_generateNewInstruction_conditional_r_s32(ppcImlGenContext_t* ppcImlGenContext, IMLInstruction* imlInstruction, uint32 operation, uint8 registerIndex, sint32 immS32, uint32 crRegisterIndex, uint32 crBitIndex, bool bitMustBeSet);
|
||||
void PPCRecompilerImlGen_generateNewInstruction_fpr_r(ppcImlGenContext_t* ppcImlGenContext, IMLInstruction* imlInstruction, sint32 operation, uint8 registerResult, sint32 crRegister = PPC_REC_INVALID_REGISTER);
|
||||
void PPCRecompilerImlGen_generateNewInstruction_conditional_r_s32(ppcImlGenContext_t* ppcImlGenContext, IMLInstruction* imlInstruction, uint32 operation, IMLReg registerIndex, sint32 immS32, uint32 crRegisterIndex, uint32 crBitIndex, bool bitMustBeSet);
|
||||
void PPCRecompilerImlGen_generateNewInstruction_fpr_r(ppcImlGenContext_t* ppcImlGenContext, IMLInstruction* imlInstruction, sint32 operation, IMLReg registerResult);
|
||||
|
||||
// IML generation - FPU
|
||||
bool PPCRecompilerImlGen_LFS(ppcImlGenContext_t* ppcImlGenContext, uint32 opcode);
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user