mirror of https://github.com/cemu-project/Cemu.git
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();
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
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));
|
||||
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
|
||||
{
|
||||
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;
|
||||
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(".");
|
||||
else
|
||||
currentLineText.add("|");
|
||||
|
||||
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("* ");
|
||||
else
|
||||
currentLineText.add("| ");
|
||||
}
|
||||
else if (subrangeItr->interval2.ContainsInstructionIndexEx(offset))
|
||||
else if (subrangeItr->interval.ContainsInstructionIndexEx(offset))
|
||||
{
|
||||
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);
|
||||
}
|
||||
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)
|
||||
{
|
||||
strOutput.addFmt("MACRO COUNT_CYCLES cycles: {}", inst.op_macro.param);
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
#include "../PPCRecompiler.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 hasSideEffects = true;
|
||||
|
@ -160,7 +161,7 @@ void IMLInstruction::CheckRegisterUsage(IMLUsedRegisters* registersUsed) const
|
|||
}
|
||||
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
|
||||
}
|
||||
|
@ -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)
|
||||
{
|
||||
if (reg.IsInvalid())
|
||||
|
@ -502,26 +494,6 @@ IMLReg replaceRegisterIdMultiple(IMLReg reg, const std::unordered_map<IMLRegID,
|
|||
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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
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
|
||||
}
|
||||
|
@ -717,228 +689,3 @@ void IMLInstruction::RewriteGPR(const std::unordered_map<IMLRegID, IMLRegID>& tr
|
|||
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_COUNT_CYCLES, // decrease current remaining thread cycles by a certain amount
|
||||
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
|
||||
// debugging
|
||||
PPCREC_IML_MACRO_DEBUGBREAK, // throws a debugbreak
|
||||
|
@ -335,19 +334,6 @@ struct IMLUsedRegisters
|
|||
{
|
||||
IMLUsedRegisters() {};
|
||||
|
||||
union
|
||||
{
|
||||
struct
|
||||
{
|
||||
IMLReg readGPR1;
|
||||
IMLReg readGPR2;
|
||||
IMLReg readGPR3;
|
||||
IMLReg readGPR4;
|
||||
IMLReg writtenGPR1;
|
||||
IMLReg writtenGPR2;
|
||||
};
|
||||
};
|
||||
|
||||
bool IsWrittenByRegId(IMLRegID regId) const
|
||||
{
|
||||
if (writtenGPR1.IsValid() && writtenGPR1.GetRegID() == regId)
|
||||
|
@ -404,6 +390,12 @@ struct IMLUsedRegisters
|
|||
F(writtenGPR2, true);
|
||||
}
|
||||
|
||||
IMLReg readGPR1;
|
||||
IMLReg readGPR2;
|
||||
IMLReg readGPR3;
|
||||
IMLReg readGPR4;
|
||||
IMLReg writtenGPR1;
|
||||
IMLReg writtenGPR2;
|
||||
};
|
||||
|
||||
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_LEAVE ||
|
||||
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_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
|
||||
|
||||
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
|
||||
|
|
|
@ -192,7 +192,7 @@ static void GetInstructionFixedRegisters(IMLInstruction* instruction, IMLFixedRe
|
|||
}
|
||||
#endif
|
||||
|
||||
uint32 PPCRecRA_getNextIterationIndex()
|
||||
uint32 IMLRA_GetNextIterationIndex()
|
||||
{
|
||||
static uint32 recRACurrentIterationIndex = 0;
|
||||
recRACurrentIterationIndex++;
|
||||
|
@ -231,9 +231,9 @@ bool _detectLoop(IMLSegment* currentSegment, sint32 depth, uint32 iterationIndex
|
|||
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;
|
||||
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)
|
||||
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)
|
||||
if (imlSegment->nextSegmentBranchTaken && imlSegment->nextSegmentBranchTaken->momentaryIndex < imlSegment->momentaryIndex)
|
||||
{
|
||||
PPCRecRA_detectLoop(ppcImlGenContext, imlSegment);
|
||||
IMLRA_DetectLoop(ppcImlGenContext, imlSegment);
|
||||
}
|
||||
}
|
||||
|
||||
#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++)
|
||||
{
|
||||
|
@ -292,8 +292,8 @@ sint32 IMLRA_CountDistanceUntilFixedRegUsageInRange(IMLSegment* imlSegment, raLi
|
|||
return fixedReqEntry.pos.GetRaw() - startPosition.GetRaw();
|
||||
}
|
||||
}
|
||||
cemu_assert_debug(range->interval2.end.IsInstructionIndex());
|
||||
return range->interval2.end.GetRaw() - startPosition.GetRaw();
|
||||
cemu_assert_debug(range->interval.end.IsInstructionIndex());
|
||||
return range->interval.end.GetRaw() - startPosition.GetRaw();
|
||||
}
|
||||
|
||||
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;
|
||||
continue;
|
||||
}
|
||||
if (subrangeItr->interval2.ContainsEdge(startPosition))
|
||||
if (subrangeItr->interval.ContainsEdge(startPosition))
|
||||
return 0;
|
||||
if (subrangeItr->interval2.end < startPosition)
|
||||
if (subrangeItr->interval.end < startPosition)
|
||||
{
|
||||
subrangeItr = subrangeItr->link_allSegmentRanges.next;
|
||||
continue;
|
||||
}
|
||||
cemu_assert_debug(startPosition <= subrangeItr->interval2.start);
|
||||
sint32 currentDist = subrangeItr->interval2.start.GetRaw() - startPosition.GetRaw();
|
||||
cemu_assert_debug(startPosition <= subrangeItr->interval.start);
|
||||
sint32 currentDist = subrangeItr->interval.start.GetRaw() - startPosition.GetRaw();
|
||||
minDistance = std::min(minDistance, currentDist);
|
||||
subrangeItr = subrangeItr->link_allSegmentRanges.next;
|
||||
}
|
||||
|
@ -377,7 +377,7 @@ struct IMLRALivenessTimeline
|
|||
for (size_t f = 0; f < count; 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
|
||||
if (!expireUpTo.ConnectsToNextSegment() && (liverange->subrangeBranchTaken || liverange->subrangeBranchNotTaken))
|
||||
|
@ -443,7 +443,7 @@ void PPCRecRA_MaskOverlappingPhysRegForGlobalRange(raLivenessRange* range2, IMLP
|
|||
subrangeItr = subrangeItr->link_allSegmentRanges.next;
|
||||
continue;
|
||||
}
|
||||
if (subrange->interval2.IsOverlapping(subrangeItr->interval2))
|
||||
if (subrange->interval.IsOverlapping(subrangeItr->interval))
|
||||
{
|
||||
if (subrangeItr->GetPhysicalRegister() >= 0)
|
||||
physRegSet.SetReserved(subrangeItr->GetPhysicalRegister());
|
||||
|
@ -456,7 +456,7 @@ void PPCRecRA_MaskOverlappingPhysRegForGlobalRange(raLivenessRange* range2, IMLP
|
|||
|
||||
bool _livenessRangeStartCompare(raLivenessRange* lhs, raLivenessRange* rhs)
|
||||
{
|
||||
return lhs->interval2.start < rhs->interval2.start;
|
||||
return lhs->interval.start < rhs->interval.start;
|
||||
}
|
||||
|
||||
void _sortSegmentAllSubrangesLinkedList(IMLSegment* imlSegment)
|
||||
|
@ -467,8 +467,7 @@ void _sortSegmentAllSubrangesLinkedList(IMLSegment* imlSegment)
|
|||
raLivenessRange* subrangeItr = imlSegment->raInfo.linkedList_allSubranges;
|
||||
while (subrangeItr)
|
||||
{
|
||||
if (count >= 4096)
|
||||
assert_dbg();
|
||||
cemu_assert(count < 4096);
|
||||
subrangeList[count] = subrangeItr;
|
||||
count++;
|
||||
// next
|
||||
|
@ -526,6 +525,9 @@ raLivenessRange* IMLRA_GetSubrange(IMLSegment* imlSegment, IMLRegID regId)
|
|||
|
||||
struct raFixedRegRequirementWithVGPR
|
||||
{
|
||||
raFixedRegRequirementWithVGPR(raInstructionEdge pos, IMLPhysRegisterSet allowedReg, IMLRegID regId)
|
||||
: pos(pos), allowedReg(allowedReg), regId(regId) {}
|
||||
|
||||
raInstructionEdge pos;
|
||||
IMLPhysRegisterSet allowedReg;
|
||||
IMLRegID regId;
|
||||
|
@ -560,7 +562,7 @@ boost::container::small_vector<raLivenessRange*, 8> IMLRA_GetRangeWithFixedRegRe
|
|||
boost::container::small_vector<raLivenessRange*, 8> rangeList;
|
||||
for (raLivenessRange* currentRange = imlSegment->raInfo.linkedList_allSubranges; currentRange; currentRange = currentRange->link_allSegmentRanges.next)
|
||||
{
|
||||
if (!currentRange->interval2.ContainsEdge(pos))
|
||||
if (!currentRange->interval.ContainsEdge(pos))
|
||||
continue;
|
||||
IMLPhysRegisterSet 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)
|
||||
{
|
||||
// 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;)
|
||||
{
|
||||
IMLPhysRegisterSet allowedRegs;
|
||||
|
@ -588,10 +590,10 @@ void IMLRA_HandleFixedRegisters(ppcImlGenContext_t* ppcImlGenContext, IMLSegment
|
|||
currentRange = currentRange->link_allSegmentRanges.next;
|
||||
continue;
|
||||
}
|
||||
if (currentRange->interval2.ExtendsPreviousSegment() || currentRange->interval2.ExtendsIntoNextSegment())
|
||||
if (currentRange->interval.ExtendsPreviousSegment() || currentRange->interval.ExtendsIntoNextSegment())
|
||||
{
|
||||
raLivenessRange* nextRange = currentRange->link_allSegmentRanges.next;
|
||||
PPCRecRA_explodeRange(ppcImlGenContext, currentRange);
|
||||
IMLRA_ExplodeRangeCluster(ppcImlGenContext, currentRange);
|
||||
currentRange = nextRange;
|
||||
continue;
|
||||
}
|
||||
|
@ -638,9 +640,9 @@ void IMLRA_HandleFixedRegisters(ppcImlGenContext_t* ppcImlGenContext, IMLSegment
|
|||
|
||||
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();
|
||||
}
|
||||
|
||||
void DbgVerifyAllRanges(IMLRegisterAllocatorContext& ctx);
|
||||
static void DbgVerifyAllRanges(IMLRegisterAllocatorContext& ctx);
|
||||
|
||||
class RASpillStrategy
|
||||
{
|
||||
|
@ -737,8 +739,8 @@ class RASpillStrategy_LocalRangeHoleCutting : public RASpillStrategy
|
|||
|
||||
void Evaluate(IMLSegment* imlSegment, raLivenessRange* currentRange, const IMLRALivenessTimeline& timeline, const IMLPhysRegisterSet& allowedRegs)
|
||||
{
|
||||
raInstructionEdge currentRangeStart = currentRange->interval2.start;
|
||||
sint32 requiredSize2 = currentRange->interval2.GetPreciseDistance();
|
||||
raInstructionEdge currentRangeStart = currentRange->interval.start;
|
||||
sint32 requiredSize2 = currentRange->interval.GetPreciseDistance();
|
||||
cemu_assert_debug(localRangeHoleCutting.distance == -1);
|
||||
cemu_assert_debug(strategyCost == INT_MAX);
|
||||
if (!currentRangeStart.ConnectsToPreviousSegment())
|
||||
|
@ -746,7 +748,7 @@ class RASpillStrategy_LocalRangeHoleCutting : public RASpillStrategy
|
|||
cemu_assert_debug(currentRangeStart.GetRaw() >= 0);
|
||||
for (auto candidate : timeline.activeRanges)
|
||||
{
|
||||
if (candidate->interval2.ExtendsIntoNextSegment())
|
||||
if (candidate->interval.ExtendsIntoNextSegment())
|
||||
continue;
|
||||
// new checks (Oct 2024):
|
||||
if (candidate == currentRange)
|
||||
|
@ -756,7 +758,7 @@ class RASpillStrategy_LocalRangeHoleCutting : public RASpillStrategy
|
|||
if (!allowedRegs.IsAvailable(candidate->GetPhysicalRegister()))
|
||||
continue;
|
||||
|
||||
sint32 distance2 = PPCRecRA_countDistanceUntilNextUse2(candidate, currentRangeStart);
|
||||
sint32 distance2 = IMLRA_CountDistanceUntilNextUse(candidate, currentRangeStart);
|
||||
IMLRA_MakeSafeSplitDistance(imlSegment, currentRangeStart, distance2);
|
||||
if (distance2 < 2)
|
||||
continue;
|
||||
|
@ -785,18 +787,18 @@ class RASpillStrategy_LocalRangeHoleCutting : public RASpillStrategy
|
|||
void Apply(ppcImlGenContext_t* ctx, IMLSegment* imlSegment, raLivenessRange* currentRange) override
|
||||
{
|
||||
cemu_assert_debug(strategyCost != INT_MAX);
|
||||
sint32 requiredSize2 = currentRange->interval2.GetPreciseDistance();
|
||||
raInstructionEdge currentRangeStart = currentRange->interval2.start;
|
||||
sint32 requiredSize2 = currentRange->interval.GetPreciseDistance();
|
||||
raInstructionEdge currentRangeStart = currentRange->interval.start;
|
||||
|
||||
raInstructionEdge holeStartPosition = currentRangeStart;
|
||||
raInstructionEdge holeEndPosition = currentRangeStart + localRangeHoleCutting.distance;
|
||||
raLivenessRange* collisionRange = localRangeHoleCutting.largestHoleSubrange;
|
||||
|
||||
if (collisionRange->interval2.start < holeStartPosition)
|
||||
if (collisionRange->interval.start < holeStartPosition)
|
||||
{
|
||||
collisionRange = PPCRecRA_splitLocalSubrange2(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->interval2.start >= holeEndPosition); // also verify that the trimmed hole is actually big enough
|
||||
collisionRange = IMLRA_SplitRange(nullptr, collisionRange, holeStartPosition, true);
|
||||
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->interval.start >= holeEndPosition); // also verify that the trimmed hole is actually big enough
|
||||
}
|
||||
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
|
||||
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)
|
||||
{
|
||||
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
|
||||
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)
|
||||
{
|
||||
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);
|
||||
availableRegisterHole.distance = -1;
|
||||
availableRegisterHole.physRegister = -1;
|
||||
|
@ -888,9 +890,9 @@ class RASpillStrategy_AvailableRegisterHole : public RASpillStrategy
|
|||
void Apply(ppcImlGenContext_t* ctx, IMLSegment* imlSegment, raLivenessRange* currentRange) override
|
||||
{
|
||||
cemu_assert_debug(strategyCost != INT_MAX);
|
||||
raInstructionEdge currentRangeStart = currentRange->interval2.start;
|
||||
raInstructionEdge currentRangeStart = currentRange->interval.start;
|
||||
// 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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
raInstructionEdge currentRangeStart = currentRange->interval2.start;
|
||||
raInstructionEdge currentRangeStart = currentRange->interval.start;
|
||||
if (currentRangeStart.ConnectsToPreviousSegment())
|
||||
currentRangeStart.Set(0, true);
|
||||
sint32 requiredSize2 = currentRange->interval2.GetPreciseDistance();
|
||||
sint32 requiredSize2 = currentRange->interval.GetPreciseDistance();
|
||||
cemu_assert_debug(strategyCost == INT_MAX);
|
||||
explodeRange.range = nullptr;
|
||||
explodeRange.distance = -1;
|
||||
for (auto candidate : timeline.activeRanges)
|
||||
{
|
||||
if (!candidate->interval2.ExtendsIntoNextSegment())
|
||||
if (!candidate->interval.ExtendsIntoNextSegment())
|
||||
continue;
|
||||
// new checks (Oct 2024):
|
||||
if (candidate == currentRange)
|
||||
|
@ -937,7 +939,7 @@ class RASpillStrategy_ExplodeRange : public RASpillStrategy
|
|||
if (!allowedRegs.IsAvailable(candidate->GetPhysicalRegister()))
|
||||
continue;
|
||||
|
||||
sint32 distance = PPCRecRA_countDistanceUntilNextUse2(candidate, currentRangeStart);
|
||||
sint32 distance = IMLRA_CountDistanceUntilNextUse(candidate, currentRangeStart);
|
||||
IMLRA_MakeSafeSplitDistance(imlSegment, currentRangeStart, distance);
|
||||
if (distance < 2)
|
||||
continue;
|
||||
|
@ -961,16 +963,16 @@ class RASpillStrategy_ExplodeRange : public RASpillStrategy
|
|||
|
||||
void Apply(ppcImlGenContext_t* ctx, IMLSegment* imlSegment, raLivenessRange* currentRange) override
|
||||
{
|
||||
raInstructionEdge currentRangeStart = currentRange->interval2.start;
|
||||
raInstructionEdge currentRangeStart = currentRange->interval.start;
|
||||
if (currentRangeStart.ConnectsToPreviousSegment())
|
||||
currentRangeStart.Set(0, true);
|
||||
sint32 requiredSize2 = currentRange->interval2.GetPreciseDistance();
|
||||
sint32 requiredSize2 = currentRange->interval.GetPreciseDistance();
|
||||
// explode range
|
||||
PPCRecRA_explodeRange(nullptr, explodeRange.range);
|
||||
IMLRA_ExplodeRangeCluster(nullptr, explodeRange.range);
|
||||
// split current subrange if necessary
|
||||
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)
|
||||
{
|
||||
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);
|
||||
for (auto candidate : timeline.activeRanges)
|
||||
{
|
||||
if (!candidate->interval2.ExtendsIntoNextSegment())
|
||||
if (!candidate->interval.ExtendsIntoNextSegment())
|
||||
continue;
|
||||
// only select candidates that clash with current subrange
|
||||
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
|
||||
{
|
||||
cemu_assert_debug(strategyCost != INT_MAX);
|
||||
PPCRecRA_explodeRange(ctx, explodeRange.range);
|
||||
IMLRA_ExplodeRangeCluster(ctx, explodeRange.range);
|
||||
}
|
||||
|
||||
private:
|
||||
|
@ -1056,16 +1058,16 @@ void IMLRA_FilterReservedFixedRegisterRequirementsForSegment(IMLRegisterAllocato
|
|||
if (seg->imlList.empty())
|
||||
return; // there can be no fixed register requirements if there are no instructions
|
||||
|
||||
raInstructionEdge firstPos = currentRange->interval2.start;
|
||||
if (currentRange->interval2.start.ConnectsToPreviousSegment())
|
||||
raInstructionEdge firstPos = currentRange->interval.start;
|
||||
if (currentRange->interval.start.ConnectsToPreviousSegment())
|
||||
firstPos.SetRaw(0);
|
||||
else if (currentRange->interval2.start.ConnectsToNextSegment())
|
||||
else if (currentRange->interval.start.ConnectsToNextSegment())
|
||||
firstPos.Set(seg->imlList.size() - 1, false);
|
||||
|
||||
raInstructionEdge lastPos = currentRange->interval2.end;
|
||||
if (currentRange->interval2.end.ConnectsToPreviousSegment())
|
||||
raInstructionEdge lastPos = currentRange->interval.end;
|
||||
if (currentRange->interval.end.ConnectsToPreviousSegment())
|
||||
lastPos.SetRaw(0);
|
||||
else if (currentRange->interval2.end.ConnectsToNextSegment())
|
||||
else if (currentRange->interval.end.ConnectsToNextSegment())
|
||||
lastPos.Set(seg->imlList.size() - 1, false);
|
||||
cemu_assert_debug(firstPos <= lastPos);
|
||||
|
||||
|
@ -1093,7 +1095,7 @@ void IMLRA_FilterReservedFixedRegisterRequirementsForSegment(IMLRegisterAllocato
|
|||
void IMLRA_FilterReservedFixedRegisterRequirementsForCluster(IMLRegisterAllocatorContext& ctx, IMLSegment* imlSegment, raLivenessRange* currentRange, IMLPhysRegisterSet& candidatePhysRegSet)
|
||||
{
|
||||
cemu_assert_debug(currentRange->imlSegment == imlSegment);
|
||||
if (currentRange->interval2.ExtendsPreviousSegment() || currentRange->interval2.ExtendsIntoNextSegment())
|
||||
if (currentRange->interval.ExtendsPreviousSegment() || currentRange->interval.ExtendsIntoNextSegment())
|
||||
{
|
||||
auto clusterRanges = currentRange->GetAllSubrangesInCluster();
|
||||
for (auto& rangeIt : clusterRanges)
|
||||
|
@ -1128,7 +1130,7 @@ bool IMLRA_AssignSegmentRegisters(IMLRegisterAllocatorContext& ctx, ppcImlGenCon
|
|||
|
||||
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);
|
||||
|
||||
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;
|
||||
};
|
||||
|
||||
if (!subrangeItr->interval2.ExtendsIntoNextSegment())
|
||||
if (!subrangeItr->interval.ExtendsIntoNextSegment())
|
||||
{
|
||||
// range ends in current segment, use local strategies
|
||||
// evaluate strategy: Cut hole into local subrange
|
||||
|
@ -1232,9 +1234,9 @@ bool IMLRA_AssignSegmentRegisters(IMLRegisterAllocatorContext& ctx, ppcImlGenCon
|
|||
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
|
||||
cemu_assert_debug(subrangeItr->interval2.ExtendsPreviousSegment());
|
||||
cemu_assert_debug(subrangeItr->interval.ExtendsPreviousSegment());
|
||||
// alternative strategy if we have no other choice: explode current range
|
||||
PPCRecRA_explodeRange(ppcImlGenContext, subrangeItr);
|
||||
IMLRA_ExplodeRangeCluster(ppcImlGenContext, subrangeItr);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
@ -1336,7 +1338,7 @@ void IMLRA_ReshapeForRegisterAllocation(ppcImlGenContext_t* ppcImlGenContext)
|
|||
for (size_t s = 0; s < ppcImlGenContext->segmentList2.size(); 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
|
||||
raInterval interval;
|
||||
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
|
||||
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->previousRanges.push_back(subrange);
|
||||
cemu_assert_debug(subrange->subrangeBranchTaken->interval2.ExtendsPreviousSegment());
|
||||
cemu_assert_debug(subrange->subrangeBranchTaken->interval.ExtendsPreviousSegment());
|
||||
}
|
||||
}
|
||||
if (imlSegment->nextSegmentBranchNotTaken)
|
||||
|
@ -1432,7 +1434,7 @@ raLivenessRange* PPCRecRA_convertToMappedRanges(IMLRegisterAllocatorContext& ctx
|
|||
{
|
||||
subrange->subrangeBranchNotTaken = PPCRecRA_convertToMappedRanges(ctx, imlSegment->nextSegmentBranchNotTaken, vGPR, name);
|
||||
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->hasStore = isWritten;
|
||||
|
||||
if (subrange->interval2.ExtendsPreviousSegment())
|
||||
if (subrange->interval.ExtendsPreviousSegment())
|
||||
subrange->_noLoad = true;
|
||||
}
|
||||
|
||||
|
@ -1796,7 +1798,7 @@ void _findSubrangeWriteEndings(raLivenessRange* subrange, uint32 iterationIndex,
|
|||
if (subrange->hasStoreDelayed)
|
||||
return; // no need to traverse this subrange
|
||||
IMLSegment* imlSegment = subrange->imlSegment;
|
||||
if (!subrange->interval2.ExtendsIntoNextSegment())
|
||||
if (!subrange->interval.ExtendsIntoNextSegment())
|
||||
{
|
||||
// ending segment
|
||||
if (info->subrangeCount >= SUBRANGE_LIST_SIZE)
|
||||
|
@ -1839,7 +1841,7 @@ void _findSubrangeWriteEndings(raLivenessRange* subrange, uint32 iterationIndex,
|
|||
|
||||
static void IMLRA_AnalyzeRangeDataFlow(raLivenessRange* subrange)
|
||||
{
|
||||
if (!subrange->interval2.ExtendsIntoNextSegment())
|
||||
if (!subrange->interval.ExtendsIntoNextSegment())
|
||||
return;
|
||||
// analyze data flow across segments (if this segment has writes)
|
||||
if (subrange->hasStore)
|
||||
|
@ -1847,7 +1849,7 @@ static void IMLRA_AnalyzeRangeDataFlow(raLivenessRange* subrange)
|
|||
subrangeEndingInfo_t writeEndingInfo;
|
||||
writeEndingInfo.subrangeCount = 0;
|
||||
writeEndingInfo.hasUndefinedEndings = false;
|
||||
_findSubrangeWriteEndings(subrange, PPCRecRA_getNextIterationIndex(), 0, &writeEndingInfo);
|
||||
_findSubrangeWriteEndings(subrange, IMLRA_GetNextIterationIndex(), 0, &writeEndingInfo);
|
||||
if (writeEndingInfo.hasUndefinedEndings == false)
|
||||
{
|
||||
// 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
|
||||
// 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
|
||||
|
||||
|
@ -1938,7 +1940,7 @@ void IMLRA_RewriteRegisters(IMLRegisterAllocatorContext& ctx, IMLSegment* imlSeg
|
|||
auto it = activeRanges.begin();
|
||||
while (it != activeRanges.end())
|
||||
{
|
||||
if ((*it)->interval2.end <= currentEdge)
|
||||
if ((*it)->interval.end <= currentEdge)
|
||||
{
|
||||
virtId2PhysReg.erase((*it)->GetVirtualRegister());
|
||||
it = activeRanges.erase(it);
|
||||
|
@ -1981,7 +1983,7 @@ void IMLRA_GenerateSegmentMoveInstructions2(IMLRegisterAllocatorContext& ctx, IM
|
|||
{
|
||||
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());
|
||||
}
|
||||
currentRange = currentRange->link_allSegmentRanges.next;
|
||||
|
@ -2001,9 +2003,9 @@ void IMLRA_GenerateSegmentMoveInstructions2(IMLRegisterAllocatorContext& ctx, IM
|
|||
|
||||
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;
|
||||
}
|
||||
|
@ -2025,9 +2027,8 @@ void IMLRA_GenerateSegmentMoveInstructions2(IMLRegisterAllocatorContext& ctx, IM
|
|||
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
|
||||
raLivenessRange* currentRange = imlSegment->raInfo.linkedList_allSubranges;
|
||||
|
||||
// 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);
|
||||
currentRange = currentRange->link_allSegmentRanges.next;
|
||||
|
@ -2038,7 +2039,7 @@ void IMLRA_GenerateSegmentMoveInstructions2(IMLRegisterAllocatorContext& ctx, IM
|
|||
firstOutputEdge.Set(0, false);
|
||||
while (it != activeRanges.end())
|
||||
{
|
||||
if ((*it)->interval2.end < firstOutputEdge)
|
||||
if ((*it)->interval.end < firstOutputEdge)
|
||||
{
|
||||
raLivenessRange* storedRange = *it;
|
||||
if (storedRange->hasStore)
|
||||
|
@ -2055,7 +2056,7 @@ void IMLRA_GenerateSegmentMoveInstructions2(IMLRegisterAllocatorContext& ctx, IM
|
|||
raInstructionEdge curEdge;
|
||||
// input edge
|
||||
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)
|
||||
{
|
||||
|
@ -2072,11 +2073,9 @@ void IMLRA_GenerateSegmentMoveInstructions2(IMLRegisterAllocatorContext& ctx, IM
|
|||
auto it = activeRanges.begin();
|
||||
while (it != activeRanges.end())
|
||||
{
|
||||
if ((*it)->interval2.end <= curEdge)
|
||||
if ((*it)->interval.end <= curEdge)
|
||||
{
|
||||
// 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
|
||||
raLivenessRange* storedRange = *it;
|
||||
if (storedRange->hasStore)
|
||||
|
@ -2084,7 +2083,6 @@ void IMLRA_GenerateSegmentMoveInstructions2(IMLRegisterAllocatorContext& ctx, IM
|
|||
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()));
|
||||
}
|
||||
|
||||
it = activeRanges.erase(it);
|
||||
continue;
|
||||
}
|
||||
|
@ -2109,7 +2107,7 @@ void IMLRA_GenerateSegmentMoveInstructions2(IMLRegisterAllocatorContext& ctx, IM
|
|||
}
|
||||
while (currentRange)
|
||||
{
|
||||
cemu_assert_debug(currentRange->interval2.IsNextSegmentOnly());
|
||||
cemu_assert_debug(currentRange->interval.IsNextSegmentOnly());
|
||||
cemu_assert_debug(!currentRange->_noLoad);
|
||||
rebuiltInstructions.emplace_back().make_r_name(_MakeNativeReg(ctx.regIdToBaseFormat[currentRange->GetVirtualRegister()], currentRange->GetPhysicalRegister()), currentRange->GetName());
|
||||
currentRange = currentRange->link_allSegmentRanges.next;
|
||||
|
|
|
@ -60,10 +60,10 @@ public:
|
|||
}
|
||||
|
||||
// returns index of first available register. Do not call when HasAnyAvailable() == false
|
||||
uint32 GetFirstAvailableReg()
|
||||
IMLPhysReg GetFirstAvailableReg()
|
||||
{
|
||||
cemu_assert_debug(m_regBitmask != 0);
|
||||
uint32 regIndex = 0;
|
||||
sint32 regIndex = 0;
|
||||
auto tmp = m_regBitmask;
|
||||
while ((tmp & 0xFF) == 0)
|
||||
{
|
||||
|
@ -80,7 +80,7 @@ public:
|
|||
|
||||
// returns index of next available register (search includes any register index >= startIndex)
|
||||
// returns -1 if there is no more register
|
||||
sint32 GetNextAvailableReg(sint32 startIndex) const
|
||||
IMLPhysReg GetNextAvailableReg(sint32 startIndex) const
|
||||
{
|
||||
if (startIndex >= 64)
|
||||
return -1;
|
||||
|
@ -111,7 +111,6 @@ private:
|
|||
uint64 m_regBitmask{ 0 };
|
||||
};
|
||||
|
||||
|
||||
struct IMLRegisterAllocatorParameters
|
||||
{
|
||||
inline IMLPhysRegisterSet& GetPhysRegPool(IMLRegFormat regFormat)
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
#include "IMLRegisterAllocatorRanges.h"
|
||||
#include "util/helpers/MemoryPool.h"
|
||||
|
||||
uint32 PPCRecRA_getNextIterationIndex();
|
||||
uint32 IMLRA_GetNextIterationIndex();
|
||||
|
||||
IMLRegID raLivenessRange::GetVirtualRegister() const
|
||||
{
|
||||
|
@ -20,12 +20,12 @@ IMLName raLivenessRange::GetName() const
|
|||
return name;
|
||||
}
|
||||
|
||||
void raLivenessRange::SetPhysicalRegister(sint32 physicalRegister)
|
||||
void raLivenessRange::SetPhysicalRegister(IMLPhysReg physicalRegister)
|
||||
{
|
||||
this->physicalRegister = physicalRegister;
|
||||
}
|
||||
|
||||
void raLivenessRange::SetPhysicalRegisterForCluster(sint32 physicalRegister)
|
||||
void raLivenessRange::SetPhysicalRegisterForCluster(IMLPhysReg physicalRegister)
|
||||
{
|
||||
auto clusterRanges = GetAllSubrangesInCluster();
|
||||
for(auto& range : clusterRanges)
|
||||
|
@ -34,7 +34,7 @@ void raLivenessRange::SetPhysicalRegisterForCluster(sint32 physicalRegister)
|
|||
|
||||
boost::container::small_vector<raLivenessRange*, 128> raLivenessRange::GetAllSubrangesInCluster()
|
||||
{
|
||||
uint32 iterationIndex = PPCRecRA_getNextIterationIndex();
|
||||
uint32 iterationIndex = IMLRA_GetNextIterationIndex();
|
||||
boost::container::small_vector<raLivenessRange*, 128> subranges;
|
||||
subranges.push_back(this);
|
||||
this->lastIterationIndex = iterationIndex;
|
||||
|
@ -87,7 +87,7 @@ void raLivenessRange::GetAllowedRegistersExRecursive(raLivenessRange* range, uin
|
|||
|
||||
bool raLivenessRange::GetAllowedRegistersEx(IMLPhysRegisterSet& allowedRegisters)
|
||||
{
|
||||
uint32 iterationIndex = PPCRecRA_getNextIterationIndex();
|
||||
uint32 iterationIndex = IMLRA_GetNextIterationIndex();
|
||||
allowedRegisters.SetAllAvailable();
|
||||
GetAllowedRegistersExRecursive(this, iterationIndex, allowedRegisters);
|
||||
return !allowedRegisters.HasAllAvailable();
|
||||
|
@ -96,7 +96,7 @@ bool raLivenessRange::GetAllowedRegistersEx(IMLPhysRegisterSet& allowedRegisters
|
|||
IMLPhysRegisterSet raLivenessRange::GetAllowedRegisters(IMLPhysRegisterSet regPool)
|
||||
{
|
||||
IMLPhysRegisterSet fixedRegRequirements = regPool;
|
||||
if(interval2.ExtendsPreviousSegment() || interval2.ExtendsIntoNextSegment())
|
||||
if(interval.ExtendsPreviousSegment() || interval.ExtendsIntoNextSegment())
|
||||
{
|
||||
auto clusterRanges = GetAllSubrangesInCluster();
|
||||
for(auto& subrange : clusterRanges)
|
||||
|
@ -203,7 +203,7 @@ void PPCRecRARange_removeLink_allSegmentRanges(raLivenessRange** root, raLivenes
|
|||
MemoryPoolPermanentObjects<raLivenessRange> memPool_livenessSubrange(4096);
|
||||
|
||||
// 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();
|
||||
range->previousRanges.clear();
|
||||
|
@ -212,8 +212,8 @@ raLivenessRange* PPCRecRA_createSubrange2(ppcImlGenContext_t* ppcImlGenContext,
|
|||
range->imlSegment = imlSegment;
|
||||
|
||||
cemu_assert_debug(startPosition <= endPosition);
|
||||
range->interval2.start = startPosition;
|
||||
range->interval2.end = endPosition;
|
||||
range->interval.start = startPosition;
|
||||
range->interval.end = endPosition;
|
||||
|
||||
// register mapping
|
||||
range->virtualRegister = virtualRegister;
|
||||
|
@ -233,42 +233,42 @@ raLivenessRange* PPCRecRA_createSubrange2(ppcImlGenContext_t* ppcImlGenContext,
|
|||
return range;
|
||||
}
|
||||
|
||||
void _unlinkSubrange(raLivenessRange* subrange)
|
||||
void _unlinkSubrange(raLivenessRange* range)
|
||||
{
|
||||
IMLSegment* imlSegment = subrange->imlSegment;
|
||||
PPCRecRARange_removeLink_perVirtualGPR(imlSegment->raInfo.linkedList_perVirtualRegister, subrange);
|
||||
PPCRecRARange_removeLink_allSegmentRanges(&imlSegment->raInfo.linkedList_allSubranges, subrange);
|
||||
IMLSegment* imlSegment = range->imlSegment;
|
||||
PPCRecRARange_removeLink_perVirtualGPR(imlSegment->raInfo.linkedList_perVirtualRegister, range);
|
||||
PPCRecRARange_removeLink_allSegmentRanges(&imlSegment->raInfo.linkedList_allSubranges, range);
|
||||
// unlink reverse references
|
||||
if(subrange->subrangeBranchTaken)
|
||||
subrange->subrangeBranchTaken->previousRanges.erase(std::find(subrange->subrangeBranchTaken->previousRanges.begin(), subrange->subrangeBranchTaken->previousRanges.end(), subrange));
|
||||
if(subrange->subrangeBranchNotTaken)
|
||||
subrange->subrangeBranchNotTaken->previousRanges.erase(std::find(subrange->subrangeBranchNotTaken->previousRanges.begin(), subrange->subrangeBranchNotTaken->previousRanges.end(), subrange));
|
||||
subrange->subrangeBranchTaken = (raLivenessRange*)(uintptr_t)-1;
|
||||
subrange->subrangeBranchNotTaken = (raLivenessRange*)(uintptr_t)-1;
|
||||
if(range->subrangeBranchTaken)
|
||||
range->subrangeBranchTaken->previousRanges.erase(std::find(range->subrangeBranchTaken->previousRanges.begin(), range->subrangeBranchTaken->previousRanges.end(), range));
|
||||
if(range->subrangeBranchNotTaken)
|
||||
range->subrangeBranchNotTaken->previousRanges.erase(std::find(range->subrangeBranchNotTaken->previousRanges.begin(), range->subrangeBranchNotTaken->previousRanges.end(), range));
|
||||
range->subrangeBranchTaken = (raLivenessRange*)(uintptr_t)-1;
|
||||
range->subrangeBranchNotTaken = (raLivenessRange*)(uintptr_t)-1;
|
||||
// remove forward references
|
||||
for(auto& prev : subrange->previousRanges)
|
||||
for(auto& prev : range->previousRanges)
|
||||
{
|
||||
if(prev->subrangeBranchTaken == subrange)
|
||||
if(prev->subrangeBranchTaken == range)
|
||||
prev->subrangeBranchTaken = nullptr;
|
||||
if(prev->subrangeBranchNotTaken == subrange)
|
||||
if(prev->subrangeBranchNotTaken == range)
|
||||
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);
|
||||
subrange->list_accessLocations.clear();
|
||||
subrange->list_fixedRegRequirements.clear();
|
||||
memPool_livenessSubrange.releaseObj(subrange);
|
||||
_unlinkSubrange(range);
|
||||
range->list_accessLocations.clear();
|
||||
range->list_fixedRegRequirements.clear();
|
||||
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)
|
||||
PPCRecRA_deleteSubrange(ppcImlGenContext, subrange);
|
||||
IMLRA_DeleteRange(ppcImlGenContext, subrange);
|
||||
}
|
||||
|
||||
void IMLRA_DeleteAllRanges(ppcImlGenContext_t* ppcImlGenContext)
|
||||
|
@ -277,13 +277,13 @@ void IMLRA_DeleteAllRanges(ppcImlGenContext_t* ppcImlGenContext)
|
|||
{
|
||||
raLivenessRange* cur;
|
||||
while(cur = seg->raInfo.linkedList_allSubranges)
|
||||
PPCRecRA_deleteSubrange(ppcImlGenContext, cur);
|
||||
IMLRA_DeleteRange(ppcImlGenContext, cur);
|
||||
seg->raInfo.linkedList_allSubranges = nullptr;
|
||||
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
|
||||
PPCRecRA_debugValidateSubrange(subrange);
|
||||
|
@ -322,17 +322,17 @@ void PPCRecRA_mergeSubranges(ppcImlGenContext_t* ppcImlGenContext, raLivenessRan
|
|||
subrange->list_fixedRegRequirements.push_back(fixedReg);
|
||||
absorbedSubrange->list_fixedRegRequirements.clear();
|
||||
|
||||
subrange->interval2.end = absorbedSubrange->interval2.end;
|
||||
subrange->interval.end = absorbedSubrange->interval.end;
|
||||
|
||||
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)
|
||||
void PPCRecRA_explodeRange(ppcImlGenContext_t* ppcImlGenContext, raLivenessRange* originRange)
|
||||
// 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 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();
|
||||
for (auto& subrange : clusterRanges)
|
||||
{
|
||||
|
@ -340,7 +340,7 @@ void PPCRecRA_explodeRange(ppcImlGenContext_t* ppcImlGenContext, raLivenessRange
|
|||
continue;
|
||||
raInterval interval;
|
||||
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
|
||||
newSubrange->list_accessLocations = subrange->list_accessLocations;
|
||||
newSubrange->list_fixedRegRequirements = subrange->list_fixedRegRequirements;
|
||||
|
@ -351,17 +351,17 @@ void PPCRecRA_explodeRange(ppcImlGenContext_t* ppcImlGenContext, raLivenessRange
|
|||
// validate
|
||||
if(!newSubrange->list_accessLocations.empty())
|
||||
{
|
||||
cemu_assert_debug(newSubrange->list_accessLocations.front().pos >= newSubrange->interval2.start);
|
||||
cemu_assert_debug(newSubrange->list_accessLocations.back().pos <= newSubrange->interval2.end);
|
||||
cemu_assert_debug(newSubrange->list_accessLocations.front().pos >= newSubrange->interval.start);
|
||||
cemu_assert_debug(newSubrange->list_accessLocations.back().pos <= newSubrange->interval.end);
|
||||
}
|
||||
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.back().pos <= newSubrange->interval2.end);
|
||||
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->interval.end);
|
||||
}
|
||||
}
|
||||
// remove subranges
|
||||
PPCRecRA_deleteSubrangeCluster(ppcImlGenContext, originRange);
|
||||
// delete the original range cluster
|
||||
IMLRA_DeleteRangeCluster(ppcImlGenContext, originRange);
|
||||
}
|
||||
|
||||
#ifdef CEMU_DEBUG_ASSERT
|
||||
|
@ -408,19 +408,19 @@ void IMLRA_TrimRangeToUse(raLivenessRange* range)
|
|||
if(range->list_accessLocations.empty())
|
||||
{
|
||||
// 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());
|
||||
if(range->interval2.start.IsInstructionIndex())
|
||||
range->interval2.start = range->interval2.end;
|
||||
if(range->interval2.end.IsInstructionIndex())
|
||||
range->interval2.end = range->interval2.start;
|
||||
cemu_assert_debug(!range->interval.start.IsInstructionIndex() || !range->interval.end.IsInstructionIndex());
|
||||
if(range->interval.start.IsInstructionIndex())
|
||||
range->interval.start = range->interval.end;
|
||||
if(range->interval.end.IsInstructionIndex())
|
||||
range->interval.end = range->interval.start;
|
||||
return;
|
||||
}
|
||||
// trim start and end
|
||||
raInterval prevInterval = range->interval2;
|
||||
if(range->interval2.start.IsInstructionIndex())
|
||||
range->interval2.start = range->list_accessLocations.front().pos;
|
||||
if(range->interval2.end.IsInstructionIndex())
|
||||
range->interval2.end = range->list_accessLocations.back().pos;
|
||||
raInterval prevInterval = range->interval;
|
||||
if(range->interval.start.IsInstructionIndex())
|
||||
range->interval.start = range->list_accessLocations.front().pos;
|
||||
if(range->interval.end.IsInstructionIndex())
|
||||
range->interval.end = range->list_accessLocations.back().pos;
|
||||
// extra checks
|
||||
#ifdef CEMU_DEBUG_ASSERT
|
||||
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
|
||||
// if head has a physical register assigned it will not carry over to tail
|
||||
// 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
|
||||
// the range after the split point does not inherit the physical register
|
||||
// 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)
|
||||
// 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
|
||||
raLivenessRange* IMLRA_SplitRange(ppcImlGenContext_t* ppcImlGenContext, raLivenessRange*& subrange, raInstructionEdge splitPosition, bool trimToUsage)
|
||||
{
|
||||
cemu_assert_debug(splitPosition.IsInstructionIndex());
|
||||
cemu_assert_debug(!subrange->interval2.IsNextSegmentOnly() && !subrange->interval2.IsPreviousSegmentOnly());
|
||||
cemu_assert_debug(subrange->interval2.ContainsEdge(splitPosition));
|
||||
cemu_assert_debug(!subrange->interval.IsNextSegmentOnly() && !subrange->interval.IsPreviousSegmentOnly());
|
||||
cemu_assert_debug(subrange->interval.ContainsEdge(splitPosition));
|
||||
// determine new intervals
|
||||
raInterval headInterval, tailInterval;
|
||||
headInterval.SetInterval(subrange->interval2.start, splitPosition-1);
|
||||
tailInterval.SetInterval(splitPosition, subrange->interval2.end);
|
||||
headInterval.SetInterval(subrange->interval.start, splitPosition-1);
|
||||
tailInterval.SetInterval(splitPosition, subrange->interval.end);
|
||||
cemu_assert_debug(headInterval.start <= headInterval.end);
|
||||
cemu_assert_debug(tailInterval.start <= tailInterval.end);
|
||||
// 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());
|
||||
// carry over branch targets and update reverse references
|
||||
tailSubrange->subrangeBranchTaken = subrange->subrangeBranchTaken;
|
||||
|
@ -505,23 +503,23 @@ raLivenessRange* PPCRecRA_splitLocalSubrange2(ppcImlGenContext_t* ppcImlGenConte
|
|||
}
|
||||
}
|
||||
// adjust intervals
|
||||
subrange->interval2 = headInterval;
|
||||
tailSubrange->interval2 = tailInterval;
|
||||
subrange->interval = headInterval;
|
||||
tailSubrange->interval = tailInterval;
|
||||
// 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;
|
||||
}
|
||||
else
|
||||
{
|
||||
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;
|
||||
}
|
||||
else
|
||||
|
@ -530,11 +528,11 @@ raLivenessRange* PPCRecRA_splitLocalSubrange2(ppcImlGenContext_t* ppcImlGenConte
|
|||
}
|
||||
}
|
||||
// validation
|
||||
cemu_assert_debug(!subrange || subrange->interval2.start <= subrange->interval2.end);
|
||||
cemu_assert_debug(!tailSubrange || tailSubrange->interval2.start <= tailSubrange->interval2.end);
|
||||
cemu_assert_debug(!tailSubrange || tailSubrange->interval2.start >= splitPosition);
|
||||
if (!trimToHole)
|
||||
cemu_assert_debug(!tailSubrange || tailSubrange->interval2.start == splitPosition);
|
||||
cemu_assert_debug(!subrange || subrange->interval.start <= subrange->interval.end);
|
||||
cemu_assert_debug(!tailSubrange || tailSubrange->interval.start <= tailSubrange->interval.end);
|
||||
cemu_assert_debug(!tailSubrange || tailSubrange->interval.start >= splitPosition);
|
||||
if (!trimToUsage)
|
||||
cemu_assert_debug(!tailSubrange || tailSubrange->interval.start == splitPosition);
|
||||
|
||||
if(subrange)
|
||||
PPCRecRA_debugValidateSubrange(subrange);
|
||||
|
@ -560,8 +558,8 @@ sint32 IMLRA_CalculateAdditionalCostOfRangeExplode(raLivenessRange* subrange)
|
|||
if (subrange->list_accessLocations.empty())
|
||||
continue; // this range would be deleted and thus has no cost
|
||||
sint32 segmentLoadStoreCost = IMLRA_GetSegmentReadWriteCost(subrange->imlSegment);
|
||||
bool hasAdditionalLoad = subrange->interval2.ExtendsPreviousSegment();
|
||||
bool hasAdditionalStore = subrange->interval2.ExtendsIntoNextSegment();
|
||||
bool hasAdditionalLoad = subrange->interval.ExtendsPreviousSegment();
|
||||
bool hasAdditionalStore = subrange->interval.ExtendsIntoNextSegment();
|
||||
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());
|
||||
|
|
|
@ -302,7 +302,7 @@ struct raFixedRegRequirement
|
|||
struct raLivenessRange
|
||||
{
|
||||
IMLSegment* imlSegment;
|
||||
raInterval interval2;
|
||||
raInterval interval;
|
||||
|
||||
// dirty state tracking
|
||||
bool _noLoad;
|
||||
|
@ -327,7 +327,7 @@ struct raLivenessRange
|
|||
IMLRegID virtualRegister;
|
||||
IMLName name;
|
||||
// register allocator result
|
||||
sint32 physicalRegister;
|
||||
IMLPhysReg physicalRegister;
|
||||
|
||||
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
|
||||
|
@ -337,23 +337,23 @@ struct raLivenessRange
|
|||
sint32 GetPhysicalRegister() const;
|
||||
bool HasPhysicalRegister() const { return physicalRegister >= 0; }
|
||||
IMLName GetName() const;
|
||||
void SetPhysicalRegister(sint32 physicalRegister);
|
||||
void SetPhysicalRegisterForCluster(sint32 physicalRegister);
|
||||
void SetPhysicalRegister(IMLPhysReg physicalRegister);
|
||||
void SetPhysicalRegisterForCluster(IMLPhysReg physicalRegister);
|
||||
void UnsetPhysicalRegister() { physicalRegister = -1; }
|
||||
|
||||
private:
|
||||
void GetAllowedRegistersExRecursive(raLivenessRange* range, uint32 iterationIndex, IMLPhysRegisterSet& allowedRegs);
|
||||
};
|
||||
|
||||
raLivenessRange* PPCRecRA_createSubrange2(ppcImlGenContext_t* ppcImlGenContext, IMLSegment* imlSegment, IMLRegID virtualRegister, IMLName name, raInstructionEdge startPosition, raInstructionEdge endPosition);
|
||||
void PPCRecRA_deleteSubrange(ppcImlGenContext_t* ppcImlGenContext, raLivenessRange* subrange);
|
||||
raLivenessRange* IMLRA_CreateRange(ppcImlGenContext_t* ppcImlGenContext, IMLSegment* imlSegment, IMLRegID virtualRegister, IMLName name, raInstructionEdge startPosition, raInstructionEdge endPosition);
|
||||
void IMLRA_DeleteRange(ppcImlGenContext_t* ppcImlGenContext, raLivenessRange* subrange);
|
||||
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);
|
||||
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
#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_LOG_RECOMPILATION_RESULTS 0
|
||||
|
||||
struct PPCInvalidationRange
|
||||
{
|
||||
|
@ -185,8 +186,10 @@ PPCRecFunction_t* PPCRecompiler_recompileFunction(PPCFunctionBoundaryTracker::PP
|
|||
ppcRecFunc->ppcAddress = range.startAddress;
|
||||
ppcRecFunc->ppcSize = range.length;
|
||||
|
||||
#if PPCREC_LOG_RECOMPILATION_RESULTS
|
||||
BenchmarkTimer bt;
|
||||
bt.Start();
|
||||
#endif
|
||||
|
||||
// generate intermediate code
|
||||
ppcImlGenContext_t ppcImlGenContext = { 0 };
|
||||
|
@ -217,18 +220,6 @@ PPCRecFunction_t* PPCRecompiler_recompileFunction(PPCFunctionBoundaryTracker::PP
|
|||
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
|
||||
bool x64GenerationSuccess = PPCRecompiler_generateX64Code(ppcRecFunc, &ppcImlGenContext);
|
||||
if (x64GenerationSuccess == false)
|
||||
|
@ -258,18 +249,16 @@ PPCRecFunction_t* PPCRecompiler_recompileFunction(PPCFunctionBoundaryTracker::PP
|
|||
entryPointsOut.emplace_back(ppcEnterOffset, x64Offset);
|
||||
}
|
||||
|
||||
#if PPCREC_LOG_RECOMPILATION_RESULTS
|
||||
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;
|
||||
for (uint32 i = 0; i < ppcRecFunc->x86Size; i++)
|
||||
{
|
||||
codeHash = _rotr(codeHash, 3);
|
||||
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);
|
||||
#endif
|
||||
|
||||
return ppcRecFunc;
|
||||
}
|
||||
|
|
|
@ -3008,7 +3008,6 @@ void PPCRecompiler_SetSegmentsUncertainFlow(ppcImlGenContext_t& ppcImlGenContext
|
|||
break;
|
||||
case PPCREC_IML_MACRO_DEBUGBREAK:
|
||||
case PPCREC_IML_MACRO_COUNT_CYCLES:
|
||||
case PPCREC_IML_MACRO_MFTB:
|
||||
break;
|
||||
default:
|
||||
cemu_assert_unimplemented();
|
||||
|
|
Loading…
Reference in New Issue