mirror of
https://github.com/cemu-project/Cemu.git
synced 2025-02-22 12:47:14 +01:00
PPCRec: Move analyzer file + move some funcs to IMLInstruction
This commit is contained in:
parent
625874a753
commit
101a2ef911
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
@ -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();
|
||||
}
|
||||
}
|
@ -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);
|
||||
};
|
@ -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);
|
||||
|
@ -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; i<segIt->imlList.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;
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -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++)
|
||||
{
|
||||
|
Loading…
x
Reference in New Issue
Block a user