diff --git a/src/Cafe/CMakeLists.txt b/src/Cafe/CMakeLists.txt index 91badaf5..bbe28a9a 100644 --- a/src/Cafe/CMakeLists.txt +++ b/src/Cafe/CMakeLists.txt @@ -73,7 +73,7 @@ add_library(CemuCafe HW/Espresso/Recompiler/IML/IMLInstruction.cpp HW/Espresso/Recompiler/IML/IMLInstruction.h HW/Espresso/Recompiler/IML/IMLDebug.cpp - HW/Espresso/Recompiler/PPCRecompilerImlAnalyzer.cpp + HW/Espresso/Recompiler/IML/IMLAnalyzer.cpp HW/Espresso/Recompiler/PPCRecompilerImlGen.cpp HW/Espresso/Recompiler/PPCRecompilerImlGenFPU.cpp HW/Espresso/Recompiler/PPCRecompilerIml.h diff --git a/src/Cafe/HW/Espresso/Recompiler/IML/IML.h b/src/Cafe/HW/Espresso/Recompiler/IML/IML.h index 6f103087..6619e75a 100644 --- a/src/Cafe/HW/Espresso/Recompiler/IML/IML.h +++ b/src/Cafe/HW/Espresso/Recompiler/IML/IML.h @@ -1,3 +1,18 @@ +#pragma once + +#include "IMLInstruction.h" +#include "IMLSegment.h" + +// analyzer +struct PPCRecCRTracking_t +{ + uint32 readCRBits; + uint32 writtenCRBits; +}; + +bool IMLAnalyzer_IsTightFiniteLoop(IMLSegment* imlSegment); +bool IMLAnalyzer_CanTypeWriteCR(IMLInstruction* imlInstruction); +void IMLAnalyzer_GetCRTracking(IMLInstruction* imlInstruction, PPCRecCRTracking_t* crTracking); // debug void IMLDebug_DumpSegment(struct IMLSegment* imlSegment, sint32 segmentIndex, bool printLivenessRangeInfo = false); diff --git a/src/Cafe/HW/Espresso/Recompiler/PPCRecompilerImlAnalyzer.cpp b/src/Cafe/HW/Espresso/Recompiler/IML/IMLAnalyzer.cpp similarity index 89% rename from src/Cafe/HW/Espresso/Recompiler/PPCRecompilerImlAnalyzer.cpp rename to src/Cafe/HW/Espresso/Recompiler/IML/IMLAnalyzer.cpp index 8c976e8f..160554d6 100644 --- a/src/Cafe/HW/Espresso/Recompiler/PPCRecompilerImlAnalyzer.cpp +++ b/src/Cafe/HW/Espresso/Recompiler/IML/IMLAnalyzer.cpp @@ -1,12 +1,13 @@ -#include "PPCRecompiler.h" -#include "PPCRecompilerIml.h" +#include "IML.h" +//#include "PPCRecompilerIml.h" #include "util/helpers/fixedSizeList.h" + #include "Cafe/HW/Espresso/Interpreter/PPCInterpreterInternal.h" /* * Initializes a single segment and returns true if it is a finite loop */ -bool PPCRecompilerImlAnalyzer_isTightFiniteLoop(IMLSegment* imlSegment) +bool IMLAnalyzer_IsTightFiniteLoop(IMLSegment* imlSegment) { bool isTightFiniteLoop = false; // base criteria, must jump to beginning of same segment @@ -35,12 +36,12 @@ bool PPCRecompilerImlAnalyzer_isTightFiniteLoop(IMLSegment* imlSegment) { // remove all registers from the list that are modified by non-ADD/SUB instructions // todo: We should also cover the case where ADD+SUB on the same register cancel the effect out - PPCImlOptimizerUsedRegisters_t registersUsed; + IMLUsedRegisters registersUsed; for (const IMLInstruction& instIt : imlSegment->imlList) { if (instIt.type == PPCREC_IML_TYPE_R_S32 && (instIt.operation == PPCREC_IML_OP_ADD || instIt.operation == PPCREC_IML_OP_SUB)) continue; - PPCRecompiler_checkRegisterUsage(nullptr, &instIt, ®istersUsed); + instIt.CheckRegisterUsage(®istersUsed); if(registersUsed.writtenNamedReg1 < 0) continue; list_modifiedRegisters.remove(registersUsed.writtenNamedReg1); @@ -56,7 +57,7 @@ bool PPCRecompilerImlAnalyzer_isTightFiniteLoop(IMLSegment* imlSegment) /* * Returns true if the imlInstruction can overwrite CR (depending on value of ->crRegister) */ -bool PPCRecompilerImlAnalyzer_canTypeWriteCR(IMLInstruction* imlInstruction) +bool IMLAnalyzer_CanTypeWriteCR(IMLInstruction* imlInstruction) { if (imlInstruction->type == PPCREC_IML_TYPE_R_R) return true; @@ -77,7 +78,7 @@ bool PPCRecompilerImlAnalyzer_canTypeWriteCR(IMLInstruction* imlInstruction) return false; } -void PPCRecompilerImlAnalyzer_getCRTracking(IMLInstruction* imlInstruction, PPCRecCRTracking_t* crTracking) +void IMLAnalyzer_GetCRTracking(IMLInstruction* imlInstruction, PPCRecCRTracking_t* crTracking) { crTracking->readCRBits = 0; crTracking->writtenCRBits = 0; @@ -125,7 +126,7 @@ void PPCRecompilerImlAnalyzer_getCRTracking(IMLInstruction* imlInstruction, PPCR else assert_dbg(); } - else if (PPCRecompilerImlAnalyzer_canTypeWriteCR(imlInstruction) && imlInstruction->crRegister >= 0 && imlInstruction->crRegister <= 7) + else if (IMLAnalyzer_CanTypeWriteCR(imlInstruction) && imlInstruction->crRegister >= 0 && imlInstruction->crRegister <= 7) { crTracking->writtenCRBits |= (0xF << (imlInstruction->crRegister * 4)); } @@ -134,4 +135,4 @@ void PPCRecompilerImlAnalyzer_getCRTracking(IMLInstruction* imlInstruction, PPCR // overwrites CR0 crTracking->writtenCRBits |= (0xF << 0); } -} +} \ No newline at end of file diff --git a/src/Cafe/HW/Espresso/Recompiler/IML/IMLInstruction.cpp b/src/Cafe/HW/Espresso/Recompiler/IML/IMLInstruction.cpp index e69de29b..1a0d8c55 100644 --- a/src/Cafe/HW/Espresso/Recompiler/IML/IMLInstruction.cpp +++ b/src/Cafe/HW/Espresso/Recompiler/IML/IMLInstruction.cpp @@ -0,0 +1,846 @@ +#include "IMLInstruction.h" +#include "IML.h" + +#include "../PPCRecompiler.h" +#include "../PPCRecompilerIml.h" + +void IMLInstruction::CheckRegisterUsage(IMLUsedRegisters* registersUsed) const +{ + registersUsed->readNamedReg1 = -1; + registersUsed->readNamedReg2 = -1; + registersUsed->readNamedReg3 = -1; + registersUsed->writtenNamedReg1 = -1; + registersUsed->readFPR1 = -1; + registersUsed->readFPR2 = -1; + registersUsed->readFPR3 = -1; + registersUsed->readFPR4 = -1; + registersUsed->writtenFPR1 = -1; + if (type == PPCREC_IML_TYPE_R_NAME) + { + registersUsed->writtenNamedReg1 = op_r_name.registerIndex; + } + else if (type == PPCREC_IML_TYPE_NAME_R) + { + registersUsed->readNamedReg1 = op_r_name.registerIndex; + } + else if (type == PPCREC_IML_TYPE_R_R) + { + if (operation == PPCREC_IML_OP_COMPARE_SIGNED || operation == PPCREC_IML_OP_COMPARE_UNSIGNED || operation == PPCREC_IML_OP_DCBZ) + { + // both operands are read only + registersUsed->readNamedReg1 = op_r_r.registerResult; + registersUsed->readNamedReg2 = op_r_r.registerA; + } + else if ( + operation == PPCREC_IML_OP_OR || + operation == PPCREC_IML_OP_AND || + operation == PPCREC_IML_OP_XOR || + operation == PPCREC_IML_OP_ADD || + operation == PPCREC_IML_OP_ADD_CARRY || + operation == PPCREC_IML_OP_ADD_CARRY_ME || + operation == PPCREC_IML_OP_SUB_CARRY_UPDATE_CARRY) + { + // result is read and written, operand is read + registersUsed->writtenNamedReg1 = op_r_r.registerResult; + registersUsed->readNamedReg1 = op_r_r.registerResult; + registersUsed->readNamedReg2 = op_r_r.registerA; + } + else if ( + operation == PPCREC_IML_OP_ASSIGN || + operation == PPCREC_IML_OP_ENDIAN_SWAP || + operation == PPCREC_IML_OP_CNTLZW || + operation == PPCREC_IML_OP_NOT || + operation == PPCREC_IML_OP_NEG || + operation == PPCREC_IML_OP_ASSIGN_S16_TO_S32 || + operation == PPCREC_IML_OP_ASSIGN_S8_TO_S32) + { + // result is written, operand is read + registersUsed->writtenNamedReg1 = op_r_r.registerResult; + registersUsed->readNamedReg1 = op_r_r.registerA; + } + else + cemu_assert_unimplemented(); + } + else if (type == PPCREC_IML_TYPE_R_S32) + { + if (operation == PPCREC_IML_OP_COMPARE_SIGNED || operation == PPCREC_IML_OP_COMPARE_UNSIGNED || operation == PPCREC_IML_OP_MTCRF) + { + // operand register is read only + registersUsed->readNamedReg1 = op_r_immS32.registerIndex; + } + else if (operation == PPCREC_IML_OP_ADD || + operation == PPCREC_IML_OP_SUB || + operation == PPCREC_IML_OP_AND || + operation == PPCREC_IML_OP_OR || + operation == PPCREC_IML_OP_XOR || + operation == PPCREC_IML_OP_LEFT_ROTATE) + { + // operand register is read and write + registersUsed->readNamedReg1 = op_r_immS32.registerIndex; + registersUsed->writtenNamedReg1 = op_r_immS32.registerIndex; + } + else + { + // operand register is write only + // todo - use explicit lists, avoid default cases + registersUsed->writtenNamedReg1 = op_r_immS32.registerIndex; + } + } + else if (type == PPCREC_IML_TYPE_CONDITIONAL_R_S32) + { + if (operation == PPCREC_IML_OP_ASSIGN) + { + // result is written, but also considered read (in case the condition fails) + registersUsed->readNamedReg1 = op_conditional_r_s32.registerIndex; + registersUsed->writtenNamedReg1 = op_conditional_r_s32.registerIndex; + } + else + cemu_assert_unimplemented(); + } + else if (type == PPCREC_IML_TYPE_R_R_S32) + { + if (operation == PPCREC_IML_OP_RLWIMI) + { + // result and operand register are both read, result is written + registersUsed->writtenNamedReg1 = op_r_r_s32.registerResult; + registersUsed->readNamedReg1 = op_r_r_s32.registerResult; + registersUsed->readNamedReg2 = op_r_r_s32.registerA; + } + else + { + // result is write only and operand is read only + registersUsed->writtenNamedReg1 = op_r_r_s32.registerResult; + registersUsed->readNamedReg1 = op_r_r_s32.registerA; + } + } + else if (type == PPCREC_IML_TYPE_R_R_R) + { + // in all cases result is written and other operands are read only + registersUsed->writtenNamedReg1 = op_r_r_r.registerResult; + registersUsed->readNamedReg1 = op_r_r_r.registerA; + registersUsed->readNamedReg2 = op_r_r_r.registerB; + } + else if (type == PPCREC_IML_TYPE_CJUMP || type == PPCREC_IML_TYPE_CJUMP_CYCLE_CHECK) + { + // no effect on registers + } + else if (type == PPCREC_IML_TYPE_NO_OP) + { + // no effect on registers + } + else if (type == PPCREC_IML_TYPE_MACRO) + { + if (operation == PPCREC_IML_MACRO_BL || operation == PPCREC_IML_MACRO_B_FAR || operation == PPCREC_IML_MACRO_BLR || operation == PPCREC_IML_MACRO_BLRL || operation == PPCREC_IML_MACRO_BCTR || operation == PPCREC_IML_MACRO_BCTRL || 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) + { + // no effect on registers + } + else + cemu_assert_unimplemented(); + } + else if (type == PPCREC_IML_TYPE_LOAD) + { + registersUsed->writtenNamedReg1 = op_storeLoad.registerData; + if (op_storeLoad.registerMem != PPC_REC_INVALID_REGISTER) + registersUsed->readNamedReg1 = op_storeLoad.registerMem; + } + else if (type == PPCREC_IML_TYPE_LOAD_INDEXED) + { + registersUsed->writtenNamedReg1 = op_storeLoad.registerData; + if (op_storeLoad.registerMem != PPC_REC_INVALID_REGISTER) + registersUsed->readNamedReg1 = op_storeLoad.registerMem; + if (op_storeLoad.registerMem2 != PPC_REC_INVALID_REGISTER) + registersUsed->readNamedReg2 = op_storeLoad.registerMem2; + } + else if (type == PPCREC_IML_TYPE_STORE) + { + registersUsed->readNamedReg1 = op_storeLoad.registerData; + if (op_storeLoad.registerMem != PPC_REC_INVALID_REGISTER) + registersUsed->readNamedReg2 = op_storeLoad.registerMem; + } + else if (type == PPCREC_IML_TYPE_STORE_INDEXED) + { + registersUsed->readNamedReg1 = op_storeLoad.registerData; + if (op_storeLoad.registerMem != PPC_REC_INVALID_REGISTER) + registersUsed->readNamedReg2 = op_storeLoad.registerMem; + if (op_storeLoad.registerMem2 != PPC_REC_INVALID_REGISTER) + registersUsed->readNamedReg3 = op_storeLoad.registerMem2; + } + else if (type == PPCREC_IML_TYPE_CR) + { + // only affects cr register + } + else if (type == PPCREC_IML_TYPE_JUMPMARK) + { + // no effect on registers + } + else if (type == PPCREC_IML_TYPE_PPC_ENTER) + { + // no op + } + else if (type == PPCREC_IML_TYPE_FPR_R_NAME) + { + // fpr operation + registersUsed->writtenFPR1 = op_r_name.registerIndex; + } + else if (type == PPCREC_IML_TYPE_FPR_NAME_R) + { + // fpr operation + registersUsed->readFPR1 = op_r_name.registerIndex; + } + else if (type == PPCREC_IML_TYPE_FPR_LOAD) + { + // fpr load operation + registersUsed->writtenFPR1 = op_storeLoad.registerData; + // address is in gpr register + if (op_storeLoad.registerMem != PPC_REC_INVALID_REGISTER) + registersUsed->readNamedReg1 = op_storeLoad.registerMem; + // determine partially written result + switch (op_storeLoad.mode) + { + case PPCREC_FPR_LD_MODE_PSQ_GENERIC_PS0: + case PPCREC_FPR_LD_MODE_PSQ_GENERIC_PS0_PS1: + cemu_assert_debug(op_storeLoad.registerGQR != PPC_REC_INVALID_REGISTER); + registersUsed->readNamedReg2 = op_storeLoad.registerGQR; + break; + case PPCREC_FPR_LD_MODE_DOUBLE_INTO_PS0: + // PS1 remains the same + registersUsed->readFPR4 = op_storeLoad.registerData; + break; + case PPCREC_FPR_LD_MODE_SINGLE_INTO_PS0_PS1: + case PPCREC_FPR_LD_MODE_PSQ_FLOAT_PS0_PS1: + case PPCREC_FPR_LD_MODE_PSQ_FLOAT_PS0: + case PPCREC_FPR_LD_MODE_PSQ_S16_PS0: + case PPCREC_FPR_LD_MODE_PSQ_S16_PS0_PS1: + case PPCREC_FPR_LD_MODE_PSQ_U16_PS0_PS1: + case PPCREC_FPR_LD_MODE_PSQ_U16_PS0: + case PPCREC_FPR_LD_MODE_PSQ_S8_PS0_PS1: + case PPCREC_FPR_LD_MODE_PSQ_U8_PS0_PS1: + case PPCREC_FPR_LD_MODE_PSQ_U8_PS0: + case PPCREC_FPR_LD_MODE_PSQ_S8_PS0: + break; + default: + cemu_assert_unimplemented(); + } + } + else if (type == PPCREC_IML_TYPE_FPR_LOAD_INDEXED) + { + // fpr load operation + registersUsed->writtenFPR1 = op_storeLoad.registerData; + // address is in gpr registers + if (op_storeLoad.registerMem != PPC_REC_INVALID_REGISTER) + registersUsed->readNamedReg1 = op_storeLoad.registerMem; + if (op_storeLoad.registerMem2 != PPC_REC_INVALID_REGISTER) + registersUsed->readNamedReg2 = op_storeLoad.registerMem2; + // determine partially written result + switch (op_storeLoad.mode) + { + case PPCREC_FPR_LD_MODE_PSQ_GENERIC_PS0: + case PPCREC_FPR_LD_MODE_PSQ_GENERIC_PS0_PS1: + cemu_assert_debug(op_storeLoad.registerGQR != PPC_REC_INVALID_REGISTER); + registersUsed->readNamedReg3 = op_storeLoad.registerGQR; + break; + case PPCREC_FPR_LD_MODE_DOUBLE_INTO_PS0: + // PS1 remains the same + registersUsed->readFPR4 = op_storeLoad.registerData; + break; + case PPCREC_FPR_LD_MODE_SINGLE_INTO_PS0_PS1: + case PPCREC_FPR_LD_MODE_PSQ_FLOAT_PS0_PS1: + case PPCREC_FPR_LD_MODE_PSQ_FLOAT_PS0: + case PPCREC_FPR_LD_MODE_PSQ_S16_PS0: + case PPCREC_FPR_LD_MODE_PSQ_S16_PS0_PS1: + case PPCREC_FPR_LD_MODE_PSQ_U16_PS0_PS1: + case PPCREC_FPR_LD_MODE_PSQ_U16_PS0: + case PPCREC_FPR_LD_MODE_PSQ_S8_PS0_PS1: + case PPCREC_FPR_LD_MODE_PSQ_U8_PS0_PS1: + case PPCREC_FPR_LD_MODE_PSQ_U8_PS0: + break; + default: + cemu_assert_unimplemented(); + } + } + else if (type == PPCREC_IML_TYPE_FPR_STORE) + { + // fpr store operation + registersUsed->readFPR1 = op_storeLoad.registerData; + if (op_storeLoad.registerMem != PPC_REC_INVALID_REGISTER) + registersUsed->readNamedReg1 = op_storeLoad.registerMem; + // PSQ generic stores also access GQR + switch (op_storeLoad.mode) + { + case PPCREC_FPR_ST_MODE_PSQ_GENERIC_PS0: + case PPCREC_FPR_ST_MODE_PSQ_GENERIC_PS0_PS1: + cemu_assert_debug(op_storeLoad.registerGQR != PPC_REC_INVALID_REGISTER); + registersUsed->readNamedReg2 = op_storeLoad.registerGQR; + break; + default: + break; + } + } + else if (type == PPCREC_IML_TYPE_FPR_STORE_INDEXED) + { + // fpr store operation + registersUsed->readFPR1 = op_storeLoad.registerData; + // address is in gpr registers + if (op_storeLoad.registerMem != PPC_REC_INVALID_REGISTER) + registersUsed->readNamedReg1 = op_storeLoad.registerMem; + if (op_storeLoad.registerMem2 != PPC_REC_INVALID_REGISTER) + registersUsed->readNamedReg2 = op_storeLoad.registerMem2; + // PSQ generic stores also access GQR + switch (op_storeLoad.mode) + { + case PPCREC_FPR_ST_MODE_PSQ_GENERIC_PS0: + case PPCREC_FPR_ST_MODE_PSQ_GENERIC_PS0_PS1: + cemu_assert_debug(op_storeLoad.registerGQR != PPC_REC_INVALID_REGISTER); + registersUsed->readNamedReg3 = op_storeLoad.registerGQR; + break; + default: + break; + } + } + else if (type == PPCREC_IML_TYPE_FPR_R_R) + { + // fpr operation + if (operation == PPCREC_IML_OP_FPR_COPY_BOTTOM_TO_BOTTOM_AND_TOP || + operation == PPCREC_IML_OP_FPR_COPY_TOP_TO_BOTTOM_AND_TOP || + operation == PPCREC_IML_OP_FPR_COPY_BOTTOM_AND_TOP_SWAPPED || + operation == PPCREC_IML_OP_ASSIGN || + operation == PPCREC_IML_OP_FPR_BOTTOM_FRES_TO_BOTTOM_AND_TOP || + operation == PPCREC_IML_OP_FPR_NEGATE_PAIR || + operation == PPCREC_IML_OP_FPR_ABS_PAIR || + operation == PPCREC_IML_OP_FPR_FRES_PAIR || + operation == PPCREC_IML_OP_FPR_FRSQRTE_PAIR) + { + // operand read, result written + registersUsed->readFPR1 = op_fpr_r_r.registerOperand; + registersUsed->writtenFPR1 = op_fpr_r_r.registerResult; + } + else if ( + operation == PPCREC_IML_OP_FPR_COPY_BOTTOM_TO_BOTTOM || + operation == PPCREC_IML_OP_FPR_COPY_BOTTOM_TO_TOP || + operation == PPCREC_IML_OP_FPR_COPY_TOP_TO_TOP || + operation == PPCREC_IML_OP_FPR_COPY_TOP_TO_BOTTOM || + operation == PPCREC_IML_OP_FPR_EXPAND_BOTTOM32_TO_BOTTOM64_AND_TOP64 || + operation == PPCREC_IML_OP_FPR_BOTTOM_FCTIWZ || + operation == PPCREC_IML_OP_FPR_BOTTOM_RECIPROCAL_SQRT + ) + { + // operand read, result read and (partially) written + registersUsed->readFPR1 = op_fpr_r_r.registerOperand; + registersUsed->readFPR4 = op_fpr_r_r.registerResult; + registersUsed->writtenFPR1 = op_fpr_r_r.registerResult; + } + else if (operation == PPCREC_IML_OP_FPR_MULTIPLY_BOTTOM || + operation == PPCREC_IML_OP_FPR_MULTIPLY_PAIR || + operation == PPCREC_IML_OP_FPR_DIVIDE_BOTTOM || + operation == PPCREC_IML_OP_FPR_DIVIDE_PAIR || + operation == PPCREC_IML_OP_FPR_ADD_BOTTOM || + operation == PPCREC_IML_OP_FPR_ADD_PAIR || + operation == PPCREC_IML_OP_FPR_SUB_PAIR || + operation == PPCREC_IML_OP_FPR_SUB_BOTTOM) + { + // operand read, result read and written + registersUsed->readFPR1 = op_fpr_r_r.registerOperand; + registersUsed->readFPR2 = op_fpr_r_r.registerResult; + registersUsed->writtenFPR1 = op_fpr_r_r.registerResult; + + } + else if (operation == PPCREC_IML_OP_FPR_FCMPU_BOTTOM || + operation == PPCREC_IML_OP_FPR_FCMPU_TOP || + operation == PPCREC_IML_OP_FPR_FCMPO_BOTTOM) + { + // operand read, result read + registersUsed->readFPR1 = op_fpr_r_r.registerOperand; + registersUsed->readFPR2 = op_fpr_r_r.registerResult; + } + else + cemu_assert_unimplemented(); + } + else if (type == PPCREC_IML_TYPE_FPR_R_R_R) + { + // fpr operation + registersUsed->readFPR1 = op_fpr_r_r_r.registerOperandA; + registersUsed->readFPR2 = op_fpr_r_r_r.registerOperandB; + registersUsed->writtenFPR1 = op_fpr_r_r_r.registerResult; + // handle partially written result + switch (operation) + { + case PPCREC_IML_OP_FPR_MULTIPLY_BOTTOM: + case PPCREC_IML_OP_FPR_ADD_BOTTOM: + case PPCREC_IML_OP_FPR_SUB_BOTTOM: + registersUsed->readFPR4 = op_fpr_r_r_r.registerResult; + break; + case PPCREC_IML_OP_FPR_SUB_PAIR: + break; + default: + cemu_assert_unimplemented(); + } + } + else if (type == PPCREC_IML_TYPE_FPR_R_R_R_R) + { + // fpr operation + registersUsed->readFPR1 = op_fpr_r_r_r_r.registerOperandA; + registersUsed->readFPR2 = op_fpr_r_r_r_r.registerOperandB; + registersUsed->readFPR3 = op_fpr_r_r_r_r.registerOperandC; + registersUsed->writtenFPR1 = op_fpr_r_r_r_r.registerResult; + // handle partially written result + switch (operation) + { + case PPCREC_IML_OP_FPR_SELECT_BOTTOM: + registersUsed->readFPR4 = op_fpr_r_r_r_r.registerResult; + break; + case PPCREC_IML_OP_FPR_SUM0: + case PPCREC_IML_OP_FPR_SUM1: + case PPCREC_IML_OP_FPR_SELECT_PAIR: + break; + default: + cemu_assert_unimplemented(); + } + } + else if (type == PPCREC_IML_TYPE_FPR_R) + { + // fpr operation + if (operation == PPCREC_IML_OP_FPR_NEGATE_BOTTOM || + operation == PPCREC_IML_OP_FPR_ABS_BOTTOM || + operation == PPCREC_IML_OP_FPR_NEGATIVE_ABS_BOTTOM || + operation == PPCREC_IML_OP_FPR_EXPAND_BOTTOM32_TO_BOTTOM64_AND_TOP64 || + operation == PPCREC_IML_OP_FPR_ROUND_TO_SINGLE_PRECISION_BOTTOM || + operation == PPCREC_IML_OP_FPR_ROUND_TO_SINGLE_PRECISION_PAIR) + { + registersUsed->readFPR1 = op_fpr_r.registerResult; + registersUsed->writtenFPR1 = op_fpr_r.registerResult; + } + else + cemu_assert_unimplemented(); + } + else + { + cemu_assert_unimplemented(); + } +} + +#define replaceRegister(__x,__r,__n) (((__x)==(__r))?(__n):(__x)) + +sint32 replaceRegisterMultiple(sint32 reg, sint32 match[4], sint32 replaced[4]) +{ + for (sint32 i = 0; i < 4; i++) + { + if (match[i] < 0) + continue; + if (reg == match[i]) + { + return replaced[i]; + } + } + return reg; +} + +void IMLInstruction::ReplaceGPRRegisterUsageMultiple(sint32 gprRegisterSearched[4], sint32 gprRegisterReplaced[4]) +{ + if (type == PPCREC_IML_TYPE_R_NAME) + { + op_r_name.registerIndex = replaceRegisterMultiple(op_r_name.registerIndex, gprRegisterSearched, gprRegisterReplaced); + } + else if (type == PPCREC_IML_TYPE_NAME_R) + { + op_r_name.registerIndex = replaceRegisterMultiple(op_r_name.registerIndex, gprRegisterSearched, gprRegisterReplaced); + } + else if (type == PPCREC_IML_TYPE_R_R) + { + op_r_r.registerResult = replaceRegisterMultiple(op_r_r.registerResult, gprRegisterSearched, gprRegisterReplaced); + op_r_r.registerA = replaceRegisterMultiple(op_r_r.registerA, gprRegisterSearched, gprRegisterReplaced); + } + else if (type == PPCREC_IML_TYPE_R_S32) + { + op_r_immS32.registerIndex = replaceRegisterMultiple(op_r_immS32.registerIndex, gprRegisterSearched, gprRegisterReplaced); + } + else if (type == PPCREC_IML_TYPE_CONDITIONAL_R_S32) + { + op_conditional_r_s32.registerIndex = replaceRegisterMultiple(op_conditional_r_s32.registerIndex, gprRegisterSearched, gprRegisterReplaced); + } + else if (type == PPCREC_IML_TYPE_R_R_S32) + { + // in all cases result is written and other operand is read only + op_r_r_s32.registerResult = replaceRegisterMultiple(op_r_r_s32.registerResult, gprRegisterSearched, gprRegisterReplaced); + op_r_r_s32.registerA = replaceRegisterMultiple(op_r_r_s32.registerA, gprRegisterSearched, gprRegisterReplaced); + } + else if (type == PPCREC_IML_TYPE_R_R_R) + { + // in all cases result is written and other operands are read only + op_r_r_r.registerResult = replaceRegisterMultiple(op_r_r_r.registerResult, gprRegisterSearched, gprRegisterReplaced); + op_r_r_r.registerA = replaceRegisterMultiple(op_r_r_r.registerA, gprRegisterSearched, gprRegisterReplaced); + op_r_r_r.registerB = replaceRegisterMultiple(op_r_r_r.registerB, gprRegisterSearched, gprRegisterReplaced); + } + else if (type == PPCREC_IML_TYPE_CJUMP || type == PPCREC_IML_TYPE_CJUMP_CYCLE_CHECK) + { + // no effect on registers + } + else if (type == PPCREC_IML_TYPE_NO_OP) + { + // no effect on registers + } + else if (type == PPCREC_IML_TYPE_MACRO) + { + if (operation == PPCREC_IML_MACRO_BL || operation == PPCREC_IML_MACRO_B_FAR || operation == PPCREC_IML_MACRO_BLR || operation == PPCREC_IML_MACRO_BLRL || operation == PPCREC_IML_MACRO_BCTR || operation == PPCREC_IML_MACRO_BCTRL || 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) + { + // no effect on registers + } + else + { + cemu_assert_unimplemented(); + } + } + else if (type == PPCREC_IML_TYPE_LOAD) + { + op_storeLoad.registerData = replaceRegisterMultiple(op_storeLoad.registerData, gprRegisterSearched, gprRegisterReplaced); + if (op_storeLoad.registerMem != PPC_REC_INVALID_REGISTER) + { + op_storeLoad.registerMem = replaceRegisterMultiple(op_storeLoad.registerMem, gprRegisterSearched, gprRegisterReplaced); + } + } + else if (type == PPCREC_IML_TYPE_LOAD_INDEXED) + { + op_storeLoad.registerData = replaceRegisterMultiple(op_storeLoad.registerData, gprRegisterSearched, gprRegisterReplaced); + if (op_storeLoad.registerMem != PPC_REC_INVALID_REGISTER) + op_storeLoad.registerMem = replaceRegisterMultiple(op_storeLoad.registerMem, gprRegisterSearched, gprRegisterReplaced); + if (op_storeLoad.registerMem2 != PPC_REC_INVALID_REGISTER) + op_storeLoad.registerMem2 = replaceRegisterMultiple(op_storeLoad.registerMem2, gprRegisterSearched, gprRegisterReplaced); + } + else if (type == PPCREC_IML_TYPE_STORE) + { + op_storeLoad.registerData = replaceRegisterMultiple(op_storeLoad.registerData, gprRegisterSearched, gprRegisterReplaced); + if (op_storeLoad.registerMem != PPC_REC_INVALID_REGISTER) + op_storeLoad.registerMem = replaceRegisterMultiple(op_storeLoad.registerMem, gprRegisterSearched, gprRegisterReplaced); + } + else if (type == PPCREC_IML_TYPE_STORE_INDEXED) + { + op_storeLoad.registerData = replaceRegisterMultiple(op_storeLoad.registerData, gprRegisterSearched, gprRegisterReplaced); + if (op_storeLoad.registerMem != PPC_REC_INVALID_REGISTER) + op_storeLoad.registerMem = replaceRegisterMultiple(op_storeLoad.registerMem, gprRegisterSearched, gprRegisterReplaced); + if (op_storeLoad.registerMem2 != PPC_REC_INVALID_REGISTER) + op_storeLoad.registerMem2 = replaceRegisterMultiple(op_storeLoad.registerMem2, gprRegisterSearched, gprRegisterReplaced); + } + else if (type == PPCREC_IML_TYPE_CR) + { + // only affects cr register + } + else if (type == PPCREC_IML_TYPE_JUMPMARK) + { + // no effect on registers + } + else if (type == PPCREC_IML_TYPE_PPC_ENTER) + { + // no op + } + else if (type == PPCREC_IML_TYPE_FPR_R_NAME) + { + + } + else if (type == PPCREC_IML_TYPE_FPR_NAME_R) + { + + } + else if (type == PPCREC_IML_TYPE_FPR_LOAD) + { + if (op_storeLoad.registerMem != PPC_REC_INVALID_REGISTER) + { + op_storeLoad.registerMem = replaceRegisterMultiple(op_storeLoad.registerMem, gprRegisterSearched, gprRegisterReplaced); + } + if (op_storeLoad.registerGQR != PPC_REC_INVALID_REGISTER) + { + op_storeLoad.registerGQR = replaceRegisterMultiple(op_storeLoad.registerGQR, gprRegisterSearched, gprRegisterReplaced); + } + } + else if (type == PPCREC_IML_TYPE_FPR_LOAD_INDEXED) + { + if (op_storeLoad.registerMem != PPC_REC_INVALID_REGISTER) + { + op_storeLoad.registerMem = replaceRegisterMultiple(op_storeLoad.registerMem, gprRegisterSearched, gprRegisterReplaced); + } + if (op_storeLoad.registerMem2 != PPC_REC_INVALID_REGISTER) + { + op_storeLoad.registerMem2 = replaceRegisterMultiple(op_storeLoad.registerMem2, gprRegisterSearched, gprRegisterReplaced); + } + if (op_storeLoad.registerGQR != PPC_REC_INVALID_REGISTER) + { + op_storeLoad.registerGQR = replaceRegisterMultiple(op_storeLoad.registerGQR, gprRegisterSearched, gprRegisterReplaced); + } + } + else if (type == PPCREC_IML_TYPE_FPR_STORE) + { + if (op_storeLoad.registerMem != PPC_REC_INVALID_REGISTER) + { + op_storeLoad.registerMem = replaceRegisterMultiple(op_storeLoad.registerMem, gprRegisterSearched, gprRegisterReplaced); + } + if (op_storeLoad.registerGQR != PPC_REC_INVALID_REGISTER) + { + op_storeLoad.registerGQR = replaceRegisterMultiple(op_storeLoad.registerGQR, gprRegisterSearched, gprRegisterReplaced); + } + } + else if (type == PPCREC_IML_TYPE_FPR_STORE_INDEXED) + { + if (op_storeLoad.registerMem != PPC_REC_INVALID_REGISTER) + { + op_storeLoad.registerMem = replaceRegisterMultiple(op_storeLoad.registerMem, gprRegisterSearched, gprRegisterReplaced); + } + if (op_storeLoad.registerMem2 != PPC_REC_INVALID_REGISTER) + { + op_storeLoad.registerMem2 = replaceRegisterMultiple(op_storeLoad.registerMem2, gprRegisterSearched, gprRegisterReplaced); + } + if (op_storeLoad.registerGQR != PPC_REC_INVALID_REGISTER) + { + op_storeLoad.registerGQR = replaceRegisterMultiple(op_storeLoad.registerGQR, gprRegisterSearched, gprRegisterReplaced); + } + } + 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) + { + } + else if (type == PPCREC_IML_TYPE_FPR_R) + { + } + else + { + cemu_assert_unimplemented(); + } +} + +void IMLInstruction::ReplaceFPRRegisterUsageMultiple(sint32 fprRegisterSearched[4], sint32 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_CJUMP || type == PPCREC_IML_TYPE_CJUMP_CYCLE_CHECK) + { + // no effect on registers + } + else if (type == PPCREC_IML_TYPE_NO_OP) + { + // no effect on registers + } + 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_CR) + { + // only affects cr register + } + else if (type == PPCREC_IML_TYPE_JUMPMARK) + { + // no effect on registers + } + else if (type == PPCREC_IML_TYPE_PPC_ENTER) + { + // no op + } + else if (type == PPCREC_IML_TYPE_FPR_R_NAME) + { + op_r_name.registerIndex = replaceRegisterMultiple(op_r_name.registerIndex, fprRegisterSearched, fprRegisterReplaced); + } + else if (type == PPCREC_IML_TYPE_FPR_NAME_R) + { + op_r_name.registerIndex = replaceRegisterMultiple(op_r_name.registerIndex, fprRegisterSearched, fprRegisterReplaced); + } + else if (type == PPCREC_IML_TYPE_FPR_LOAD) + { + op_storeLoad.registerData = replaceRegisterMultiple(op_storeLoad.registerData, fprRegisterSearched, fprRegisterReplaced); + } + else if (type == PPCREC_IML_TYPE_FPR_LOAD_INDEXED) + { + op_storeLoad.registerData = replaceRegisterMultiple(op_storeLoad.registerData, fprRegisterSearched, fprRegisterReplaced); + } + else if (type == PPCREC_IML_TYPE_FPR_STORE) + { + op_storeLoad.registerData = replaceRegisterMultiple(op_storeLoad.registerData, fprRegisterSearched, fprRegisterReplaced); + } + else if (type == PPCREC_IML_TYPE_FPR_STORE_INDEXED) + { + op_storeLoad.registerData = replaceRegisterMultiple(op_storeLoad.registerData, fprRegisterSearched, fprRegisterReplaced); + } + else if (type == PPCREC_IML_TYPE_FPR_R_R) + { + op_fpr_r_r.registerResult = replaceRegisterMultiple(op_fpr_r_r.registerResult, fprRegisterSearched, fprRegisterReplaced); + op_fpr_r_r.registerOperand = replaceRegisterMultiple(op_fpr_r_r.registerOperand, fprRegisterSearched, fprRegisterReplaced); + } + else if (type == PPCREC_IML_TYPE_FPR_R_R_R) + { + op_fpr_r_r_r.registerResult = replaceRegisterMultiple(op_fpr_r_r_r.registerResult, fprRegisterSearched, fprRegisterReplaced); + op_fpr_r_r_r.registerOperandA = replaceRegisterMultiple(op_fpr_r_r_r.registerOperandA, fprRegisterSearched, fprRegisterReplaced); + op_fpr_r_r_r.registerOperandB = replaceRegisterMultiple(op_fpr_r_r_r.registerOperandB, fprRegisterSearched, fprRegisterReplaced); + } + else if (type == PPCREC_IML_TYPE_FPR_R_R_R_R) + { + op_fpr_r_r_r_r.registerResult = replaceRegisterMultiple(op_fpr_r_r_r_r.registerResult, fprRegisterSearched, fprRegisterReplaced); + op_fpr_r_r_r_r.registerOperandA = replaceRegisterMultiple(op_fpr_r_r_r_r.registerOperandA, fprRegisterSearched, fprRegisterReplaced); + op_fpr_r_r_r_r.registerOperandB = replaceRegisterMultiple(op_fpr_r_r_r_r.registerOperandB, fprRegisterSearched, fprRegisterReplaced); + op_fpr_r_r_r_r.registerOperandC = replaceRegisterMultiple(op_fpr_r_r_r_r.registerOperandC, fprRegisterSearched, fprRegisterReplaced); + } + else if (type == PPCREC_IML_TYPE_FPR_R) + { + op_fpr_r.registerResult = replaceRegisterMultiple(op_fpr_r.registerResult, fprRegisterSearched, fprRegisterReplaced); + } + else + { + cemu_assert_unimplemented(); + } +} + +void IMLInstruction::ReplaceFPRRegisterUsage(sint32 fprRegisterSearched, sint32 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) + { + // not affected + } + else if (type == PPCREC_IML_TYPE_R_R_R) + { + // not affected + } + else if (type == PPCREC_IML_TYPE_CJUMP || type == PPCREC_IML_TYPE_CJUMP_CYCLE_CHECK) + { + // no effect on registers + } + else if (type == PPCREC_IML_TYPE_NO_OP) + { + // no effect on registers + } + 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_CR) + { + // only affects cr register + } + else if (type == PPCREC_IML_TYPE_JUMPMARK) + { + // no effect on registers + } + else if (type == PPCREC_IML_TYPE_PPC_ENTER) + { + // no op + } + else if (type == PPCREC_IML_TYPE_FPR_R_NAME) + { + op_r_name.registerIndex = replaceRegister(op_r_name.registerIndex, fprRegisterSearched, fprRegisterReplaced); + } + else if (type == PPCREC_IML_TYPE_FPR_NAME_R) + { + op_r_name.registerIndex = replaceRegister(op_r_name.registerIndex, fprRegisterSearched, fprRegisterReplaced); + } + else if (type == PPCREC_IML_TYPE_FPR_LOAD) + { + op_storeLoad.registerData = replaceRegister(op_storeLoad.registerData, fprRegisterSearched, fprRegisterReplaced); + } + else if (type == PPCREC_IML_TYPE_FPR_LOAD_INDEXED) + { + op_storeLoad.registerData = replaceRegister(op_storeLoad.registerData, fprRegisterSearched, fprRegisterReplaced); + } + else if (type == PPCREC_IML_TYPE_FPR_STORE) + { + op_storeLoad.registerData = replaceRegister(op_storeLoad.registerData, fprRegisterSearched, fprRegisterReplaced); + } + else if (type == PPCREC_IML_TYPE_FPR_STORE_INDEXED) + { + op_storeLoad.registerData = replaceRegister(op_storeLoad.registerData, fprRegisterSearched, fprRegisterReplaced); + } + else if (type == PPCREC_IML_TYPE_FPR_R_R) + { + op_fpr_r_r.registerResult = replaceRegister(op_fpr_r_r.registerResult, fprRegisterSearched, fprRegisterReplaced); + op_fpr_r_r.registerOperand = replaceRegister(op_fpr_r_r.registerOperand, fprRegisterSearched, fprRegisterReplaced); + } + else if (type == PPCREC_IML_TYPE_FPR_R_R_R) + { + op_fpr_r_r_r.registerResult = replaceRegister(op_fpr_r_r_r.registerResult, fprRegisterSearched, fprRegisterReplaced); + op_fpr_r_r_r.registerOperandA = replaceRegister(op_fpr_r_r_r.registerOperandA, fprRegisterSearched, fprRegisterReplaced); + op_fpr_r_r_r.registerOperandB = replaceRegister(op_fpr_r_r_r.registerOperandB, fprRegisterSearched, fprRegisterReplaced); + } + else if (type == PPCREC_IML_TYPE_FPR_R_R_R_R) + { + op_fpr_r_r_r_r.registerResult = replaceRegister(op_fpr_r_r_r_r.registerResult, fprRegisterSearched, fprRegisterReplaced); + op_fpr_r_r_r_r.registerOperandA = replaceRegister(op_fpr_r_r_r_r.registerOperandA, fprRegisterSearched, fprRegisterReplaced); + op_fpr_r_r_r_r.registerOperandB = replaceRegister(op_fpr_r_r_r_r.registerOperandB, fprRegisterSearched, fprRegisterReplaced); + op_fpr_r_r_r_r.registerOperandC = replaceRegister(op_fpr_r_r_r_r.registerOperandC, fprRegisterSearched, fprRegisterReplaced); + } + else if (type == PPCREC_IML_TYPE_FPR_R) + { + op_fpr_r.registerResult = replaceRegister(op_fpr_r.registerResult, fprRegisterSearched, fprRegisterReplaced); + } + else + { + cemu_assert_unimplemented(); + } +} diff --git a/src/Cafe/HW/Espresso/Recompiler/IML/IMLInstruction.h b/src/Cafe/HW/Espresso/Recompiler/IML/IMLInstruction.h index 34733c4f..b72e7a67 100644 --- a/src/Cafe/HW/Espresso/Recompiler/IML/IMLInstruction.h +++ b/src/Cafe/HW/Espresso/Recompiler/IML/IMLInstruction.h @@ -236,6 +236,35 @@ enum PPCREC_FPR_ST_MODE_PSQ_S16_PS0_PS1, }; +struct IMLUsedRegisters +{ + union + { + struct + { + sint16 readNamedReg1; + sint16 readNamedReg2; + sint16 readNamedReg3; + sint16 writtenNamedReg1; + }; + sint16 gpr[4]; // 3 read + 1 write + }; + // FPR + union + { + struct + { + // note: If destination operand is not fully written (PS0 and PS1) it will be added to the read registers + sint16 readFPR1; + sint16 readFPR2; + sint16 readFPR3; + sint16 readFPR4; + sint16 writtenFPR1; + }; + sint16 fpr[4]; + }; +}; + struct IMLInstruction { uint8 type; @@ -409,4 +438,9 @@ struct IMLInstruction associatedPPCAddress = 0; } + void CheckRegisterUsage(IMLUsedRegisters* registersUsed) const; + + void ReplaceGPRRegisterUsageMultiple(sint32 gprRegisterSearched[4], sint32 gprRegisterReplaced[4]); + void ReplaceFPRRegisterUsageMultiple(sint32 fprRegisterSearched[4], sint32 fprRegisterReplaced[4]); + void ReplaceFPRRegisterUsage(sint32 fprRegisterSearched, sint32 fprRegisterReplaced); }; \ No newline at end of file diff --git a/src/Cafe/HW/Espresso/Recompiler/PPCRecompilerIml.h b/src/Cafe/HW/Espresso/Recompiler/PPCRecompilerIml.h index 7ee5dffc..1af1ee08 100644 --- a/src/Cafe/HW/Espresso/Recompiler/PPCRecompilerIml.h +++ b/src/Cafe/HW/Espresso/Recompiler/PPCRecompilerIml.h @@ -122,17 +122,6 @@ void PPCRecompilerIML_isolateEnterableSegments(ppcImlGenContext_t* ppcImlGenCont IMLInstruction* PPCRecompilerIML_getLastInstruction(IMLSegment* imlSegment); -// IML analyzer -typedef struct -{ - uint32 readCRBits; - uint32 writtenCRBits; -}PPCRecCRTracking_t; - -bool PPCRecompilerImlAnalyzer_isTightFiniteLoop(IMLSegment* imlSegment); -bool PPCRecompilerImlAnalyzer_canTypeWriteCR(IMLInstruction* imlInstruction); -void PPCRecompilerImlAnalyzer_getCRTracking(IMLInstruction* imlInstruction, PPCRecCRTracking_t* crTracking); - // IML optimizer bool PPCRecompiler_reduceNumberOfFPRRegisters(ppcImlGenContext_t* ppcImlGenContext); @@ -149,34 +138,3 @@ void PPCRecompilerImm_allocateRegisters(ppcImlGenContext_t* ppcImlGenContext); // late optimizations void PPCRecompiler_reorderConditionModifyInstructions(ppcImlGenContext_t* ppcImlGenContext); - -typedef struct -{ - union - { - struct - { - sint16 readNamedReg1; - sint16 readNamedReg2; - sint16 readNamedReg3; - sint16 writtenNamedReg1; - }; - sint16 gpr[4]; // 3 read + 1 write - }; - // FPR - union - { - struct - { - // note: If destination operand is not fully written, it will be added as a read FPR as well - sint16 readFPR1; - sint16 readFPR2; - sint16 readFPR3; - sint16 readFPR4; // usually this is set to the result FPR if only partially overwritten - sint16 writtenFPR1; - }; - sint16 fpr[4]; - }; -}PPCImlOptimizerUsedRegisters_t; - -void PPCRecompiler_checkRegisterUsage(ppcImlGenContext_t* ppcImlGenContext, const IMLInstruction* imlInstruction, PPCImlOptimizerUsedRegisters_t* registersUsed); diff --git a/src/Cafe/HW/Espresso/Recompiler/PPCRecompilerImlGen.cpp b/src/Cafe/HW/Espresso/Recompiler/PPCRecompilerImlGen.cpp index 7fdbff17..4e91bbe6 100644 --- a/src/Cafe/HW/Espresso/Recompiler/PPCRecompilerImlGen.cpp +++ b/src/Cafe/HW/Espresso/Recompiler/PPCRecompilerImlGen.cpp @@ -2,8 +2,8 @@ #include "Cafe/HW/Espresso/Interpreter/PPCInterpreterHelper.h" #include "PPCRecompiler.h" #include "PPCRecompilerIml.h" -#include "PPCRecompilerX64.h" #include "PPCRecompilerImlRanges.h" +#include "IML/IML.h" bool PPCRecompiler_decodePPCInstruction(ppcImlGenContext_t* ppcImlGenContext); uint32 PPCRecompiler_iterateCurrentInstruction(ppcImlGenContext_t* ppcImlGenContext); @@ -4277,7 +4277,7 @@ bool PPCRecompiler_generateIntermediateCode(ppcImlGenContext_t& ppcImlGenContext if (imlSegment->imlList[imlSegment->imlList.size() - 1].type != PPCREC_IML_TYPE_CJUMP || imlSegment->imlList[imlSegment->imlList.size() - 1].op_conditionalJump.jumpAccordingToSegment) continue; // exclude non-infinite tight loops - if (PPCRecompilerImlAnalyzer_isTightFiniteLoop(imlSegment)) + if (IMLAnalyzer_IsTightFiniteLoop(imlSegment)) continue; // potential loop segment found, split this segment into four: // P0: This segment checks if the remaining cycles counter is still above zero. If yes, it jumps to segment P2 (it's also the jump destination for other segments) @@ -4376,11 +4376,10 @@ bool PPCRecompiler_generateIntermediateCode(ppcImlGenContext_t& ppcImlGenContext if(segIt->imlList.size() == 0 ) continue; // ignore empty segments // analyze segment for register usage - PPCImlOptimizerUsedRegisters_t registersUsed; + IMLUsedRegisters registersUsed; for(sint32 i=0; iimlList.size(); i++) { - PPCRecompiler_checkRegisterUsage(&ppcImlGenContext, segIt->imlList.data() + i, ®istersUsed); - //PPCRecompilerImlGen_findRegisterByMappedName(ppcImlGenContext, registersUsed.readGPR1); + segIt->imlList[i].CheckRegisterUsage(®istersUsed); sint32 accessedTempReg[5]; // intermediate FPRs accessedTempReg[0] = registersUsed.readFPR1; diff --git a/src/Cafe/HW/Espresso/Recompiler/PPCRecompilerImlOptimizer.cpp b/src/Cafe/HW/Espresso/Recompiler/PPCRecompilerImlOptimizer.cpp index 9edbc6ff..4a7115c0 100644 --- a/src/Cafe/HW/Espresso/Recompiler/PPCRecompilerImlOptimizer.cpp +++ b/src/Cafe/HW/Espresso/Recompiler/PPCRecompilerImlOptimizer.cpp @@ -1,849 +1,10 @@ #include "../Interpreter/PPCInterpreterInternal.h" +#include "Cafe/HW/Espresso/Recompiler/IML/IML.h" +#include "Cafe/HW/Espresso/Recompiler/IML/IMLInstruction.h" #include "PPCRecompiler.h" #include "PPCRecompilerIml.h" #include "PPCRecompilerX64.h" -void PPCRecompiler_checkRegisterUsage(ppcImlGenContext_t* ppcImlGenContext, const IMLInstruction* imlInstruction, PPCImlOptimizerUsedRegisters_t* registersUsed) -{ - registersUsed->readNamedReg1 = -1; - registersUsed->readNamedReg2 = -1; - registersUsed->readNamedReg3 = -1; - registersUsed->writtenNamedReg1 = -1; - registersUsed->readFPR1 = -1; - registersUsed->readFPR2 = -1; - registersUsed->readFPR3 = -1; - registersUsed->readFPR4 = -1; - registersUsed->writtenFPR1 = -1; - if( imlInstruction->type == PPCREC_IML_TYPE_R_NAME ) - { - registersUsed->writtenNamedReg1 = imlInstruction->op_r_name.registerIndex; - } - else if( imlInstruction->type == PPCREC_IML_TYPE_NAME_R ) - { - registersUsed->readNamedReg1 = imlInstruction->op_r_name.registerIndex; - } - else if( imlInstruction->type == PPCREC_IML_TYPE_R_R ) - { - if (imlInstruction->operation == PPCREC_IML_OP_COMPARE_SIGNED || imlInstruction->operation == PPCREC_IML_OP_COMPARE_UNSIGNED || imlInstruction->operation == PPCREC_IML_OP_DCBZ) - { - // both operands are read only - registersUsed->readNamedReg1 = imlInstruction->op_r_r.registerResult; - registersUsed->readNamedReg2 = imlInstruction->op_r_r.registerA; - } - else if ( - imlInstruction->operation == PPCREC_IML_OP_OR || - imlInstruction->operation == PPCREC_IML_OP_AND || - imlInstruction->operation == PPCREC_IML_OP_XOR || - imlInstruction->operation == PPCREC_IML_OP_ADD || - imlInstruction->operation == PPCREC_IML_OP_ADD_CARRY || - imlInstruction->operation == PPCREC_IML_OP_ADD_CARRY_ME || - imlInstruction->operation == PPCREC_IML_OP_SUB_CARRY_UPDATE_CARRY) - { - // result is read and written, operand is read - registersUsed->writtenNamedReg1 = imlInstruction->op_r_r.registerResult; - registersUsed->readNamedReg1 = imlInstruction->op_r_r.registerResult; - registersUsed->readNamedReg2 = imlInstruction->op_r_r.registerA; - } - else if ( - imlInstruction->operation == PPCREC_IML_OP_ASSIGN || - imlInstruction->operation == PPCREC_IML_OP_ENDIAN_SWAP || - imlInstruction->operation == PPCREC_IML_OP_CNTLZW || - imlInstruction->operation == PPCREC_IML_OP_NOT || - imlInstruction->operation == PPCREC_IML_OP_NEG || - imlInstruction->operation == PPCREC_IML_OP_ASSIGN_S16_TO_S32 || - imlInstruction->operation == PPCREC_IML_OP_ASSIGN_S8_TO_S32) - { - // result is written, operand is read - registersUsed->writtenNamedReg1 = imlInstruction->op_r_r.registerResult; - registersUsed->readNamedReg1 = imlInstruction->op_r_r.registerA; - } - else - cemu_assert_unimplemented(); - } - else if (imlInstruction->type == PPCREC_IML_TYPE_R_S32) - { - if (imlInstruction->operation == PPCREC_IML_OP_COMPARE_SIGNED || imlInstruction->operation == PPCREC_IML_OP_COMPARE_UNSIGNED || imlInstruction->operation == PPCREC_IML_OP_MTCRF) - { - // operand register is read only - registersUsed->readNamedReg1 = imlInstruction->op_r_immS32.registerIndex; - } - else if (imlInstruction->operation == PPCREC_IML_OP_ADD || - imlInstruction->operation == PPCREC_IML_OP_SUB || - imlInstruction->operation == PPCREC_IML_OP_AND || - imlInstruction->operation == PPCREC_IML_OP_OR || - imlInstruction->operation == PPCREC_IML_OP_XOR || - imlInstruction->operation == PPCREC_IML_OP_LEFT_ROTATE) - { - // operand register is read and write - registersUsed->readNamedReg1 = imlInstruction->op_r_immS32.registerIndex; - registersUsed->writtenNamedReg1 = imlInstruction->op_r_immS32.registerIndex; - } - else - { - // operand register is write only - // todo - use explicit lists, avoid default cases - registersUsed->writtenNamedReg1 = imlInstruction->op_r_immS32.registerIndex; - } - } - else if (imlInstruction->type == PPCREC_IML_TYPE_CONDITIONAL_R_S32) - { - if (imlInstruction->operation == PPCREC_IML_OP_ASSIGN) - { - // result is written, but also considered read (in case the condition fails) - registersUsed->readNamedReg1 = imlInstruction->op_conditional_r_s32.registerIndex; - registersUsed->writtenNamedReg1 = imlInstruction->op_conditional_r_s32.registerIndex; - } - else - cemu_assert_unimplemented(); - } - else if( imlInstruction->type == PPCREC_IML_TYPE_R_R_S32 ) - { - if( imlInstruction->operation == PPCREC_IML_OP_RLWIMI ) - { - // result and operand register are both read, result is written - registersUsed->writtenNamedReg1 = imlInstruction->op_r_r_s32.registerResult; - registersUsed->readNamedReg1 = imlInstruction->op_r_r_s32.registerResult; - registersUsed->readNamedReg2 = imlInstruction->op_r_r_s32.registerA; - } - else - { - // result is write only and operand is read only - registersUsed->writtenNamedReg1 = imlInstruction->op_r_r_s32.registerResult; - registersUsed->readNamedReg1 = imlInstruction->op_r_r_s32.registerA; - } - } - else if( imlInstruction->type == PPCREC_IML_TYPE_R_R_R ) - { - // in all cases result is written and other operands are read only - registersUsed->writtenNamedReg1 = imlInstruction->op_r_r_r.registerResult; - registersUsed->readNamedReg1 = imlInstruction->op_r_r_r.registerA; - registersUsed->readNamedReg2 = imlInstruction->op_r_r_r.registerB; - } - else if( imlInstruction->type == PPCREC_IML_TYPE_CJUMP || imlInstruction->type == PPCREC_IML_TYPE_CJUMP_CYCLE_CHECK ) - { - // no effect on registers - } - else if( imlInstruction->type == PPCREC_IML_TYPE_NO_OP ) - { - // no effect on registers - } - else if( imlInstruction->type == PPCREC_IML_TYPE_MACRO ) - { - if( imlInstruction->operation == PPCREC_IML_MACRO_BL || imlInstruction->operation == PPCREC_IML_MACRO_B_FAR || imlInstruction->operation == PPCREC_IML_MACRO_BLR || imlInstruction->operation == PPCREC_IML_MACRO_BLRL || imlInstruction->operation == PPCREC_IML_MACRO_BCTR || imlInstruction->operation == PPCREC_IML_MACRO_BCTRL || imlInstruction->operation == PPCREC_IML_MACRO_LEAVE || imlInstruction->operation == PPCREC_IML_MACRO_DEBUGBREAK || imlInstruction->operation == PPCREC_IML_MACRO_COUNT_CYCLES || imlInstruction->operation == PPCREC_IML_MACRO_HLE || imlInstruction->operation == PPCREC_IML_MACRO_MFTB ) - { - // no effect on registers - } - else - cemu_assert_unimplemented(); - } - else if (imlInstruction->type == PPCREC_IML_TYPE_LOAD) - { - registersUsed->writtenNamedReg1 = imlInstruction->op_storeLoad.registerData; - if (imlInstruction->op_storeLoad.registerMem != PPC_REC_INVALID_REGISTER) - registersUsed->readNamedReg1 = imlInstruction->op_storeLoad.registerMem; - } - else if( imlInstruction->type == PPCREC_IML_TYPE_LOAD_INDEXED ) - { - registersUsed->writtenNamedReg1 = imlInstruction->op_storeLoad.registerData; - if( imlInstruction->op_storeLoad.registerMem != PPC_REC_INVALID_REGISTER ) - registersUsed->readNamedReg1 = imlInstruction->op_storeLoad.registerMem; - if( imlInstruction->op_storeLoad.registerMem2 != PPC_REC_INVALID_REGISTER ) - registersUsed->readNamedReg2 = imlInstruction->op_storeLoad.registerMem2; - } - else if( imlInstruction->type == PPCREC_IML_TYPE_STORE ) - { - registersUsed->readNamedReg1 = imlInstruction->op_storeLoad.registerData; - if( imlInstruction->op_storeLoad.registerMem != PPC_REC_INVALID_REGISTER ) - registersUsed->readNamedReg2 = imlInstruction->op_storeLoad.registerMem; - } - else if( imlInstruction->type == PPCREC_IML_TYPE_STORE_INDEXED ) - { - registersUsed->readNamedReg1 = imlInstruction->op_storeLoad.registerData; - if( imlInstruction->op_storeLoad.registerMem != PPC_REC_INVALID_REGISTER ) - registersUsed->readNamedReg2 = imlInstruction->op_storeLoad.registerMem; - if( imlInstruction->op_storeLoad.registerMem2 != PPC_REC_INVALID_REGISTER ) - registersUsed->readNamedReg3 = imlInstruction->op_storeLoad.registerMem2; - } - else if( imlInstruction->type == PPCREC_IML_TYPE_CR ) - { - // only affects cr register - } - else if( imlInstruction->type == PPCREC_IML_TYPE_JUMPMARK ) - { - // no effect on registers - } - else if( imlInstruction->type == PPCREC_IML_TYPE_PPC_ENTER ) - { - // no op - } - else if( imlInstruction->type == PPCREC_IML_TYPE_FPR_R_NAME ) - { - // fpr operation - registersUsed->writtenFPR1 = imlInstruction->op_r_name.registerIndex; - } - else if( imlInstruction->type == PPCREC_IML_TYPE_FPR_NAME_R ) - { - // fpr operation - registersUsed->readFPR1 = imlInstruction->op_r_name.registerIndex; - } - else if( imlInstruction->type == PPCREC_IML_TYPE_FPR_LOAD ) - { - // fpr load operation - registersUsed->writtenFPR1 = imlInstruction->op_storeLoad.registerData; - // address is in gpr register - if (imlInstruction->op_storeLoad.registerMem != PPC_REC_INVALID_REGISTER) - registersUsed->readNamedReg1 = imlInstruction->op_storeLoad.registerMem; - // determine partially written result - switch (imlInstruction->op_storeLoad.mode) - { - case PPCREC_FPR_LD_MODE_PSQ_GENERIC_PS0: - case PPCREC_FPR_LD_MODE_PSQ_GENERIC_PS0_PS1: - cemu_assert_debug(imlInstruction->op_storeLoad.registerGQR != PPC_REC_INVALID_REGISTER); - registersUsed->readNamedReg2 = imlInstruction->op_storeLoad.registerGQR; - break; - case PPCREC_FPR_LD_MODE_DOUBLE_INTO_PS0: - // PS1 remains the same - registersUsed->readFPR4 = imlInstruction->op_storeLoad.registerData; - break; - case PPCREC_FPR_LD_MODE_SINGLE_INTO_PS0_PS1: - case PPCREC_FPR_LD_MODE_PSQ_FLOAT_PS0_PS1: - case PPCREC_FPR_LD_MODE_PSQ_FLOAT_PS0: - case PPCREC_FPR_LD_MODE_PSQ_S16_PS0: - case PPCREC_FPR_LD_MODE_PSQ_S16_PS0_PS1: - case PPCREC_FPR_LD_MODE_PSQ_U16_PS0_PS1: - case PPCREC_FPR_LD_MODE_PSQ_U16_PS0: - case PPCREC_FPR_LD_MODE_PSQ_S8_PS0_PS1: - case PPCREC_FPR_LD_MODE_PSQ_U8_PS0_PS1: - case PPCREC_FPR_LD_MODE_PSQ_U8_PS0: - case PPCREC_FPR_LD_MODE_PSQ_S8_PS0: - break; - default: - cemu_assert_unimplemented(); - } - } - else if( imlInstruction->type == PPCREC_IML_TYPE_FPR_LOAD_INDEXED ) - { - // fpr load operation - registersUsed->writtenFPR1 = imlInstruction->op_storeLoad.registerData; - // address is in gpr registers - if (imlInstruction->op_storeLoad.registerMem != PPC_REC_INVALID_REGISTER) - registersUsed->readNamedReg1 = imlInstruction->op_storeLoad.registerMem; - if (imlInstruction->op_storeLoad.registerMem2 != PPC_REC_INVALID_REGISTER) - registersUsed->readNamedReg2 = imlInstruction->op_storeLoad.registerMem2; - // determine partially written result - switch (imlInstruction->op_storeLoad.mode) - { - case PPCREC_FPR_LD_MODE_PSQ_GENERIC_PS0: - case PPCREC_FPR_LD_MODE_PSQ_GENERIC_PS0_PS1: - cemu_assert_debug(imlInstruction->op_storeLoad.registerGQR != PPC_REC_INVALID_REGISTER); - registersUsed->readNamedReg3 = imlInstruction->op_storeLoad.registerGQR; - break; - case PPCREC_FPR_LD_MODE_DOUBLE_INTO_PS0: - // PS1 remains the same - registersUsed->readFPR4 = imlInstruction->op_storeLoad.registerData; - break; - case PPCREC_FPR_LD_MODE_SINGLE_INTO_PS0_PS1: - case PPCREC_FPR_LD_MODE_PSQ_FLOAT_PS0_PS1: - case PPCREC_FPR_LD_MODE_PSQ_FLOAT_PS0: - case PPCREC_FPR_LD_MODE_PSQ_S16_PS0: - case PPCREC_FPR_LD_MODE_PSQ_S16_PS0_PS1: - case PPCREC_FPR_LD_MODE_PSQ_U16_PS0_PS1: - case PPCREC_FPR_LD_MODE_PSQ_U16_PS0: - case PPCREC_FPR_LD_MODE_PSQ_S8_PS0_PS1: - case PPCREC_FPR_LD_MODE_PSQ_U8_PS0_PS1: - case PPCREC_FPR_LD_MODE_PSQ_U8_PS0: - break; - default: - cemu_assert_unimplemented(); - } - } - else if( imlInstruction->type == PPCREC_IML_TYPE_FPR_STORE ) - { - // fpr store operation - registersUsed->readFPR1 = imlInstruction->op_storeLoad.registerData; - if( imlInstruction->op_storeLoad.registerMem != PPC_REC_INVALID_REGISTER ) - registersUsed->readNamedReg1 = imlInstruction->op_storeLoad.registerMem; - // PSQ generic stores also access GQR - switch (imlInstruction->op_storeLoad.mode) - { - case PPCREC_FPR_ST_MODE_PSQ_GENERIC_PS0: - case PPCREC_FPR_ST_MODE_PSQ_GENERIC_PS0_PS1: - cemu_assert_debug(imlInstruction->op_storeLoad.registerGQR != PPC_REC_INVALID_REGISTER); - registersUsed->readNamedReg2 = imlInstruction->op_storeLoad.registerGQR; - break; - default: - break; - } - } - else if( imlInstruction->type == PPCREC_IML_TYPE_FPR_STORE_INDEXED ) - { - // fpr store operation - registersUsed->readFPR1 = imlInstruction->op_storeLoad.registerData; - // address is in gpr registers - if( imlInstruction->op_storeLoad.registerMem != PPC_REC_INVALID_REGISTER ) - registersUsed->readNamedReg1 = imlInstruction->op_storeLoad.registerMem; - if( imlInstruction->op_storeLoad.registerMem2 != PPC_REC_INVALID_REGISTER ) - registersUsed->readNamedReg2 = imlInstruction->op_storeLoad.registerMem2; - // PSQ generic stores also access GQR - switch (imlInstruction->op_storeLoad.mode) - { - case PPCREC_FPR_ST_MODE_PSQ_GENERIC_PS0: - case PPCREC_FPR_ST_MODE_PSQ_GENERIC_PS0_PS1: - cemu_assert_debug(imlInstruction->op_storeLoad.registerGQR != PPC_REC_INVALID_REGISTER); - registersUsed->readNamedReg3 = imlInstruction->op_storeLoad.registerGQR; - break; - default: - break; - } - } - else if( imlInstruction->type == PPCREC_IML_TYPE_FPR_R_R ) - { - // fpr operation - if( imlInstruction->operation == PPCREC_IML_OP_FPR_COPY_BOTTOM_TO_BOTTOM_AND_TOP || - imlInstruction->operation == PPCREC_IML_OP_FPR_COPY_TOP_TO_BOTTOM_AND_TOP || - imlInstruction->operation == PPCREC_IML_OP_FPR_COPY_BOTTOM_AND_TOP_SWAPPED || - imlInstruction->operation == PPCREC_IML_OP_ASSIGN || - imlInstruction->operation == PPCREC_IML_OP_FPR_BOTTOM_FRES_TO_BOTTOM_AND_TOP || - imlInstruction->operation == PPCREC_IML_OP_FPR_NEGATE_PAIR || - imlInstruction->operation == PPCREC_IML_OP_FPR_ABS_PAIR || - imlInstruction->operation == PPCREC_IML_OP_FPR_FRES_PAIR || - imlInstruction->operation == PPCREC_IML_OP_FPR_FRSQRTE_PAIR ) - { - // operand read, result written - registersUsed->readFPR1 = imlInstruction->op_fpr_r_r.registerOperand; - registersUsed->writtenFPR1 = imlInstruction->op_fpr_r_r.registerResult; - } - else if( - imlInstruction->operation == PPCREC_IML_OP_FPR_COPY_BOTTOM_TO_BOTTOM || - imlInstruction->operation == PPCREC_IML_OP_FPR_COPY_BOTTOM_TO_TOP || - imlInstruction->operation == PPCREC_IML_OP_FPR_COPY_TOP_TO_TOP || - imlInstruction->operation == PPCREC_IML_OP_FPR_COPY_TOP_TO_BOTTOM || - imlInstruction->operation == PPCREC_IML_OP_FPR_EXPAND_BOTTOM32_TO_BOTTOM64_AND_TOP64 || - imlInstruction->operation == PPCREC_IML_OP_FPR_BOTTOM_FCTIWZ || - imlInstruction->operation == PPCREC_IML_OP_FPR_BOTTOM_RECIPROCAL_SQRT - ) - { - // operand read, result read and (partially) written - registersUsed->readFPR1 = imlInstruction->op_fpr_r_r.registerOperand; - registersUsed->readFPR4 = imlInstruction->op_fpr_r_r.registerResult; - registersUsed->writtenFPR1 = imlInstruction->op_fpr_r_r.registerResult; - } - else if( imlInstruction->operation == PPCREC_IML_OP_FPR_MULTIPLY_BOTTOM || - imlInstruction->operation == PPCREC_IML_OP_FPR_MULTIPLY_PAIR || - imlInstruction->operation == PPCREC_IML_OP_FPR_DIVIDE_BOTTOM || - imlInstruction->operation == PPCREC_IML_OP_FPR_DIVIDE_PAIR || - imlInstruction->operation == PPCREC_IML_OP_FPR_ADD_BOTTOM || - imlInstruction->operation == PPCREC_IML_OP_FPR_ADD_PAIR || - imlInstruction->operation == PPCREC_IML_OP_FPR_SUB_PAIR || - imlInstruction->operation == PPCREC_IML_OP_FPR_SUB_BOTTOM ) - { - // operand read, result read and written - registersUsed->readFPR1 = imlInstruction->op_fpr_r_r.registerOperand; - registersUsed->readFPR2 = imlInstruction->op_fpr_r_r.registerResult; - registersUsed->writtenFPR1 = imlInstruction->op_fpr_r_r.registerResult; - - } - else if(imlInstruction->operation == PPCREC_IML_OP_FPR_FCMPU_BOTTOM || - imlInstruction->operation == PPCREC_IML_OP_FPR_FCMPU_TOP || - imlInstruction->operation == PPCREC_IML_OP_FPR_FCMPO_BOTTOM) - { - // operand read, result read - registersUsed->readFPR1 = imlInstruction->op_fpr_r_r.registerOperand; - registersUsed->readFPR2 = imlInstruction->op_fpr_r_r.registerResult; - } - else - cemu_assert_unimplemented(); - } - else if( imlInstruction->type == PPCREC_IML_TYPE_FPR_R_R_R ) - { - // fpr operation - registersUsed->readFPR1 = imlInstruction->op_fpr_r_r_r.registerOperandA; - registersUsed->readFPR2 = imlInstruction->op_fpr_r_r_r.registerOperandB; - registersUsed->writtenFPR1 = imlInstruction->op_fpr_r_r_r.registerResult; - // handle partially written result - switch (imlInstruction->operation) - { - case PPCREC_IML_OP_FPR_MULTIPLY_BOTTOM: - case PPCREC_IML_OP_FPR_ADD_BOTTOM: - case PPCREC_IML_OP_FPR_SUB_BOTTOM: - registersUsed->readFPR4 = imlInstruction->op_fpr_r_r_r.registerResult; - break; - case PPCREC_IML_OP_FPR_SUB_PAIR: - break; - default: - cemu_assert_unimplemented(); - } - } - else if( imlInstruction->type == PPCREC_IML_TYPE_FPR_R_R_R_R ) - { - // fpr operation - registersUsed->readFPR1 = imlInstruction->op_fpr_r_r_r_r.registerOperandA; - registersUsed->readFPR2 = imlInstruction->op_fpr_r_r_r_r.registerOperandB; - registersUsed->readFPR3 = imlInstruction->op_fpr_r_r_r_r.registerOperandC; - registersUsed->writtenFPR1 = imlInstruction->op_fpr_r_r_r_r.registerResult; - // handle partially written result - switch (imlInstruction->operation) - { - case PPCREC_IML_OP_FPR_SELECT_BOTTOM: - registersUsed->readFPR4 = imlInstruction->op_fpr_r_r_r_r.registerResult; - break; - case PPCREC_IML_OP_FPR_SUM0: - case PPCREC_IML_OP_FPR_SUM1: - case PPCREC_IML_OP_FPR_SELECT_PAIR: - break; - default: - cemu_assert_unimplemented(); - } - } - else if( imlInstruction->type == PPCREC_IML_TYPE_FPR_R ) - { - // fpr operation - if( imlInstruction->operation == PPCREC_IML_OP_FPR_NEGATE_BOTTOM || - imlInstruction->operation == PPCREC_IML_OP_FPR_ABS_BOTTOM || - imlInstruction->operation == PPCREC_IML_OP_FPR_NEGATIVE_ABS_BOTTOM || - imlInstruction->operation == PPCREC_IML_OP_FPR_EXPAND_BOTTOM32_TO_BOTTOM64_AND_TOP64 || - imlInstruction->operation == PPCREC_IML_OP_FPR_ROUND_TO_SINGLE_PRECISION_BOTTOM || - imlInstruction->operation == PPCREC_IML_OP_FPR_ROUND_TO_SINGLE_PRECISION_PAIR ) - { - registersUsed->readFPR1 = imlInstruction->op_fpr_r.registerResult; - registersUsed->writtenFPR1 = imlInstruction->op_fpr_r.registerResult; - } - else - cemu_assert_unimplemented(); - } - else - { - cemu_assert_unimplemented(); - } -} - -#define replaceRegister(__x,__r,__n) (((__x)==(__r))?(__n):(__x)) - -sint32 replaceRegisterMultiple(sint32 reg, sint32 match[4], sint32 replaced[4]) -{ - for (sint32 i = 0; i < 4; i++) - { - if(match[i] < 0) - continue; - if (reg == match[i]) - { - return replaced[i]; - } - } - return reg; -} - -void PPCRecompiler_replaceGPRRegisterUsageMultiple(ppcImlGenContext_t* ppcImlGenContext, IMLInstruction* imlInstruction, sint32 gprRegisterSearched[4], sint32 gprRegisterReplaced[4]) -{ - if (imlInstruction->type == PPCREC_IML_TYPE_R_NAME) - { - imlInstruction->op_r_name.registerIndex = replaceRegisterMultiple(imlInstruction->op_r_name.registerIndex, gprRegisterSearched, gprRegisterReplaced); - } - else if (imlInstruction->type == PPCREC_IML_TYPE_NAME_R) - { - imlInstruction->op_r_name.registerIndex = replaceRegisterMultiple(imlInstruction->op_r_name.registerIndex, gprRegisterSearched, gprRegisterReplaced); - } - else if (imlInstruction->type == PPCREC_IML_TYPE_R_R) - { - imlInstruction->op_r_r.registerResult = replaceRegisterMultiple(imlInstruction->op_r_r.registerResult, gprRegisterSearched, gprRegisterReplaced); - imlInstruction->op_r_r.registerA = replaceRegisterMultiple(imlInstruction->op_r_r.registerA, gprRegisterSearched, gprRegisterReplaced); - } - else if (imlInstruction->type == PPCREC_IML_TYPE_R_S32) - { - imlInstruction->op_r_immS32.registerIndex = replaceRegisterMultiple(imlInstruction->op_r_immS32.registerIndex, gprRegisterSearched, gprRegisterReplaced); - } - else if (imlInstruction->type == PPCREC_IML_TYPE_CONDITIONAL_R_S32) - { - imlInstruction->op_conditional_r_s32.registerIndex = replaceRegisterMultiple(imlInstruction->op_conditional_r_s32.registerIndex, gprRegisterSearched, gprRegisterReplaced); - } - else if (imlInstruction->type == PPCREC_IML_TYPE_R_R_S32) - { - // in all cases result is written and other operand is read only - imlInstruction->op_r_r_s32.registerResult = replaceRegisterMultiple(imlInstruction->op_r_r_s32.registerResult, gprRegisterSearched, gprRegisterReplaced); - imlInstruction->op_r_r_s32.registerA = replaceRegisterMultiple(imlInstruction->op_r_r_s32.registerA, gprRegisterSearched, gprRegisterReplaced); - } - else if (imlInstruction->type == PPCREC_IML_TYPE_R_R_R) - { - // in all cases result is written and other operands are read only - imlInstruction->op_r_r_r.registerResult = replaceRegisterMultiple(imlInstruction->op_r_r_r.registerResult, gprRegisterSearched, gprRegisterReplaced); - imlInstruction->op_r_r_r.registerA = replaceRegisterMultiple(imlInstruction->op_r_r_r.registerA, gprRegisterSearched, gprRegisterReplaced); - imlInstruction->op_r_r_r.registerB = replaceRegisterMultiple(imlInstruction->op_r_r_r.registerB, gprRegisterSearched, gprRegisterReplaced); - } - else if (imlInstruction->type == PPCREC_IML_TYPE_CJUMP || imlInstruction->type == PPCREC_IML_TYPE_CJUMP_CYCLE_CHECK) - { - // no effect on registers - } - else if (imlInstruction->type == PPCREC_IML_TYPE_NO_OP) - { - // no effect on registers - } - else if (imlInstruction->type == PPCREC_IML_TYPE_MACRO) - { - if (imlInstruction->operation == PPCREC_IML_MACRO_BL || imlInstruction->operation == PPCREC_IML_MACRO_B_FAR || imlInstruction->operation == PPCREC_IML_MACRO_BLR || imlInstruction->operation == PPCREC_IML_MACRO_BLRL || imlInstruction->operation == PPCREC_IML_MACRO_BCTR || imlInstruction->operation == PPCREC_IML_MACRO_BCTRL || imlInstruction->operation == PPCREC_IML_MACRO_LEAVE || imlInstruction->operation == PPCREC_IML_MACRO_DEBUGBREAK || imlInstruction->operation == PPCREC_IML_MACRO_HLE || imlInstruction->operation == PPCREC_IML_MACRO_MFTB || imlInstruction->operation == PPCREC_IML_MACRO_COUNT_CYCLES ) - { - // no effect on registers - } - else - { - cemu_assert_unimplemented(); - } - } - else if (imlInstruction->type == PPCREC_IML_TYPE_LOAD) - { - imlInstruction->op_storeLoad.registerData = replaceRegisterMultiple(imlInstruction->op_storeLoad.registerData, gprRegisterSearched, gprRegisterReplaced); - if (imlInstruction->op_storeLoad.registerMem != PPC_REC_INVALID_REGISTER) - { - imlInstruction->op_storeLoad.registerMem = replaceRegisterMultiple(imlInstruction->op_storeLoad.registerMem, gprRegisterSearched, gprRegisterReplaced); - } - } - else if (imlInstruction->type == PPCREC_IML_TYPE_LOAD_INDEXED) - { - imlInstruction->op_storeLoad.registerData = replaceRegisterMultiple(imlInstruction->op_storeLoad.registerData, gprRegisterSearched, gprRegisterReplaced); - if (imlInstruction->op_storeLoad.registerMem != PPC_REC_INVALID_REGISTER) - imlInstruction->op_storeLoad.registerMem = replaceRegisterMultiple(imlInstruction->op_storeLoad.registerMem, gprRegisterSearched, gprRegisterReplaced); - if (imlInstruction->op_storeLoad.registerMem2 != PPC_REC_INVALID_REGISTER) - imlInstruction->op_storeLoad.registerMem2 = replaceRegisterMultiple(imlInstruction->op_storeLoad.registerMem2, gprRegisterSearched, gprRegisterReplaced); - } - else if (imlInstruction->type == PPCREC_IML_TYPE_STORE) - { - imlInstruction->op_storeLoad.registerData = replaceRegisterMultiple(imlInstruction->op_storeLoad.registerData, gprRegisterSearched, gprRegisterReplaced); - if (imlInstruction->op_storeLoad.registerMem != PPC_REC_INVALID_REGISTER) - imlInstruction->op_storeLoad.registerMem = replaceRegisterMultiple(imlInstruction->op_storeLoad.registerMem, gprRegisterSearched, gprRegisterReplaced); - } - else if (imlInstruction->type == PPCREC_IML_TYPE_STORE_INDEXED) - { - imlInstruction->op_storeLoad.registerData = replaceRegisterMultiple(imlInstruction->op_storeLoad.registerData, gprRegisterSearched, gprRegisterReplaced); - if (imlInstruction->op_storeLoad.registerMem != PPC_REC_INVALID_REGISTER) - imlInstruction->op_storeLoad.registerMem = replaceRegisterMultiple(imlInstruction->op_storeLoad.registerMem, gprRegisterSearched, gprRegisterReplaced); - if (imlInstruction->op_storeLoad.registerMem2 != PPC_REC_INVALID_REGISTER) - imlInstruction->op_storeLoad.registerMem2 = replaceRegisterMultiple(imlInstruction->op_storeLoad.registerMem2, gprRegisterSearched, gprRegisterReplaced); - } - else if (imlInstruction->type == PPCREC_IML_TYPE_CR) - { - // only affects cr register - } - else if (imlInstruction->type == PPCREC_IML_TYPE_JUMPMARK) - { - // no effect on registers - } - else if (imlInstruction->type == PPCREC_IML_TYPE_PPC_ENTER) - { - // no op - } - else if (imlInstruction->type == PPCREC_IML_TYPE_FPR_R_NAME) - { - - } - else if (imlInstruction->type == PPCREC_IML_TYPE_FPR_NAME_R) - { - - } - else if (imlInstruction->type == PPCREC_IML_TYPE_FPR_LOAD) - { - if (imlInstruction->op_storeLoad.registerMem != PPC_REC_INVALID_REGISTER) - { - imlInstruction->op_storeLoad.registerMem = replaceRegisterMultiple(imlInstruction->op_storeLoad.registerMem, gprRegisterSearched, gprRegisterReplaced); - } - if (imlInstruction->op_storeLoad.registerGQR != PPC_REC_INVALID_REGISTER) - { - imlInstruction->op_storeLoad.registerGQR = replaceRegisterMultiple(imlInstruction->op_storeLoad.registerGQR, gprRegisterSearched, gprRegisterReplaced); - } - } - else if (imlInstruction->type == PPCREC_IML_TYPE_FPR_LOAD_INDEXED) - { - if (imlInstruction->op_storeLoad.registerMem != PPC_REC_INVALID_REGISTER) - { - imlInstruction->op_storeLoad.registerMem = replaceRegisterMultiple(imlInstruction->op_storeLoad.registerMem, gprRegisterSearched, gprRegisterReplaced); - } - if (imlInstruction->op_storeLoad.registerMem2 != PPC_REC_INVALID_REGISTER) - { - imlInstruction->op_storeLoad.registerMem2 = replaceRegisterMultiple(imlInstruction->op_storeLoad.registerMem2, gprRegisterSearched, gprRegisterReplaced); - } - if (imlInstruction->op_storeLoad.registerGQR != PPC_REC_INVALID_REGISTER) - { - imlInstruction->op_storeLoad.registerGQR = replaceRegisterMultiple(imlInstruction->op_storeLoad.registerGQR, gprRegisterSearched, gprRegisterReplaced); - } - } - else if (imlInstruction->type == PPCREC_IML_TYPE_FPR_STORE) - { - if (imlInstruction->op_storeLoad.registerMem != PPC_REC_INVALID_REGISTER) - { - imlInstruction->op_storeLoad.registerMem = replaceRegisterMultiple(imlInstruction->op_storeLoad.registerMem, gprRegisterSearched, gprRegisterReplaced); - } - if (imlInstruction->op_storeLoad.registerGQR != PPC_REC_INVALID_REGISTER) - { - imlInstruction->op_storeLoad.registerGQR = replaceRegisterMultiple(imlInstruction->op_storeLoad.registerGQR, gprRegisterSearched, gprRegisterReplaced); - } - } - else if (imlInstruction->type == PPCREC_IML_TYPE_FPR_STORE_INDEXED) - { - if (imlInstruction->op_storeLoad.registerMem != PPC_REC_INVALID_REGISTER) - { - imlInstruction->op_storeLoad.registerMem = replaceRegisterMultiple(imlInstruction->op_storeLoad.registerMem, gprRegisterSearched, gprRegisterReplaced); - } - if (imlInstruction->op_storeLoad.registerMem2 != PPC_REC_INVALID_REGISTER) - { - imlInstruction->op_storeLoad.registerMem2 = replaceRegisterMultiple(imlInstruction->op_storeLoad.registerMem2, gprRegisterSearched, gprRegisterReplaced); - } - if (imlInstruction->op_storeLoad.registerGQR != PPC_REC_INVALID_REGISTER) - { - imlInstruction->op_storeLoad.registerGQR = replaceRegisterMultiple(imlInstruction->op_storeLoad.registerGQR, gprRegisterSearched, gprRegisterReplaced); - } - } - else if (imlInstruction->type == PPCREC_IML_TYPE_FPR_R_R) - { - } - else if (imlInstruction->type == PPCREC_IML_TYPE_FPR_R_R_R) - { - } - else if (imlInstruction->type == PPCREC_IML_TYPE_FPR_R_R_R_R) - { - } - else if (imlInstruction->type == PPCREC_IML_TYPE_FPR_R) - { - } - else - { - cemu_assert_unimplemented(); - } -} - -void PPCRecompiler_replaceFPRRegisterUsageMultiple(ppcImlGenContext_t* ppcImlGenContext, IMLInstruction* imlInstruction, sint32 fprRegisterSearched[4], sint32 fprRegisterReplaced[4]) -{ - if (imlInstruction->type == PPCREC_IML_TYPE_R_NAME) - { - // not affected - } - else if (imlInstruction->type == PPCREC_IML_TYPE_NAME_R) - { - // not affected - } - else if (imlInstruction->type == PPCREC_IML_TYPE_R_R) - { - // not affected - } - else if (imlInstruction->type == PPCREC_IML_TYPE_R_S32) - { - // not affected - } - else if (imlInstruction->type == PPCREC_IML_TYPE_R_R_S32) - { - // not affected - } - else if (imlInstruction->type == PPCREC_IML_TYPE_R_R_R) - { - // not affected - } - else if (imlInstruction->type == PPCREC_IML_TYPE_CJUMP || imlInstruction->type == PPCREC_IML_TYPE_CJUMP_CYCLE_CHECK) - { - // no effect on registers - } - else if (imlInstruction->type == PPCREC_IML_TYPE_NO_OP) - { - // no effect on registers - } - else if (imlInstruction->type == PPCREC_IML_TYPE_MACRO) - { - // not affected - } - else if (imlInstruction->type == PPCREC_IML_TYPE_LOAD) - { - // not affected - } - else if (imlInstruction->type == PPCREC_IML_TYPE_LOAD_INDEXED) - { - // not affected - } - else if (imlInstruction->type == PPCREC_IML_TYPE_STORE) - { - // not affected - } - else if (imlInstruction->type == PPCREC_IML_TYPE_STORE_INDEXED) - { - // not affected - } - else if (imlInstruction->type == PPCREC_IML_TYPE_CR) - { - // only affects cr register - } - else if (imlInstruction->type == PPCREC_IML_TYPE_JUMPMARK) - { - // no effect on registers - } - else if (imlInstruction->type == PPCREC_IML_TYPE_PPC_ENTER) - { - // no op - } - else if (imlInstruction->type == PPCREC_IML_TYPE_FPR_R_NAME) - { - imlInstruction->op_r_name.registerIndex = replaceRegisterMultiple(imlInstruction->op_r_name.registerIndex, fprRegisterSearched, fprRegisterReplaced); - } - else if (imlInstruction->type == PPCREC_IML_TYPE_FPR_NAME_R) - { - imlInstruction->op_r_name.registerIndex = replaceRegisterMultiple(imlInstruction->op_r_name.registerIndex, fprRegisterSearched, fprRegisterReplaced); - } - else if (imlInstruction->type == PPCREC_IML_TYPE_FPR_LOAD) - { - imlInstruction->op_storeLoad.registerData = replaceRegisterMultiple(imlInstruction->op_storeLoad.registerData, fprRegisterSearched, fprRegisterReplaced); - } - else if (imlInstruction->type == PPCREC_IML_TYPE_FPR_LOAD_INDEXED) - { - imlInstruction->op_storeLoad.registerData = replaceRegisterMultiple(imlInstruction->op_storeLoad.registerData, fprRegisterSearched, fprRegisterReplaced); - } - else if (imlInstruction->type == PPCREC_IML_TYPE_FPR_STORE) - { - imlInstruction->op_storeLoad.registerData = replaceRegisterMultiple(imlInstruction->op_storeLoad.registerData, fprRegisterSearched, fprRegisterReplaced); - } - else if (imlInstruction->type == PPCREC_IML_TYPE_FPR_STORE_INDEXED) - { - imlInstruction->op_storeLoad.registerData = replaceRegisterMultiple(imlInstruction->op_storeLoad.registerData, fprRegisterSearched, fprRegisterReplaced); - } - else if (imlInstruction->type == PPCREC_IML_TYPE_FPR_R_R) - { - imlInstruction->op_fpr_r_r.registerResult = replaceRegisterMultiple(imlInstruction->op_fpr_r_r.registerResult, fprRegisterSearched, fprRegisterReplaced); - imlInstruction->op_fpr_r_r.registerOperand = replaceRegisterMultiple(imlInstruction->op_fpr_r_r.registerOperand, fprRegisterSearched, fprRegisterReplaced); - } - else if (imlInstruction->type == PPCREC_IML_TYPE_FPR_R_R_R) - { - imlInstruction->op_fpr_r_r_r.registerResult = replaceRegisterMultiple(imlInstruction->op_fpr_r_r_r.registerResult, fprRegisterSearched, fprRegisterReplaced); - imlInstruction->op_fpr_r_r_r.registerOperandA = replaceRegisterMultiple(imlInstruction->op_fpr_r_r_r.registerOperandA, fprRegisterSearched, fprRegisterReplaced); - imlInstruction->op_fpr_r_r_r.registerOperandB = replaceRegisterMultiple(imlInstruction->op_fpr_r_r_r.registerOperandB, fprRegisterSearched, fprRegisterReplaced); - } - else if (imlInstruction->type == PPCREC_IML_TYPE_FPR_R_R_R_R) - { - imlInstruction->op_fpr_r_r_r_r.registerResult = replaceRegisterMultiple(imlInstruction->op_fpr_r_r_r_r.registerResult, fprRegisterSearched, fprRegisterReplaced); - imlInstruction->op_fpr_r_r_r_r.registerOperandA = replaceRegisterMultiple(imlInstruction->op_fpr_r_r_r_r.registerOperandA, fprRegisterSearched, fprRegisterReplaced); - imlInstruction->op_fpr_r_r_r_r.registerOperandB = replaceRegisterMultiple(imlInstruction->op_fpr_r_r_r_r.registerOperandB, fprRegisterSearched, fprRegisterReplaced); - imlInstruction->op_fpr_r_r_r_r.registerOperandC = replaceRegisterMultiple(imlInstruction->op_fpr_r_r_r_r.registerOperandC, fprRegisterSearched, fprRegisterReplaced); - } - else if (imlInstruction->type == PPCREC_IML_TYPE_FPR_R) - { - imlInstruction->op_fpr_r.registerResult = replaceRegisterMultiple(imlInstruction->op_fpr_r.registerResult, fprRegisterSearched, fprRegisterReplaced); - } - else - { - cemu_assert_unimplemented(); - } -} - -void PPCRecompiler_replaceFPRRegisterUsage(ppcImlGenContext_t* ppcImlGenContext, IMLInstruction* imlInstruction, sint32 fprRegisterSearched, sint32 fprRegisterReplaced) -{ - if( imlInstruction->type == PPCREC_IML_TYPE_R_NAME ) - { - // not affected - } - else if( imlInstruction->type == PPCREC_IML_TYPE_NAME_R ) - { - // not affected - } - else if( imlInstruction->type == PPCREC_IML_TYPE_R_R ) - { - // not affected - } - else if( imlInstruction->type == PPCREC_IML_TYPE_R_S32 ) - { - // not affected - } - else if( imlInstruction->type == PPCREC_IML_TYPE_R_R_S32 ) - { - // not affected - } - else if( imlInstruction->type == PPCREC_IML_TYPE_R_R_R ) - { - // not affected - } - else if( imlInstruction->type == PPCREC_IML_TYPE_CJUMP || imlInstruction->type == PPCREC_IML_TYPE_CJUMP_CYCLE_CHECK ) - { - // no effect on registers - } - else if( imlInstruction->type == PPCREC_IML_TYPE_NO_OP ) - { - // no effect on registers - } - else if( imlInstruction->type == PPCREC_IML_TYPE_MACRO ) - { - // not affected - } - else if( imlInstruction->type == PPCREC_IML_TYPE_LOAD ) - { - // not affected - } - else if( imlInstruction->type == PPCREC_IML_TYPE_LOAD_INDEXED ) - { - // not affected - } - else if( imlInstruction->type == PPCREC_IML_TYPE_STORE ) - { - // not affected - } - else if( imlInstruction->type == PPCREC_IML_TYPE_STORE_INDEXED ) - { - // not affected - } - else if( imlInstruction->type == PPCREC_IML_TYPE_CR ) - { - // only affects cr register - } - else if( imlInstruction->type == PPCREC_IML_TYPE_JUMPMARK ) - { - // no effect on registers - } - else if( imlInstruction->type == PPCREC_IML_TYPE_PPC_ENTER ) - { - // no op - } - else if( imlInstruction->type == PPCREC_IML_TYPE_FPR_R_NAME ) - { - imlInstruction->op_r_name.registerIndex = replaceRegister(imlInstruction->op_r_name.registerIndex, fprRegisterSearched, fprRegisterReplaced); - } - else if( imlInstruction->type == PPCREC_IML_TYPE_FPR_NAME_R ) - { - imlInstruction->op_r_name.registerIndex = replaceRegister(imlInstruction->op_r_name.registerIndex, fprRegisterSearched, fprRegisterReplaced); - } - else if( imlInstruction->type == PPCREC_IML_TYPE_FPR_LOAD ) - { - imlInstruction->op_storeLoad.registerData = replaceRegister(imlInstruction->op_storeLoad.registerData, fprRegisterSearched, fprRegisterReplaced); - } - else if( imlInstruction->type == PPCREC_IML_TYPE_FPR_LOAD_INDEXED ) - { - imlInstruction->op_storeLoad.registerData = replaceRegister(imlInstruction->op_storeLoad.registerData, fprRegisterSearched, fprRegisterReplaced); - } - else if( imlInstruction->type == PPCREC_IML_TYPE_FPR_STORE ) - { - imlInstruction->op_storeLoad.registerData = replaceRegister(imlInstruction->op_storeLoad.registerData, fprRegisterSearched, fprRegisterReplaced); - } - else if( imlInstruction->type == PPCREC_IML_TYPE_FPR_STORE_INDEXED ) - { - imlInstruction->op_storeLoad.registerData = replaceRegister(imlInstruction->op_storeLoad.registerData, fprRegisterSearched, fprRegisterReplaced); - } - else if( imlInstruction->type == PPCREC_IML_TYPE_FPR_R_R ) - { - imlInstruction->op_fpr_r_r.registerResult = replaceRegister(imlInstruction->op_fpr_r_r.registerResult, fprRegisterSearched, fprRegisterReplaced); - imlInstruction->op_fpr_r_r.registerOperand = replaceRegister(imlInstruction->op_fpr_r_r.registerOperand, fprRegisterSearched, fprRegisterReplaced); - } - else if( imlInstruction->type == PPCREC_IML_TYPE_FPR_R_R_R ) - { - imlInstruction->op_fpr_r_r_r.registerResult = replaceRegister(imlInstruction->op_fpr_r_r_r.registerResult, fprRegisterSearched, fprRegisterReplaced); - imlInstruction->op_fpr_r_r_r.registerOperandA = replaceRegister(imlInstruction->op_fpr_r_r_r.registerOperandA, fprRegisterSearched, fprRegisterReplaced); - imlInstruction->op_fpr_r_r_r.registerOperandB = replaceRegister(imlInstruction->op_fpr_r_r_r.registerOperandB, fprRegisterSearched, fprRegisterReplaced); - } - else if( imlInstruction->type == PPCREC_IML_TYPE_FPR_R_R_R_R ) - { - imlInstruction->op_fpr_r_r_r_r.registerResult = replaceRegister(imlInstruction->op_fpr_r_r_r_r.registerResult, fprRegisterSearched, fprRegisterReplaced); - imlInstruction->op_fpr_r_r_r_r.registerOperandA = replaceRegister(imlInstruction->op_fpr_r_r_r_r.registerOperandA, fprRegisterSearched, fprRegisterReplaced); - imlInstruction->op_fpr_r_r_r_r.registerOperandB = replaceRegister(imlInstruction->op_fpr_r_r_r_r.registerOperandB, fprRegisterSearched, fprRegisterReplaced); - imlInstruction->op_fpr_r_r_r_r.registerOperandC = replaceRegister(imlInstruction->op_fpr_r_r_r_r.registerOperandC, fprRegisterSearched, fprRegisterReplaced); - } - else if( imlInstruction->type == PPCREC_IML_TYPE_FPR_R ) - { - imlInstruction->op_fpr_r.registerResult = replaceRegister(imlInstruction->op_fpr_r.registerResult, fprRegisterSearched, fprRegisterReplaced); - } - else - { - cemu_assert_unimplemented(); - } -} - typedef struct { struct @@ -858,7 +19,7 @@ typedef struct sint32 count; }replacedRegisterTracker_t; -bool PPCRecompiler_checkIfGPRRegisterIsAccessed(PPCImlOptimizerUsedRegisters_t* registersUsed, sint32 gprRegister) +bool PPCRecompiler_checkIfGPRRegisterIsAccessed(IMLUsedRegisters* registersUsed, sint32 gprRegister) { if( registersUsed->readNamedReg1 == gprRegister ) return true; @@ -875,7 +36,7 @@ bool PPCRecompiler_checkIfGPRRegisterIsAccessed(PPCImlOptimizerUsedRegisters_t* * Returns index of register to replace * If no register needs to be replaced, -1 is returned */ -sint32 PPCRecompiler_getNextRegisterToReplace(PPCImlOptimizerUsedRegisters_t* registersUsed) +sint32 PPCRecompiler_getNextRegisterToReplace(IMLUsedRegisters* registersUsed) { // get index of register to replace sint32 gprToReplace = -1; @@ -893,10 +54,10 @@ sint32 PPCRecompiler_getNextRegisterToReplace(PPCImlOptimizerUsedRegisters_t* re bool PPCRecompiler_findAvailableRegisterDepr(ppcImlGenContext_t* ppcImlGenContext, IMLSegment* imlSegment, sint32 imlIndexStart, replacedRegisterTracker_t* replacedRegisterTracker, sint32* registerIndex, sint32* registerName, bool* isUsed) { - PPCImlOptimizerUsedRegisters_t registersUsed; - PPCRecompiler_checkRegisterUsage(ppcImlGenContext, &imlSegment->imlList[imlIndexStart], ®istersUsed); + IMLUsedRegisters registersUsed; + imlSegment->imlList[imlIndexStart].CheckRegisterUsage(®istersUsed); // mask all registers used by this instruction - uint32 instructionReservedRegisterMask = 0;//(1<<(PPC_X64_GPR_USABLE_REGISTERS+1))-1; + uint32 instructionReservedRegisterMask = 0; if( registersUsed.readNamedReg1 != -1 ) instructionReservedRegisterMask |= (1<<(registersUsed.readNamedReg1)); if( registersUsed.readNamedReg2 != -1 ) @@ -1006,10 +167,10 @@ bool PPCRecompiler_reduceNumberOfFPRRegisters(ppcImlGenContext_t* ppcImlGenConte size_t imlIndex = 0; while( imlIndex < segIt->imlList.size() ) { - PPCImlOptimizerUsedRegisters_t registersUsed; + IMLUsedRegisters registersUsed; while( true ) { - PPCRecompiler_checkRegisterUsage(ppcImlGenContext, segIt->imlList.data()+imlIndex, ®istersUsed); + segIt->imlList[imlIndex].CheckRegisterUsage(®istersUsed); if( registersUsed.readFPR1 >= PPC_X64_FPR_USABLE_REGISTERS || registersUsed.readFPR2 >= PPC_X64_FPR_USABLE_REGISTERS || registersUsed.readFPR3 >= PPC_X64_FPR_USABLE_REGISTERS || registersUsed.readFPR4 >= PPC_X64_FPR_USABLE_REGISTERS || registersUsed.writtenFPR1 >= PPC_X64_FPR_USABLE_REGISTERS ) { // get index of register to replace @@ -1055,7 +216,7 @@ bool PPCRecompiler_reduceNumberOfFPRRegisters(ppcImlGenContext_t* ppcImlGenConte replacedRegisterIsUsed = segIt->ppcFPRUsed[unusedRegisterName-PPCREC_NAME_FPR0]; } // replace registers that are out of range - PPCRecompiler_replaceFPRRegisterUsage(ppcImlGenContext, segIt->imlList.data() + imlIndex, fprToReplace, unusedRegisterIndex); + segIt->imlList[imlIndex].ReplaceFPRRegisterUsage(fprToReplace, unusedRegisterIndex); // add load/store name after instruction PPCRecompiler_pushBackIMLInstructions(segIt, imlIndex+1, 2); // add load/store before current instruction @@ -1121,7 +282,7 @@ typedef struct sint32 currentUseIndex; }ppcRecManageRegisters_t; -ppcRecRegisterMapping_t* PPCRecompiler_findAvailableRegisterDepr(ppcRecManageRegisters_t* rCtx, PPCImlOptimizerUsedRegisters_t* instructionUsedRegisters) +ppcRecRegisterMapping_t* PPCRecompiler_findAvailableRegisterDepr(ppcRecManageRegisters_t* rCtx, IMLUsedRegisters* instructionUsedRegisters) { // find free register for (sint32 i = 0; i < PPC_X64_FPR_USABLE_REGISTERS; i++) @@ -1138,7 +299,7 @@ ppcRecRegisterMapping_t* PPCRecompiler_findAvailableRegisterDepr(ppcRecManageReg return nullptr; } -ppcRecRegisterMapping_t* PPCRecompiler_findUnloadableRegister(ppcRecManageRegisters_t* rCtx, PPCImlOptimizerUsedRegisters_t* instructionUsedRegisters, uint32 unloadLockedMask) +ppcRecRegisterMapping_t* PPCRecompiler_findUnloadableRegister(ppcRecManageRegisters_t* rCtx, IMLUsedRegisters* instructionUsedRegisters, uint32 unloadLockedMask) { // find unloadable register (with lowest lastUseIndex) sint32 unloadIndex = -1; @@ -1179,13 +340,13 @@ bool PPCRecompiler_manageFPRRegistersForSegment(ppcImlGenContext_t* ppcImlGenCon IMLSegment* imlSegment = ppcImlGenContext->segmentList2[segmentIndex]; size_t idx = 0; sint32 currentUseIndex = 0; - PPCImlOptimizerUsedRegisters_t registersUsed; + IMLUsedRegisters registersUsed; while (idx < imlSegment->imlList.size()) { IMLInstruction& idxInst = imlSegment->imlList[idx]; if (idxInst.IsSuffixInstruction()) break; - PPCRecompiler_checkRegisterUsage(ppcImlGenContext, &idxInst, ®istersUsed); + idxInst.CheckRegisterUsage(®istersUsed); sint32 fprMatch[4]; sint32 fprReplace[4]; fprMatch[0] = -1; @@ -1288,7 +449,7 @@ bool PPCRecompiler_manageFPRRegistersForSegment(ppcImlGenContext_t* ppcImlGenCon } if (numReplacedOperands > 0) { - PPCRecompiler_replaceFPRRegisterUsageMultiple(ppcImlGenContext, imlSegment->imlList.data() + idx, fprMatch, fprReplace); + imlSegment->imlList[idx].ReplaceFPRRegisterUsageMultiple(fprMatch, fprReplace); } // next idx++; @@ -1340,9 +501,8 @@ bool PPCRecompiler_trackRedundantNameLoadInstruction(ppcImlGenContext_t* ppcImlG for(size_t i=startIndex; iimlList.size(); i++) { IMLInstruction* imlInstruction = imlSegment->imlList.data() + i; - //nameStoreInstruction->op_r_name.registerIndex - PPCImlOptimizerUsedRegisters_t registersUsed; - PPCRecompiler_checkRegisterUsage(ppcImlGenContext, imlInstruction, ®istersUsed); + IMLUsedRegisters registersUsed; + imlInstruction->CheckRegisterUsage(®istersUsed); if( registersUsed.readNamedReg1 == registerIndex || registersUsed.readNamedReg2 == registerIndex || registersUsed.readNamedReg3 == registerIndex ) return false; if( registersUsed.writtenNamedReg1 == registerIndex ) @@ -1361,8 +521,8 @@ bool PPCRecompiler_trackRedundantFPRNameLoadInstruction(ppcImlGenContext_t* ppcI for(size_t i=startIndex; iimlList.size(); i++) { IMLInstruction* imlInstruction = imlSegment->imlList.data() + i; - PPCImlOptimizerUsedRegisters_t registersUsed; - PPCRecompiler_checkRegisterUsage(ppcImlGenContext, imlInstruction, ®istersUsed); + IMLUsedRegisters registersUsed; + imlInstruction->CheckRegisterUsage(®istersUsed); if( registersUsed.readFPR1 == registerIndex || registersUsed.readFPR2 == registerIndex || registersUsed.readFPR3 == registerIndex || registersUsed.readFPR4 == registerIndex) return false; if( registersUsed.writtenFPR1 == registerIndex ) @@ -1381,8 +541,8 @@ bool PPCRecompiler_trackRedundantNameStoreInstruction(ppcImlGenContext_t* ppcIml for(sint32 i=startIndex; i>=0; i--) { IMLInstruction* imlInstruction = imlSegment->imlList.data() + i; - PPCImlOptimizerUsedRegisters_t registersUsed; - PPCRecompiler_checkRegisterUsage(ppcImlGenContext, imlInstruction, ®istersUsed); + IMLUsedRegisters registersUsed; + imlInstruction->CheckRegisterUsage(®istersUsed); if( registersUsed.writtenNamedReg1 == registerIndex ) { if( imlSegment->imlList[i].type == PPCREC_IML_TYPE_R_NAME ) @@ -1440,8 +600,8 @@ bool PPCRecompiler_trackRedundantFPRNameStoreInstruction(ppcImlGenContext_t* ppc for(sint32 i=startIndex; i>=0; i--) { IMLInstruction* imlInstruction = imlSegment->imlList.data() + i; - PPCImlOptimizerUsedRegisters_t registersUsed; - PPCRecompiler_checkRegisterUsage(ppcImlGenContext, imlInstruction, ®istersUsed); + IMLUsedRegisters registersUsed; + imlInstruction->CheckRegisterUsage(®istersUsed); if( registersUsed.writtenFPR1 == registerIndex ) { if(imlInstruction->type == PPCREC_IML_TYPE_FPR_R_NAME ) @@ -1565,7 +725,7 @@ void PPCRecompiler_removeRedundantCRUpdates(ppcImlGenContext_t* ppcImlGenContext else cemu_assert_unimplemented(); } - else if( PPCRecompilerImlAnalyzer_canTypeWriteCR(&instIt) && instIt.crRegister >= 0 && instIt.crRegister <= 7 ) + else if (IMLAnalyzer_CanTypeWriteCR(&instIt) && instIt.crRegister >= 0 && instIt.crRegister <= 7) { segIt->crBitsWritten |= (0xF<<(instIt.crRegister*4)); } @@ -1581,7 +741,7 @@ void PPCRecompiler_removeRedundantCRUpdates(ppcImlGenContext_t* ppcImlGenContext { for (IMLInstruction& instIt : segIt->imlList) { - if( PPCRecompilerImlAnalyzer_canTypeWriteCR(&instIt) && instIt.crRegister >= 0 && instIt.crRegister <= 7 ) + if (IMLAnalyzer_CanTypeWriteCR(&instIt) && instIt.crRegister >= 0 && instIt.crRegister <= 7) { uint32 crBitFlags = 0xF<<((uint32)instIt.crRegister*4); uint32 crOverwriteMask = PPCRecompiler_getCROverwriteMask(ppcImlGenContext, segIt); @@ -1594,11 +754,11 @@ void PPCRecompiler_removeRedundantCRUpdates(ppcImlGenContext_t* ppcImlGenContext bool PPCRecompiler_checkIfGPRIsModifiedInRange(ppcImlGenContext_t* ppcImlGenContext, IMLSegment* imlSegment, sint32 startIndex, sint32 endIndex, sint32 vreg) { - PPCImlOptimizerUsedRegisters_t registersUsed; + IMLUsedRegisters registersUsed; for (sint32 i = startIndex; i <= endIndex; i++) { IMLInstruction* imlInstruction = imlSegment->imlList.data() + i; - PPCRecompiler_checkRegisterUsage(ppcImlGenContext, imlInstruction, ®istersUsed); + imlInstruction->CheckRegisterUsage(®istersUsed); if (registersUsed.writtenNamedReg1 == vreg) return true; } @@ -1642,13 +802,13 @@ sint32 PPCRecompiler_scanBackwardsForReusableRegister(ppcImlGenContext_t* ppcIml currentIndex = startIndex; currentSegment = startSegment; segmentIterateCount = 0; - PPCImlOptimizerUsedRegisters_t registersUsed; + IMLUsedRegisters registersUsed; while (true) { while (currentIndex >= 0) { // check if register is modified - PPCRecompiler_checkRegisterUsage(ppcImlGenContext, currentSegment->imlList.data() + currentIndex, ®istersUsed); + currentSegment->imlList[currentIndex].CheckRegisterUsage(®istersUsed); if (registersUsed.writtenNamedReg1 == foundRegister) return -1; // check if end of scan reached @@ -1677,7 +837,7 @@ void PPCRecompiler_optimizeDirectFloatCopiesScanForward(ppcImlGenContext_t* ppcI if (imlInstructionLoad->op_storeLoad.flags2.notExpanded) return; - PPCImlOptimizerUsedRegisters_t registersUsed; + IMLUsedRegisters registersUsed; sint32 scanRangeEnd = std::min(imlIndexLoad + 25, imlSegment->imlList.size()); // don't scan too far (saves performance and also the chances we can merge the load+store become low at high distances) bool foundMatch = false; sint32 lastStore = -1; @@ -1709,7 +869,7 @@ void PPCRecompiler_optimizeDirectFloatCopiesScanForward(ppcImlGenContext_t* ppcI } // check if FPR is overwritten (we can actually ignore read operations?) - PPCRecompiler_checkRegisterUsage(ppcImlGenContext, imlInstruction, ®istersUsed); + imlInstruction->CheckRegisterUsage(®istersUsed); if (registersUsed.writtenFPR1 == fprIndex) break; if (registersUsed.readFPR1 == fprIndex) @@ -1766,7 +926,7 @@ void PPCRecompiler_optimizeDirectIntegerCopiesScanForward(ppcImlGenContext_t* pp if ( imlInstructionLoad->op_storeLoad.flags2.swapEndian == false ) return; bool foundMatch = false; - PPCImlOptimizerUsedRegisters_t registersUsed; + IMLUsedRegisters registersUsed; sint32 scanRangeEnd = std::min(imlIndexLoad + 25, imlSegment->imlList.size()); // don't scan too far (saves performance and also the chances we can merge the load+store become low at high distances) sint32 i = imlIndexLoad + 1; for (; i < scanRangeEnd; i++) @@ -1795,7 +955,7 @@ void PPCRecompiler_optimizeDirectIntegerCopiesScanForward(ppcImlGenContext_t* pp } } // check if GPR is accessed - PPCRecompiler_checkRegisterUsage(ppcImlGenContext, imlInstruction, ®istersUsed); + imlInstruction->CheckRegisterUsage(®istersUsed); if (registersUsed.readNamedReg1 == gprIndex || registersUsed.readNamedReg2 == gprIndex || registersUsed.readNamedReg3 == gprIndex) @@ -1930,7 +1090,7 @@ void PPCRecompiler_optimizePSQLoadAndStore(ppcImlGenContext_t* ppcImlGenContext) // get GQR value cemu_assert_debug(instIt.op_storeLoad.registerGQR != PPC_REC_INVALID_REGISTER); sint32 gqrIndex = _getGQRIndexFromRegister(ppcImlGenContext, instIt.op_storeLoad.registerGQR); - cemu_assert(gqrIndex >= 0); + cemu_assert(gqrIndex >= 0 && gqrIndex < 8); if (ppcImlGenContext->tracking.modifiesGQR[gqrIndex]) continue; uint32 gqrValue; @@ -1974,7 +1134,7 @@ void PPCRecompiler_optimizePSQLoadAndStore(ppcImlGenContext_t* ppcImlGenContext) /* * Returns true if registerWrite overwrites any of the registers read by registerRead */ -bool PPCRecompilerAnalyzer_checkForGPROverwrite(PPCImlOptimizerUsedRegisters_t* registerRead, PPCImlOptimizerUsedRegisters_t* registerWrite) +bool PPCRecompilerAnalyzer_checkForGPROverwrite(IMLUsedRegisters* registerRead, IMLUsedRegisters* registerWrite) { if (registerWrite->writtenNamedReg1 < 0) return false; @@ -1998,7 +1158,7 @@ void _reorderConditionModifyInstructions(IMLSegment* imlSegment) return; // get CR bitmask of bit required for conditional jump PPCRecCRTracking_t crTracking; - PPCRecompilerImlAnalyzer_getCRTracking(lastInstruction, &crTracking); + IMLAnalyzer_GetCRTracking(lastInstruction, &crTracking); uint32 requiredCRBits = crTracking.readCRBits; // scan backwards until we find the instruction that sets the CR @@ -2007,7 +1167,7 @@ void _reorderConditionModifyInstructions(IMLSegment* imlSegment) for (sint32 i = imlSegment->imlList.size() - 2; i >= 0; i--) { IMLInstruction* imlInstruction = imlSegment->imlList.data() + i; - PPCRecompilerImlAnalyzer_getCRTracking(imlInstruction, &crTracking); + IMLAnalyzer_GetCRTracking(imlInstruction, &crTracking); if (crTracking.readCRBits != 0) return; // dont handle complex cases for now if (crTracking.writtenCRBits != 0) @@ -2039,17 +1199,17 @@ void _reorderConditionModifyInstructions(IMLSegment* imlSegment) return; // no danger of overwriting eflags, don't reorder // check if we can move the CR setter instruction to after unsafeInstructionIndex PPCRecCRTracking_t crTrackingSetter = crTracking; - PPCImlOptimizerUsedRegisters_t regTrackingCRSetter; - PPCRecompiler_checkRegisterUsage(nullptr, imlSegment->imlList.data() + crSetterInstructionIndex, ®TrackingCRSetter); + IMLUsedRegisters regTrackingCRSetter; + imlSegment->imlList[crSetterInstructionIndex].CheckRegisterUsage(®TrackingCRSetter); if (regTrackingCRSetter.writtenFPR1 >= 0 || regTrackingCRSetter.readFPR1 >= 0 || regTrackingCRSetter.readFPR2 >= 0 || regTrackingCRSetter.readFPR3 >= 0 || regTrackingCRSetter.readFPR4 >= 0) return; // we don't handle FPR dependency yet so just ignore FPR instructions - PPCImlOptimizerUsedRegisters_t registerTracking; + IMLUsedRegisters registerTracking; if (regTrackingCRSetter.writtenNamedReg1 >= 0) { // CR setter does write GPR for (sint32 i = crSetterInstructionIndex + 1; i <= unsafeInstructionIndex; i++) { - PPCRecompiler_checkRegisterUsage(nullptr, imlSegment->imlList.data() + i, ®isterTracking); + imlSegment->imlList[i].CheckRegisterUsage(®isterTracking); // reads register written by CR setter? if (PPCRecompilerAnalyzer_checkForGPROverwrite(®isterTracking, ®TrackingCRSetter)) { @@ -2070,7 +1230,7 @@ void _reorderConditionModifyInstructions(IMLSegment* imlSegment) // CR setter does not write GPR for (sint32 i = crSetterInstructionIndex + 1; i <= unsafeInstructionIndex; i++) { - PPCRecompiler_checkRegisterUsage(nullptr, imlSegment->imlList.data() + i, ®isterTracking); + imlSegment->imlList[i].CheckRegisterUsage(®isterTracking); // writes register read by CR setter? if (PPCRecompilerAnalyzer_checkForGPROverwrite(®TrackingCRSetter, ®isterTracking)) { diff --git a/src/Cafe/HW/Espresso/Recompiler/PPCRecompilerImlRegisterAllocator.cpp b/src/Cafe/HW/Espresso/Recompiler/PPCRecompilerImlRegisterAllocator.cpp index afe6d943..f162e023 100644 --- a/src/Cafe/HW/Espresso/Recompiler/PPCRecompilerImlRegisterAllocator.cpp +++ b/src/Cafe/HW/Espresso/Recompiler/PPCRecompilerImlRegisterAllocator.cpp @@ -1,10 +1,10 @@ +#include "./IML/IML.h" + #include "PPCRecompiler.h" #include "PPCRecompilerIml.h" #include "PPCRecompilerX64.h" #include "PPCRecompilerImlRanges.h" -void PPCRecompiler_replaceGPRRegisterUsageMultiple(ppcImlGenContext_t* ppcImlGenContext, IMLInstruction* imlInstruction, sint32 gprRegisterSearched[4], sint32 gprRegisterReplaced[4]); - uint32 recRACurrentIterationIndex = 0; uint32 PPCRecRA_getNextIterationIndex() @@ -831,8 +831,8 @@ void PPCRecRA_generateSegmentInstructions(ppcImlGenContext_t* ppcImlGenContext, // replace registers if (index < imlSegment->imlList.size()) { - PPCImlOptimizerUsedRegisters_t gprTracking; - PPCRecompiler_checkRegisterUsage(nullptr, imlSegment->imlList.data() + index, &gprTracking); + IMLUsedRegisters gprTracking; + imlSegment->imlList[index].CheckRegisterUsage(&gprTracking); sint32 inputGpr[4]; inputGpr[0] = gprTracking.gpr[0]; @@ -853,7 +853,7 @@ void PPCRecRA_generateSegmentInstructions(ppcImlGenContext_t* ppcImlGenContext, replaceGpr[f] = virtualReg2PhysReg[virtualRegister]; cemu_assert_debug(replaceGpr[f] >= 0); } - PPCRecompiler_replaceGPRRegisterUsageMultiple(ppcImlGenContext, imlSegment->imlList.data() + index, inputGpr, replaceGpr); + imlSegment->imlList[index].ReplaceGPRRegisterUsageMultiple(inputGpr, replaceGpr); } // next iml instruction index++; @@ -1014,14 +1014,14 @@ void PPCRecRA_calculateSegmentMinMaxRanges(ppcImlGenContext_t* ppcImlGenContext, } // scan instructions for usage range size_t index = 0; - PPCImlOptimizerUsedRegisters_t gprTracking; + IMLUsedRegisters gprTracking; while (index < imlSegment->imlList.size()) { // end loop at suffix instruction if (imlSegment->imlList[index].IsSuffixInstruction()) break; // get accessed GPRs - PPCRecompiler_checkRegisterUsage(NULL, imlSegment->imlList.data() + index, &gprTracking); + imlSegment->imlList[index].CheckRegisterUsage(&gprTracking); for (sint32 t = 0; t < 4; t++) { sint32 virtualRegister = gprTracking.gpr[t]; @@ -1107,14 +1107,14 @@ void PPCRecRA_createSegmentLivenessRanges(ppcImlGenContext_t* ppcImlGenContext, } // parse instructions and convert to locations size_t index = 0; - PPCImlOptimizerUsedRegisters_t gprTracking; + IMLUsedRegisters gprTracking; while (index < imlSegment->imlList.size()) { // end loop at suffix instruction if (imlSegment->imlList[index].IsSuffixInstruction()) break; // get accessed GPRs - PPCRecompiler_checkRegisterUsage(NULL, imlSegment->imlList.data() + index, &gprTracking); + imlSegment->imlList[index].CheckRegisterUsage(&gprTracking); // handle accessed GPR for (sint32 t = 0; t < 4; t++) {