mirror of
https://github.com/cemu-project/Cemu.git
synced 2025-02-22 04:37:15 +01:00
PPCRec: Code cleanup
This commit is contained in:
parent
126a682143
commit
f309d5d8a8
@ -172,18 +172,6 @@ void* ATTR_MS_ABI PPCRecompiler_virtualHLE(PPCInterpreter_t* hCPU, uint32 hleFun
|
|||||||
return PPCInterpreter_getCurrentInstance();
|
return PPCInterpreter_getCurrentInstance();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ATTR_MS_ABI PPCRecompiler_getTBL(PPCInterpreter_t* hCPU, uint32 gprIndex)
|
|
||||||
{
|
|
||||||
uint64 coreTime = coreinit::coreinit_getTimerTick();
|
|
||||||
hCPU->gpr[gprIndex] = (uint32)(coreTime&0xFFFFFFFF);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ATTR_MS_ABI PPCRecompiler_getTBU(PPCInterpreter_t* hCPU, uint32 gprIndex)
|
|
||||||
{
|
|
||||||
uint64 coreTime = coreinit::coreinit_getTimerTick();
|
|
||||||
hCPU->gpr[gprIndex] = (uint32)((coreTime>>32)&0xFFFFFFFF);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool PPCRecompilerX64Gen_imlInstruction_macro(PPCRecFunction_t* PPCRecFunction, ppcImlGenContext_t* ppcImlGenContext, x64GenContext_t* x64GenContext, IMLInstruction* imlInstruction)
|
bool PPCRecompilerX64Gen_imlInstruction_macro(PPCRecFunction_t* PPCRecFunction, ppcImlGenContext_t* ppcImlGenContext, x64GenContext_t* x64GenContext, IMLInstruction* imlInstruction)
|
||||||
{
|
{
|
||||||
if (imlInstruction->operation == PPCREC_IML_MACRO_B_TO_REG)
|
if (imlInstruction->operation == PPCREC_IML_MACRO_B_TO_REG)
|
||||||
@ -340,43 +328,6 @@ bool PPCRecompilerX64Gen_imlInstruction_macro(PPCRecFunction_t* PPCRecFunction,
|
|||||||
x64Gen_jmp_memReg64(x64GenContext, X86_REG_RAX, (uint32)offsetof(PPCRecompilerInstanceData_t, ppcRecompilerDirectJumpTable));
|
x64Gen_jmp_memReg64(x64GenContext, X86_REG_RAX, (uint32)offsetof(PPCRecompilerInstanceData_t, ppcRecompilerDirectJumpTable));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
else if( imlInstruction->operation == PPCREC_IML_MACRO_MFTB )
|
|
||||||
{
|
|
||||||
// according to MS ABI the caller needs to save:
|
|
||||||
// RAX, RCX, RDX, R8, R9, R10, R11
|
|
||||||
|
|
||||||
uint32 ppcAddress = imlInstruction->op_macro.param;
|
|
||||||
uint32 sprId = imlInstruction->op_macro.param2&0xFFFF;
|
|
||||||
uint32 gprIndex = (imlInstruction->op_macro.param2>>16)&0x1F;
|
|
||||||
// update instruction pointer
|
|
||||||
x64Gen_mov_mem32Reg64_imm32(x64GenContext, X86_REG_RSP, offsetof(PPCInterpreter_t, instructionPointer), ppcAddress);
|
|
||||||
// set parameters
|
|
||||||
x64Gen_mov_reg64_reg64(x64GenContext, X86_REG_RCX, X86_REG_RSP);
|
|
||||||
x64Gen_mov_reg64_imm64(x64GenContext, X86_REG_RDX, gprIndex);
|
|
||||||
// restore stackpointer to original RSP
|
|
||||||
x64Emit_mov_reg64_mem64(x64GenContext, X86_REG_RSP, REG_RESV_HCPU, offsetof(PPCInterpreter_t, rspTemp));
|
|
||||||
// push hCPU on stack
|
|
||||||
x64Gen_push_reg64(x64GenContext, X86_REG_RCX);
|
|
||||||
// reserve space on stack for call parameters
|
|
||||||
x64Gen_sub_reg64_imm32(x64GenContext, X86_REG_RSP, 8*11 + 8);
|
|
||||||
x64Gen_mov_reg64_imm64(x64GenContext, X86_REG_RBP, 0);
|
|
||||||
// call function
|
|
||||||
if( sprId == SPR_TBL )
|
|
||||||
x64Gen_mov_reg64_imm64(x64GenContext, X86_REG_RAX, (uint64)PPCRecompiler_getTBL);
|
|
||||||
else if( sprId == SPR_TBU )
|
|
||||||
x64Gen_mov_reg64_imm64(x64GenContext, X86_REG_RAX, (uint64)PPCRecompiler_getTBU);
|
|
||||||
else
|
|
||||||
assert_dbg();
|
|
||||||
x64Gen_call_reg64(x64GenContext, X86_REG_RAX);
|
|
||||||
// restore hCPU from stack
|
|
||||||
x64Gen_add_reg64_imm32(x64GenContext, X86_REG_RSP, 8 * 11 + 8);
|
|
||||||
x64Gen_pop_reg64(x64GenContext, X86_REG_RSP);
|
|
||||||
// MOV R15, ppcRecompilerInstanceData
|
|
||||||
x64Gen_mov_reg64_imm64(x64GenContext, X86_REG_R15, (uint64)ppcRecompilerInstanceData);
|
|
||||||
// MOV R13, memory_base
|
|
||||||
x64Gen_mov_reg64_imm64(x64GenContext, X86_REG_R13, (uint64)memory_base);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
debug_printf("Unknown recompiler macro operation %d\n", imlInstruction->operation);
|
debug_printf("Unknown recompiler macro operation %d\n", imlInstruction->operation);
|
||||||
|
@ -97,23 +97,23 @@ void IMLDebug_PrintLivenessRangeInfo(StringBuf& currentLineText, IMLSegment* iml
|
|||||||
raLivenessRange* subrangeItr = imlSegment->raInfo.linkedList_allSubranges;
|
raLivenessRange* subrangeItr = imlSegment->raInfo.linkedList_allSubranges;
|
||||||
while (subrangeItr)
|
while (subrangeItr)
|
||||||
{
|
{
|
||||||
if (subrangeItr->interval2.start.GetInstructionIndexEx() == offset)
|
if (subrangeItr->interval.start.GetInstructionIndexEx() == offset)
|
||||||
{
|
{
|
||||||
if(subrangeItr->interval2.start.IsInstructionIndex() && !subrangeItr->interval2.start.IsOnInputEdge())
|
if(subrangeItr->interval.start.IsInstructionIndex() && !subrangeItr->interval.start.IsOnInputEdge())
|
||||||
currentLineText.add(".");
|
currentLineText.add(".");
|
||||||
else
|
else
|
||||||
currentLineText.add("|");
|
currentLineText.add("|");
|
||||||
|
|
||||||
currentLineText.addFmt("{:<4}", subrangeItr->GetVirtualRegister());
|
currentLineText.addFmt("{:<4}", subrangeItr->GetVirtualRegister());
|
||||||
}
|
}
|
||||||
else if (subrangeItr->interval2.end.GetInstructionIndexEx() == offset)
|
else if (subrangeItr->interval.end.GetInstructionIndexEx() == offset)
|
||||||
{
|
{
|
||||||
if(subrangeItr->interval2.end.IsInstructionIndex() && !subrangeItr->interval2.end.IsOnOutputEdge())
|
if(subrangeItr->interval.end.IsInstructionIndex() && !subrangeItr->interval.end.IsOnOutputEdge())
|
||||||
currentLineText.add("* ");
|
currentLineText.add("* ");
|
||||||
else
|
else
|
||||||
currentLineText.add("| ");
|
currentLineText.add("| ");
|
||||||
}
|
}
|
||||||
else if (subrangeItr->interval2.ContainsInstructionIndexEx(offset))
|
else if (subrangeItr->interval.ContainsInstructionIndexEx(offset))
|
||||||
{
|
{
|
||||||
currentLineText.add("| ");
|
currentLineText.add("| ");
|
||||||
}
|
}
|
||||||
@ -374,10 +374,6 @@ void IMLDebug_DisassembleInstruction(const IMLInstruction& inst, std::string& di
|
|||||||
{
|
{
|
||||||
strOutput.addFmt("MACRO HLE ppcAddr: 0x{:08x} funcId: 0x{:08x}", inst.op_macro.param, inst.op_macro.param2);
|
strOutput.addFmt("MACRO HLE ppcAddr: 0x{:08x} funcId: 0x{:08x}", inst.op_macro.param, inst.op_macro.param2);
|
||||||
}
|
}
|
||||||
else if (inst.operation == PPCREC_IML_MACRO_MFTB)
|
|
||||||
{
|
|
||||||
strOutput.addFmt("MACRO MFTB ppcAddr: 0x{:08x} sprId: 0x{:08x}", inst.op_macro.param, inst.op_macro.param2);
|
|
||||||
}
|
|
||||||
else if (inst.operation == PPCREC_IML_MACRO_COUNT_CYCLES)
|
else if (inst.operation == PPCREC_IML_MACRO_COUNT_CYCLES)
|
||||||
{
|
{
|
||||||
strOutput.addFmt("MACRO COUNT_CYCLES cycles: {}", inst.op_macro.param);
|
strOutput.addFmt("MACRO COUNT_CYCLES cycles: {}", inst.op_macro.param);
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
#include "../PPCRecompiler.h"
|
#include "../PPCRecompiler.h"
|
||||||
#include "../PPCRecompilerIml.h"
|
#include "../PPCRecompilerIml.h"
|
||||||
|
|
||||||
|
// return true if an instruction has side effects on top of just reading and writing registers
|
||||||
bool IMLInstruction::HasSideEffects() const
|
bool IMLInstruction::HasSideEffects() const
|
||||||
{
|
{
|
||||||
bool hasSideEffects = true;
|
bool hasSideEffects = true;
|
||||||
@ -160,7 +161,7 @@ void IMLInstruction::CheckRegisterUsage(IMLUsedRegisters* registersUsed) const
|
|||||||
}
|
}
|
||||||
else if (type == PPCREC_IML_TYPE_MACRO)
|
else if (type == PPCREC_IML_TYPE_MACRO)
|
||||||
{
|
{
|
||||||
if (operation == PPCREC_IML_MACRO_BL || operation == PPCREC_IML_MACRO_B_FAR || operation == PPCREC_IML_MACRO_LEAVE || operation == PPCREC_IML_MACRO_DEBUGBREAK || operation == PPCREC_IML_MACRO_COUNT_CYCLES || operation == PPCREC_IML_MACRO_HLE || operation == PPCREC_IML_MACRO_MFTB)
|
if (operation == PPCREC_IML_MACRO_BL || operation == PPCREC_IML_MACRO_B_FAR || operation == PPCREC_IML_MACRO_LEAVE || operation == PPCREC_IML_MACRO_DEBUGBREAK || operation == PPCREC_IML_MACRO_COUNT_CYCLES || operation == PPCREC_IML_MACRO_HLE)
|
||||||
{
|
{
|
||||||
// no effect on registers
|
// no effect on registers
|
||||||
}
|
}
|
||||||
@ -482,15 +483,6 @@ void IMLInstruction::CheckRegisterUsage(IMLUsedRegisters* registersUsed) const
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//#define replaceRegister(__x,__r,__n) (((__x)==(__r))?(__n):(__x))
|
|
||||||
IMLReg replaceRegisterId(IMLReg reg, IMLRegID oldId, IMLRegID newId)
|
|
||||||
{
|
|
||||||
if (reg.GetRegID() != oldId)
|
|
||||||
return reg;
|
|
||||||
reg.SetRegID(newId);
|
|
||||||
return reg;
|
|
||||||
}
|
|
||||||
|
|
||||||
IMLReg replaceRegisterIdMultiple(IMLReg reg, const std::unordered_map<IMLRegID, IMLRegID>& translationTable)
|
IMLReg replaceRegisterIdMultiple(IMLReg reg, const std::unordered_map<IMLRegID, IMLRegID>& translationTable)
|
||||||
{
|
{
|
||||||
if (reg.IsInvalid())
|
if (reg.IsInvalid())
|
||||||
@ -502,26 +494,6 @@ IMLReg replaceRegisterIdMultiple(IMLReg reg, const std::unordered_map<IMLRegID,
|
|||||||
return alteredReg;
|
return alteredReg;
|
||||||
}
|
}
|
||||||
|
|
||||||
IMLReg replaceRegisterIdMultiple(IMLReg reg, IMLReg match[4], IMLReg replaced[4])
|
|
||||||
{
|
|
||||||
// deprecated but still used for FPRs
|
|
||||||
for (sint32 i = 0; i < 4; i++)
|
|
||||||
{
|
|
||||||
if (match[i].IsInvalid())
|
|
||||||
continue;
|
|
||||||
if (reg.GetRegID() == match[i].GetRegID())
|
|
||||||
{
|
|
||||||
cemu_assert_debug(reg.GetBaseFormat() == match[i].GetBaseFormat());
|
|
||||||
cemu_assert_debug(reg.GetRegFormat() == match[i].GetRegFormat());
|
|
||||||
cemu_assert_debug(reg.GetBaseFormat() == replaced[i].GetBaseFormat());
|
|
||||||
cemu_assert_debug(reg.GetRegFormat() == replaced[i].GetRegFormat());
|
|
||||||
|
|
||||||
return replaced[i];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return reg;
|
|
||||||
}
|
|
||||||
|
|
||||||
void IMLInstruction::RewriteGPR(const std::unordered_map<IMLRegID, IMLRegID>& translationTable)
|
void IMLInstruction::RewriteGPR(const std::unordered_map<IMLRegID, IMLRegID>& translationTable)
|
||||||
{
|
{
|
||||||
if (type == PPCREC_IML_TYPE_R_NAME)
|
if (type == PPCREC_IML_TYPE_R_NAME)
|
||||||
@ -594,7 +566,7 @@ void IMLInstruction::RewriteGPR(const std::unordered_map<IMLRegID, IMLRegID>& tr
|
|||||||
}
|
}
|
||||||
else if (type == PPCREC_IML_TYPE_MACRO)
|
else if (type == PPCREC_IML_TYPE_MACRO)
|
||||||
{
|
{
|
||||||
if (operation == PPCREC_IML_MACRO_BL || operation == PPCREC_IML_MACRO_B_FAR || operation == PPCREC_IML_MACRO_LEAVE || operation == PPCREC_IML_MACRO_DEBUGBREAK || operation == PPCREC_IML_MACRO_HLE || operation == PPCREC_IML_MACRO_MFTB || operation == PPCREC_IML_MACRO_COUNT_CYCLES)
|
if (operation == PPCREC_IML_MACRO_BL || operation == PPCREC_IML_MACRO_B_FAR || operation == PPCREC_IML_MACRO_LEAVE || operation == PPCREC_IML_MACRO_DEBUGBREAK || operation == PPCREC_IML_MACRO_HLE || operation == PPCREC_IML_MACRO_COUNT_CYCLES)
|
||||||
{
|
{
|
||||||
// no effect on registers
|
// no effect on registers
|
||||||
}
|
}
|
||||||
@ -717,228 +689,3 @@ void IMLInstruction::RewriteGPR(const std::unordered_map<IMLRegID, IMLRegID>& tr
|
|||||||
cemu_assert_unimplemented();
|
cemu_assert_unimplemented();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void IMLInstruction::ReplaceFPRs(IMLReg fprRegisterSearched[4], IMLReg fprRegisterReplaced[4])
|
|
||||||
{
|
|
||||||
if (type == PPCREC_IML_TYPE_R_NAME)
|
|
||||||
{
|
|
||||||
// not affected
|
|
||||||
}
|
|
||||||
else if (type == PPCREC_IML_TYPE_NAME_R)
|
|
||||||
{
|
|
||||||
// not affected
|
|
||||||
}
|
|
||||||
else if (type == PPCREC_IML_TYPE_R_R)
|
|
||||||
{
|
|
||||||
// not affected
|
|
||||||
}
|
|
||||||
else if (type == PPCREC_IML_TYPE_R_S32)
|
|
||||||
{
|
|
||||||
// not affected
|
|
||||||
}
|
|
||||||
else if (type == PPCREC_IML_TYPE_R_R_S32)
|
|
||||||
{
|
|
||||||
// not affected
|
|
||||||
}
|
|
||||||
else if (type == PPCREC_IML_TYPE_R_R_R)
|
|
||||||
{
|
|
||||||
// not affected
|
|
||||||
}
|
|
||||||
else if (type == PPCREC_IML_TYPE_COMPARE || type == PPCREC_IML_TYPE_COMPARE_S32 || type == PPCREC_IML_TYPE_CONDITIONAL_JUMP || type == PPCREC_IML_TYPE_JUMP)
|
|
||||||
{
|
|
||||||
// not affected
|
|
||||||
}
|
|
||||||
else if (type == PPCREC_IML_TYPE_CJUMP_CYCLE_CHECK)
|
|
||||||
{
|
|
||||||
// not affected
|
|
||||||
}
|
|
||||||
else if (type == PPCREC_IML_TYPE_NO_OP)
|
|
||||||
{
|
|
||||||
// not affected
|
|
||||||
}
|
|
||||||
else if (type == PPCREC_IML_TYPE_MACRO)
|
|
||||||
{
|
|
||||||
// not affected
|
|
||||||
}
|
|
||||||
else if (type == PPCREC_IML_TYPE_LOAD)
|
|
||||||
{
|
|
||||||
// not affected
|
|
||||||
}
|
|
||||||
else if (type == PPCREC_IML_TYPE_LOAD_INDEXED)
|
|
||||||
{
|
|
||||||
// not affected
|
|
||||||
}
|
|
||||||
else if (type == PPCREC_IML_TYPE_STORE)
|
|
||||||
{
|
|
||||||
// not affected
|
|
||||||
}
|
|
||||||
else if (type == PPCREC_IML_TYPE_STORE_INDEXED)
|
|
||||||
{
|
|
||||||
// not affected
|
|
||||||
}
|
|
||||||
else if (type == PPCREC_IML_TYPE_ATOMIC_CMP_STORE)
|
|
||||||
{
|
|
||||||
;
|
|
||||||
}
|
|
||||||
else if (type == PPCREC_IML_TYPE_CALL_IMM)
|
|
||||||
{
|
|
||||||
// not affected
|
|
||||||
}
|
|
||||||
else if (type == PPCREC_IML_TYPE_FPR_LOAD)
|
|
||||||
{
|
|
||||||
op_storeLoad.registerData = replaceRegisterIdMultiple(op_storeLoad.registerData, fprRegisterSearched, fprRegisterReplaced);
|
|
||||||
}
|
|
||||||
else if (type == PPCREC_IML_TYPE_FPR_LOAD_INDEXED)
|
|
||||||
{
|
|
||||||
op_storeLoad.registerData = replaceRegisterIdMultiple(op_storeLoad.registerData, fprRegisterSearched, fprRegisterReplaced);
|
|
||||||
}
|
|
||||||
else if (type == PPCREC_IML_TYPE_FPR_STORE)
|
|
||||||
{
|
|
||||||
op_storeLoad.registerData = replaceRegisterIdMultiple(op_storeLoad.registerData, fprRegisterSearched, fprRegisterReplaced);
|
|
||||||
}
|
|
||||||
else if (type == PPCREC_IML_TYPE_FPR_STORE_INDEXED)
|
|
||||||
{
|
|
||||||
op_storeLoad.registerData = replaceRegisterIdMultiple(op_storeLoad.registerData, fprRegisterSearched, fprRegisterReplaced);
|
|
||||||
}
|
|
||||||
else if (type == PPCREC_IML_TYPE_FPR_R_R)
|
|
||||||
{
|
|
||||||
op_fpr_r_r.regR = replaceRegisterIdMultiple(op_fpr_r_r.regR, fprRegisterSearched, fprRegisterReplaced);
|
|
||||||
op_fpr_r_r.regA = replaceRegisterIdMultiple(op_fpr_r_r.regA, fprRegisterSearched, fprRegisterReplaced);
|
|
||||||
}
|
|
||||||
else if (type == PPCREC_IML_TYPE_FPR_R_R_R)
|
|
||||||
{
|
|
||||||
op_fpr_r_r_r.regR = replaceRegisterIdMultiple(op_fpr_r_r_r.regR, fprRegisterSearched, fprRegisterReplaced);
|
|
||||||
op_fpr_r_r_r.regA = replaceRegisterIdMultiple(op_fpr_r_r_r.regA, fprRegisterSearched, fprRegisterReplaced);
|
|
||||||
op_fpr_r_r_r.regB = replaceRegisterIdMultiple(op_fpr_r_r_r.regB, fprRegisterSearched, fprRegisterReplaced);
|
|
||||||
}
|
|
||||||
else if (type == PPCREC_IML_TYPE_FPR_R_R_R_R)
|
|
||||||
{
|
|
||||||
op_fpr_r_r_r_r.regR = replaceRegisterIdMultiple(op_fpr_r_r_r_r.regR, fprRegisterSearched, fprRegisterReplaced);
|
|
||||||
op_fpr_r_r_r_r.regA = replaceRegisterIdMultiple(op_fpr_r_r_r_r.regA, fprRegisterSearched, fprRegisterReplaced);
|
|
||||||
op_fpr_r_r_r_r.regB = replaceRegisterIdMultiple(op_fpr_r_r_r_r.regB, fprRegisterSearched, fprRegisterReplaced);
|
|
||||||
op_fpr_r_r_r_r.regC = replaceRegisterIdMultiple(op_fpr_r_r_r_r.regC, fprRegisterSearched, fprRegisterReplaced);
|
|
||||||
}
|
|
||||||
else if (type == PPCREC_IML_TYPE_FPR_R)
|
|
||||||
{
|
|
||||||
op_fpr_r.regR = replaceRegisterIdMultiple(op_fpr_r.regR, fprRegisterSearched, fprRegisterReplaced);
|
|
||||||
}
|
|
||||||
else if (type == PPCREC_IML_TYPE_FPR_COMPARE)
|
|
||||||
{
|
|
||||||
op_fpr_compare.regA = replaceRegisterIdMultiple(op_fpr_compare.regA, fprRegisterSearched, fprRegisterReplaced);
|
|
||||||
op_fpr_compare.regB = replaceRegisterIdMultiple(op_fpr_compare.regB, fprRegisterSearched, fprRegisterReplaced);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
cemu_assert_unimplemented();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void IMLInstruction::ReplaceFPR(IMLRegID fprRegisterSearched, IMLRegID fprRegisterReplaced)
|
|
||||||
{
|
|
||||||
if (type == PPCREC_IML_TYPE_R_NAME)
|
|
||||||
{
|
|
||||||
// not affected
|
|
||||||
}
|
|
||||||
else if (type == PPCREC_IML_TYPE_NAME_R)
|
|
||||||
{
|
|
||||||
// not affected
|
|
||||||
}
|
|
||||||
else if (type == PPCREC_IML_TYPE_R_R)
|
|
||||||
{
|
|
||||||
// not affected
|
|
||||||
}
|
|
||||||
else if (type == PPCREC_IML_TYPE_R_S32)
|
|
||||||
{
|
|
||||||
// not affected
|
|
||||||
}
|
|
||||||
else if (type == PPCREC_IML_TYPE_R_R_S32 || type == PPCREC_IML_TYPE_R_R_S32_CARRY)
|
|
||||||
{
|
|
||||||
// not affected
|
|
||||||
}
|
|
||||||
else if (type == PPCREC_IML_TYPE_R_R_R || type == PPCREC_IML_TYPE_R_R_R_CARRY)
|
|
||||||
{
|
|
||||||
// not affected
|
|
||||||
}
|
|
||||||
else if (type == PPCREC_IML_TYPE_COMPARE || type == PPCREC_IML_TYPE_COMPARE_S32 || type == PPCREC_IML_TYPE_CONDITIONAL_JUMP || type == PPCREC_IML_TYPE_JUMP)
|
|
||||||
{
|
|
||||||
// not affected
|
|
||||||
}
|
|
||||||
else if (type == PPCREC_IML_TYPE_CJUMP_CYCLE_CHECK)
|
|
||||||
{
|
|
||||||
// not affected
|
|
||||||
}
|
|
||||||
else if (type == PPCREC_IML_TYPE_NO_OP)
|
|
||||||
{
|
|
||||||
// not affected
|
|
||||||
}
|
|
||||||
else if (type == PPCREC_IML_TYPE_MACRO)
|
|
||||||
{
|
|
||||||
// not affected
|
|
||||||
}
|
|
||||||
else if (type == PPCREC_IML_TYPE_LOAD)
|
|
||||||
{
|
|
||||||
// not affected
|
|
||||||
}
|
|
||||||
else if (type == PPCREC_IML_TYPE_LOAD_INDEXED)
|
|
||||||
{
|
|
||||||
// not affected
|
|
||||||
}
|
|
||||||
else if (type == PPCREC_IML_TYPE_STORE)
|
|
||||||
{
|
|
||||||
// not affected
|
|
||||||
}
|
|
||||||
else if (type == PPCREC_IML_TYPE_STORE_INDEXED)
|
|
||||||
{
|
|
||||||
// not affected
|
|
||||||
}
|
|
||||||
else if (type == PPCREC_IML_TYPE_ATOMIC_CMP_STORE)
|
|
||||||
{
|
|
||||||
// not affected
|
|
||||||
}
|
|
||||||
else if (type == PPCREC_IML_TYPE_CALL_IMM)
|
|
||||||
{
|
|
||||||
// not affected
|
|
||||||
}
|
|
||||||
else if (type == PPCREC_IML_TYPE_FPR_LOAD)
|
|
||||||
{
|
|
||||||
op_storeLoad.registerData = replaceRegisterId(op_storeLoad.registerData, fprRegisterSearched, fprRegisterReplaced);
|
|
||||||
}
|
|
||||||
else if (type == PPCREC_IML_TYPE_FPR_LOAD_INDEXED)
|
|
||||||
{
|
|
||||||
op_storeLoad.registerData = replaceRegisterId(op_storeLoad.registerData, fprRegisterSearched, fprRegisterReplaced);
|
|
||||||
}
|
|
||||||
else if (type == PPCREC_IML_TYPE_FPR_STORE)
|
|
||||||
{
|
|
||||||
op_storeLoad.registerData = replaceRegisterId(op_storeLoad.registerData, fprRegisterSearched, fprRegisterReplaced);
|
|
||||||
}
|
|
||||||
else if (type == PPCREC_IML_TYPE_FPR_STORE_INDEXED)
|
|
||||||
{
|
|
||||||
op_storeLoad.registerData = replaceRegisterId(op_storeLoad.registerData, fprRegisterSearched, fprRegisterReplaced);
|
|
||||||
}
|
|
||||||
else if (type == PPCREC_IML_TYPE_FPR_R_R)
|
|
||||||
{
|
|
||||||
op_fpr_r_r.regR = replaceRegisterId(op_fpr_r_r.regR, fprRegisterSearched, fprRegisterReplaced);
|
|
||||||
op_fpr_r_r.regA = replaceRegisterId(op_fpr_r_r.regA, fprRegisterSearched, fprRegisterReplaced);
|
|
||||||
}
|
|
||||||
else if (type == PPCREC_IML_TYPE_FPR_R_R_R)
|
|
||||||
{
|
|
||||||
op_fpr_r_r_r.regR = replaceRegisterId(op_fpr_r_r_r.regR, fprRegisterSearched, fprRegisterReplaced);
|
|
||||||
op_fpr_r_r_r.regA = replaceRegisterId(op_fpr_r_r_r.regA, fprRegisterSearched, fprRegisterReplaced);
|
|
||||||
op_fpr_r_r_r.regB = replaceRegisterId(op_fpr_r_r_r.regB, fprRegisterSearched, fprRegisterReplaced);
|
|
||||||
}
|
|
||||||
else if (type == PPCREC_IML_TYPE_FPR_R_R_R_R)
|
|
||||||
{
|
|
||||||
op_fpr_r_r_r_r.regR = replaceRegisterId(op_fpr_r_r_r_r.regR, fprRegisterSearched, fprRegisterReplaced);
|
|
||||||
op_fpr_r_r_r_r.regA = replaceRegisterId(op_fpr_r_r_r_r.regA, fprRegisterSearched, fprRegisterReplaced);
|
|
||||||
op_fpr_r_r_r_r.regB = replaceRegisterId(op_fpr_r_r_r_r.regB, fprRegisterSearched, fprRegisterReplaced);
|
|
||||||
op_fpr_r_r_r_r.regC = replaceRegisterId(op_fpr_r_r_r_r.regC, fprRegisterSearched, fprRegisterReplaced);
|
|
||||||
}
|
|
||||||
else if (type == PPCREC_IML_TYPE_FPR_R)
|
|
||||||
{
|
|
||||||
op_fpr_r.regR = replaceRegisterId(op_fpr_r.regR, fprRegisterSearched, fprRegisterReplaced);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
cemu_assert_unimplemented();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
@ -197,7 +197,6 @@ enum
|
|||||||
PPCREC_IML_MACRO_B_FAR, // branch to different function
|
PPCREC_IML_MACRO_B_FAR, // branch to different function
|
||||||
PPCREC_IML_MACRO_COUNT_CYCLES, // decrease current remaining thread cycles by a certain amount
|
PPCREC_IML_MACRO_COUNT_CYCLES, // decrease current remaining thread cycles by a certain amount
|
||||||
PPCREC_IML_MACRO_HLE, // HLE function call
|
PPCREC_IML_MACRO_HLE, // HLE function call
|
||||||
PPCREC_IML_MACRO_MFTB, // get TB register value (low or high)
|
|
||||||
PPCREC_IML_MACRO_LEAVE, // leaves recompiler and switches to interpeter
|
PPCREC_IML_MACRO_LEAVE, // leaves recompiler and switches to interpeter
|
||||||
// debugging
|
// debugging
|
||||||
PPCREC_IML_MACRO_DEBUGBREAK, // throws a debugbreak
|
PPCREC_IML_MACRO_DEBUGBREAK, // throws a debugbreak
|
||||||
@ -335,19 +334,6 @@ struct IMLUsedRegisters
|
|||||||
{
|
{
|
||||||
IMLUsedRegisters() {};
|
IMLUsedRegisters() {};
|
||||||
|
|
||||||
union
|
|
||||||
{
|
|
||||||
struct
|
|
||||||
{
|
|
||||||
IMLReg readGPR1;
|
|
||||||
IMLReg readGPR2;
|
|
||||||
IMLReg readGPR3;
|
|
||||||
IMLReg readGPR4;
|
|
||||||
IMLReg writtenGPR1;
|
|
||||||
IMLReg writtenGPR2;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
bool IsWrittenByRegId(IMLRegID regId) const
|
bool IsWrittenByRegId(IMLRegID regId) const
|
||||||
{
|
{
|
||||||
if (writtenGPR1.IsValid() && writtenGPR1.GetRegID() == regId)
|
if (writtenGPR1.IsValid() && writtenGPR1.GetRegID() == regId)
|
||||||
@ -404,6 +390,12 @@ struct IMLUsedRegisters
|
|||||||
F(writtenGPR2, true);
|
F(writtenGPR2, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
IMLReg readGPR1;
|
||||||
|
IMLReg readGPR2;
|
||||||
|
IMLReg readGPR3;
|
||||||
|
IMLReg readGPR4;
|
||||||
|
IMLReg writtenGPR1;
|
||||||
|
IMLReg writtenGPR2;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct IMLInstruction
|
struct IMLInstruction
|
||||||
@ -575,7 +567,6 @@ struct IMLInstruction
|
|||||||
type == PPCREC_IML_TYPE_MACRO && operation == PPCREC_IML_MACRO_B_TO_REG ||
|
type == PPCREC_IML_TYPE_MACRO && operation == PPCREC_IML_MACRO_B_TO_REG ||
|
||||||
type == PPCREC_IML_TYPE_MACRO && operation == PPCREC_IML_MACRO_LEAVE ||
|
type == PPCREC_IML_TYPE_MACRO && operation == PPCREC_IML_MACRO_LEAVE ||
|
||||||
type == PPCREC_IML_TYPE_MACRO && operation == PPCREC_IML_MACRO_HLE ||
|
type == PPCREC_IML_TYPE_MACRO && operation == PPCREC_IML_MACRO_HLE ||
|
||||||
type == PPCREC_IML_TYPE_MACRO && operation == PPCREC_IML_MACRO_MFTB ||
|
|
||||||
type == PPCREC_IML_TYPE_CJUMP_CYCLE_CHECK ||
|
type == PPCREC_IML_TYPE_CJUMP_CYCLE_CHECK ||
|
||||||
type == PPCREC_IML_TYPE_JUMP ||
|
type == PPCREC_IML_TYPE_JUMP ||
|
||||||
type == PPCREC_IML_TYPE_CONDITIONAL_JUMP ||
|
type == PPCREC_IML_TYPE_CONDITIONAL_JUMP ||
|
||||||
@ -788,9 +779,6 @@ struct IMLInstruction
|
|||||||
bool HasSideEffects() const; // returns true if the instruction has side effects beyond just reading and writing registers. Dead code elimination uses this to know if an instruction can be dropped when the regular register outputs are not used
|
bool HasSideEffects() const; // returns true if the instruction has side effects beyond just reading and writing registers. Dead code elimination uses this to know if an instruction can be dropped when the regular register outputs are not used
|
||||||
|
|
||||||
void RewriteGPR(const std::unordered_map<IMLRegID, IMLRegID>& translationTable);
|
void RewriteGPR(const std::unordered_map<IMLRegID, IMLRegID>& translationTable);
|
||||||
void ReplaceFPRs(IMLReg fprRegisterSearched[4], IMLReg fprRegisterReplaced[4]);
|
|
||||||
void ReplaceFPR(IMLRegID fprRegisterSearched, IMLRegID fprRegisterReplaced);
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// architecture specific constants
|
// architecture specific constants
|
||||||
|
@ -192,7 +192,7 @@ static void GetInstructionFixedRegisters(IMLInstruction* instruction, IMLFixedRe
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
uint32 PPCRecRA_getNextIterationIndex()
|
uint32 IMLRA_GetNextIterationIndex()
|
||||||
{
|
{
|
||||||
static uint32 recRACurrentIterationIndex = 0;
|
static uint32 recRACurrentIterationIndex = 0;
|
||||||
recRACurrentIterationIndex++;
|
recRACurrentIterationIndex++;
|
||||||
@ -231,9 +231,9 @@ bool _detectLoop(IMLSegment* currentSegment, sint32 depth, uint32 iterationIndex
|
|||||||
return currentSegment->raInfo.isPartOfProcessedLoop;
|
return currentSegment->raInfo.isPartOfProcessedLoop;
|
||||||
}
|
}
|
||||||
|
|
||||||
void PPCRecRA_detectLoop(ppcImlGenContext_t* ppcImlGenContext, IMLSegment* imlSegmentLoopBase)
|
void IMLRA_DetectLoop(ppcImlGenContext_t* ppcImlGenContext, IMLSegment* imlSegmentLoopBase)
|
||||||
{
|
{
|
||||||
uint32 iterationIndex = PPCRecRA_getNextIterationIndex();
|
uint32 iterationIndex = IMLRA_GetNextIterationIndex();
|
||||||
imlSegmentLoopBase->raInfo.lastIterationIndex = iterationIndex;
|
imlSegmentLoopBase->raInfo.lastIterationIndex = iterationIndex;
|
||||||
if (_detectLoop(imlSegmentLoopBase->nextSegmentBranchTaken, 0, iterationIndex, imlSegmentLoopBase))
|
if (_detectLoop(imlSegmentLoopBase->nextSegmentBranchTaken, 0, iterationIndex, imlSegmentLoopBase))
|
||||||
{
|
{
|
||||||
@ -241,7 +241,7 @@ void PPCRecRA_detectLoop(ppcImlGenContext_t* ppcImlGenContext, IMLSegment* imlSe
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void PPCRecRA_identifyLoop(ppcImlGenContext_t* ppcImlGenContext, IMLSegment* imlSegment)
|
void IMLRA_IdentifyLoop(ppcImlGenContext_t* ppcImlGenContext, IMLSegment* imlSegment)
|
||||||
{
|
{
|
||||||
if (imlSegment->nextSegmentIsUncertain)
|
if (imlSegment->nextSegmentIsUncertain)
|
||||||
return;
|
return;
|
||||||
@ -255,13 +255,13 @@ void PPCRecRA_identifyLoop(ppcImlGenContext_t* ppcImlGenContext, IMLSegment* iml
|
|||||||
// check if this segment has a branch that goes backwards (potential complex loop)
|
// check if this segment has a branch that goes backwards (potential complex loop)
|
||||||
if (imlSegment->nextSegmentBranchTaken && imlSegment->nextSegmentBranchTaken->momentaryIndex < imlSegment->momentaryIndex)
|
if (imlSegment->nextSegmentBranchTaken && imlSegment->nextSegmentBranchTaken->momentaryIndex < imlSegment->momentaryIndex)
|
||||||
{
|
{
|
||||||
PPCRecRA_detectLoop(ppcImlGenContext, imlSegment);
|
IMLRA_DetectLoop(ppcImlGenContext, imlSegment);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#define SUBRANGE_LIST_SIZE (128)
|
#define SUBRANGE_LIST_SIZE (128)
|
||||||
|
|
||||||
sint32 PPCRecRA_countDistanceUntilNextUse2(raLivenessRange* subrange, raInstructionEdge startPosition)
|
sint32 IMLRA_CountDistanceUntilNextUse(raLivenessRange* subrange, raInstructionEdge startPosition)
|
||||||
{
|
{
|
||||||
for (sint32 i = 0; i < subrange->list_accessLocations.size(); i++)
|
for (sint32 i = 0; i < subrange->list_accessLocations.size(); i++)
|
||||||
{
|
{
|
||||||
@ -292,8 +292,8 @@ sint32 IMLRA_CountDistanceUntilFixedRegUsageInRange(IMLSegment* imlSegment, raLi
|
|||||||
return fixedReqEntry.pos.GetRaw() - startPosition.GetRaw();
|
return fixedReqEntry.pos.GetRaw() - startPosition.GetRaw();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
cemu_assert_debug(range->interval2.end.IsInstructionIndex());
|
cemu_assert_debug(range->interval.end.IsInstructionIndex());
|
||||||
return range->interval2.end.GetRaw() - startPosition.GetRaw();
|
return range->interval.end.GetRaw() - startPosition.GetRaw();
|
||||||
}
|
}
|
||||||
|
|
||||||
sint32 IMLRA_CountDistanceUntilFixedRegUsage(IMLSegment* imlSegment, raInstructionEdge startPosition, sint32 maxDistance, IMLRegID ourRegId, sint32 physRegister)
|
sint32 IMLRA_CountDistanceUntilFixedRegUsage(IMLSegment* imlSegment, raInstructionEdge startPosition, sint32 maxDistance, IMLRegID ourRegId, sint32 physRegister)
|
||||||
@ -343,15 +343,15 @@ sint32 PPCRecRA_countDistanceUntilNextLocalPhysRegisterUse(IMLSegment* imlSegmen
|
|||||||
subrangeItr = subrangeItr->link_allSegmentRanges.next;
|
subrangeItr = subrangeItr->link_allSegmentRanges.next;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (subrangeItr->interval2.ContainsEdge(startPosition))
|
if (subrangeItr->interval.ContainsEdge(startPosition))
|
||||||
return 0;
|
return 0;
|
||||||
if (subrangeItr->interval2.end < startPosition)
|
if (subrangeItr->interval.end < startPosition)
|
||||||
{
|
{
|
||||||
subrangeItr = subrangeItr->link_allSegmentRanges.next;
|
subrangeItr = subrangeItr->link_allSegmentRanges.next;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
cemu_assert_debug(startPosition <= subrangeItr->interval2.start);
|
cemu_assert_debug(startPosition <= subrangeItr->interval.start);
|
||||||
sint32 currentDist = subrangeItr->interval2.start.GetRaw() - startPosition.GetRaw();
|
sint32 currentDist = subrangeItr->interval.start.GetRaw() - startPosition.GetRaw();
|
||||||
minDistance = std::min(minDistance, currentDist);
|
minDistance = std::min(minDistance, currentDist);
|
||||||
subrangeItr = subrangeItr->link_allSegmentRanges.next;
|
subrangeItr = subrangeItr->link_allSegmentRanges.next;
|
||||||
}
|
}
|
||||||
@ -377,7 +377,7 @@ struct IMLRALivenessTimeline
|
|||||||
for (size_t f = 0; f < count; f++)
|
for (size_t f = 0; f < count; f++)
|
||||||
{
|
{
|
||||||
raLivenessRange* liverange = activeRanges[f];
|
raLivenessRange* liverange = activeRanges[f];
|
||||||
if (liverange->interval2.end < expireUpTo) // this was <= but since end is not inclusive we need to use <
|
if (liverange->interval.end < expireUpTo) // this was <= but since end is not inclusive we need to use <
|
||||||
{
|
{
|
||||||
#ifdef CEMU_DEBUG_ASSERT
|
#ifdef CEMU_DEBUG_ASSERT
|
||||||
if (!expireUpTo.ConnectsToNextSegment() && (liverange->subrangeBranchTaken || liverange->subrangeBranchNotTaken))
|
if (!expireUpTo.ConnectsToNextSegment() && (liverange->subrangeBranchTaken || liverange->subrangeBranchNotTaken))
|
||||||
@ -443,7 +443,7 @@ void PPCRecRA_MaskOverlappingPhysRegForGlobalRange(raLivenessRange* range2, IMLP
|
|||||||
subrangeItr = subrangeItr->link_allSegmentRanges.next;
|
subrangeItr = subrangeItr->link_allSegmentRanges.next;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (subrange->interval2.IsOverlapping(subrangeItr->interval2))
|
if (subrange->interval.IsOverlapping(subrangeItr->interval))
|
||||||
{
|
{
|
||||||
if (subrangeItr->GetPhysicalRegister() >= 0)
|
if (subrangeItr->GetPhysicalRegister() >= 0)
|
||||||
physRegSet.SetReserved(subrangeItr->GetPhysicalRegister());
|
physRegSet.SetReserved(subrangeItr->GetPhysicalRegister());
|
||||||
@ -456,7 +456,7 @@ void PPCRecRA_MaskOverlappingPhysRegForGlobalRange(raLivenessRange* range2, IMLP
|
|||||||
|
|
||||||
bool _livenessRangeStartCompare(raLivenessRange* lhs, raLivenessRange* rhs)
|
bool _livenessRangeStartCompare(raLivenessRange* lhs, raLivenessRange* rhs)
|
||||||
{
|
{
|
||||||
return lhs->interval2.start < rhs->interval2.start;
|
return lhs->interval.start < rhs->interval.start;
|
||||||
}
|
}
|
||||||
|
|
||||||
void _sortSegmentAllSubrangesLinkedList(IMLSegment* imlSegment)
|
void _sortSegmentAllSubrangesLinkedList(IMLSegment* imlSegment)
|
||||||
@ -467,8 +467,7 @@ void _sortSegmentAllSubrangesLinkedList(IMLSegment* imlSegment)
|
|||||||
raLivenessRange* subrangeItr = imlSegment->raInfo.linkedList_allSubranges;
|
raLivenessRange* subrangeItr = imlSegment->raInfo.linkedList_allSubranges;
|
||||||
while (subrangeItr)
|
while (subrangeItr)
|
||||||
{
|
{
|
||||||
if (count >= 4096)
|
cemu_assert(count < 4096);
|
||||||
assert_dbg();
|
|
||||||
subrangeList[count] = subrangeItr;
|
subrangeList[count] = subrangeItr;
|
||||||
count++;
|
count++;
|
||||||
// next
|
// next
|
||||||
@ -526,6 +525,9 @@ raLivenessRange* IMLRA_GetSubrange(IMLSegment* imlSegment, IMLRegID regId)
|
|||||||
|
|
||||||
struct raFixedRegRequirementWithVGPR
|
struct raFixedRegRequirementWithVGPR
|
||||||
{
|
{
|
||||||
|
raFixedRegRequirementWithVGPR(raInstructionEdge pos, IMLPhysRegisterSet allowedReg, IMLRegID regId)
|
||||||
|
: pos(pos), allowedReg(allowedReg), regId(regId) {}
|
||||||
|
|
||||||
raInstructionEdge pos;
|
raInstructionEdge pos;
|
||||||
IMLPhysRegisterSet allowedReg;
|
IMLPhysRegisterSet allowedReg;
|
||||||
IMLRegID regId;
|
IMLRegID regId;
|
||||||
@ -560,7 +562,7 @@ boost::container::small_vector<raLivenessRange*, 8> IMLRA_GetRangeWithFixedRegRe
|
|||||||
boost::container::small_vector<raLivenessRange*, 8> rangeList;
|
boost::container::small_vector<raLivenessRange*, 8> rangeList;
|
||||||
for (raLivenessRange* currentRange = imlSegment->raInfo.linkedList_allSubranges; currentRange; currentRange = currentRange->link_allSegmentRanges.next)
|
for (raLivenessRange* currentRange = imlSegment->raInfo.linkedList_allSubranges; currentRange; currentRange = currentRange->link_allSegmentRanges.next)
|
||||||
{
|
{
|
||||||
if (!currentRange->interval2.ContainsEdge(pos))
|
if (!currentRange->interval.ContainsEdge(pos))
|
||||||
continue;
|
continue;
|
||||||
IMLPhysRegisterSet allowedRegs;
|
IMLPhysRegisterSet allowedRegs;
|
||||||
if (!currentRange->GetAllowedRegistersEx(allowedRegs))
|
if (!currentRange->GetAllowedRegistersEx(allowedRegs))
|
||||||
@ -574,7 +576,7 @@ boost::container::small_vector<raLivenessRange*, 8> IMLRA_GetRangeWithFixedRegRe
|
|||||||
void IMLRA_HandleFixedRegisters(ppcImlGenContext_t* ppcImlGenContext, IMLSegment* imlSegment)
|
void IMLRA_HandleFixedRegisters(ppcImlGenContext_t* ppcImlGenContext, IMLSegment* imlSegment)
|
||||||
{
|
{
|
||||||
// first pass - iterate over all ranges with fixed register requirements and split them if they cross the segment border
|
// first pass - iterate over all ranges with fixed register requirements and split them if they cross the segment border
|
||||||
// todo - this pass currently creates suboptimal results by splitting all ranges that cross the segment border if they have any fixed register requirement. This isn't always necessary
|
// todo - this pass currently creates suboptimal results by splitting all ranges that cross the segment border if they have any fixed register requirement. This can be avoided in some cases
|
||||||
for (raLivenessRange* currentRange = imlSegment->raInfo.linkedList_allSubranges; currentRange;)
|
for (raLivenessRange* currentRange = imlSegment->raInfo.linkedList_allSubranges; currentRange;)
|
||||||
{
|
{
|
||||||
IMLPhysRegisterSet allowedRegs;
|
IMLPhysRegisterSet allowedRegs;
|
||||||
@ -588,10 +590,10 @@ void IMLRA_HandleFixedRegisters(ppcImlGenContext_t* ppcImlGenContext, IMLSegment
|
|||||||
currentRange = currentRange->link_allSegmentRanges.next;
|
currentRange = currentRange->link_allSegmentRanges.next;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (currentRange->interval2.ExtendsPreviousSegment() || currentRange->interval2.ExtendsIntoNextSegment())
|
if (currentRange->interval.ExtendsPreviousSegment() || currentRange->interval.ExtendsIntoNextSegment())
|
||||||
{
|
{
|
||||||
raLivenessRange* nextRange = currentRange->link_allSegmentRanges.next;
|
raLivenessRange* nextRange = currentRange->link_allSegmentRanges.next;
|
||||||
PPCRecRA_explodeRange(ppcImlGenContext, currentRange);
|
IMLRA_ExplodeRangeCluster(ppcImlGenContext, currentRange);
|
||||||
currentRange = nextRange;
|
currentRange = nextRange;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -638,9 +640,9 @@ void IMLRA_HandleFixedRegisters(ppcImlGenContext_t* ppcImlGenContext, IMLSegment
|
|||||||
|
|
||||||
for (auto& range : overlappingRanges)
|
for (auto& range : overlappingRanges)
|
||||||
{
|
{
|
||||||
if (range->interval2.start < entry.pos)
|
if (range->interval.start < entry.pos)
|
||||||
{
|
{
|
||||||
PPCRecRA_splitLocalSubrange2(ppcImlGenContext, range, entry.pos, true);
|
IMLRA_SplitRange(ppcImlGenContext, range, entry.pos, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -704,7 +706,7 @@ void IMLRA_MakeSafeSplitDistance(IMLSegment* imlSegment, raInstructionEdge start
|
|||||||
distance = endPos.GetRaw() - startPos.GetRaw();
|
distance = endPos.GetRaw() - startPos.GetRaw();
|
||||||
}
|
}
|
||||||
|
|
||||||
void DbgVerifyAllRanges(IMLRegisterAllocatorContext& ctx);
|
static void DbgVerifyAllRanges(IMLRegisterAllocatorContext& ctx);
|
||||||
|
|
||||||
class RASpillStrategy
|
class RASpillStrategy
|
||||||
{
|
{
|
||||||
@ -737,8 +739,8 @@ class RASpillStrategy_LocalRangeHoleCutting : public RASpillStrategy
|
|||||||
|
|
||||||
void Evaluate(IMLSegment* imlSegment, raLivenessRange* currentRange, const IMLRALivenessTimeline& timeline, const IMLPhysRegisterSet& allowedRegs)
|
void Evaluate(IMLSegment* imlSegment, raLivenessRange* currentRange, const IMLRALivenessTimeline& timeline, const IMLPhysRegisterSet& allowedRegs)
|
||||||
{
|
{
|
||||||
raInstructionEdge currentRangeStart = currentRange->interval2.start;
|
raInstructionEdge currentRangeStart = currentRange->interval.start;
|
||||||
sint32 requiredSize2 = currentRange->interval2.GetPreciseDistance();
|
sint32 requiredSize2 = currentRange->interval.GetPreciseDistance();
|
||||||
cemu_assert_debug(localRangeHoleCutting.distance == -1);
|
cemu_assert_debug(localRangeHoleCutting.distance == -1);
|
||||||
cemu_assert_debug(strategyCost == INT_MAX);
|
cemu_assert_debug(strategyCost == INT_MAX);
|
||||||
if (!currentRangeStart.ConnectsToPreviousSegment())
|
if (!currentRangeStart.ConnectsToPreviousSegment())
|
||||||
@ -746,7 +748,7 @@ class RASpillStrategy_LocalRangeHoleCutting : public RASpillStrategy
|
|||||||
cemu_assert_debug(currentRangeStart.GetRaw() >= 0);
|
cemu_assert_debug(currentRangeStart.GetRaw() >= 0);
|
||||||
for (auto candidate : timeline.activeRanges)
|
for (auto candidate : timeline.activeRanges)
|
||||||
{
|
{
|
||||||
if (candidate->interval2.ExtendsIntoNextSegment())
|
if (candidate->interval.ExtendsIntoNextSegment())
|
||||||
continue;
|
continue;
|
||||||
// new checks (Oct 2024):
|
// new checks (Oct 2024):
|
||||||
if (candidate == currentRange)
|
if (candidate == currentRange)
|
||||||
@ -756,7 +758,7 @@ class RASpillStrategy_LocalRangeHoleCutting : public RASpillStrategy
|
|||||||
if (!allowedRegs.IsAvailable(candidate->GetPhysicalRegister()))
|
if (!allowedRegs.IsAvailable(candidate->GetPhysicalRegister()))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
sint32 distance2 = PPCRecRA_countDistanceUntilNextUse2(candidate, currentRangeStart);
|
sint32 distance2 = IMLRA_CountDistanceUntilNextUse(candidate, currentRangeStart);
|
||||||
IMLRA_MakeSafeSplitDistance(imlSegment, currentRangeStart, distance2);
|
IMLRA_MakeSafeSplitDistance(imlSegment, currentRangeStart, distance2);
|
||||||
if (distance2 < 2)
|
if (distance2 < 2)
|
||||||
continue;
|
continue;
|
||||||
@ -785,18 +787,18 @@ class RASpillStrategy_LocalRangeHoleCutting : public RASpillStrategy
|
|||||||
void Apply(ppcImlGenContext_t* ctx, IMLSegment* imlSegment, raLivenessRange* currentRange) override
|
void Apply(ppcImlGenContext_t* ctx, IMLSegment* imlSegment, raLivenessRange* currentRange) override
|
||||||
{
|
{
|
||||||
cemu_assert_debug(strategyCost != INT_MAX);
|
cemu_assert_debug(strategyCost != INT_MAX);
|
||||||
sint32 requiredSize2 = currentRange->interval2.GetPreciseDistance();
|
sint32 requiredSize2 = currentRange->interval.GetPreciseDistance();
|
||||||
raInstructionEdge currentRangeStart = currentRange->interval2.start;
|
raInstructionEdge currentRangeStart = currentRange->interval.start;
|
||||||
|
|
||||||
raInstructionEdge holeStartPosition = currentRangeStart;
|
raInstructionEdge holeStartPosition = currentRangeStart;
|
||||||
raInstructionEdge holeEndPosition = currentRangeStart + localRangeHoleCutting.distance;
|
raInstructionEdge holeEndPosition = currentRangeStart + localRangeHoleCutting.distance;
|
||||||
raLivenessRange* collisionRange = localRangeHoleCutting.largestHoleSubrange;
|
raLivenessRange* collisionRange = localRangeHoleCutting.largestHoleSubrange;
|
||||||
|
|
||||||
if (collisionRange->interval2.start < holeStartPosition)
|
if (collisionRange->interval.start < holeStartPosition)
|
||||||
{
|
{
|
||||||
collisionRange = PPCRecRA_splitLocalSubrange2(nullptr, collisionRange, holeStartPosition, true);
|
collisionRange = IMLRA_SplitRange(nullptr, collisionRange, holeStartPosition, true);
|
||||||
cemu_assert_debug(!collisionRange || collisionRange->interval2.start >= holeStartPosition); // verify if splitting worked at all, tail must be on or after the split point
|
cemu_assert_debug(!collisionRange || collisionRange->interval.start >= holeStartPosition); // verify if splitting worked at all, tail must be on or after the split point
|
||||||
cemu_assert_debug(!collisionRange || collisionRange->interval2.start >= holeEndPosition); // also verify that the trimmed hole is actually big enough
|
cemu_assert_debug(!collisionRange || collisionRange->interval.start >= holeEndPosition); // also verify that the trimmed hole is actually big enough
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -805,7 +807,7 @@ class RASpillStrategy_LocalRangeHoleCutting : public RASpillStrategy
|
|||||||
// we may also have to cut the current range to fit partially into the hole
|
// we may also have to cut the current range to fit partially into the hole
|
||||||
if (requiredSize2 > localRangeHoleCutting.distance)
|
if (requiredSize2 > localRangeHoleCutting.distance)
|
||||||
{
|
{
|
||||||
raLivenessRange* tailRange = PPCRecRA_splitLocalSubrange2(nullptr, currentRange, currentRangeStart + localRangeHoleCutting.distance, true);
|
raLivenessRange* tailRange = IMLRA_SplitRange(nullptr, currentRange, currentRangeStart + localRangeHoleCutting.distance, true);
|
||||||
if (tailRange)
|
if (tailRange)
|
||||||
{
|
{
|
||||||
cemu_assert_debug(tailRange->list_fixedRegRequirements.empty()); // we are not allowed to unassign fixed registers
|
cemu_assert_debug(tailRange->list_fixedRegRequirements.empty()); // we are not allowed to unassign fixed registers
|
||||||
@ -815,7 +817,7 @@ class RASpillStrategy_LocalRangeHoleCutting : public RASpillStrategy
|
|||||||
// verify that the hole is large enough
|
// verify that the hole is large enough
|
||||||
if (collisionRange)
|
if (collisionRange)
|
||||||
{
|
{
|
||||||
cemu_assert_debug(!collisionRange->interval2.IsOverlapping(currentRange->interval2));
|
cemu_assert_debug(!collisionRange->interval.IsOverlapping(currentRange->interval));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -840,9 +842,9 @@ class RASpillStrategy_AvailableRegisterHole : public RASpillStrategy
|
|||||||
|
|
||||||
void Evaluate(IMLSegment* imlSegment, raLivenessRange* currentRange, const IMLRALivenessTimeline& timeline, const IMLPhysRegisterSet& localAvailableRegsMask, const IMLPhysRegisterSet& allowedRegs)
|
void Evaluate(IMLSegment* imlSegment, raLivenessRange* currentRange, const IMLRALivenessTimeline& timeline, const IMLPhysRegisterSet& localAvailableRegsMask, const IMLPhysRegisterSet& allowedRegs)
|
||||||
{
|
{
|
||||||
sint32 requiredSize2 = currentRange->interval2.GetPreciseDistance();
|
sint32 requiredSize2 = currentRange->interval.GetPreciseDistance();
|
||||||
|
|
||||||
raInstructionEdge currentRangeStart = currentRange->interval2.start;
|
raInstructionEdge currentRangeStart = currentRange->interval.start;
|
||||||
cemu_assert_debug(strategyCost == INT_MAX);
|
cemu_assert_debug(strategyCost == INT_MAX);
|
||||||
availableRegisterHole.distance = -1;
|
availableRegisterHole.distance = -1;
|
||||||
availableRegisterHole.physRegister = -1;
|
availableRegisterHole.physRegister = -1;
|
||||||
@ -888,9 +890,9 @@ class RASpillStrategy_AvailableRegisterHole : public RASpillStrategy
|
|||||||
void Apply(ppcImlGenContext_t* ctx, IMLSegment* imlSegment, raLivenessRange* currentRange) override
|
void Apply(ppcImlGenContext_t* ctx, IMLSegment* imlSegment, raLivenessRange* currentRange) override
|
||||||
{
|
{
|
||||||
cemu_assert_debug(strategyCost != INT_MAX);
|
cemu_assert_debug(strategyCost != INT_MAX);
|
||||||
raInstructionEdge currentRangeStart = currentRange->interval2.start;
|
raInstructionEdge currentRangeStart = currentRange->interval.start;
|
||||||
// use available register
|
// use available register
|
||||||
raLivenessRange* tailRange = PPCRecRA_splitLocalSubrange2(nullptr, currentRange, currentRangeStart + availableRegisterHole.distance, true);
|
raLivenessRange* tailRange = IMLRA_SplitRange(nullptr, currentRange, currentRangeStart + availableRegisterHole.distance, true);
|
||||||
if (tailRange)
|
if (tailRange)
|
||||||
{
|
{
|
||||||
cemu_assert_debug(tailRange->list_fixedRegRequirements.empty()); // we are not allowed to unassign fixed registers
|
cemu_assert_debug(tailRange->list_fixedRegRequirements.empty()); // we are not allowed to unassign fixed registers
|
||||||
@ -918,16 +920,16 @@ class RASpillStrategy_ExplodeRange : public RASpillStrategy
|
|||||||
|
|
||||||
void Evaluate(IMLSegment* imlSegment, raLivenessRange* currentRange, const IMLRALivenessTimeline& timeline, const IMLPhysRegisterSet& allowedRegs)
|
void Evaluate(IMLSegment* imlSegment, raLivenessRange* currentRange, const IMLRALivenessTimeline& timeline, const IMLPhysRegisterSet& allowedRegs)
|
||||||
{
|
{
|
||||||
raInstructionEdge currentRangeStart = currentRange->interval2.start;
|
raInstructionEdge currentRangeStart = currentRange->interval.start;
|
||||||
if (currentRangeStart.ConnectsToPreviousSegment())
|
if (currentRangeStart.ConnectsToPreviousSegment())
|
||||||
currentRangeStart.Set(0, true);
|
currentRangeStart.Set(0, true);
|
||||||
sint32 requiredSize2 = currentRange->interval2.GetPreciseDistance();
|
sint32 requiredSize2 = currentRange->interval.GetPreciseDistance();
|
||||||
cemu_assert_debug(strategyCost == INT_MAX);
|
cemu_assert_debug(strategyCost == INT_MAX);
|
||||||
explodeRange.range = nullptr;
|
explodeRange.range = nullptr;
|
||||||
explodeRange.distance = -1;
|
explodeRange.distance = -1;
|
||||||
for (auto candidate : timeline.activeRanges)
|
for (auto candidate : timeline.activeRanges)
|
||||||
{
|
{
|
||||||
if (!candidate->interval2.ExtendsIntoNextSegment())
|
if (!candidate->interval.ExtendsIntoNextSegment())
|
||||||
continue;
|
continue;
|
||||||
// new checks (Oct 2024):
|
// new checks (Oct 2024):
|
||||||
if (candidate == currentRange)
|
if (candidate == currentRange)
|
||||||
@ -937,7 +939,7 @@ class RASpillStrategy_ExplodeRange : public RASpillStrategy
|
|||||||
if (!allowedRegs.IsAvailable(candidate->GetPhysicalRegister()))
|
if (!allowedRegs.IsAvailable(candidate->GetPhysicalRegister()))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
sint32 distance = PPCRecRA_countDistanceUntilNextUse2(candidate, currentRangeStart);
|
sint32 distance = IMLRA_CountDistanceUntilNextUse(candidate, currentRangeStart);
|
||||||
IMLRA_MakeSafeSplitDistance(imlSegment, currentRangeStart, distance);
|
IMLRA_MakeSafeSplitDistance(imlSegment, currentRangeStart, distance);
|
||||||
if (distance < 2)
|
if (distance < 2)
|
||||||
continue;
|
continue;
|
||||||
@ -961,16 +963,16 @@ class RASpillStrategy_ExplodeRange : public RASpillStrategy
|
|||||||
|
|
||||||
void Apply(ppcImlGenContext_t* ctx, IMLSegment* imlSegment, raLivenessRange* currentRange) override
|
void Apply(ppcImlGenContext_t* ctx, IMLSegment* imlSegment, raLivenessRange* currentRange) override
|
||||||
{
|
{
|
||||||
raInstructionEdge currentRangeStart = currentRange->interval2.start;
|
raInstructionEdge currentRangeStart = currentRange->interval.start;
|
||||||
if (currentRangeStart.ConnectsToPreviousSegment())
|
if (currentRangeStart.ConnectsToPreviousSegment())
|
||||||
currentRangeStart.Set(0, true);
|
currentRangeStart.Set(0, true);
|
||||||
sint32 requiredSize2 = currentRange->interval2.GetPreciseDistance();
|
sint32 requiredSize2 = currentRange->interval.GetPreciseDistance();
|
||||||
// explode range
|
// explode range
|
||||||
PPCRecRA_explodeRange(nullptr, explodeRange.range);
|
IMLRA_ExplodeRangeCluster(nullptr, explodeRange.range);
|
||||||
// split current subrange if necessary
|
// split current subrange if necessary
|
||||||
if (requiredSize2 > explodeRange.distance)
|
if (requiredSize2 > explodeRange.distance)
|
||||||
{
|
{
|
||||||
raLivenessRange* tailRange = PPCRecRA_splitLocalSubrange2(nullptr, currentRange, currentRangeStart + explodeRange.distance, true);
|
raLivenessRange* tailRange = IMLRA_SplitRange(nullptr, currentRange, currentRangeStart + explodeRange.distance, true);
|
||||||
if (tailRange)
|
if (tailRange)
|
||||||
{
|
{
|
||||||
cemu_assert_debug(tailRange->list_fixedRegRequirements.empty()); // we are not allowed to unassign fixed registers
|
cemu_assert_debug(tailRange->list_fixedRegRequirements.empty()); // we are not allowed to unassign fixed registers
|
||||||
@ -1005,7 +1007,7 @@ class RASpillStrategy_ExplodeRangeInter : public RASpillStrategy
|
|||||||
cemu_assert_debug(explodeRange.range == nullptr && explodeRange.distance == -1);
|
cemu_assert_debug(explodeRange.range == nullptr && explodeRange.distance == -1);
|
||||||
for (auto candidate : timeline.activeRanges)
|
for (auto candidate : timeline.activeRanges)
|
||||||
{
|
{
|
||||||
if (!candidate->interval2.ExtendsIntoNextSegment())
|
if (!candidate->interval.ExtendsIntoNextSegment())
|
||||||
continue;
|
continue;
|
||||||
// only select candidates that clash with current subrange
|
// only select candidates that clash with current subrange
|
||||||
if (candidate->GetPhysicalRegister() < 0 && candidate != currentRange)
|
if (candidate->GetPhysicalRegister() < 0 && candidate != currentRange)
|
||||||
@ -1037,7 +1039,7 @@ class RASpillStrategy_ExplodeRangeInter : public RASpillStrategy
|
|||||||
void Apply(ppcImlGenContext_t* ctx, IMLSegment* imlSegment, raLivenessRange* currentRange) override
|
void Apply(ppcImlGenContext_t* ctx, IMLSegment* imlSegment, raLivenessRange* currentRange) override
|
||||||
{
|
{
|
||||||
cemu_assert_debug(strategyCost != INT_MAX);
|
cemu_assert_debug(strategyCost != INT_MAX);
|
||||||
PPCRecRA_explodeRange(ctx, explodeRange.range);
|
IMLRA_ExplodeRangeCluster(ctx, explodeRange.range);
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@ -1056,16 +1058,16 @@ void IMLRA_FilterReservedFixedRegisterRequirementsForSegment(IMLRegisterAllocato
|
|||||||
if (seg->imlList.empty())
|
if (seg->imlList.empty())
|
||||||
return; // there can be no fixed register requirements if there are no instructions
|
return; // there can be no fixed register requirements if there are no instructions
|
||||||
|
|
||||||
raInstructionEdge firstPos = currentRange->interval2.start;
|
raInstructionEdge firstPos = currentRange->interval.start;
|
||||||
if (currentRange->interval2.start.ConnectsToPreviousSegment())
|
if (currentRange->interval.start.ConnectsToPreviousSegment())
|
||||||
firstPos.SetRaw(0);
|
firstPos.SetRaw(0);
|
||||||
else if (currentRange->interval2.start.ConnectsToNextSegment())
|
else if (currentRange->interval.start.ConnectsToNextSegment())
|
||||||
firstPos.Set(seg->imlList.size() - 1, false);
|
firstPos.Set(seg->imlList.size() - 1, false);
|
||||||
|
|
||||||
raInstructionEdge lastPos = currentRange->interval2.end;
|
raInstructionEdge lastPos = currentRange->interval.end;
|
||||||
if (currentRange->interval2.end.ConnectsToPreviousSegment())
|
if (currentRange->interval.end.ConnectsToPreviousSegment())
|
||||||
lastPos.SetRaw(0);
|
lastPos.SetRaw(0);
|
||||||
else if (currentRange->interval2.end.ConnectsToNextSegment())
|
else if (currentRange->interval.end.ConnectsToNextSegment())
|
||||||
lastPos.Set(seg->imlList.size() - 1, false);
|
lastPos.Set(seg->imlList.size() - 1, false);
|
||||||
cemu_assert_debug(firstPos <= lastPos);
|
cemu_assert_debug(firstPos <= lastPos);
|
||||||
|
|
||||||
@ -1093,7 +1095,7 @@ void IMLRA_FilterReservedFixedRegisterRequirementsForSegment(IMLRegisterAllocato
|
|||||||
void IMLRA_FilterReservedFixedRegisterRequirementsForCluster(IMLRegisterAllocatorContext& ctx, IMLSegment* imlSegment, raLivenessRange* currentRange, IMLPhysRegisterSet& candidatePhysRegSet)
|
void IMLRA_FilterReservedFixedRegisterRequirementsForCluster(IMLRegisterAllocatorContext& ctx, IMLSegment* imlSegment, raLivenessRange* currentRange, IMLPhysRegisterSet& candidatePhysRegSet)
|
||||||
{
|
{
|
||||||
cemu_assert_debug(currentRange->imlSegment == imlSegment);
|
cemu_assert_debug(currentRange->imlSegment == imlSegment);
|
||||||
if (currentRange->interval2.ExtendsPreviousSegment() || currentRange->interval2.ExtendsIntoNextSegment())
|
if (currentRange->interval.ExtendsPreviousSegment() || currentRange->interval.ExtendsIntoNextSegment())
|
||||||
{
|
{
|
||||||
auto clusterRanges = currentRange->GetAllSubrangesInCluster();
|
auto clusterRanges = currentRange->GetAllSubrangesInCluster();
|
||||||
for (auto& rangeIt : clusterRanges)
|
for (auto& rangeIt : clusterRanges)
|
||||||
@ -1128,7 +1130,7 @@ bool IMLRA_AssignSegmentRegisters(IMLRegisterAllocatorContext& ctx, ppcImlGenCon
|
|||||||
|
|
||||||
while (subrangeItr)
|
while (subrangeItr)
|
||||||
{
|
{
|
||||||
raInstructionEdge currentRangeStart = subrangeItr->interval2.start; // used to be currentIndex before refactor
|
raInstructionEdge currentRangeStart = subrangeItr->interval.start; // used to be currentIndex before refactor
|
||||||
PPCRecRA_debugValidateSubrange(subrangeItr);
|
PPCRecRA_debugValidateSubrange(subrangeItr);
|
||||||
|
|
||||||
livenessTimeline.ExpireRanges((currentRangeStart > lastInstructionEdge) ? lastInstructionEdge : currentRangeStart); // expire up to currentIndex (inclusive), but exclude infinite ranges
|
livenessTimeline.ExpireRanges((currentRangeStart > lastInstructionEdge) ? lastInstructionEdge : currentRangeStart); // expire up to currentIndex (inclusive), but exclude infinite ranges
|
||||||
@ -1204,7 +1206,7 @@ bool IMLRA_AssignSegmentRegisters(IMLRegisterAllocatorContext& ctx, ppcImlGenCon
|
|||||||
selectedStrategy = &newStrategy;
|
selectedStrategy = &newStrategy;
|
||||||
};
|
};
|
||||||
|
|
||||||
if (!subrangeItr->interval2.ExtendsIntoNextSegment())
|
if (!subrangeItr->interval.ExtendsIntoNextSegment())
|
||||||
{
|
{
|
||||||
// range ends in current segment, use local strategies
|
// range ends in current segment, use local strategies
|
||||||
// evaluate strategy: Cut hole into local subrange
|
// evaluate strategy: Cut hole into local subrange
|
||||||
@ -1232,9 +1234,9 @@ bool IMLRA_AssignSegmentRegisters(IMLRegisterAllocatorContext& ctx, ppcImlGenCon
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
// none of the evulated strategies can be applied, this should only happen if the segment extends into the next segment(s) for which we have no good strategy
|
// none of the evulated strategies can be applied, this should only happen if the segment extends into the next segment(s) for which we have no good strategy
|
||||||
cemu_assert_debug(subrangeItr->interval2.ExtendsPreviousSegment());
|
cemu_assert_debug(subrangeItr->interval.ExtendsPreviousSegment());
|
||||||
// alternative strategy if we have no other choice: explode current range
|
// alternative strategy if we have no other choice: explode current range
|
||||||
PPCRecRA_explodeRange(ppcImlGenContext, subrangeItr);
|
IMLRA_ExplodeRangeCluster(ppcImlGenContext, subrangeItr);
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -1336,7 +1338,7 @@ void IMLRA_ReshapeForRegisterAllocation(ppcImlGenContext_t* ppcImlGenContext)
|
|||||||
for (size_t s = 0; s < ppcImlGenContext->segmentList2.size(); s++)
|
for (size_t s = 0; s < ppcImlGenContext->segmentList2.size(); s++)
|
||||||
{
|
{
|
||||||
IMLSegment* imlSegment = ppcImlGenContext->segmentList2[s];
|
IMLSegment* imlSegment = ppcImlGenContext->segmentList2[s];
|
||||||
PPCRecRA_identifyLoop(ppcImlGenContext, imlSegment);
|
IMLRA_IdentifyLoop(ppcImlGenContext, imlSegment);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1411,7 +1413,7 @@ raLivenessRange* PPCRecRA_convertToMappedRanges(IMLRegisterAllocatorContext& ctx
|
|||||||
inclusiveEnd--; // subtract one, because usageEnd is exclusive, but the end value of the interval passed to createSubrange is inclusive
|
inclusiveEnd--; // subtract one, because usageEnd is exclusive, but the end value of the interval passed to createSubrange is inclusive
|
||||||
raInterval interval;
|
raInterval interval;
|
||||||
interval.SetInterval(abstractRange->usageStart, true, inclusiveEnd, true);
|
interval.SetInterval(abstractRange->usageStart, true, inclusiveEnd, true);
|
||||||
raLivenessRange* subrange = PPCRecRA_createSubrange2(ctx.deprGenContext, imlSegment, vGPR, name, interval.start, interval.end);
|
raLivenessRange* subrange = IMLRA_CreateRange(ctx.deprGenContext, imlSegment, vGPR, name, interval.start, interval.end);
|
||||||
// traverse forward
|
// traverse forward
|
||||||
if (abstractRange->usageEnd == RA_INTER_RANGE_END)
|
if (abstractRange->usageEnd == RA_INTER_RANGE_END)
|
||||||
{
|
{
|
||||||
@ -1422,7 +1424,7 @@ raLivenessRange* PPCRecRA_convertToMappedRanges(IMLRegisterAllocatorContext& ctx
|
|||||||
{
|
{
|
||||||
subrange->subrangeBranchTaken = PPCRecRA_convertToMappedRanges(ctx, imlSegment->nextSegmentBranchTaken, vGPR, name);
|
subrange->subrangeBranchTaken = PPCRecRA_convertToMappedRanges(ctx, imlSegment->nextSegmentBranchTaken, vGPR, name);
|
||||||
subrange->subrangeBranchTaken->previousRanges.push_back(subrange);
|
subrange->subrangeBranchTaken->previousRanges.push_back(subrange);
|
||||||
cemu_assert_debug(subrange->subrangeBranchTaken->interval2.ExtendsPreviousSegment());
|
cemu_assert_debug(subrange->subrangeBranchTaken->interval.ExtendsPreviousSegment());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (imlSegment->nextSegmentBranchNotTaken)
|
if (imlSegment->nextSegmentBranchNotTaken)
|
||||||
@ -1432,7 +1434,7 @@ raLivenessRange* PPCRecRA_convertToMappedRanges(IMLRegisterAllocatorContext& ctx
|
|||||||
{
|
{
|
||||||
subrange->subrangeBranchNotTaken = PPCRecRA_convertToMappedRanges(ctx, imlSegment->nextSegmentBranchNotTaken, vGPR, name);
|
subrange->subrangeBranchNotTaken = PPCRecRA_convertToMappedRanges(ctx, imlSegment->nextSegmentBranchNotTaken, vGPR, name);
|
||||||
subrange->subrangeBranchNotTaken->previousRanges.push_back(subrange);
|
subrange->subrangeBranchNotTaken->previousRanges.push_back(subrange);
|
||||||
cemu_assert_debug(subrange->subrangeBranchNotTaken->interval2.ExtendsPreviousSegment());
|
cemu_assert_debug(subrange->subrangeBranchNotTaken->interval.ExtendsPreviousSegment());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1771,7 +1773,7 @@ void IMLRA_AnalyzeSubrangeDataDependency(raLivenessRange* subrange)
|
|||||||
subrange->_noLoad = isOverwritten;
|
subrange->_noLoad = isOverwritten;
|
||||||
subrange->hasStore = isWritten;
|
subrange->hasStore = isWritten;
|
||||||
|
|
||||||
if (subrange->interval2.ExtendsPreviousSegment())
|
if (subrange->interval.ExtendsPreviousSegment())
|
||||||
subrange->_noLoad = true;
|
subrange->_noLoad = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1796,7 +1798,7 @@ void _findSubrangeWriteEndings(raLivenessRange* subrange, uint32 iterationIndex,
|
|||||||
if (subrange->hasStoreDelayed)
|
if (subrange->hasStoreDelayed)
|
||||||
return; // no need to traverse this subrange
|
return; // no need to traverse this subrange
|
||||||
IMLSegment* imlSegment = subrange->imlSegment;
|
IMLSegment* imlSegment = subrange->imlSegment;
|
||||||
if (!subrange->interval2.ExtendsIntoNextSegment())
|
if (!subrange->interval.ExtendsIntoNextSegment())
|
||||||
{
|
{
|
||||||
// ending segment
|
// ending segment
|
||||||
if (info->subrangeCount >= SUBRANGE_LIST_SIZE)
|
if (info->subrangeCount >= SUBRANGE_LIST_SIZE)
|
||||||
@ -1839,7 +1841,7 @@ void _findSubrangeWriteEndings(raLivenessRange* subrange, uint32 iterationIndex,
|
|||||||
|
|
||||||
static void IMLRA_AnalyzeRangeDataFlow(raLivenessRange* subrange)
|
static void IMLRA_AnalyzeRangeDataFlow(raLivenessRange* subrange)
|
||||||
{
|
{
|
||||||
if (!subrange->interval2.ExtendsIntoNextSegment())
|
if (!subrange->interval.ExtendsIntoNextSegment())
|
||||||
return;
|
return;
|
||||||
// analyze data flow across segments (if this segment has writes)
|
// analyze data flow across segments (if this segment has writes)
|
||||||
if (subrange->hasStore)
|
if (subrange->hasStore)
|
||||||
@ -1847,7 +1849,7 @@ static void IMLRA_AnalyzeRangeDataFlow(raLivenessRange* subrange)
|
|||||||
subrangeEndingInfo_t writeEndingInfo;
|
subrangeEndingInfo_t writeEndingInfo;
|
||||||
writeEndingInfo.subrangeCount = 0;
|
writeEndingInfo.subrangeCount = 0;
|
||||||
writeEndingInfo.hasUndefinedEndings = false;
|
writeEndingInfo.hasUndefinedEndings = false;
|
||||||
_findSubrangeWriteEndings(subrange, PPCRecRA_getNextIterationIndex(), 0, &writeEndingInfo);
|
_findSubrangeWriteEndings(subrange, IMLRA_GetNextIterationIndex(), 0, &writeEndingInfo);
|
||||||
if (writeEndingInfo.hasUndefinedEndings == false)
|
if (writeEndingInfo.hasUndefinedEndings == false)
|
||||||
{
|
{
|
||||||
// get cost of delaying store into endings
|
// get cost of delaying store into endings
|
||||||
@ -1924,7 +1926,7 @@ void IMLRA_RewriteRegisters(IMLRegisterAllocatorContext& ctx, IMLSegment* imlSeg
|
|||||||
{
|
{
|
||||||
currentEdge.Set(i, false); // set to instruction index on output edge
|
currentEdge.Set(i, false); // set to instruction index on output edge
|
||||||
// activate ranges which begin before or during this instruction
|
// activate ranges which begin before or during this instruction
|
||||||
while (currentRange && currentRange->interval2.start <= currentEdge)
|
while (currentRange && currentRange->interval.start <= currentEdge)
|
||||||
{
|
{
|
||||||
cemu_assert_debug(virtId2PhysReg.find(currentRange->GetVirtualRegister()) == virtId2PhysReg.end() || virtId2PhysReg[currentRange->GetVirtualRegister()] == currentRange->GetPhysicalRegister()); // check for register conflict
|
cemu_assert_debug(virtId2PhysReg.find(currentRange->GetVirtualRegister()) == virtId2PhysReg.end() || virtId2PhysReg[currentRange->GetVirtualRegister()] == currentRange->GetPhysicalRegister()); // check for register conflict
|
||||||
|
|
||||||
@ -1938,7 +1940,7 @@ void IMLRA_RewriteRegisters(IMLRegisterAllocatorContext& ctx, IMLSegment* imlSeg
|
|||||||
auto it = activeRanges.begin();
|
auto it = activeRanges.begin();
|
||||||
while (it != activeRanges.end())
|
while (it != activeRanges.end())
|
||||||
{
|
{
|
||||||
if ((*it)->interval2.end <= currentEdge)
|
if ((*it)->interval.end <= currentEdge)
|
||||||
{
|
{
|
||||||
virtId2PhysReg.erase((*it)->GetVirtualRegister());
|
virtId2PhysReg.erase((*it)->GetVirtualRegister());
|
||||||
it = activeRanges.erase(it);
|
it = activeRanges.erase(it);
|
||||||
@ -1981,7 +1983,7 @@ void IMLRA_GenerateSegmentMoveInstructions2(IMLRegisterAllocatorContext& ctx, IM
|
|||||||
{
|
{
|
||||||
if (!currentRange->_noLoad)
|
if (!currentRange->_noLoad)
|
||||||
{
|
{
|
||||||
cemu_assert_debug(currentRange->interval2.ExtendsIntoNextSegment());
|
cemu_assert_debug(currentRange->interval.ExtendsIntoNextSegment());
|
||||||
rebuiltInstructions.emplace_back().make_r_name(_MakeNativeReg(ctx.regIdToBaseFormat[currentRange->GetVirtualRegister()], currentRange->GetPhysicalRegister()), currentRange->GetName());
|
rebuiltInstructions.emplace_back().make_r_name(_MakeNativeReg(ctx.regIdToBaseFormat[currentRange->GetVirtualRegister()], currentRange->GetPhysicalRegister()), currentRange->GetName());
|
||||||
}
|
}
|
||||||
currentRange = currentRange->link_allSegmentRanges.next;
|
currentRange = currentRange->link_allSegmentRanges.next;
|
||||||
@ -2001,9 +2003,9 @@ void IMLRA_GenerateSegmentMoveInstructions2(IMLRegisterAllocatorContext& ctx, IM
|
|||||||
|
|
||||||
while (currentRange)
|
while (currentRange)
|
||||||
{
|
{
|
||||||
if (!currentRange->interval2.IsNextSegmentOnly() && currentRange->interval2.end > edge)
|
if (!currentRange->interval.IsNextSegmentOnly() && currentRange->interval.end > edge)
|
||||||
{
|
{
|
||||||
currentRange->interval2.SetEnd(edge);
|
currentRange->interval.SetEnd(edge);
|
||||||
}
|
}
|
||||||
currentRange = currentRange->link_allSegmentRanges.next;
|
currentRange = currentRange->link_allSegmentRanges.next;
|
||||||
}
|
}
|
||||||
@ -2025,9 +2027,8 @@ void IMLRA_GenerateSegmentMoveInstructions2(IMLRegisterAllocatorContext& ctx, IM
|
|||||||
boost::container::small_vector<raLivenessRange*, 64> activeRanges;
|
boost::container::small_vector<raLivenessRange*, 64> activeRanges;
|
||||||
// first we add all the ranges that extend from the previous segment, some of these will end immediately at the first instruction so we might need to store them early
|
// first we add all the ranges that extend from the previous segment, some of these will end immediately at the first instruction so we might need to store them early
|
||||||
raLivenessRange* currentRange = imlSegment->raInfo.linkedList_allSubranges;
|
raLivenessRange* currentRange = imlSegment->raInfo.linkedList_allSubranges;
|
||||||
|
|
||||||
// make all ranges active that start on RA_INTER_RANGE_START
|
// make all ranges active that start on RA_INTER_RANGE_START
|
||||||
while (currentRange && currentRange->interval2.start.ConnectsToPreviousSegment())
|
while (currentRange && currentRange->interval.start.ConnectsToPreviousSegment())
|
||||||
{
|
{
|
||||||
activeRanges.push_back(currentRange);
|
activeRanges.push_back(currentRange);
|
||||||
currentRange = currentRange->link_allSegmentRanges.next;
|
currentRange = currentRange->link_allSegmentRanges.next;
|
||||||
@ -2038,7 +2039,7 @@ void IMLRA_GenerateSegmentMoveInstructions2(IMLRegisterAllocatorContext& ctx, IM
|
|||||||
firstOutputEdge.Set(0, false);
|
firstOutputEdge.Set(0, false);
|
||||||
while (it != activeRanges.end())
|
while (it != activeRanges.end())
|
||||||
{
|
{
|
||||||
if ((*it)->interval2.end < firstOutputEdge)
|
if ((*it)->interval.end < firstOutputEdge)
|
||||||
{
|
{
|
||||||
raLivenessRange* storedRange = *it;
|
raLivenessRange* storedRange = *it;
|
||||||
if (storedRange->hasStore)
|
if (storedRange->hasStore)
|
||||||
@ -2055,7 +2056,7 @@ void IMLRA_GenerateSegmentMoveInstructions2(IMLRegisterAllocatorContext& ctx, IM
|
|||||||
raInstructionEdge curEdge;
|
raInstructionEdge curEdge;
|
||||||
// input edge
|
// input edge
|
||||||
curEdge.SetRaw(i * 2 + 1); // +1 to include ranges that start at the output of the instruction
|
curEdge.SetRaw(i * 2 + 1); // +1 to include ranges that start at the output of the instruction
|
||||||
while (currentRange && currentRange->interval2.start <= curEdge)
|
while (currentRange && currentRange->interval.start <= curEdge)
|
||||||
{
|
{
|
||||||
if (!currentRange->_noLoad)
|
if (!currentRange->_noLoad)
|
||||||
{
|
{
|
||||||
@ -2072,11 +2073,9 @@ void IMLRA_GenerateSegmentMoveInstructions2(IMLRegisterAllocatorContext& ctx, IM
|
|||||||
auto it = activeRanges.begin();
|
auto it = activeRanges.begin();
|
||||||
while (it != activeRanges.end())
|
while (it != activeRanges.end())
|
||||||
{
|
{
|
||||||
if ((*it)->interval2.end <= curEdge)
|
if ((*it)->interval.end <= curEdge)
|
||||||
{
|
{
|
||||||
// range expires
|
// range expires
|
||||||
// we cant erase it from virtId2PhysReg right away because a store might happen before the last use (the +1 thing above)
|
|
||||||
|
|
||||||
// todo - check hasStore
|
// todo - check hasStore
|
||||||
raLivenessRange* storedRange = *it;
|
raLivenessRange* storedRange = *it;
|
||||||
if (storedRange->hasStore)
|
if (storedRange->hasStore)
|
||||||
@ -2084,7 +2083,6 @@ void IMLRA_GenerateSegmentMoveInstructions2(IMLRegisterAllocatorContext& ctx, IM
|
|||||||
cemu_assert_debug(i != numInstructionsWithoutSuffix); // not allowed to emit after suffix
|
cemu_assert_debug(i != numInstructionsWithoutSuffix); // not allowed to emit after suffix
|
||||||
rebuiltInstructions.emplace_back().make_name_r(storedRange->GetName(), _MakeNativeReg(ctx.regIdToBaseFormat[storedRange->GetVirtualRegister()], storedRange->GetPhysicalRegister()));
|
rebuiltInstructions.emplace_back().make_name_r(storedRange->GetName(), _MakeNativeReg(ctx.regIdToBaseFormat[storedRange->GetVirtualRegister()], storedRange->GetPhysicalRegister()));
|
||||||
}
|
}
|
||||||
|
|
||||||
it = activeRanges.erase(it);
|
it = activeRanges.erase(it);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -2109,7 +2107,7 @@ void IMLRA_GenerateSegmentMoveInstructions2(IMLRegisterAllocatorContext& ctx, IM
|
|||||||
}
|
}
|
||||||
while (currentRange)
|
while (currentRange)
|
||||||
{
|
{
|
||||||
cemu_assert_debug(currentRange->interval2.IsNextSegmentOnly());
|
cemu_assert_debug(currentRange->interval.IsNextSegmentOnly());
|
||||||
cemu_assert_debug(!currentRange->_noLoad);
|
cemu_assert_debug(!currentRange->_noLoad);
|
||||||
rebuiltInstructions.emplace_back().make_r_name(_MakeNativeReg(ctx.regIdToBaseFormat[currentRange->GetVirtualRegister()], currentRange->GetPhysicalRegister()), currentRange->GetName());
|
rebuiltInstructions.emplace_back().make_r_name(_MakeNativeReg(ctx.regIdToBaseFormat[currentRange->GetVirtualRegister()], currentRange->GetPhysicalRegister()), currentRange->GetName());
|
||||||
currentRange = currentRange->link_allSegmentRanges.next;
|
currentRange = currentRange->link_allSegmentRanges.next;
|
||||||
|
@ -60,10 +60,10 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
// returns index of first available register. Do not call when HasAnyAvailable() == false
|
// returns index of first available register. Do not call when HasAnyAvailable() == false
|
||||||
uint32 GetFirstAvailableReg()
|
IMLPhysReg GetFirstAvailableReg()
|
||||||
{
|
{
|
||||||
cemu_assert_debug(m_regBitmask != 0);
|
cemu_assert_debug(m_regBitmask != 0);
|
||||||
uint32 regIndex = 0;
|
sint32 regIndex = 0;
|
||||||
auto tmp = m_regBitmask;
|
auto tmp = m_regBitmask;
|
||||||
while ((tmp & 0xFF) == 0)
|
while ((tmp & 0xFF) == 0)
|
||||||
{
|
{
|
||||||
@ -80,7 +80,7 @@ public:
|
|||||||
|
|
||||||
// returns index of next available register (search includes any register index >= startIndex)
|
// returns index of next available register (search includes any register index >= startIndex)
|
||||||
// returns -1 if there is no more register
|
// returns -1 if there is no more register
|
||||||
sint32 GetNextAvailableReg(sint32 startIndex) const
|
IMLPhysReg GetNextAvailableReg(sint32 startIndex) const
|
||||||
{
|
{
|
||||||
if (startIndex >= 64)
|
if (startIndex >= 64)
|
||||||
return -1;
|
return -1;
|
||||||
@ -111,7 +111,6 @@ private:
|
|||||||
uint64 m_regBitmask{ 0 };
|
uint64 m_regBitmask{ 0 };
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
struct IMLRegisterAllocatorParameters
|
struct IMLRegisterAllocatorParameters
|
||||||
{
|
{
|
||||||
inline IMLPhysRegisterSet& GetPhysRegPool(IMLRegFormat regFormat)
|
inline IMLPhysRegisterSet& GetPhysRegPool(IMLRegFormat regFormat)
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
#include "IMLRegisterAllocatorRanges.h"
|
#include "IMLRegisterAllocatorRanges.h"
|
||||||
#include "util/helpers/MemoryPool.h"
|
#include "util/helpers/MemoryPool.h"
|
||||||
|
|
||||||
uint32 PPCRecRA_getNextIterationIndex();
|
uint32 IMLRA_GetNextIterationIndex();
|
||||||
|
|
||||||
IMLRegID raLivenessRange::GetVirtualRegister() const
|
IMLRegID raLivenessRange::GetVirtualRegister() const
|
||||||
{
|
{
|
||||||
@ -20,12 +20,12 @@ IMLName raLivenessRange::GetName() const
|
|||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
|
|
||||||
void raLivenessRange::SetPhysicalRegister(sint32 physicalRegister)
|
void raLivenessRange::SetPhysicalRegister(IMLPhysReg physicalRegister)
|
||||||
{
|
{
|
||||||
this->physicalRegister = physicalRegister;
|
this->physicalRegister = physicalRegister;
|
||||||
}
|
}
|
||||||
|
|
||||||
void raLivenessRange::SetPhysicalRegisterForCluster(sint32 physicalRegister)
|
void raLivenessRange::SetPhysicalRegisterForCluster(IMLPhysReg physicalRegister)
|
||||||
{
|
{
|
||||||
auto clusterRanges = GetAllSubrangesInCluster();
|
auto clusterRanges = GetAllSubrangesInCluster();
|
||||||
for(auto& range : clusterRanges)
|
for(auto& range : clusterRanges)
|
||||||
@ -34,7 +34,7 @@ void raLivenessRange::SetPhysicalRegisterForCluster(sint32 physicalRegister)
|
|||||||
|
|
||||||
boost::container::small_vector<raLivenessRange*, 128> raLivenessRange::GetAllSubrangesInCluster()
|
boost::container::small_vector<raLivenessRange*, 128> raLivenessRange::GetAllSubrangesInCluster()
|
||||||
{
|
{
|
||||||
uint32 iterationIndex = PPCRecRA_getNextIterationIndex();
|
uint32 iterationIndex = IMLRA_GetNextIterationIndex();
|
||||||
boost::container::small_vector<raLivenessRange*, 128> subranges;
|
boost::container::small_vector<raLivenessRange*, 128> subranges;
|
||||||
subranges.push_back(this);
|
subranges.push_back(this);
|
||||||
this->lastIterationIndex = iterationIndex;
|
this->lastIterationIndex = iterationIndex;
|
||||||
@ -87,7 +87,7 @@ void raLivenessRange::GetAllowedRegistersExRecursive(raLivenessRange* range, uin
|
|||||||
|
|
||||||
bool raLivenessRange::GetAllowedRegistersEx(IMLPhysRegisterSet& allowedRegisters)
|
bool raLivenessRange::GetAllowedRegistersEx(IMLPhysRegisterSet& allowedRegisters)
|
||||||
{
|
{
|
||||||
uint32 iterationIndex = PPCRecRA_getNextIterationIndex();
|
uint32 iterationIndex = IMLRA_GetNextIterationIndex();
|
||||||
allowedRegisters.SetAllAvailable();
|
allowedRegisters.SetAllAvailable();
|
||||||
GetAllowedRegistersExRecursive(this, iterationIndex, allowedRegisters);
|
GetAllowedRegistersExRecursive(this, iterationIndex, allowedRegisters);
|
||||||
return !allowedRegisters.HasAllAvailable();
|
return !allowedRegisters.HasAllAvailable();
|
||||||
@ -96,7 +96,7 @@ bool raLivenessRange::GetAllowedRegistersEx(IMLPhysRegisterSet& allowedRegisters
|
|||||||
IMLPhysRegisterSet raLivenessRange::GetAllowedRegisters(IMLPhysRegisterSet regPool)
|
IMLPhysRegisterSet raLivenessRange::GetAllowedRegisters(IMLPhysRegisterSet regPool)
|
||||||
{
|
{
|
||||||
IMLPhysRegisterSet fixedRegRequirements = regPool;
|
IMLPhysRegisterSet fixedRegRequirements = regPool;
|
||||||
if(interval2.ExtendsPreviousSegment() || interval2.ExtendsIntoNextSegment())
|
if(interval.ExtendsPreviousSegment() || interval.ExtendsIntoNextSegment())
|
||||||
{
|
{
|
||||||
auto clusterRanges = GetAllSubrangesInCluster();
|
auto clusterRanges = GetAllSubrangesInCluster();
|
||||||
for(auto& subrange : clusterRanges)
|
for(auto& subrange : clusterRanges)
|
||||||
@ -203,7 +203,7 @@ void PPCRecRARange_removeLink_allSegmentRanges(raLivenessRange** root, raLivenes
|
|||||||
MemoryPoolPermanentObjects<raLivenessRange> memPool_livenessSubrange(4096);
|
MemoryPoolPermanentObjects<raLivenessRange> memPool_livenessSubrange(4096);
|
||||||
|
|
||||||
// startPosition and endPosition are inclusive
|
// startPosition and endPosition are inclusive
|
||||||
raLivenessRange* PPCRecRA_createSubrange2(ppcImlGenContext_t* ppcImlGenContext, IMLSegment* imlSegment, IMLRegID virtualRegister, IMLName name, raInstructionEdge startPosition, raInstructionEdge endPosition)
|
raLivenessRange* IMLRA_CreateRange(ppcImlGenContext_t* ppcImlGenContext, IMLSegment* imlSegment, IMLRegID virtualRegister, IMLName name, raInstructionEdge startPosition, raInstructionEdge endPosition)
|
||||||
{
|
{
|
||||||
raLivenessRange* range = memPool_livenessSubrange.acquireObj();
|
raLivenessRange* range = memPool_livenessSubrange.acquireObj();
|
||||||
range->previousRanges.clear();
|
range->previousRanges.clear();
|
||||||
@ -212,8 +212,8 @@ raLivenessRange* PPCRecRA_createSubrange2(ppcImlGenContext_t* ppcImlGenContext,
|
|||||||
range->imlSegment = imlSegment;
|
range->imlSegment = imlSegment;
|
||||||
|
|
||||||
cemu_assert_debug(startPosition <= endPosition);
|
cemu_assert_debug(startPosition <= endPosition);
|
||||||
range->interval2.start = startPosition;
|
range->interval.start = startPosition;
|
||||||
range->interval2.end = endPosition;
|
range->interval.end = endPosition;
|
||||||
|
|
||||||
// register mapping
|
// register mapping
|
||||||
range->virtualRegister = virtualRegister;
|
range->virtualRegister = virtualRegister;
|
||||||
@ -233,42 +233,42 @@ raLivenessRange* PPCRecRA_createSubrange2(ppcImlGenContext_t* ppcImlGenContext,
|
|||||||
return range;
|
return range;
|
||||||
}
|
}
|
||||||
|
|
||||||
void _unlinkSubrange(raLivenessRange* subrange)
|
void _unlinkSubrange(raLivenessRange* range)
|
||||||
{
|
{
|
||||||
IMLSegment* imlSegment = subrange->imlSegment;
|
IMLSegment* imlSegment = range->imlSegment;
|
||||||
PPCRecRARange_removeLink_perVirtualGPR(imlSegment->raInfo.linkedList_perVirtualRegister, subrange);
|
PPCRecRARange_removeLink_perVirtualGPR(imlSegment->raInfo.linkedList_perVirtualRegister, range);
|
||||||
PPCRecRARange_removeLink_allSegmentRanges(&imlSegment->raInfo.linkedList_allSubranges, subrange);
|
PPCRecRARange_removeLink_allSegmentRanges(&imlSegment->raInfo.linkedList_allSubranges, range);
|
||||||
// unlink reverse references
|
// unlink reverse references
|
||||||
if(subrange->subrangeBranchTaken)
|
if(range->subrangeBranchTaken)
|
||||||
subrange->subrangeBranchTaken->previousRanges.erase(std::find(subrange->subrangeBranchTaken->previousRanges.begin(), subrange->subrangeBranchTaken->previousRanges.end(), subrange));
|
range->subrangeBranchTaken->previousRanges.erase(std::find(range->subrangeBranchTaken->previousRanges.begin(), range->subrangeBranchTaken->previousRanges.end(), range));
|
||||||
if(subrange->subrangeBranchNotTaken)
|
if(range->subrangeBranchNotTaken)
|
||||||
subrange->subrangeBranchNotTaken->previousRanges.erase(std::find(subrange->subrangeBranchNotTaken->previousRanges.begin(), subrange->subrangeBranchNotTaken->previousRanges.end(), subrange));
|
range->subrangeBranchNotTaken->previousRanges.erase(std::find(range->subrangeBranchNotTaken->previousRanges.begin(), range->subrangeBranchNotTaken->previousRanges.end(), range));
|
||||||
subrange->subrangeBranchTaken = (raLivenessRange*)(uintptr_t)-1;
|
range->subrangeBranchTaken = (raLivenessRange*)(uintptr_t)-1;
|
||||||
subrange->subrangeBranchNotTaken = (raLivenessRange*)(uintptr_t)-1;
|
range->subrangeBranchNotTaken = (raLivenessRange*)(uintptr_t)-1;
|
||||||
// remove forward references
|
// remove forward references
|
||||||
for(auto& prev : subrange->previousRanges)
|
for(auto& prev : range->previousRanges)
|
||||||
{
|
{
|
||||||
if(prev->subrangeBranchTaken == subrange)
|
if(prev->subrangeBranchTaken == range)
|
||||||
prev->subrangeBranchTaken = nullptr;
|
prev->subrangeBranchTaken = nullptr;
|
||||||
if(prev->subrangeBranchNotTaken == subrange)
|
if(prev->subrangeBranchNotTaken == range)
|
||||||
prev->subrangeBranchNotTaken = nullptr;
|
prev->subrangeBranchNotTaken = nullptr;
|
||||||
}
|
}
|
||||||
subrange->previousRanges.clear();
|
range->previousRanges.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
void PPCRecRA_deleteSubrange(ppcImlGenContext_t* ppcImlGenContext, raLivenessRange* subrange)
|
void IMLRA_DeleteRange(ppcImlGenContext_t* ppcImlGenContext, raLivenessRange* range)
|
||||||
{
|
{
|
||||||
_unlinkSubrange(subrange);
|
_unlinkSubrange(range);
|
||||||
subrange->list_accessLocations.clear();
|
range->list_accessLocations.clear();
|
||||||
subrange->list_fixedRegRequirements.clear();
|
range->list_fixedRegRequirements.clear();
|
||||||
memPool_livenessSubrange.releaseObj(subrange);
|
memPool_livenessSubrange.releaseObj(range);
|
||||||
}
|
}
|
||||||
|
|
||||||
void PPCRecRA_deleteSubrangeCluster(ppcImlGenContext_t* ppcImlGenContext, raLivenessRange* subrange)
|
void IMLRA_DeleteRangeCluster(ppcImlGenContext_t* ppcImlGenContext, raLivenessRange* range)
|
||||||
{
|
{
|
||||||
auto clusterRanges = subrange->GetAllSubrangesInCluster();
|
auto clusterRanges = range->GetAllSubrangesInCluster();
|
||||||
for (auto& subrange : clusterRanges)
|
for (auto& subrange : clusterRanges)
|
||||||
PPCRecRA_deleteSubrange(ppcImlGenContext, subrange);
|
IMLRA_DeleteRange(ppcImlGenContext, subrange);
|
||||||
}
|
}
|
||||||
|
|
||||||
void IMLRA_DeleteAllRanges(ppcImlGenContext_t* ppcImlGenContext)
|
void IMLRA_DeleteAllRanges(ppcImlGenContext_t* ppcImlGenContext)
|
||||||
@ -277,13 +277,13 @@ void IMLRA_DeleteAllRanges(ppcImlGenContext_t* ppcImlGenContext)
|
|||||||
{
|
{
|
||||||
raLivenessRange* cur;
|
raLivenessRange* cur;
|
||||||
while(cur = seg->raInfo.linkedList_allSubranges)
|
while(cur = seg->raInfo.linkedList_allSubranges)
|
||||||
PPCRecRA_deleteSubrange(ppcImlGenContext, cur);
|
IMLRA_DeleteRange(ppcImlGenContext, cur);
|
||||||
seg->raInfo.linkedList_allSubranges = nullptr;
|
seg->raInfo.linkedList_allSubranges = nullptr;
|
||||||
seg->raInfo.linkedList_perVirtualRegister.clear();
|
seg->raInfo.linkedList_perVirtualRegister.clear();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void PPCRecRA_mergeSubranges(ppcImlGenContext_t* ppcImlGenContext, raLivenessRange* subrange, raLivenessRange* absorbedSubrange)
|
void IMLRA_MergeSubranges(ppcImlGenContext_t* ppcImlGenContext, raLivenessRange* subrange, raLivenessRange* absorbedSubrange)
|
||||||
{
|
{
|
||||||
#ifdef CEMU_DEBUG_ASSERT
|
#ifdef CEMU_DEBUG_ASSERT
|
||||||
PPCRecRA_debugValidateSubrange(subrange);
|
PPCRecRA_debugValidateSubrange(subrange);
|
||||||
@ -322,17 +322,17 @@ void PPCRecRA_mergeSubranges(ppcImlGenContext_t* ppcImlGenContext, raLivenessRan
|
|||||||
subrange->list_fixedRegRequirements.push_back(fixedReg);
|
subrange->list_fixedRegRequirements.push_back(fixedReg);
|
||||||
absorbedSubrange->list_fixedRegRequirements.clear();
|
absorbedSubrange->list_fixedRegRequirements.clear();
|
||||||
|
|
||||||
subrange->interval2.end = absorbedSubrange->interval2.end;
|
subrange->interval.end = absorbedSubrange->interval.end;
|
||||||
|
|
||||||
PPCRecRA_debugValidateSubrange(subrange);
|
PPCRecRA_debugValidateSubrange(subrange);
|
||||||
|
|
||||||
PPCRecRA_deleteSubrange(ppcImlGenContext, absorbedSubrange);
|
IMLRA_DeleteRange(ppcImlGenContext, absorbedSubrange);
|
||||||
}
|
}
|
||||||
|
|
||||||
// remove all inter-segment connections from the range cluster and split it into local ranges (also removes empty ranges)
|
// remove all inter-segment connections from the range cluster and split it into local ranges. Ranges are trimmed and if they have no access location they will be removed
|
||||||
void PPCRecRA_explodeRange(ppcImlGenContext_t* ppcImlGenContext, raLivenessRange* originRange)
|
void IMLRA_ExplodeRangeCluster(ppcImlGenContext_t* ppcImlGenContext, raLivenessRange* originRange)
|
||||||
{
|
{
|
||||||
cemu_assert_debug(originRange->interval2.ExtendsPreviousSegment() || originRange->interval2.ExtendsIntoNextSegment()); // only call this on ranges that span multiple segments
|
cemu_assert_debug(originRange->interval.ExtendsPreviousSegment() || originRange->interval.ExtendsIntoNextSegment()); // only call this on ranges that span multiple segments
|
||||||
auto clusterRanges = originRange->GetAllSubrangesInCluster();
|
auto clusterRanges = originRange->GetAllSubrangesInCluster();
|
||||||
for (auto& subrange : clusterRanges)
|
for (auto& subrange : clusterRanges)
|
||||||
{
|
{
|
||||||
@ -340,7 +340,7 @@ void PPCRecRA_explodeRange(ppcImlGenContext_t* ppcImlGenContext, raLivenessRange
|
|||||||
continue;
|
continue;
|
||||||
raInterval interval;
|
raInterval interval;
|
||||||
interval.SetInterval(subrange->list_accessLocations.front().pos, subrange->list_accessLocations.back().pos);
|
interval.SetInterval(subrange->list_accessLocations.front().pos, subrange->list_accessLocations.back().pos);
|
||||||
raLivenessRange* newSubrange = PPCRecRA_createSubrange2(ppcImlGenContext, subrange->imlSegment, subrange->GetVirtualRegister(), subrange->GetName(), interval.start, interval.end);
|
raLivenessRange* newSubrange = IMLRA_CreateRange(ppcImlGenContext, subrange->imlSegment, subrange->GetVirtualRegister(), subrange->GetName(), interval.start, interval.end);
|
||||||
// copy locations and fixed reg indices
|
// copy locations and fixed reg indices
|
||||||
newSubrange->list_accessLocations = subrange->list_accessLocations;
|
newSubrange->list_accessLocations = subrange->list_accessLocations;
|
||||||
newSubrange->list_fixedRegRequirements = subrange->list_fixedRegRequirements;
|
newSubrange->list_fixedRegRequirements = subrange->list_fixedRegRequirements;
|
||||||
@ -351,17 +351,17 @@ void PPCRecRA_explodeRange(ppcImlGenContext_t* ppcImlGenContext, raLivenessRange
|
|||||||
// validate
|
// validate
|
||||||
if(!newSubrange->list_accessLocations.empty())
|
if(!newSubrange->list_accessLocations.empty())
|
||||||
{
|
{
|
||||||
cemu_assert_debug(newSubrange->list_accessLocations.front().pos >= newSubrange->interval2.start);
|
cemu_assert_debug(newSubrange->list_accessLocations.front().pos >= newSubrange->interval.start);
|
||||||
cemu_assert_debug(newSubrange->list_accessLocations.back().pos <= newSubrange->interval2.end);
|
cemu_assert_debug(newSubrange->list_accessLocations.back().pos <= newSubrange->interval.end);
|
||||||
}
|
}
|
||||||
if(!newSubrange->list_fixedRegRequirements.empty())
|
if(!newSubrange->list_fixedRegRequirements.empty())
|
||||||
{
|
{
|
||||||
cemu_assert_debug(newSubrange->list_fixedRegRequirements.front().pos >= newSubrange->interval2.start); // fixed register requirements outside of the actual access range probably means there is a mistake in GetInstructionFixedRegisters()
|
cemu_assert_debug(newSubrange->list_fixedRegRequirements.front().pos >= newSubrange->interval.start); // fixed register requirements outside of the actual access range probably means there is a mistake in GetInstructionFixedRegisters()
|
||||||
cemu_assert_debug(newSubrange->list_fixedRegRequirements.back().pos <= newSubrange->interval2.end);
|
cemu_assert_debug(newSubrange->list_fixedRegRequirements.back().pos <= newSubrange->interval.end);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// remove subranges
|
// delete the original range cluster
|
||||||
PPCRecRA_deleteSubrangeCluster(ppcImlGenContext, originRange);
|
IMLRA_DeleteRangeCluster(ppcImlGenContext, originRange);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CEMU_DEBUG_ASSERT
|
#ifdef CEMU_DEBUG_ASSERT
|
||||||
@ -408,19 +408,19 @@ void IMLRA_TrimRangeToUse(raLivenessRange* range)
|
|||||||
if(range->list_accessLocations.empty())
|
if(range->list_accessLocations.empty())
|
||||||
{
|
{
|
||||||
// special case where we trim ranges extending from other segments to a single instruction edge
|
// special case where we trim ranges extending from other segments to a single instruction edge
|
||||||
cemu_assert_debug(!range->interval2.start.IsInstructionIndex() || !range->interval2.end.IsInstructionIndex());
|
cemu_assert_debug(!range->interval.start.IsInstructionIndex() || !range->interval.end.IsInstructionIndex());
|
||||||
if(range->interval2.start.IsInstructionIndex())
|
if(range->interval.start.IsInstructionIndex())
|
||||||
range->interval2.start = range->interval2.end;
|
range->interval.start = range->interval.end;
|
||||||
if(range->interval2.end.IsInstructionIndex())
|
if(range->interval.end.IsInstructionIndex())
|
||||||
range->interval2.end = range->interval2.start;
|
range->interval.end = range->interval.start;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// trim start and end
|
// trim start and end
|
||||||
raInterval prevInterval = range->interval2;
|
raInterval prevInterval = range->interval;
|
||||||
if(range->interval2.start.IsInstructionIndex())
|
if(range->interval.start.IsInstructionIndex())
|
||||||
range->interval2.start = range->list_accessLocations.front().pos;
|
range->interval.start = range->list_accessLocations.front().pos;
|
||||||
if(range->interval2.end.IsInstructionIndex())
|
if(range->interval.end.IsInstructionIndex())
|
||||||
range->interval2.end = range->list_accessLocations.back().pos;
|
range->interval.end = range->list_accessLocations.back().pos;
|
||||||
// extra checks
|
// extra checks
|
||||||
#ifdef CEMU_DEBUG_ASSERT
|
#ifdef CEMU_DEBUG_ASSERT
|
||||||
cemu_assert_debug(range->interval2.start <= range->interval2.end);
|
cemu_assert_debug(range->interval2.start <= range->interval2.end);
|
||||||
@ -438,22 +438,20 @@ void IMLRA_TrimRangeToUse(raLivenessRange* range)
|
|||||||
// tail -> a new subrange that ranges from splitIndex (inclusive) to the end of the original subrange
|
// tail -> a new subrange that ranges from splitIndex (inclusive) to the end of the original subrange
|
||||||
// if head has a physical register assigned it will not carry over to tail
|
// if head has a physical register assigned it will not carry over to tail
|
||||||
// The return value is the tail range
|
// The return value is the tail range
|
||||||
// If trimToHole is true, the end of the head subrange and the start of the tail subrange will be shrunk to fit the read/write locations within them
|
// If trimToUsage is true, the end of the head subrange and the start of the tail subrange will be shrunk to fit the read/write locations within. If there are no locations then the range will be deleted
|
||||||
// the range after the split point does not inherit the physical register
|
raLivenessRange* IMLRA_SplitRange(ppcImlGenContext_t* ppcImlGenContext, raLivenessRange*& subrange, raInstructionEdge splitPosition, bool trimToUsage)
|
||||||
// if trimToHole is true and any of the halfes is empty, it will be deleted
|
|
||||||
raLivenessRange* PPCRecRA_splitLocalSubrange2(ppcImlGenContext_t* ppcImlGenContext, raLivenessRange*& subrange, raInstructionEdge splitPosition, bool trimToHole)
|
|
||||||
{
|
{
|
||||||
cemu_assert_debug(splitPosition.IsInstructionIndex());
|
cemu_assert_debug(splitPosition.IsInstructionIndex());
|
||||||
cemu_assert_debug(!subrange->interval2.IsNextSegmentOnly() && !subrange->interval2.IsPreviousSegmentOnly());
|
cemu_assert_debug(!subrange->interval.IsNextSegmentOnly() && !subrange->interval.IsPreviousSegmentOnly());
|
||||||
cemu_assert_debug(subrange->interval2.ContainsEdge(splitPosition));
|
cemu_assert_debug(subrange->interval.ContainsEdge(splitPosition));
|
||||||
// determine new intervals
|
// determine new intervals
|
||||||
raInterval headInterval, tailInterval;
|
raInterval headInterval, tailInterval;
|
||||||
headInterval.SetInterval(subrange->interval2.start, splitPosition-1);
|
headInterval.SetInterval(subrange->interval.start, splitPosition-1);
|
||||||
tailInterval.SetInterval(splitPosition, subrange->interval2.end);
|
tailInterval.SetInterval(splitPosition, subrange->interval.end);
|
||||||
cemu_assert_debug(headInterval.start <= headInterval.end);
|
cemu_assert_debug(headInterval.start <= headInterval.end);
|
||||||
cemu_assert_debug(tailInterval.start <= tailInterval.end);
|
cemu_assert_debug(tailInterval.start <= tailInterval.end);
|
||||||
// create tail
|
// create tail
|
||||||
raLivenessRange* tailSubrange = PPCRecRA_createSubrange2(ppcImlGenContext, subrange->imlSegment, subrange->GetVirtualRegister(), subrange->GetName(), tailInterval.start, tailInterval.end);
|
raLivenessRange* tailSubrange = IMLRA_CreateRange(ppcImlGenContext, subrange->imlSegment, subrange->GetVirtualRegister(), subrange->GetName(), tailInterval.start, tailInterval.end);
|
||||||
tailSubrange->SetPhysicalRegister(subrange->GetPhysicalRegister());
|
tailSubrange->SetPhysicalRegister(subrange->GetPhysicalRegister());
|
||||||
// carry over branch targets and update reverse references
|
// carry over branch targets and update reverse references
|
||||||
tailSubrange->subrangeBranchTaken = subrange->subrangeBranchTaken;
|
tailSubrange->subrangeBranchTaken = subrange->subrangeBranchTaken;
|
||||||
@ -505,23 +503,23 @@ raLivenessRange* PPCRecRA_splitLocalSubrange2(ppcImlGenContext_t* ppcImlGenConte
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
// adjust intervals
|
// adjust intervals
|
||||||
subrange->interval2 = headInterval;
|
subrange->interval = headInterval;
|
||||||
tailSubrange->interval2 = tailInterval;
|
tailSubrange->interval = tailInterval;
|
||||||
// trim to hole
|
// trim to hole
|
||||||
if(trimToHole)
|
if(trimToUsage)
|
||||||
{
|
{
|
||||||
if(subrange->list_accessLocations.empty() && (subrange->interval2.start.IsInstructionIndex() && subrange->interval2.end.IsInstructionIndex()))
|
if(subrange->list_accessLocations.empty() && (subrange->interval.start.IsInstructionIndex() && subrange->interval.end.IsInstructionIndex()))
|
||||||
{
|
{
|
||||||
PPCRecRA_deleteSubrange(ppcImlGenContext, subrange);
|
IMLRA_DeleteRange(ppcImlGenContext, subrange);
|
||||||
subrange = nullptr;
|
subrange = nullptr;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
IMLRA_TrimRangeToUse(subrange);
|
IMLRA_TrimRangeToUse(subrange);
|
||||||
}
|
}
|
||||||
if(tailSubrange->list_accessLocations.empty() && (tailSubrange->interval2.start.IsInstructionIndex() && tailSubrange->interval2.end.IsInstructionIndex()))
|
if(tailSubrange->list_accessLocations.empty() && (tailSubrange->interval.start.IsInstructionIndex() && tailSubrange->interval.end.IsInstructionIndex()))
|
||||||
{
|
{
|
||||||
PPCRecRA_deleteSubrange(ppcImlGenContext, tailSubrange);
|
IMLRA_DeleteRange(ppcImlGenContext, tailSubrange);
|
||||||
tailSubrange = nullptr;
|
tailSubrange = nullptr;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -530,11 +528,11 @@ raLivenessRange* PPCRecRA_splitLocalSubrange2(ppcImlGenContext_t* ppcImlGenConte
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
// validation
|
// validation
|
||||||
cemu_assert_debug(!subrange || subrange->interval2.start <= subrange->interval2.end);
|
cemu_assert_debug(!subrange || subrange->interval.start <= subrange->interval.end);
|
||||||
cemu_assert_debug(!tailSubrange || tailSubrange->interval2.start <= tailSubrange->interval2.end);
|
cemu_assert_debug(!tailSubrange || tailSubrange->interval.start <= tailSubrange->interval.end);
|
||||||
cemu_assert_debug(!tailSubrange || tailSubrange->interval2.start >= splitPosition);
|
cemu_assert_debug(!tailSubrange || tailSubrange->interval.start >= splitPosition);
|
||||||
if (!trimToHole)
|
if (!trimToUsage)
|
||||||
cemu_assert_debug(!tailSubrange || tailSubrange->interval2.start == splitPosition);
|
cemu_assert_debug(!tailSubrange || tailSubrange->interval.start == splitPosition);
|
||||||
|
|
||||||
if(subrange)
|
if(subrange)
|
||||||
PPCRecRA_debugValidateSubrange(subrange);
|
PPCRecRA_debugValidateSubrange(subrange);
|
||||||
@ -560,8 +558,8 @@ sint32 IMLRA_CalculateAdditionalCostOfRangeExplode(raLivenessRange* subrange)
|
|||||||
if (subrange->list_accessLocations.empty())
|
if (subrange->list_accessLocations.empty())
|
||||||
continue; // this range would be deleted and thus has no cost
|
continue; // this range would be deleted and thus has no cost
|
||||||
sint32 segmentLoadStoreCost = IMLRA_GetSegmentReadWriteCost(subrange->imlSegment);
|
sint32 segmentLoadStoreCost = IMLRA_GetSegmentReadWriteCost(subrange->imlSegment);
|
||||||
bool hasAdditionalLoad = subrange->interval2.ExtendsPreviousSegment();
|
bool hasAdditionalLoad = subrange->interval.ExtendsPreviousSegment();
|
||||||
bool hasAdditionalStore = subrange->interval2.ExtendsIntoNextSegment();
|
bool hasAdditionalStore = subrange->interval.ExtendsIntoNextSegment();
|
||||||
if(hasAdditionalLoad && subrange->list_accessLocations.front().IsWrite()) // if written before read then a load isn't necessary
|
if(hasAdditionalLoad && subrange->list_accessLocations.front().IsWrite()) // if written before read then a load isn't necessary
|
||||||
{
|
{
|
||||||
cemu_assert_debug(!subrange->list_accessLocations.front().IsRead());
|
cemu_assert_debug(!subrange->list_accessLocations.front().IsRead());
|
||||||
|
@ -302,7 +302,7 @@ struct raFixedRegRequirement
|
|||||||
struct raLivenessRange
|
struct raLivenessRange
|
||||||
{
|
{
|
||||||
IMLSegment* imlSegment;
|
IMLSegment* imlSegment;
|
||||||
raInterval interval2;
|
raInterval interval;
|
||||||
|
|
||||||
// dirty state tracking
|
// dirty state tracking
|
||||||
bool _noLoad;
|
bool _noLoad;
|
||||||
@ -327,7 +327,7 @@ struct raLivenessRange
|
|||||||
IMLRegID virtualRegister;
|
IMLRegID virtualRegister;
|
||||||
IMLName name;
|
IMLName name;
|
||||||
// register allocator result
|
// register allocator result
|
||||||
sint32 physicalRegister;
|
IMLPhysReg physicalRegister;
|
||||||
|
|
||||||
boost::container::small_vector<raLivenessRange*, 128> GetAllSubrangesInCluster();
|
boost::container::small_vector<raLivenessRange*, 128> GetAllSubrangesInCluster();
|
||||||
bool GetAllowedRegistersEx(IMLPhysRegisterSet& allowedRegisters); // if the cluster has fixed register requirements in any instruction this returns the combined register mask. Otherwise returns false in which case allowedRegisters is left undefined
|
bool GetAllowedRegistersEx(IMLPhysRegisterSet& allowedRegisters); // if the cluster has fixed register requirements in any instruction this returns the combined register mask. Otherwise returns false in which case allowedRegisters is left undefined
|
||||||
@ -337,23 +337,23 @@ struct raLivenessRange
|
|||||||
sint32 GetPhysicalRegister() const;
|
sint32 GetPhysicalRegister() const;
|
||||||
bool HasPhysicalRegister() const { return physicalRegister >= 0; }
|
bool HasPhysicalRegister() const { return physicalRegister >= 0; }
|
||||||
IMLName GetName() const;
|
IMLName GetName() const;
|
||||||
void SetPhysicalRegister(sint32 physicalRegister);
|
void SetPhysicalRegister(IMLPhysReg physicalRegister);
|
||||||
void SetPhysicalRegisterForCluster(sint32 physicalRegister);
|
void SetPhysicalRegisterForCluster(IMLPhysReg physicalRegister);
|
||||||
void UnsetPhysicalRegister() { physicalRegister = -1; }
|
void UnsetPhysicalRegister() { physicalRegister = -1; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void GetAllowedRegistersExRecursive(raLivenessRange* range, uint32 iterationIndex, IMLPhysRegisterSet& allowedRegs);
|
void GetAllowedRegistersExRecursive(raLivenessRange* range, uint32 iterationIndex, IMLPhysRegisterSet& allowedRegs);
|
||||||
};
|
};
|
||||||
|
|
||||||
raLivenessRange* PPCRecRA_createSubrange2(ppcImlGenContext_t* ppcImlGenContext, IMLSegment* imlSegment, IMLRegID virtualRegister, IMLName name, raInstructionEdge startPosition, raInstructionEdge endPosition);
|
raLivenessRange* IMLRA_CreateRange(ppcImlGenContext_t* ppcImlGenContext, IMLSegment* imlSegment, IMLRegID virtualRegister, IMLName name, raInstructionEdge startPosition, raInstructionEdge endPosition);
|
||||||
void PPCRecRA_deleteSubrange(ppcImlGenContext_t* ppcImlGenContext, raLivenessRange* subrange);
|
void IMLRA_DeleteRange(ppcImlGenContext_t* ppcImlGenContext, raLivenessRange* subrange);
|
||||||
void IMLRA_DeleteAllRanges(ppcImlGenContext_t* ppcImlGenContext);
|
void IMLRA_DeleteAllRanges(ppcImlGenContext_t* ppcImlGenContext);
|
||||||
|
|
||||||
void PPCRecRA_explodeRange(ppcImlGenContext_t* ppcImlGenContext, raLivenessRange* originRange);
|
void IMLRA_ExplodeRangeCluster(ppcImlGenContext_t* ppcImlGenContext, raLivenessRange* originRange);
|
||||||
|
|
||||||
void PPCRecRA_mergeSubranges(ppcImlGenContext_t* ppcImlGenContext, raLivenessRange* subrange, raLivenessRange* absorbedSubrange);
|
void IMLRA_MergeSubranges(ppcImlGenContext_t* ppcImlGenContext, raLivenessRange* subrange, raLivenessRange* absorbedSubrange);
|
||||||
|
|
||||||
raLivenessRange* PPCRecRA_splitLocalSubrange2(ppcImlGenContext_t* ppcImlGenContext, raLivenessRange*& subrange, raInstructionEdge splitPosition, bool trimToHole = false);
|
raLivenessRange* IMLRA_SplitRange(ppcImlGenContext_t* ppcImlGenContext, raLivenessRange*& subrange, raInstructionEdge splitPosition, bool trimToUsage = false);
|
||||||
|
|
||||||
void PPCRecRA_debugValidateSubrange(raLivenessRange* subrange);
|
void PPCRecRA_debugValidateSubrange(raLivenessRange* subrange);
|
||||||
|
|
||||||
|
@ -19,6 +19,7 @@
|
|||||||
#include "util/highresolutiontimer/HighResolutionTimer.h"
|
#include "util/highresolutiontimer/HighResolutionTimer.h"
|
||||||
|
|
||||||
#define PPCREC_FORCE_SYNCHRONOUS_COMPILATION 0 // if 1, then function recompilation will block and execute on the thread that called PPCRecompiler_visitAddressNoBlock
|
#define PPCREC_FORCE_SYNCHRONOUS_COMPILATION 0 // if 1, then function recompilation will block and execute on the thread that called PPCRecompiler_visitAddressNoBlock
|
||||||
|
#define PPCREC_LOG_RECOMPILATION_RESULTS 0
|
||||||
|
|
||||||
struct PPCInvalidationRange
|
struct PPCInvalidationRange
|
||||||
{
|
{
|
||||||
@ -185,8 +186,10 @@ PPCRecFunction_t* PPCRecompiler_recompileFunction(PPCFunctionBoundaryTracker::PP
|
|||||||
ppcRecFunc->ppcAddress = range.startAddress;
|
ppcRecFunc->ppcAddress = range.startAddress;
|
||||||
ppcRecFunc->ppcSize = range.length;
|
ppcRecFunc->ppcSize = range.length;
|
||||||
|
|
||||||
|
#if PPCREC_LOG_RECOMPILATION_RESULTS
|
||||||
BenchmarkTimer bt;
|
BenchmarkTimer bt;
|
||||||
bt.Start();
|
bt.Start();
|
||||||
|
#endif
|
||||||
|
|
||||||
// generate intermediate code
|
// generate intermediate code
|
||||||
ppcImlGenContext_t ppcImlGenContext = { 0 };
|
ppcImlGenContext_t ppcImlGenContext = { 0 };
|
||||||
@ -217,18 +220,6 @@ PPCRecFunction_t* PPCRecompiler_recompileFunction(PPCFunctionBoundaryTracker::PP
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
// if (ppcRecFunc->ppcAddress == 0x2BDA9F4)
|
|
||||||
// {
|
|
||||||
// IMLDebug_Dump(&ppcImlGenContext);
|
|
||||||
// __debugbreak();
|
|
||||||
// }
|
|
||||||
|
|
||||||
// Functions for testing (botw):
|
|
||||||
// 3B4049C (large with switch case)
|
|
||||||
// 30BF118 (has a bndz copy loop + some float instructions at the end)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// emit x64 code
|
// emit x64 code
|
||||||
bool x64GenerationSuccess = PPCRecompiler_generateX64Code(ppcRecFunc, &ppcImlGenContext);
|
bool x64GenerationSuccess = PPCRecompiler_generateX64Code(ppcRecFunc, &ppcImlGenContext);
|
||||||
if (x64GenerationSuccess == false)
|
if (x64GenerationSuccess == false)
|
||||||
@ -258,18 +249,16 @@ PPCRecFunction_t* PPCRecompiler_recompileFunction(PPCFunctionBoundaryTracker::PP
|
|||||||
entryPointsOut.emplace_back(ppcEnterOffset, x64Offset);
|
entryPointsOut.emplace_back(ppcEnterOffset, x64Offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if PPCREC_LOG_RECOMPILATION_RESULTS
|
||||||
bt.Stop();
|
bt.Stop();
|
||||||
|
|
||||||
//cemuLog_log(LogType::Force, "[Recompiler] Successfully compiled {:08x} - {:08x} Segments: {} Entrypoints: {}", ppcRecFunc->ppcAddress, ppcRecFunc->ppcAddress + ppcRecFunc->ppcSize, ppcImlGenContext.segmentList2.size(), entryPointsOut.size());
|
|
||||||
|
|
||||||
uint32 codeHash = 0;
|
uint32 codeHash = 0;
|
||||||
for (uint32 i = 0; i < ppcRecFunc->x86Size; i++)
|
for (uint32 i = 0; i < ppcRecFunc->x86Size; i++)
|
||||||
{
|
{
|
||||||
codeHash = _rotr(codeHash, 3);
|
codeHash = _rotr(codeHash, 3);
|
||||||
codeHash += ((uint8*)ppcRecFunc->x86Code)[i];
|
codeHash += ((uint8*)ppcRecFunc->x86Code)[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
cemuLog_log(LogType::Force, "[Recompiler] PPC 0x{:08x} -> x64: 0x{:x} Took {:.4}ms | Size {:04x} CodeHash {:08x}", (uint32)ppcRecFunc->ppcAddress, (uint64)(uintptr_t)ppcRecFunc->x86Code, bt.GetElapsedMilliseconds(), ppcRecFunc->x86Size, codeHash);
|
cemuLog_log(LogType::Force, "[Recompiler] PPC 0x{:08x} -> x64: 0x{:x} Took {:.4}ms | Size {:04x} CodeHash {:08x}", (uint32)ppcRecFunc->ppcAddress, (uint64)(uintptr_t)ppcRecFunc->x86Code, bt.GetElapsedMilliseconds(), ppcRecFunc->x86Size, codeHash);
|
||||||
|
#endif
|
||||||
|
|
||||||
return ppcRecFunc;
|
return ppcRecFunc;
|
||||||
}
|
}
|
||||||
|
@ -3008,7 +3008,6 @@ void PPCRecompiler_SetSegmentsUncertainFlow(ppcImlGenContext_t& ppcImlGenContext
|
|||||||
break;
|
break;
|
||||||
case PPCREC_IML_MACRO_DEBUGBREAK:
|
case PPCREC_IML_MACRO_DEBUGBREAK:
|
||||||
case PPCREC_IML_MACRO_COUNT_CYCLES:
|
case PPCREC_IML_MACRO_COUNT_CYCLES:
|
||||||
case PPCREC_IML_MACRO_MFTB:
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
cemu_assert_unimplemented();
|
cemu_assert_unimplemented();
|
||||||
|
Loading…
x
Reference in New Issue
Block a user