mirror of
https://github.com/izzy2lost/WeeU.git
synced 2026-07-06 00:19:59 -07:00
PPCRec: FPRs now use the shared register allocator
This commit is contained in:
@@ -11,13 +11,26 @@
|
||||
static x86Assembler64::GPR32 _reg32(IMLReg physReg)
|
||||
{
|
||||
cemu_assert_debug(physReg.GetRegFormat() == IMLRegFormat::I32);
|
||||
return (x86Assembler64::GPR32)physReg.GetRegID();
|
||||
IMLRegID regId = physReg.GetRegID();
|
||||
cemu_assert_debug(regId < 16);
|
||||
return (x86Assembler64::GPR32)regId;
|
||||
}
|
||||
|
||||
static uint32 _reg64(IMLReg physReg)
|
||||
{
|
||||
cemu_assert_debug(physReg.GetRegFormat() == IMLRegFormat::I64);
|
||||
return physReg.GetRegID();
|
||||
IMLRegID regId = physReg.GetRegID();
|
||||
cemu_assert_debug(regId < 16);
|
||||
return regId;
|
||||
}
|
||||
|
||||
uint32 _regF64(IMLReg physReg)
|
||||
{
|
||||
cemu_assert_debug(physReg.GetRegFormat() == IMLRegFormat::F64);
|
||||
IMLRegID regId = physReg.GetRegID();
|
||||
cemu_assert_debug(regId >= IMLArchX86::PHYSREG_FPR_BASE && regId < IMLArchX86::PHYSREG_FPR_BASE+16);
|
||||
regId -= IMLArchX86::PHYSREG_FPR_BASE;
|
||||
return regId;
|
||||
}
|
||||
|
||||
static x86Assembler64::GPR8_REX _reg8(IMLReg physReg)
|
||||
@@ -1233,111 +1246,192 @@ bool PPCRecompilerX64Gen_imlInstruction_conditionalJumpCycleCheck(PPCRecFunction
|
||||
void PPCRecompilerX64Gen_imlInstruction_r_name(PPCRecFunction_t* PPCRecFunction, ppcImlGenContext_t* ppcImlGenContext, x64GenContext_t* x64GenContext, IMLInstruction* imlInstruction)
|
||||
{
|
||||
uint32 name = imlInstruction->op_r_name.name;
|
||||
auto regR = _reg64(imlInstruction->op_r_name.regR);
|
||||
|
||||
if( name >= PPCREC_NAME_R0 && name < PPCREC_NAME_R0+32 )
|
||||
if (imlInstruction->op_r_name.regR.GetBaseFormat() == IMLRegFormat::I64)
|
||||
{
|
||||
x64Emit_mov_reg64_mem32(x64GenContext, regR, X86_REG_RSP, offsetof(PPCInterpreter_t, gpr)+sizeof(uint32)*(name-PPCREC_NAME_R0));
|
||||
}
|
||||
else if( name >= PPCREC_NAME_SPR0 && name < PPCREC_NAME_SPR0+999 )
|
||||
{
|
||||
sint32 sprIndex = (name - PPCREC_NAME_SPR0);
|
||||
if (sprIndex == SPR_LR)
|
||||
x64Emit_mov_reg64_mem32(x64GenContext, regR, X86_REG_RSP, offsetof(PPCInterpreter_t, spr.LR));
|
||||
else if (sprIndex == SPR_CTR)
|
||||
x64Emit_mov_reg64_mem32(x64GenContext, regR, X86_REG_RSP, offsetof(PPCInterpreter_t, spr.CTR));
|
||||
else if (sprIndex == SPR_XER)
|
||||
x64Emit_mov_reg64_mem32(x64GenContext, regR, X86_REG_RSP, offsetof(PPCInterpreter_t, spr.XER));
|
||||
else if (sprIndex >= SPR_UGQR0 && sprIndex <= SPR_UGQR7)
|
||||
auto regR = _reg64(imlInstruction->op_r_name.regR);
|
||||
if (name >= PPCREC_NAME_R0 && name < PPCREC_NAME_R0 + 32)
|
||||
{
|
||||
sint32 memOffset = offsetof(PPCInterpreter_t, spr.UGQR) + sizeof(PPCInterpreter_t::spr.UGQR[0]) * (sprIndex - SPR_UGQR0);
|
||||
x64Emit_mov_reg64_mem32(x64GenContext, regR, X86_REG_RSP, memOffset);
|
||||
x64Emit_mov_reg64_mem32(x64GenContext, regR, X86_REG_RSP, offsetof(PPCInterpreter_t, gpr) + sizeof(uint32) * (name - PPCREC_NAME_R0));
|
||||
}
|
||||
else if (name >= PPCREC_NAME_SPR0 && name < PPCREC_NAME_SPR0 + 999)
|
||||
{
|
||||
sint32 sprIndex = (name - PPCREC_NAME_SPR0);
|
||||
if (sprIndex == SPR_LR)
|
||||
x64Emit_mov_reg64_mem32(x64GenContext, regR, X86_REG_RSP, offsetof(PPCInterpreter_t, spr.LR));
|
||||
else if (sprIndex == SPR_CTR)
|
||||
x64Emit_mov_reg64_mem32(x64GenContext, regR, X86_REG_RSP, offsetof(PPCInterpreter_t, spr.CTR));
|
||||
else if (sprIndex == SPR_XER)
|
||||
x64Emit_mov_reg64_mem32(x64GenContext, regR, X86_REG_RSP, offsetof(PPCInterpreter_t, spr.XER));
|
||||
else if (sprIndex >= SPR_UGQR0 && sprIndex <= SPR_UGQR7)
|
||||
{
|
||||
sint32 memOffset = offsetof(PPCInterpreter_t, spr.UGQR) + sizeof(PPCInterpreter_t::spr.UGQR[0]) * (sprIndex - SPR_UGQR0);
|
||||
x64Emit_mov_reg64_mem32(x64GenContext, regR, X86_REG_RSP, memOffset);
|
||||
}
|
||||
else
|
||||
assert_dbg();
|
||||
}
|
||||
else if (name >= PPCREC_NAME_TEMPORARY && name < PPCREC_NAME_TEMPORARY + 4)
|
||||
{
|
||||
x64Emit_mov_reg64_mem32(x64GenContext, regR, X86_REG_RSP, offsetof(PPCInterpreter_t, temporaryGPR_reg) + sizeof(uint32) * (name - PPCREC_NAME_TEMPORARY));
|
||||
}
|
||||
else if (name == PPCREC_NAME_XER_CA)
|
||||
{
|
||||
x64Emit_movZX_reg64_mem8(x64GenContext, regR, X86_REG_RSP, offsetof(PPCInterpreter_t, xer_ca));
|
||||
}
|
||||
else if (name == PPCREC_NAME_XER_SO)
|
||||
{
|
||||
x64Emit_movZX_reg64_mem8(x64GenContext, regR, X86_REG_RSP, offsetof(PPCInterpreter_t, xer_so));
|
||||
}
|
||||
else if (name >= PPCREC_NAME_CR && name <= PPCREC_NAME_CR_LAST)
|
||||
{
|
||||
x64Emit_movZX_reg64_mem8(x64GenContext, regR, X86_REG_RSP, offsetof(PPCInterpreter_t, cr) + (name - PPCREC_NAME_CR));
|
||||
}
|
||||
else if (name == PPCREC_NAME_CPU_MEMRES_EA)
|
||||
{
|
||||
x64Emit_mov_reg64_mem32(x64GenContext, regR, X86_REG_RSP, offsetof(PPCInterpreter_t, reservedMemAddr));
|
||||
}
|
||||
else if (name == PPCREC_NAME_CPU_MEMRES_VAL)
|
||||
{
|
||||
x64Emit_mov_reg64_mem32(x64GenContext, regR, X86_REG_RSP, offsetof(PPCInterpreter_t, reservedMemValue));
|
||||
}
|
||||
else
|
||||
assert_dbg();
|
||||
}
|
||||
else if (name >= PPCREC_NAME_TEMPORARY && name < PPCREC_NAME_TEMPORARY + 4)
|
||||
else if (imlInstruction->op_r_name.regR.GetBaseFormat() == IMLRegFormat::F64)
|
||||
{
|
||||
x64Emit_mov_reg64_mem32(x64GenContext, regR, X86_REG_RSP, offsetof(PPCInterpreter_t, temporaryGPR_reg) + sizeof(uint32) * (name - PPCREC_NAME_TEMPORARY));
|
||||
}
|
||||
else if (name == PPCREC_NAME_XER_CA)
|
||||
{
|
||||
x64Emit_movZX_reg64_mem8(x64GenContext, regR, X86_REG_RSP, offsetof(PPCInterpreter_t, xer_ca));
|
||||
}
|
||||
else if (name == PPCREC_NAME_XER_SO)
|
||||
{
|
||||
x64Emit_movZX_reg64_mem8(x64GenContext, regR, X86_REG_RSP, offsetof(PPCInterpreter_t, xer_so));
|
||||
}
|
||||
else if (name >= PPCREC_NAME_CR && name <= PPCREC_NAME_CR_LAST)
|
||||
{
|
||||
x64Emit_movZX_reg64_mem8(x64GenContext, regR, X86_REG_RSP, offsetof(PPCInterpreter_t, cr) + (name - PPCREC_NAME_CR));
|
||||
}
|
||||
else if (name == PPCREC_NAME_CPU_MEMRES_EA)
|
||||
{
|
||||
x64Emit_mov_reg64_mem32(x64GenContext, regR, X86_REG_RSP, offsetof(PPCInterpreter_t, reservedMemAddr));
|
||||
}
|
||||
else if (name == PPCREC_NAME_CPU_MEMRES_VAL)
|
||||
{
|
||||
x64Emit_mov_reg64_mem32(x64GenContext, regR, X86_REG_RSP, offsetof(PPCInterpreter_t, reservedMemValue));
|
||||
auto regR = _regF64(imlInstruction->op_r_name.regR);
|
||||
if (name >= PPCREC_NAME_FPR0 && name < (PPCREC_NAME_FPR0 + 32))
|
||||
{
|
||||
x64Gen_movupd_xmmReg_memReg128(x64GenContext, regR, X86_REG_ESP, offsetof(PPCInterpreter_t, fpr) + sizeof(FPR_t) * (name - PPCREC_NAME_FPR0));
|
||||
}
|
||||
else if (name >= PPCREC_NAME_TEMPORARY_FPR0 || name < (PPCREC_NAME_TEMPORARY_FPR0 + 8))
|
||||
{
|
||||
x64Gen_movupd_xmmReg_memReg128(x64GenContext, regR, X86_REG_ESP, offsetof(PPCInterpreter_t, temporaryFPR) + sizeof(FPR_t) * (name - PPCREC_NAME_TEMPORARY_FPR0));
|
||||
}
|
||||
else
|
||||
{
|
||||
cemu_assert_debug(false);
|
||||
}
|
||||
}
|
||||
else
|
||||
assert_dbg();
|
||||
DEBUG_BREAK;
|
||||
|
||||
}
|
||||
|
||||
void PPCRecompilerX64Gen_imlInstruction_name_r(PPCRecFunction_t* PPCRecFunction, ppcImlGenContext_t* ppcImlGenContext, x64GenContext_t* x64GenContext, IMLInstruction* imlInstruction)
|
||||
{
|
||||
uint32 name = imlInstruction->op_r_name.name;
|
||||
auto regR = _reg64(imlInstruction->op_r_name.regR);
|
||||
|
||||
if( name >= PPCREC_NAME_R0 && name < PPCREC_NAME_R0+32 )
|
||||
|
||||
if (imlInstruction->op_r_name.regR.GetBaseFormat() == IMLRegFormat::I64)
|
||||
{
|
||||
x64Emit_mov_mem32_reg64(x64GenContext, X86_REG_RSP, offsetof(PPCInterpreter_t, gpr)+sizeof(uint32)*(name-PPCREC_NAME_R0), regR);
|
||||
}
|
||||
else if( name >= PPCREC_NAME_SPR0 && name < PPCREC_NAME_SPR0+999 )
|
||||
{
|
||||
uint32 sprIndex = (name - PPCREC_NAME_SPR0);
|
||||
if (sprIndex == SPR_LR)
|
||||
x64Emit_mov_mem32_reg64(x64GenContext, X86_REG_RSP, offsetof(PPCInterpreter_t, spr.LR), regR);
|
||||
else if (sprIndex == SPR_CTR)
|
||||
x64Emit_mov_mem32_reg64(x64GenContext, X86_REG_RSP, offsetof(PPCInterpreter_t, spr.CTR), regR);
|
||||
else if (sprIndex == SPR_XER)
|
||||
x64Emit_mov_mem32_reg64(x64GenContext, X86_REG_RSP, offsetof(PPCInterpreter_t, spr.XER), regR);
|
||||
else if (sprIndex >= SPR_UGQR0 && sprIndex <= SPR_UGQR7)
|
||||
auto regR = _reg64(imlInstruction->op_r_name.regR);
|
||||
if (name >= PPCREC_NAME_R0 && name < PPCREC_NAME_R0 + 32)
|
||||
{
|
||||
sint32 memOffset = offsetof(PPCInterpreter_t, spr.UGQR) + sizeof(PPCInterpreter_t::spr.UGQR[0]) * (sprIndex - SPR_UGQR0);
|
||||
x64Emit_mov_mem32_reg64(x64GenContext, X86_REG_RSP, memOffset, regR);
|
||||
x64Emit_mov_mem32_reg64(x64GenContext, X86_REG_RSP, offsetof(PPCInterpreter_t, gpr) + sizeof(uint32) * (name - PPCREC_NAME_R0), regR);
|
||||
}
|
||||
else if (name >= PPCREC_NAME_SPR0 && name < PPCREC_NAME_SPR0 + 999)
|
||||
{
|
||||
uint32 sprIndex = (name - PPCREC_NAME_SPR0);
|
||||
if (sprIndex == SPR_LR)
|
||||
x64Emit_mov_mem32_reg64(x64GenContext, X86_REG_RSP, offsetof(PPCInterpreter_t, spr.LR), regR);
|
||||
else if (sprIndex == SPR_CTR)
|
||||
x64Emit_mov_mem32_reg64(x64GenContext, X86_REG_RSP, offsetof(PPCInterpreter_t, spr.CTR), regR);
|
||||
else if (sprIndex == SPR_XER)
|
||||
x64Emit_mov_mem32_reg64(x64GenContext, X86_REG_RSP, offsetof(PPCInterpreter_t, spr.XER), regR);
|
||||
else if (sprIndex >= SPR_UGQR0 && sprIndex <= SPR_UGQR7)
|
||||
{
|
||||
sint32 memOffset = offsetof(PPCInterpreter_t, spr.UGQR) + sizeof(PPCInterpreter_t::spr.UGQR[0]) * (sprIndex - SPR_UGQR0);
|
||||
x64Emit_mov_mem32_reg64(x64GenContext, X86_REG_RSP, memOffset, regR);
|
||||
}
|
||||
else
|
||||
assert_dbg();
|
||||
}
|
||||
else if (name >= PPCREC_NAME_TEMPORARY && name < PPCREC_NAME_TEMPORARY + 4)
|
||||
{
|
||||
x64Emit_mov_mem32_reg64(x64GenContext, X86_REG_RSP, offsetof(PPCInterpreter_t, temporaryGPR_reg) + sizeof(uint32) * (name - PPCREC_NAME_TEMPORARY), regR);
|
||||
}
|
||||
else if (name == PPCREC_NAME_XER_CA)
|
||||
{
|
||||
x64GenContext->emitter->MOV_bb_l(X86_REG_RSP, offsetof(PPCInterpreter_t, xer_ca), X86_REG_NONE, 0, _reg8_from_reg64(regR));
|
||||
}
|
||||
else if (name == PPCREC_NAME_XER_SO)
|
||||
{
|
||||
x64GenContext->emitter->MOV_bb_l(X86_REG_RSP, offsetof(PPCInterpreter_t, xer_so), X86_REG_NONE, 0, _reg8_from_reg64(regR));
|
||||
}
|
||||
else if (name >= PPCREC_NAME_CR && name <= PPCREC_NAME_CR_LAST)
|
||||
{
|
||||
x64GenContext->emitter->MOV_bb_l(X86_REG_RSP, offsetof(PPCInterpreter_t, cr) + (name - PPCREC_NAME_CR), X86_REG_NONE, 0, _reg8_from_reg64(regR));
|
||||
}
|
||||
else if (name == PPCREC_NAME_CPU_MEMRES_EA)
|
||||
{
|
||||
x64Emit_mov_mem32_reg64(x64GenContext, X86_REG_RSP, offsetof(PPCInterpreter_t, reservedMemAddr), regR);
|
||||
}
|
||||
else if (name == PPCREC_NAME_CPU_MEMRES_VAL)
|
||||
{
|
||||
x64Emit_mov_mem32_reg64(x64GenContext, X86_REG_RSP, offsetof(PPCInterpreter_t, reservedMemValue), regR);
|
||||
}
|
||||
else
|
||||
assert_dbg();
|
||||
assert_dbg();
|
||||
}
|
||||
else if (name >= PPCREC_NAME_TEMPORARY && name < PPCREC_NAME_TEMPORARY + 4)
|
||||
else if (imlInstruction->op_r_name.regR.GetBaseFormat() == IMLRegFormat::F64)
|
||||
{
|
||||
x64Emit_mov_mem32_reg64(x64GenContext, X86_REG_RSP, offsetof(PPCInterpreter_t, temporaryGPR_reg) + sizeof(uint32) * (name - PPCREC_NAME_TEMPORARY), regR);
|
||||
}
|
||||
else if (name == PPCREC_NAME_XER_CA)
|
||||
{
|
||||
x64GenContext->emitter->MOV_bb_l(X86_REG_RSP, offsetof(PPCInterpreter_t, xer_ca), X86_REG_NONE, 0, _reg8_from_reg64(regR));
|
||||
}
|
||||
else if (name == PPCREC_NAME_XER_SO)
|
||||
{
|
||||
x64GenContext->emitter->MOV_bb_l(X86_REG_RSP, offsetof(PPCInterpreter_t, xer_so), X86_REG_NONE, 0, _reg8_from_reg64(regR));
|
||||
}
|
||||
else if (name >= PPCREC_NAME_CR && name <= PPCREC_NAME_CR_LAST)
|
||||
{
|
||||
x64GenContext->emitter->MOV_bb_l(X86_REG_RSP, offsetof(PPCInterpreter_t, cr) + (name - PPCREC_NAME_CR), X86_REG_NONE, 0, _reg8_from_reg64(regR));
|
||||
}
|
||||
else if (name == PPCREC_NAME_CPU_MEMRES_EA)
|
||||
{
|
||||
x64Emit_mov_mem32_reg64(x64GenContext, X86_REG_RSP, offsetof(PPCInterpreter_t, reservedMemAddr), regR);
|
||||
}
|
||||
else if (name == PPCREC_NAME_CPU_MEMRES_VAL)
|
||||
{
|
||||
x64Emit_mov_mem32_reg64(x64GenContext, X86_REG_RSP, offsetof(PPCInterpreter_t, reservedMemValue), regR);
|
||||
auto regR = _regF64(imlInstruction->op_r_name.regR);
|
||||
uint32 name = imlInstruction->op_r_name.name;
|
||||
if (name >= PPCREC_NAME_FPR0 && name < (PPCREC_NAME_FPR0 + 32))
|
||||
{
|
||||
x64Gen_movupd_memReg128_xmmReg(x64GenContext, regR, X86_REG_ESP, offsetof(PPCInterpreter_t, fpr) + sizeof(FPR_t) * (name - PPCREC_NAME_FPR0));
|
||||
}
|
||||
else if (name >= PPCREC_NAME_TEMPORARY_FPR0 && name < (PPCREC_NAME_TEMPORARY_FPR0 + 8))
|
||||
{
|
||||
x64Gen_movupd_memReg128_xmmReg(x64GenContext, regR, X86_REG_ESP, offsetof(PPCInterpreter_t, temporaryFPR) + sizeof(FPR_t) * (name - PPCREC_NAME_TEMPORARY_FPR0));
|
||||
}
|
||||
else
|
||||
{
|
||||
cemu_assert_debug(false);
|
||||
}
|
||||
}
|
||||
else
|
||||
assert_dbg();
|
||||
DEBUG_BREAK;
|
||||
|
||||
|
||||
}
|
||||
|
||||
//void PPCRecompilerX64Gen_imlInstruction_fpr_r_name(PPCRecFunction_t* PPCRecFunction, ppcImlGenContext_t* ppcImlGenContext, x64GenContext_t* x64GenContext, IMLInstruction* imlInstruction)
|
||||
//{
|
||||
// uint32 name = imlInstruction->op_r_name.name;
|
||||
// uint32 fprReg = _regF64(imlInstruction->op_r_name.regR);
|
||||
// if (name >= PPCREC_NAME_FPR0 && name < (PPCREC_NAME_FPR0 + 32))
|
||||
// {
|
||||
// x64Gen_movupd_xmmReg_memReg128(x64GenContext, fprReg, X86_REG_ESP, offsetof(PPCInterpreter_t, fpr) + sizeof(FPR_t) * (name - PPCREC_NAME_FPR0));
|
||||
// }
|
||||
// else if (name >= PPCREC_NAME_TEMPORARY_FPR0 || name < (PPCREC_NAME_TEMPORARY_FPR0 + 8))
|
||||
// {
|
||||
// x64Gen_movupd_xmmReg_memReg128(x64GenContext, fprReg, X86_REG_ESP, offsetof(PPCInterpreter_t, temporaryFPR) + sizeof(FPR_t) * (name - PPCREC_NAME_TEMPORARY_FPR0));
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// cemu_assert_debug(false);
|
||||
// }
|
||||
//}
|
||||
//
|
||||
//void PPCRecompilerX64Gen_imlInstruction_fpr_name_r(PPCRecFunction_t* PPCRecFunction, ppcImlGenContext_t* ppcImlGenContext, x64GenContext_t* x64GenContext, IMLInstruction* imlInstruction)
|
||||
//{
|
||||
// uint32 name = imlInstruction->op_r_name.name;
|
||||
// uint32 fprReg = _regF64(imlInstruction->op_r_name.regR);
|
||||
// if (name >= PPCREC_NAME_FPR0 && name < (PPCREC_NAME_FPR0 + 32))
|
||||
// {
|
||||
// x64Gen_movupd_memReg128_xmmReg(x64GenContext, fprReg, X86_REG_ESP, offsetof(PPCInterpreter_t, fpr) + sizeof(FPR_t) * (name - PPCREC_NAME_FPR0));
|
||||
// }
|
||||
// else if (name >= PPCREC_NAME_TEMPORARY_FPR0 && name < (PPCREC_NAME_TEMPORARY_FPR0 + 8))
|
||||
// {
|
||||
// x64Gen_movupd_memReg128_xmmReg(x64GenContext, fprReg, X86_REG_ESP, offsetof(PPCInterpreter_t, temporaryFPR) + sizeof(FPR_t) * (name - PPCREC_NAME_TEMPORARY_FPR0));
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// cemu_assert_debug(false);
|
||||
// }
|
||||
//}
|
||||
|
||||
uint8* codeMemoryBlock = nullptr;
|
||||
sint32 codeMemoryBlockIndex = 0;
|
||||
sint32 codeMemoryBlockSize = 0;
|
||||
|
||||
@@ -5,11 +5,7 @@
|
||||
|
||||
#include "asm/x64util.h" // for recompiler_fres / frsqrte
|
||||
|
||||
uint32 _regF64(IMLReg r)
|
||||
{
|
||||
cemu_assert_debug(r.GetRegFormat() == IMLRegFormat::F64);
|
||||
return (uint32)r.GetRegID();
|
||||
}
|
||||
uint32 _regF64(IMLReg physReg);
|
||||
|
||||
uint32 _regI32(IMLReg r)
|
||||
{
|
||||
|
||||
@@ -15,8 +15,8 @@ bool IMLAnalyzer_CanTypeWriteCR(IMLInstruction* imlInstruction);
|
||||
|
||||
// optimizer passes
|
||||
// todo - rename
|
||||
bool PPCRecompiler_reduceNumberOfFPRRegisters(struct ppcImlGenContext_t* ppcImlGenContext);
|
||||
bool PPCRecompiler_manageFPRRegisters(struct ppcImlGenContext_t* ppcImlGenContext);
|
||||
//bool PPCRecompiler_reduceNumberOfFPRRegisters(struct ppcImlGenContext_t* ppcImlGenContext);
|
||||
//bool PPCRecompiler_manageFPRRegisters(struct ppcImlGenContext_t* ppcImlGenContext);
|
||||
void PPCRecompiler_optimizeDirectFloatCopies(struct ppcImlGenContext_t* ppcImlGenContext);
|
||||
void PPCRecompiler_optimizeDirectIntegerCopies(struct ppcImlGenContext_t* ppcImlGenContext);
|
||||
void PPCRecompiler_optimizePSQLoadAndStore(struct ppcImlGenContext_t* ppcImlGenContext);
|
||||
|
||||
@@ -41,22 +41,36 @@ const char* IMLDebug_GetOpcodeName(const IMLInstruction* iml)
|
||||
return _tempOpcodename;
|
||||
}
|
||||
|
||||
std::string IMLDebug_GetRegName(IMLReg r)
|
||||
{
|
||||
std::string regName;
|
||||
uint32 regId = r.GetRegID();
|
||||
switch (r.GetRegFormat())
|
||||
{
|
||||
case IMLRegFormat::F32:
|
||||
regName.append("f");
|
||||
break;
|
||||
case IMLRegFormat::F64:
|
||||
regName.append("fd");
|
||||
break;
|
||||
case IMLRegFormat::I32:
|
||||
regName.append("i");
|
||||
break;
|
||||
case IMLRegFormat::I64:
|
||||
regName.append("r");
|
||||
break;
|
||||
default:
|
||||
__debugbreak();
|
||||
}
|
||||
regName.append(fmt::format("{}", regId));
|
||||
return regName;
|
||||
}
|
||||
|
||||
void IMLDebug_AppendRegisterParam(StringBuf& strOutput, IMLReg virtualRegister, bool isLast = false)
|
||||
{
|
||||
uint32 regId = virtualRegister.GetRegID();
|
||||
DEBUG_BREAK; // todo (print type)
|
||||
if (isLast)
|
||||
{
|
||||
if (regId < 10)
|
||||
strOutput.addFmt("t{} ", regId);
|
||||
else
|
||||
strOutput.addFmt("t{}", regId);
|
||||
return;
|
||||
}
|
||||
if (regId < 10)
|
||||
strOutput.addFmt("t{} , ", regId);
|
||||
else
|
||||
strOutput.addFmt("t{}, ", regId);
|
||||
strOutput.add(IMLDebug_GetRegName(virtualRegister));
|
||||
if (!isLast)
|
||||
strOutput.add(", ");
|
||||
}
|
||||
|
||||
void IMLDebug_AppendS32Param(StringBuf& strOutput, sint32 val, bool isLast = false)
|
||||
@@ -149,12 +163,6 @@ std::string IMLDebug_GetConditionName(IMLCondition cond)
|
||||
return "ukn";
|
||||
}
|
||||
|
||||
std::string IMLDebug_GetRegName(IMLReg r)
|
||||
{
|
||||
cemu_assert_unimplemented();
|
||||
return "";
|
||||
}
|
||||
|
||||
void IMLDebug_DumpSegment(ppcImlGenContext_t* ctx, IMLSegment* imlSegment, bool printLivenessRangeInfo)
|
||||
{
|
||||
StringBuf strOutput(1024);
|
||||
@@ -197,19 +205,24 @@ void IMLDebug_DumpSegment(ppcImlGenContext_t* ctx, IMLSegment* imlSegment, bool
|
||||
if (inst.type == PPCREC_IML_TYPE_R_NAME || inst.type == PPCREC_IML_TYPE_NAME_R)
|
||||
{
|
||||
if (inst.type == PPCREC_IML_TYPE_R_NAME)
|
||||
strOutput.add("LD_NAME");
|
||||
strOutput.add("R_NAME");
|
||||
else
|
||||
strOutput.add("ST_NAME");
|
||||
strOutput.add("NAME_R");
|
||||
while ((sint32)strOutput.getLen() < lineOffsetParameters)
|
||||
strOutput.add(" ");
|
||||
|
||||
IMLDebug_AppendRegisterParam(strOutput, inst.op_r_name.regR);
|
||||
if(inst.type == PPCREC_IML_TYPE_R_NAME)
|
||||
IMLDebug_AppendRegisterParam(strOutput, inst.op_r_name.regR);
|
||||
|
||||
strOutput.addFmt("name_{} (", inst.op_r_name.regR.GetRegID());
|
||||
strOutput.add("name_");
|
||||
if (inst.op_r_name.name >= PPCREC_NAME_R0 && inst.op_r_name.name < (PPCREC_NAME_R0 + 999))
|
||||
{
|
||||
strOutput.addFmt("r{}", inst.op_r_name.name - PPCREC_NAME_R0);
|
||||
}
|
||||
else if (inst.op_r_name.name >= PPCREC_NAME_FPR0 && inst.op_r_name.name < (PPCREC_NAME_FPR0 + 999))
|
||||
{
|
||||
strOutput.addFmt("f{}", inst.op_r_name.name - PPCREC_NAME_FPR0);
|
||||
}
|
||||
else if (inst.op_r_name.name >= PPCREC_NAME_SPR0 && inst.op_r_name.name < (PPCREC_NAME_SPR0 + 999))
|
||||
{
|
||||
strOutput.addFmt("spr{}", inst.op_r_name.name - PPCREC_NAME_SPR0);
|
||||
@@ -227,8 +240,15 @@ void IMLDebug_DumpSegment(ppcImlGenContext_t* ctx, IMLSegment* imlSegment, bool
|
||||
else if (inst.op_r_name.name == PPCREC_NAME_CPU_MEMRES_VAL)
|
||||
strOutput.add("cpuReservation.value");
|
||||
else
|
||||
strOutput.add("ukn");
|
||||
strOutput.add(")");
|
||||
{
|
||||
strOutput.addFmt("name_ukn{}", inst.op_r_name.name);
|
||||
}
|
||||
if (inst.type != PPCREC_IML_TYPE_R_NAME)
|
||||
{
|
||||
strOutput.add(", ");
|
||||
IMLDebug_AppendRegisterParam(strOutput, inst.op_r_name.regR, true);
|
||||
}
|
||||
|
||||
}
|
||||
else if (inst.type == PPCREC_IML_TYPE_R_R)
|
||||
{
|
||||
@@ -281,7 +301,7 @@ void IMLDebug_DumpSegment(ppcImlGenContext_t* ctx, IMLSegment* imlSegment, bool
|
||||
}
|
||||
else if (inst.type == PPCREC_IML_TYPE_CONDITIONAL_JUMP)
|
||||
{
|
||||
strOutput.add("CJUMP2 ");
|
||||
strOutput.add("CJUMP ");
|
||||
while ((sint32)strOutput.getLen() < lineOffsetParameters)
|
||||
strOutput.add(" ");
|
||||
IMLDebug_AppendRegisterParam(strOutput, inst.op_conditional_jump.registerBool, true);
|
||||
@@ -342,9 +362,9 @@ void IMLDebug_DumpSegment(ppcImlGenContext_t* ctx, IMLSegment* imlSegment, bool
|
||||
IMLDebug_AppendRegisterParam(strOutput, inst.op_storeLoad.registerData);
|
||||
|
||||
if (inst.type == PPCREC_IML_TYPE_LOAD_INDEXED || inst.type == PPCREC_IML_TYPE_STORE_INDEXED)
|
||||
strOutput.addFmt("[t{}+t{}]", inst.op_storeLoad.registerMem.GetRegID(), inst.op_storeLoad.registerMem2.GetRegID());
|
||||
strOutput.addFmt("[{}+{}]", IMLDebug_GetRegName(inst.op_storeLoad.registerMem), IMLDebug_GetRegName(inst.op_storeLoad.registerMem2));
|
||||
else
|
||||
strOutput.addFmt("[t{}+{}]", inst.op_storeLoad.registerMem.GetRegID(), inst.op_storeLoad.immS32);
|
||||
strOutput.addFmt("[{}+{}]", IMLDebug_GetRegName(inst.op_storeLoad.registerMem), inst.op_storeLoad.immS32);
|
||||
}
|
||||
else if (inst.type == PPCREC_IML_TYPE_ATOMIC_CMP_STORE)
|
||||
{
|
||||
@@ -366,7 +386,7 @@ void IMLDebug_DumpSegment(ppcImlGenContext_t* ctx, IMLSegment* imlSegment, bool
|
||||
{
|
||||
if (inst.operation == PPCREC_IML_MACRO_B_TO_REG)
|
||||
{
|
||||
strOutput.addFmt("MACRO B_TO_REG t{}", inst.op_macro.param);
|
||||
strOutput.addFmt("MACRO B_TO_REG {}", IMLDebug_GetRegName(inst.op_macro.paramReg));
|
||||
}
|
||||
else if (inst.operation == PPCREC_IML_MACRO_BL)
|
||||
{
|
||||
|
||||
@@ -638,78 +638,64 @@ void IMLInstruction::RewriteGPR(const std::unordered_map<IMLRegID, IMLRegID>& tr
|
||||
}
|
||||
else if (type == PPCREC_IML_TYPE_FPR_R_NAME)
|
||||
{
|
||||
|
||||
op_r_name.regR = replaceRegisterIdMultiple(op_r_name.regR, translationTable);
|
||||
}
|
||||
else if (type == PPCREC_IML_TYPE_FPR_NAME_R)
|
||||
{
|
||||
|
||||
op_r_name.regR = replaceRegisterIdMultiple(op_r_name.regR, translationTable);
|
||||
}
|
||||
else if (type == PPCREC_IML_TYPE_FPR_LOAD)
|
||||
{
|
||||
if (op_storeLoad.registerMem.IsValid())
|
||||
{
|
||||
op_storeLoad.registerMem = replaceRegisterIdMultiple(op_storeLoad.registerMem, translationTable);
|
||||
}
|
||||
if (op_storeLoad.registerGQR.IsValid())
|
||||
{
|
||||
op_storeLoad.registerGQR = replaceRegisterIdMultiple(op_storeLoad.registerGQR, translationTable);
|
||||
}
|
||||
op_storeLoad.registerData = replaceRegisterIdMultiple(op_storeLoad.registerData, translationTable);
|
||||
op_storeLoad.registerMem = replaceRegisterIdMultiple(op_storeLoad.registerMem, translationTable);
|
||||
op_storeLoad.registerGQR = replaceRegisterIdMultiple(op_storeLoad.registerGQR, translationTable);
|
||||
}
|
||||
else if (type == PPCREC_IML_TYPE_FPR_LOAD_INDEXED)
|
||||
{
|
||||
if (op_storeLoad.registerMem.IsValid())
|
||||
{
|
||||
op_storeLoad.registerMem = replaceRegisterIdMultiple(op_storeLoad.registerMem, translationTable);
|
||||
}
|
||||
if (op_storeLoad.registerMem2.IsValid())
|
||||
{
|
||||
op_storeLoad.registerMem2 = replaceRegisterIdMultiple(op_storeLoad.registerMem2, translationTable);
|
||||
}
|
||||
if (op_storeLoad.registerGQR.IsValid())
|
||||
{
|
||||
op_storeLoad.registerGQR = replaceRegisterIdMultiple(op_storeLoad.registerGQR, translationTable);
|
||||
}
|
||||
op_storeLoad.registerData = replaceRegisterIdMultiple(op_storeLoad.registerData, translationTable);
|
||||
op_storeLoad.registerMem = replaceRegisterIdMultiple(op_storeLoad.registerMem, translationTable);
|
||||
op_storeLoad.registerMem2 = replaceRegisterIdMultiple(op_storeLoad.registerMem2, translationTable);
|
||||
op_storeLoad.registerGQR = replaceRegisterIdMultiple(op_storeLoad.registerGQR, translationTable);
|
||||
}
|
||||
else if (type == PPCREC_IML_TYPE_FPR_STORE)
|
||||
{
|
||||
if (op_storeLoad.registerMem.IsValid())
|
||||
{
|
||||
op_storeLoad.registerMem = replaceRegisterIdMultiple(op_storeLoad.registerMem, translationTable);
|
||||
}
|
||||
if (op_storeLoad.registerGQR.IsValid())
|
||||
{
|
||||
op_storeLoad.registerGQR = replaceRegisterIdMultiple(op_storeLoad.registerGQR, translationTable);
|
||||
}
|
||||
op_storeLoad.registerData = replaceRegisterIdMultiple(op_storeLoad.registerData, translationTable);
|
||||
op_storeLoad.registerMem = replaceRegisterIdMultiple(op_storeLoad.registerMem, translationTable);
|
||||
op_storeLoad.registerGQR = replaceRegisterIdMultiple(op_storeLoad.registerGQR, translationTable);
|
||||
}
|
||||
else if (type == PPCREC_IML_TYPE_FPR_STORE_INDEXED)
|
||||
{
|
||||
if (op_storeLoad.registerMem.IsValid())
|
||||
{
|
||||
op_storeLoad.registerMem = replaceRegisterIdMultiple(op_storeLoad.registerMem, translationTable);
|
||||
}
|
||||
if (op_storeLoad.registerMem2.IsValid())
|
||||
{
|
||||
op_storeLoad.registerMem2 = replaceRegisterIdMultiple(op_storeLoad.registerMem2, translationTable);
|
||||
}
|
||||
if (op_storeLoad.registerGQR.IsValid())
|
||||
{
|
||||
op_storeLoad.registerGQR = replaceRegisterIdMultiple(op_storeLoad.registerGQR, translationTable);
|
||||
}
|
||||
}
|
||||
else if (type == PPCREC_IML_TYPE_FPR_R_R)
|
||||
{
|
||||
}
|
||||
else if (type == PPCREC_IML_TYPE_FPR_R_R_R)
|
||||
{
|
||||
}
|
||||
else if (type == PPCREC_IML_TYPE_FPR_R_R_R_R)
|
||||
{
|
||||
op_storeLoad.registerData = replaceRegisterIdMultiple(op_storeLoad.registerData, translationTable);
|
||||
op_storeLoad.registerMem = replaceRegisterIdMultiple(op_storeLoad.registerMem, translationTable);
|
||||
op_storeLoad.registerMem2 = replaceRegisterIdMultiple(op_storeLoad.registerMem2, translationTable);
|
||||
op_storeLoad.registerGQR = replaceRegisterIdMultiple(op_storeLoad.registerGQR, translationTable);
|
||||
}
|
||||
else if (type == PPCREC_IML_TYPE_FPR_R)
|
||||
{
|
||||
op_fpr_r.regR = replaceRegisterIdMultiple(op_fpr_r.regR, translationTable);
|
||||
}
|
||||
else if (type == PPCREC_IML_TYPE_FPR_R_R)
|
||||
{
|
||||
op_fpr_r_r.regR = replaceRegisterIdMultiple(op_fpr_r_r.regR, translationTable);
|
||||
op_fpr_r_r.regA = replaceRegisterIdMultiple(op_fpr_r_r.regA, translationTable);
|
||||
}
|
||||
else if (type == PPCREC_IML_TYPE_FPR_R_R_R)
|
||||
{
|
||||
op_fpr_r_r_r.regR = replaceRegisterIdMultiple(op_fpr_r_r_r.regR, translationTable);
|
||||
op_fpr_r_r_r.regA = replaceRegisterIdMultiple(op_fpr_r_r_r.regA, translationTable);
|
||||
op_fpr_r_r_r.regB = replaceRegisterIdMultiple(op_fpr_r_r_r.regB, translationTable);
|
||||
}
|
||||
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, translationTable);
|
||||
op_fpr_r_r_r_r.regA = replaceRegisterIdMultiple(op_fpr_r_r_r_r.regA, translationTable);
|
||||
op_fpr_r_r_r_r.regB = replaceRegisterIdMultiple(op_fpr_r_r_r_r.regB, translationTable);
|
||||
op_fpr_r_r_r_r.regC = replaceRegisterIdMultiple(op_fpr_r_r_r_r.regC, translationTable);
|
||||
}
|
||||
else if (type == PPCREC_IML_TYPE_FPR_COMPARE)
|
||||
{
|
||||
op_fpr_compare.regA = replaceRegisterIdMultiple(op_fpr_compare.regA, translationTable);
|
||||
op_fpr_compare.regB = replaceRegisterIdMultiple(op_fpr_compare.regB, translationTable);
|
||||
op_fpr_compare.regR = replaceRegisterIdMultiple(op_fpr_compare.regR, translationTable);
|
||||
}
|
||||
else
|
||||
|
||||
@@ -388,6 +388,7 @@ struct IMLUsedRegisters
|
||||
template<typename Fn>
|
||||
void ForEachAccessedGPR(Fn F) const
|
||||
{
|
||||
// GPRs
|
||||
if (readGPR1.IsValid())
|
||||
F(readGPR1, false);
|
||||
if (readGPR2.IsValid())
|
||||
@@ -398,22 +399,33 @@ struct IMLUsedRegisters
|
||||
F(writtenGPR1, true);
|
||||
if (writtenGPR2.IsValid())
|
||||
F(writtenGPR2, true);
|
||||
// FPRs
|
||||
if (readFPR1.IsValid())
|
||||
F(readFPR1, false);
|
||||
if (readFPR2.IsValid())
|
||||
F(readFPR2, false);
|
||||
if (readFPR3.IsValid())
|
||||
F(readFPR3, false);
|
||||
if (readFPR4.IsValid())
|
||||
F(readFPR4, false);
|
||||
if (writtenFPR1.IsValid())
|
||||
F(writtenFPR1, true);
|
||||
}
|
||||
|
||||
bool HasSameBaseFPRRegId(IMLRegID regId) const
|
||||
{
|
||||
if (readFPR1.IsValid() && readFPR1.GetRegID() == regId)
|
||||
return true;
|
||||
if (readFPR2.IsValid() && readFPR2.GetRegID() == regId)
|
||||
return true;
|
||||
if (readFPR3.IsValid() && readFPR3.GetRegID() == regId)
|
||||
return true;
|
||||
if (readFPR4.IsValid() && readFPR4.GetRegID() == regId)
|
||||
return true;
|
||||
if (writtenFPR1.IsValid() && writtenFPR1.GetRegID() == regId)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
//bool HasSameBaseFPRRegId(IMLRegID regId) const
|
||||
//{
|
||||
// if (readFPR1.IsValid() && readFPR1.GetRegID() == regId)
|
||||
// return true;
|
||||
// if (readFPR2.IsValid() && readFPR2.GetRegID() == regId)
|
||||
// return true;
|
||||
// if (readFPR3.IsValid() && readFPR3.GetRegID() == regId)
|
||||
// return true;
|
||||
// if (readFPR4.IsValid() && readFPR4.GetRegID() == regId)
|
||||
// return true;
|
||||
// if (writtenFPR1.IsValid() && writtenFPR1.GetRegID() == regId)
|
||||
// return true;
|
||||
// return false;
|
||||
//}
|
||||
};
|
||||
|
||||
struct IMLInstruction
|
||||
@@ -765,4 +777,11 @@ struct IMLInstruction
|
||||
void ReplaceFPRs(IMLReg fprRegisterSearched[4], IMLReg fprRegisterReplaced[4]);
|
||||
void ReplaceFPR(IMLRegID fprRegisterSearched, IMLRegID fprRegisterReplaced);
|
||||
|
||||
};
|
||||
|
||||
// architecture specific constants
|
||||
namespace IMLArchX86
|
||||
{
|
||||
static constexpr int PHYSREG_GPR_BASE = 0;
|
||||
static constexpr int PHYSREG_FPR_BASE = 16;
|
||||
};
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1100,7 +1100,7 @@ void IMLRA_ConvertAbstractToLivenessRanges(IMLRegisterAllocatorContext& ctx, IML
|
||||
if(it.second.isProcessed)
|
||||
continue;
|
||||
IMLRegID regId = it.first;
|
||||
raLivenessRange_t* range = PPCRecRA_createRangeBase(ctx.deprGenContext, regId, ctx.deprGenContext->mappedRegister[regId]);
|
||||
raLivenessRange_t* range = PPCRecRA_createRangeBase(ctx.deprGenContext, regId, ctx.raParam->regIdToName.find(regId)->second);
|
||||
PPCRecRA_convertToMappedRanges(ctx, imlSegment, regId, range);
|
||||
}
|
||||
// fill created ranges with read/write location indices
|
||||
|
||||
@@ -93,7 +93,8 @@ struct IMLRegisterAllocatorParameters
|
||||
return perTypePhysPool[stdx::to_underlying(regFormat)];
|
||||
}
|
||||
|
||||
IMLPhysRegisterSet perTypePhysPool[stdx::to_underlying(IMLRegFormat::TYPE_COUNT)];// physicalRegisterPool;
|
||||
IMLPhysRegisterSet perTypePhysPool[stdx::to_underlying(IMLRegFormat::TYPE_COUNT)];
|
||||
std::unordered_map<IMLRegID, IMLName> regIdToName;
|
||||
};
|
||||
|
||||
void IMLRegisterAllocator_AllocateRegisters(ppcImlGenContext_t* ppcImlGenContext, IMLRegisterAllocatorParameters& raParam);
|
||||
@@ -91,7 +91,7 @@ struct IMLSegment
|
||||
bool isEnterable{}; // this segment can be entered from outside the recompiler (no preloaded registers necessary)
|
||||
uint32 enterPPCAddress{}; // used if isEnterable is true
|
||||
// PPC FPR use mask
|
||||
bool ppcFPRUsed[32]{}; // same as ppcGPRUsed, but for FPR
|
||||
//bool ppcFPRUsed[32]{}; // same as ppcGPRUsed, but for FPR
|
||||
// CR use mask
|
||||
uint32 crBitsInput{}; // bits that are expected to be set from the previous segment (read in this segment but not overwritten)
|
||||
uint32 crBitsRead{}; // all bits that are read in this segment
|
||||
|
||||
@@ -206,8 +206,19 @@ PPCRecFunction_t* PPCRecompiler_recompileFunction(PPCFunctionBoundaryTracker::PP
|
||||
// return nullptr;
|
||||
//}
|
||||
|
||||
// Large functions for testing (botw):
|
||||
// 3B4049C
|
||||
//if (ppcRecFunc->ppcAddress == 0x03C26844)
|
||||
//{
|
||||
// __debugbreak();
|
||||
// IMLDebug_Dump(&ppcImlGenContext);
|
||||
// __debugbreak();
|
||||
//}
|
||||
// 31A8778
|
||||
|
||||
// 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);
|
||||
@@ -217,8 +228,6 @@ PPCRecFunction_t* PPCRecompiler_recompileFunction(PPCFunctionBoundaryTracker::PP
|
||||
}
|
||||
|
||||
// collect list of PPC-->x64 entry points
|
||||
cemuLog_log(LogType::Force, "[Recompiler] Successfully compiled {:08x} - {:08x} Segments: {}", ppcRecFunc->ppcAddress, ppcRecFunc->ppcAddress + ppcRecFunc->ppcSize, ppcImlGenContext.segmentList2.size());
|
||||
|
||||
entryPointsOut.clear();
|
||||
for(IMLSegment* imlSegment : ppcImlGenContext.segmentList2)
|
||||
{
|
||||
@@ -230,6 +239,9 @@ PPCRecFunction_t* PPCRecompiler_recompileFunction(PPCFunctionBoundaryTracker::PP
|
||||
|
||||
entryPointsOut.emplace_back(ppcEnterOffset, x64Offset);
|
||||
}
|
||||
|
||||
cemuLog_log(LogType::Force, "[Recompiler] Successfully compiled {:08x} - {:08x} Segments: {} Entrypoints: {}", ppcRecFunc->ppcAddress, ppcRecFunc->ppcAddress + ppcRecFunc->ppcSize, ppcImlGenContext.segmentList2.size(), entryPointsOut.size());
|
||||
|
||||
return ppcRecFunc;
|
||||
}
|
||||
|
||||
@@ -242,72 +254,85 @@ bool PPCRecompiler_ApplyIMLPasses(ppcImlGenContext_t& ppcImlGenContext)
|
||||
// if GQRs can be predicted, optimize PSQ load/stores
|
||||
PPCRecompiler_optimizePSQLoadAndStore(&ppcImlGenContext);
|
||||
|
||||
// count number of used registers
|
||||
uint32 numLoadedFPRRegisters = 0;
|
||||
for (uint32 i = 0; i < 255; i++)
|
||||
{
|
||||
if (ppcImlGenContext.mappedFPRRegister[i])
|
||||
numLoadedFPRRegisters++;
|
||||
}
|
||||
|
||||
// insert name store instructions at the end of each segment but before branch instructions
|
||||
for (IMLSegment* segIt : ppcImlGenContext.segmentList2)
|
||||
{
|
||||
if (segIt->imlList.size() == 0)
|
||||
continue; // ignore empty segments
|
||||
// analyze segment for register usage
|
||||
IMLUsedRegisters registersUsed;
|
||||
for (sint32 i = 0; i < segIt->imlList.size(); i++)
|
||||
{
|
||||
segIt->imlList[i].CheckRegisterUsage(®istersUsed);
|
||||
IMLReg accessedTempReg[5];
|
||||
// intermediate FPRs
|
||||
accessedTempReg[0] = registersUsed.readFPR1;
|
||||
accessedTempReg[1] = registersUsed.readFPR2;
|
||||
accessedTempReg[2] = registersUsed.readFPR3;
|
||||
accessedTempReg[3] = registersUsed.readFPR4;
|
||||
accessedTempReg[4] = registersUsed.writtenFPR1;
|
||||
for (sint32 f = 0; f < 5; f++)
|
||||
{
|
||||
if (accessedTempReg[f].IsInvalid())
|
||||
continue;
|
||||
uint32 regName = ppcImlGenContext.mappedFPRRegister[accessedTempReg[f].GetRegID()];
|
||||
if (regName >= PPCREC_NAME_FPR0 && regName < PPCREC_NAME_FPR0 + 32)
|
||||
{
|
||||
segIt->ppcFPRUsed[regName - PPCREC_NAME_FPR0] = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
//for (IMLSegment* segIt : ppcImlGenContext.segmentList2)
|
||||
//{
|
||||
// if (segIt->imlList.size() == 0)
|
||||
// continue; // ignore empty segments
|
||||
// // analyze segment for register usage
|
||||
// IMLUsedRegisters registersUsed;
|
||||
// for (sint32 i = 0; i < segIt->imlList.size(); i++)
|
||||
// {
|
||||
// segIt->imlList[i].CheckRegisterUsage(®istersUsed);
|
||||
// IMLReg accessedTempReg[5];
|
||||
// // intermediate FPRs
|
||||
// accessedTempReg[0] = registersUsed.readFPR1;
|
||||
// accessedTempReg[1] = registersUsed.readFPR2;
|
||||
// accessedTempReg[2] = registersUsed.readFPR3;
|
||||
// accessedTempReg[3] = registersUsed.readFPR4;
|
||||
// accessedTempReg[4] = registersUsed.writtenFPR1;
|
||||
// for (sint32 f = 0; f < 5; f++)
|
||||
// {
|
||||
// if (accessedTempReg[f].IsInvalid())
|
||||
// continue;
|
||||
// uint32 regName = ppcImlGenContext.mappedFPRRegister[accessedTempReg[f].GetRegID()];
|
||||
// if (regName >= PPCREC_NAME_FPR0 && regName < PPCREC_NAME_FPR0 + 32)
|
||||
// {
|
||||
// segIt->ppcFPRUsed[regName - PPCREC_NAME_FPR0] = true;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//}
|
||||
|
||||
// merge certain float load+store patterns (must happen before FPR register remapping)
|
||||
PPCRecompiler_optimizeDirectFloatCopies(&ppcImlGenContext);
|
||||
// delay byte swapping for certain load+store patterns
|
||||
PPCRecompiler_optimizeDirectIntegerCopies(&ppcImlGenContext);
|
||||
|
||||
if (numLoadedFPRRegisters > 0)
|
||||
{
|
||||
if (PPCRecompiler_manageFPRRegisters(&ppcImlGenContext) == false)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
//if (numLoadedFPRRegisters > 0)
|
||||
//{
|
||||
// if (PPCRecompiler_manageFPRRegisters(&ppcImlGenContext) == false)
|
||||
// {
|
||||
// return false;
|
||||
// }
|
||||
//}
|
||||
|
||||
IMLRegisterAllocatorParameters raParam;
|
||||
|
||||
for (auto& it : ppcImlGenContext.mappedRegs)
|
||||
raParam.regIdToName.try_emplace(it.second.GetRegID(), it.first);
|
||||
|
||||
auto& gprPhysPool = raParam.GetPhysRegPool(IMLRegFormat::I64);
|
||||
gprPhysPool.SetAvailable(X86_REG_RAX);
|
||||
gprPhysPool.SetAvailable(X86_REG_RDX);
|
||||
gprPhysPool.SetAvailable(X86_REG_RBX);
|
||||
gprPhysPool.SetAvailable(X86_REG_RBP);
|
||||
gprPhysPool.SetAvailable(X86_REG_RSI);
|
||||
gprPhysPool.SetAvailable(X86_REG_RDI);
|
||||
gprPhysPool.SetAvailable(X86_REG_R8);
|
||||
gprPhysPool.SetAvailable(X86_REG_R9);
|
||||
gprPhysPool.SetAvailable(X86_REG_R10);
|
||||
gprPhysPool.SetAvailable(X86_REG_R11);
|
||||
gprPhysPool.SetAvailable(X86_REG_R12);
|
||||
gprPhysPool.SetAvailable(X86_REG_RCX);
|
||||
gprPhysPool.SetAvailable(IMLArchX86::PHYSREG_GPR_BASE + X86_REG_RAX);
|
||||
gprPhysPool.SetAvailable(IMLArchX86::PHYSREG_GPR_BASE + X86_REG_RDX);
|
||||
gprPhysPool.SetAvailable(IMLArchX86::PHYSREG_GPR_BASE + X86_REG_RBX);
|
||||
gprPhysPool.SetAvailable(IMLArchX86::PHYSREG_GPR_BASE + X86_REG_RBP);
|
||||
gprPhysPool.SetAvailable(IMLArchX86::PHYSREG_GPR_BASE + X86_REG_RSI);
|
||||
gprPhysPool.SetAvailable(IMLArchX86::PHYSREG_GPR_BASE + X86_REG_RDI);
|
||||
gprPhysPool.SetAvailable(IMLArchX86::PHYSREG_GPR_BASE + X86_REG_R8);
|
||||
gprPhysPool.SetAvailable(IMLArchX86::PHYSREG_GPR_BASE + X86_REG_R9);
|
||||
gprPhysPool.SetAvailable(IMLArchX86::PHYSREG_GPR_BASE + X86_REG_R10);
|
||||
gprPhysPool.SetAvailable(IMLArchX86::PHYSREG_GPR_BASE + X86_REG_R11);
|
||||
gprPhysPool.SetAvailable(IMLArchX86::PHYSREG_GPR_BASE + X86_REG_R12);
|
||||
gprPhysPool.SetAvailable(IMLArchX86::PHYSREG_GPR_BASE + X86_REG_RCX);
|
||||
|
||||
// add XMM registers, except XMM15 which is the temporary register
|
||||
auto& fprPhysPool = raParam.GetPhysRegPool(IMLRegFormat::F64);
|
||||
fprPhysPool.SetAvailable(IMLArchX86::PHYSREG_FPR_BASE + 0);
|
||||
fprPhysPool.SetAvailable(IMLArchX86::PHYSREG_FPR_BASE + 1);
|
||||
fprPhysPool.SetAvailable(IMLArchX86::PHYSREG_FPR_BASE + 2);
|
||||
fprPhysPool.SetAvailable(IMLArchX86::PHYSREG_FPR_BASE + 3);
|
||||
fprPhysPool.SetAvailable(IMLArchX86::PHYSREG_FPR_BASE + 4);
|
||||
fprPhysPool.SetAvailable(IMLArchX86::PHYSREG_FPR_BASE + 5);
|
||||
fprPhysPool.SetAvailable(IMLArchX86::PHYSREG_FPR_BASE + 6);
|
||||
fprPhysPool.SetAvailable(IMLArchX86::PHYSREG_FPR_BASE + 7);
|
||||
fprPhysPool.SetAvailable(IMLArchX86::PHYSREG_FPR_BASE + 8);
|
||||
fprPhysPool.SetAvailable(IMLArchX86::PHYSREG_FPR_BASE + 9);
|
||||
fprPhysPool.SetAvailable(IMLArchX86::PHYSREG_FPR_BASE + 10);
|
||||
fprPhysPool.SetAvailable(IMLArchX86::PHYSREG_FPR_BASE + 11);
|
||||
fprPhysPool.SetAvailable(IMLArchX86::PHYSREG_FPR_BASE + 12);
|
||||
fprPhysPool.SetAvailable(IMLArchX86::PHYSREG_FPR_BASE + 13);
|
||||
fprPhysPool.SetAvailable(IMLArchX86::PHYSREG_FPR_BASE + 14);
|
||||
|
||||
IMLRegisterAllocator_AllocateRegisters(&ppcImlGenContext, raParam);
|
||||
|
||||
|
||||
@@ -42,9 +42,12 @@ struct ppcImlGenContext_t
|
||||
// cycle counter
|
||||
uint32 cyclesSinceLastBranch; // used to track ppc cycles
|
||||
// temporary general purpose registers
|
||||
uint32 mappedRegister[PPC_REC_MAX_VIRTUAL_GPR];
|
||||
//uint32 mappedRegister[PPC_REC_MAX_VIRTUAL_GPR];
|
||||
// temporary floating point registers (single and double precision)
|
||||
uint32 mappedFPRRegister[256];
|
||||
//uint32 mappedFPRRegister[256];
|
||||
|
||||
std::unordered_map<IMLName, IMLReg> mappedRegs;
|
||||
|
||||
// list of segments
|
||||
std::vector<IMLSegment*> segmentList2;
|
||||
// code generation control
|
||||
|
||||
@@ -102,4 +102,3 @@ bool PPCRecompilerImlGen_PS_CMPU1(ppcImlGenContext_t* ppcImlGenContext, uint32 o
|
||||
// IML general
|
||||
|
||||
void PPCRecompilerIML_isolateEnterableSegments(ppcImlGenContext_t* ppcImlGenContext);
|
||||
|
||||
|
||||
@@ -134,74 +134,73 @@ void PPCIMLGen_CreateSegmentBranchedPath(ppcImlGenContext_t& ppcImlGenContext, P
|
||||
basicBlockInfo.appendSegment = segMerge;
|
||||
}
|
||||
|
||||
uint32 PPCRecompilerImlGen_getAndLockFreeTemporaryGPR(ppcImlGenContext_t* ppcImlGenContext, uint32 mappedName)
|
||||
IMLReg PPCRecompilerImlGen_LookupReg(ppcImlGenContext_t* ppcImlGenContext, IMLName mappedName, IMLRegFormat regFormat)
|
||||
{
|
||||
if( mappedName == PPCREC_NAME_NONE )
|
||||
auto it = ppcImlGenContext->mappedRegs.find(mappedName);
|
||||
if (it != ppcImlGenContext->mappedRegs.end())
|
||||
return it->second;
|
||||
// create new reg entry
|
||||
IMLRegFormat baseFormat;
|
||||
if (regFormat == IMLRegFormat::F64)
|
||||
baseFormat = IMLRegFormat::F64;
|
||||
else if (regFormat == IMLRegFormat::I32)
|
||||
baseFormat = IMLRegFormat::I64;
|
||||
else
|
||||
{
|
||||
debug_printf("PPCRecompilerImlGen_getAndLockFreeTemporaryGPR(): Invalid mappedName parameter\n");
|
||||
return PPC_REC_INVALID_REGISTER;
|
||||
cemu_assert_suspicious();
|
||||
}
|
||||
for(uint32 i=0; i<(PPC_REC_MAX_VIRTUAL_GPR-1); i++)
|
||||
{
|
||||
if( ppcImlGenContext->mappedRegister[i] == PPCREC_NAME_NONE )
|
||||
{
|
||||
ppcImlGenContext->mappedRegister[i] = mappedName;
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
IMLRegID newRegId = ppcImlGenContext->mappedRegs.size();
|
||||
IMLReg newReg(baseFormat, regFormat, 0, newRegId);
|
||||
ppcImlGenContext->mappedRegs.try_emplace(mappedName, newReg);
|
||||
return newReg;
|
||||
}
|
||||
|
||||
uint32 PPCRecompilerImlGen_findRegisterByMappedName(ppcImlGenContext_t* ppcImlGenContext, uint32 mappedName)
|
||||
IMLName PPCRecompilerImlGen_GetRegName(ppcImlGenContext_t* ppcImlGenContext, IMLReg reg)
|
||||
{
|
||||
for(uint32 i=0; i< PPC_REC_MAX_VIRTUAL_GPR; i++)
|
||||
for (auto& it : ppcImlGenContext->mappedRegs)
|
||||
{
|
||||
if( ppcImlGenContext->mappedRegister[i] == mappedName )
|
||||
{
|
||||
return i;
|
||||
}
|
||||
if (it.second.GetRegID() == reg.GetRegID())
|
||||
return it.first;
|
||||
}
|
||||
return PPC_REC_INVALID_REGISTER;
|
||||
cemu_assert(false);
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint32 PPCRecompilerImlGen_getAndLockFreeTemporaryFPR(ppcImlGenContext_t* ppcImlGenContext, uint32 mappedName)
|
||||
{
|
||||
if( mappedName == PPCREC_NAME_NONE )
|
||||
{
|
||||
debug_printf("PPCRecompilerImlGen_getAndLockFreeTemporaryFPR(): Invalid mappedName parameter\n");
|
||||
return PPC_REC_INVALID_REGISTER;
|
||||
}
|
||||
for(uint32 i=0; i<255; i++)
|
||||
{
|
||||
if( ppcImlGenContext->mappedFPRRegister[i] == PPCREC_NAME_NONE )
|
||||
{
|
||||
ppcImlGenContext->mappedFPRRegister[i] = mappedName;
|
||||
return i;
|
||||
}
|
||||
}
|
||||
__debugbreak();
|
||||
//if( mappedName == PPCREC_NAME_NONE )
|
||||
//{
|
||||
// debug_printf("PPCRecompilerImlGen_getAndLockFreeTemporaryFPR(): Invalid mappedName parameter\n");
|
||||
// return PPC_REC_INVALID_REGISTER;
|
||||
//}
|
||||
//for(uint32 i=0; i<255; i++)
|
||||
//{
|
||||
// if( ppcImlGenContext->mappedFPRRegister[i] == PPCREC_NAME_NONE )
|
||||
// {
|
||||
// ppcImlGenContext->mappedFPRRegister[i] = mappedName;
|
||||
// return i;
|
||||
// }
|
||||
//}
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint32 PPCRecompilerImlGen_findFPRRegisterByMappedName(ppcImlGenContext_t* ppcImlGenContext, uint32 mappedName)
|
||||
{
|
||||
for(uint32 i=0; i<255; i++)
|
||||
{
|
||||
if( ppcImlGenContext->mappedFPRRegister[i] == mappedName )
|
||||
{
|
||||
return i;
|
||||
}
|
||||
}
|
||||
__debugbreak();
|
||||
//for(uint32 i=0; i<255; i++)
|
||||
//{
|
||||
// if( ppcImlGenContext->mappedFPRRegister[i] == mappedName )
|
||||
// {
|
||||
// return i;
|
||||
// }
|
||||
//}
|
||||
return PPC_REC_INVALID_REGISTER;
|
||||
}
|
||||
|
||||
IMLReg PPCRecompilerImlGen_loadRegister(ppcImlGenContext_t* ppcImlGenContext, uint32 mappedName)
|
||||
{
|
||||
uint32 loadedRegisterIndex = PPCRecompilerImlGen_findRegisterByMappedName(ppcImlGenContext, mappedName);
|
||||
if (loadedRegisterIndex != PPC_REC_INVALID_REGISTER)
|
||||
return IMLReg(IMLRegFormat::I64, IMLRegFormat::I32, 0, loadedRegisterIndex);
|
||||
|
||||
uint32 registerIndex = PPCRecompilerImlGen_getAndLockFreeTemporaryGPR(ppcImlGenContext, mappedName);
|
||||
return IMLReg(IMLRegFormat::I64, IMLRegFormat::I32, 0, registerIndex);
|
||||
return PPCRecompilerImlGen_LookupReg(ppcImlGenContext, mappedName, IMLRegFormat::I32);
|
||||
}
|
||||
|
||||
IMLReg _GetRegGPR(ppcImlGenContext_t* ppcImlGenContext, uint32 index)
|
||||
@@ -243,14 +242,15 @@ IMLReg _GetRegTemporaryS8(ppcImlGenContext_t* ppcImlGenContext, uint32 index)
|
||||
*/
|
||||
IMLReg PPCRecompilerImlGen_loadFPRRegister(ppcImlGenContext_t* ppcImlGenContext, uint32 mappedName, bool loadNew)
|
||||
{
|
||||
if( loadNew == false )
|
||||
{
|
||||
uint32 loadedRegisterIndex = PPCRecompilerImlGen_findFPRRegisterByMappedName(ppcImlGenContext, mappedName);
|
||||
if( loadedRegisterIndex != PPC_REC_INVALID_REGISTER )
|
||||
return IMLReg(IMLRegFormat::F64, IMLRegFormat::F64, 0, loadedRegisterIndex);
|
||||
}
|
||||
uint32 registerIndex = PPCRecompilerImlGen_getAndLockFreeTemporaryFPR(ppcImlGenContext, mappedName);
|
||||
return IMLReg(IMLRegFormat::F64, IMLRegFormat::F64, 0, registerIndex);
|
||||
//if( loadNew == false )
|
||||
//{
|
||||
// uint32 loadedRegisterIndex = PPCRecompilerImlGen_findFPRRegisterByMappedName(ppcImlGenContext, mappedName);
|
||||
// if( loadedRegisterIndex != PPC_REC_INVALID_REGISTER )
|
||||
// return IMLReg(IMLRegFormat::F64, IMLRegFormat::F64, 0, loadedRegisterIndex);
|
||||
//}
|
||||
//uint32 registerIndex = PPCRecompilerImlGen_getAndLockFreeTemporaryFPR(ppcImlGenContext, mappedName);
|
||||
//return IMLReg(IMLRegFormat::F64, IMLRegFormat::F64, 0, registerIndex);
|
||||
return PPCRecompilerImlGen_LookupReg(ppcImlGenContext, mappedName, IMLRegFormat::F64);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -259,11 +259,12 @@ IMLReg PPCRecompilerImlGen_loadFPRRegister(ppcImlGenContext_t* ppcImlGenContext,
|
||||
*/
|
||||
IMLReg PPCRecompilerImlGen_loadOverwriteFPRRegister(ppcImlGenContext_t* ppcImlGenContext, uint32 mappedName)
|
||||
{
|
||||
uint32 loadedRegisterIndex = PPCRecompilerImlGen_findFPRRegisterByMappedName(ppcImlGenContext, mappedName);
|
||||
if( loadedRegisterIndex != PPC_REC_INVALID_REGISTER )
|
||||
return IMLReg(IMLRegFormat::F64, IMLRegFormat::F64, 0, loadedRegisterIndex);
|
||||
uint32 registerIndex = PPCRecompilerImlGen_getAndLockFreeTemporaryFPR(ppcImlGenContext, mappedName);
|
||||
return IMLReg(IMLRegFormat::F64, IMLRegFormat::F64, 0, registerIndex);
|
||||
//uint32 loadedRegisterIndex = PPCRecompilerImlGen_findFPRRegisterByMappedName(ppcImlGenContext, mappedName);
|
||||
//if( loadedRegisterIndex != PPC_REC_INVALID_REGISTER )
|
||||
// return IMLReg(IMLRegFormat::F64, IMLRegFormat::F64, 0, loadedRegisterIndex);
|
||||
//uint32 registerIndex = PPCRecompilerImlGen_getAndLockFreeTemporaryFPR(ppcImlGenContext, mappedName);
|
||||
//return IMLReg(IMLRegFormat::F64, IMLRegFormat::F64, 0, registerIndex);
|
||||
return PPCRecompilerImlGen_LookupReg(ppcImlGenContext, mappedName, IMLRegFormat::F64);
|
||||
}
|
||||
|
||||
bool PPCRecompiler_canInlineFunction(MPTR functionPtr, sint32* functionInstructionCount)
|
||||
|
||||
@@ -44,12 +44,12 @@ public:
|
||||
|
||||
void add(std::string_view appendedStr)
|
||||
{
|
||||
size_t remainingLen = this->limit - this->length;
|
||||
if (this->length + appendedStr.size() + 1 >= this->limit)
|
||||
_reserve(std::max<uint32>(this->length + appendedStr.size() + 64, this->limit + this->limit / 2));
|
||||
size_t copyLen = appendedStr.size();
|
||||
if (remainingLen > copyLen)
|
||||
copyLen = remainingLen;
|
||||
char* outputStart = (char*)(this->str + this->length);
|
||||
std::copy(appendedStr.data(), appendedStr.data() + copyLen, outputStart);
|
||||
this->length += copyLen;
|
||||
outputStart[copyLen] = '\0';
|
||||
}
|
||||
|
||||
@@ -79,6 +79,13 @@ public:
|
||||
}
|
||||
|
||||
private:
|
||||
void _reserve(uint32 newLimit)
|
||||
{
|
||||
cemu_assert_debug(newLimit > length);
|
||||
this->str = (uint8*)realloc(this->str, newLimit + 4);
|
||||
this->limit = newLimit;
|
||||
}
|
||||
|
||||
uint8* str;
|
||||
uint32 length; /* in bytes */
|
||||
uint32 limit; /* in bytes */
|
||||
|
||||
Reference in New Issue
Block a user