Cemu/src/Cafe/HW/Espresso/Recompiler/IML/IMLInstruction.cpp

846 lines
29 KiB
C++

#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();
}
}