PPCRec: Use IMLReg in more places, unify and simplify var names

This commit is contained in:
Exzap 2023-01-05 05:34:36 +01:00
parent b4f2e02e55
commit 3ba9460dc1
13 changed files with 575 additions and 917 deletions

View File

@ -545,54 +545,54 @@ bool PPCRecompilerX64Gen_imlInstruction_r_r(PPCRecFunction_t* PPCRecFunction, pp
if (imlInstruction->operation == PPCREC_IML_OP_ASSIGN)
{
// registerResult = registerA
if (imlInstruction->op_r_r.registerResult != imlInstruction->op_r_r.registerA)
x64Gen_mov_reg64Low32_reg64Low32(x64GenContext, imlInstruction->op_r_r.registerResult, imlInstruction->op_r_r.registerA);
if (imlInstruction->op_r_r.regR != imlInstruction->op_r_r.regA)
x64Gen_mov_reg64Low32_reg64Low32(x64GenContext, imlInstruction->op_r_r.regR, imlInstruction->op_r_r.regA);
}
else if (imlInstruction->operation == PPCREC_IML_OP_ENDIAN_SWAP)
{
if (imlInstruction->op_r_r.registerA != imlInstruction->op_r_r.registerResult)
x64Gen_mov_reg64Low32_reg64Low32(x64GenContext, imlInstruction->op_r_r.registerResult, imlInstruction->op_r_r.registerA); // if movbe is available we can move and swap in a single instruction?
x64Gen_bswap_reg64Lower32bit(x64GenContext, imlInstruction->op_r_r.registerResult);
if (imlInstruction->op_r_r.regA != imlInstruction->op_r_r.regR)
x64Gen_mov_reg64Low32_reg64Low32(x64GenContext, imlInstruction->op_r_r.regR, imlInstruction->op_r_r.regA); // if movbe is available we can move and swap in a single instruction?
x64Gen_bswap_reg64Lower32bit(x64GenContext, imlInstruction->op_r_r.regR);
}
else if( imlInstruction->operation == PPCREC_IML_OP_ASSIGN_S8_TO_S32 )
{
x64Gen_movSignExtend_reg64Low32_reg64Low8(x64GenContext, imlInstruction->op_r_r.registerResult, imlInstruction->op_r_r.registerA);
x64Gen_movSignExtend_reg64Low32_reg64Low8(x64GenContext, imlInstruction->op_r_r.regR, imlInstruction->op_r_r.regA);
}
else if (imlInstruction->operation == PPCREC_IML_OP_ASSIGN_S16_TO_S32)
{
x64Gen_movSignExtend_reg64Low32_reg64Low16(x64GenContext, imlInstruction->op_r_r.registerResult, reg32ToReg16(imlInstruction->op_r_r.registerA));
x64Gen_movSignExtend_reg64Low32_reg64Low16(x64GenContext, imlInstruction->op_r_r.regR, reg32ToReg16(imlInstruction->op_r_r.regA));
}
else if( imlInstruction->operation == PPCREC_IML_OP_OR || imlInstruction->operation == PPCREC_IML_OP_AND || imlInstruction->operation == PPCREC_IML_OP_XOR )
{
if( imlInstruction->operation == PPCREC_IML_OP_OR )
{
// registerResult |= registerA
x64Gen_or_reg64Low32_reg64Low32(x64GenContext, imlInstruction->op_r_r.registerResult, imlInstruction->op_r_r.registerA);
x64Gen_or_reg64Low32_reg64Low32(x64GenContext, imlInstruction->op_r_r.regR, imlInstruction->op_r_r.regA);
}
else if( imlInstruction->operation == PPCREC_IML_OP_AND )
{
// registerResult &= registerA
x64Gen_and_reg64Low32_reg64Low32(x64GenContext, imlInstruction->op_r_r.registerResult, imlInstruction->op_r_r.registerA);
x64Gen_and_reg64Low32_reg64Low32(x64GenContext, imlInstruction->op_r_r.regR, imlInstruction->op_r_r.regA);
}
else
{
// registerResult ^= registerA
x64Gen_xor_reg64Low32_reg64Low32(x64GenContext, imlInstruction->op_r_r.registerResult, imlInstruction->op_r_r.registerA);
x64Gen_xor_reg64Low32_reg64Low32(x64GenContext, imlInstruction->op_r_r.regR, imlInstruction->op_r_r.regA);
}
}
else if( imlInstruction->operation == PPCREC_IML_OP_NOT )
{
// copy register content if different registers
if( imlInstruction->op_r_r.registerResult != imlInstruction->op_r_r.registerA )
x64Gen_mov_reg64_reg64(x64GenContext, imlInstruction->op_r_r.registerResult, imlInstruction->op_r_r.registerA);
x64Gen_not_reg64Low32(x64GenContext, imlInstruction->op_r_r.registerResult);
if( imlInstruction->op_r_r.regR != imlInstruction->op_r_r.regA )
x64Gen_mov_reg64_reg64(x64GenContext, imlInstruction->op_r_r.regR, imlInstruction->op_r_r.regA);
x64Gen_not_reg64Low32(x64GenContext, imlInstruction->op_r_r.regR);
}
else if (imlInstruction->operation == PPCREC_IML_OP_NEG)
{
// copy register content if different registers
if (imlInstruction->op_r_r.registerResult != imlInstruction->op_r_r.registerA)
x64Gen_mov_reg64_reg64(x64GenContext, imlInstruction->op_r_r.registerResult, imlInstruction->op_r_r.registerA);
x64Gen_neg_reg64Low32(x64GenContext, imlInstruction->op_r_r.registerResult);
if (imlInstruction->op_r_r.regR != imlInstruction->op_r_r.regA)
x64Gen_mov_reg64_reg64(x64GenContext, imlInstruction->op_r_r.regR, imlInstruction->op_r_r.regA);
x64Gen_neg_reg64Low32(x64GenContext, imlInstruction->op_r_r.regR);
}
else if( imlInstruction->operation == PPCREC_IML_OP_CNTLZW )
{
@ -600,29 +600,29 @@ bool PPCRecompilerX64Gen_imlInstruction_r_r(PPCRecFunction_t* PPCRecFunction, pp
// LZCNT instruction (part of SSE4, CPUID.80000001H:ECX.ABM[Bit 5])
if(g_CPUFeatures.x86.lzcnt)
{
x64Gen_lzcnt_reg64Low32_reg64Low32(x64GenContext, imlInstruction->op_r_r.registerResult, imlInstruction->op_r_r.registerA);
x64Gen_lzcnt_reg64Low32_reg64Low32(x64GenContext, imlInstruction->op_r_r.regR, imlInstruction->op_r_r.regA);
}
else
{
x64Gen_test_reg64Low32_reg64Low32(x64GenContext, imlInstruction->op_r_r.registerA, imlInstruction->op_r_r.registerA);
x64Gen_test_reg64Low32_reg64Low32(x64GenContext, imlInstruction->op_r_r.regA, imlInstruction->op_r_r.regA);
sint32 jumpInstructionOffset1 = x64GenContext->emitter->GetWriteIndex();
x64Gen_jmpc_near(x64GenContext, X86_CONDITION_EQUAL, 0);
x64Gen_bsr_reg64Low32_reg64Low32(x64GenContext, imlInstruction->op_r_r.registerResult, imlInstruction->op_r_r.registerA);
x64Gen_neg_reg64Low32(x64GenContext, imlInstruction->op_r_r.registerResult);
x64Gen_add_reg64Low32_imm32(x64GenContext, imlInstruction->op_r_r.registerResult, 32-1);
x64Gen_bsr_reg64Low32_reg64Low32(x64GenContext, imlInstruction->op_r_r.regR, imlInstruction->op_r_r.regA);
x64Gen_neg_reg64Low32(x64GenContext, imlInstruction->op_r_r.regR);
x64Gen_add_reg64Low32_imm32(x64GenContext, imlInstruction->op_r_r.regR, 32-1);
sint32 jumpInstructionOffset2 = x64GenContext->emitter->GetWriteIndex();
x64Gen_jmpc_near(x64GenContext, X86_CONDITION_NONE, 0);
PPCRecompilerX64Gen_redirectRelativeJump(x64GenContext, jumpInstructionOffset1, x64GenContext->emitter->GetWriteIndex());
x64Gen_mov_reg64Low32_imm32(x64GenContext, imlInstruction->op_r_r.registerResult, 32);
x64Gen_mov_reg64Low32_imm32(x64GenContext, imlInstruction->op_r_r.regR, 32);
PPCRecompilerX64Gen_redirectRelativeJump(x64GenContext, jumpInstructionOffset2, x64GenContext->emitter->GetWriteIndex());
}
}
else if( imlInstruction->operation == PPCREC_IML_OP_DCBZ )
{
if( imlInstruction->op_r_r.registerResult != imlInstruction->op_r_r.registerA )
if( imlInstruction->op_r_r.regR != imlInstruction->op_r_r.regA )
{
x64Gen_mov_reg64_reg64(x64GenContext, REG_RESV_TEMP, imlInstruction->op_r_r.registerA);
x64Gen_add_reg64Low32_reg64Low32(x64GenContext, REG_RESV_TEMP, imlInstruction->op_r_r.registerResult);
x64Gen_mov_reg64_reg64(x64GenContext, REG_RESV_TEMP, imlInstruction->op_r_r.regA);
x64Gen_add_reg64Low32_reg64Low32(x64GenContext, REG_RESV_TEMP, imlInstruction->op_r_r.regR);
x64Gen_and_reg64Low32_imm32(x64GenContext, REG_RESV_TEMP, ~0x1F);
x64Gen_add_reg64_reg64(x64GenContext, REG_RESV_TEMP, REG_RESV_MEMBASE);
for(sint32 f=0; f<0x20; f+=8)
@ -631,7 +631,7 @@ bool PPCRecompilerX64Gen_imlInstruction_r_r(PPCRecFunction_t* PPCRecFunction, pp
else
{
// calculate effective address
x64Gen_mov_reg64_reg64(x64GenContext, REG_RESV_TEMP, imlInstruction->op_r_r.registerA);
x64Gen_mov_reg64_reg64(x64GenContext, REG_RESV_TEMP, imlInstruction->op_r_r.regA);
x64Gen_and_reg64Low32_imm32(x64GenContext, REG_RESV_TEMP, ~0x1F);
x64Gen_add_reg64_reg64(x64GenContext, REG_RESV_TEMP, REG_RESV_MEMBASE);
for(sint32 f=0; f<0x20; f+=8)
@ -650,25 +650,25 @@ bool PPCRecompilerX64Gen_imlInstruction_r_s32(PPCRecFunction_t* PPCRecFunction,
{
if( imlInstruction->operation == PPCREC_IML_OP_ASSIGN )
{
x64Gen_mov_reg64Low32_imm32(x64GenContext, imlInstruction->op_r_immS32.registerIndex, (uint32)imlInstruction->op_r_immS32.immS32);
x64Gen_mov_reg64Low32_imm32(x64GenContext, imlInstruction->op_r_immS32.regR, (uint32)imlInstruction->op_r_immS32.immS32);
}
else if( imlInstruction->operation == PPCREC_IML_OP_AND )
{
x64Gen_and_reg64Low32_imm32(x64GenContext, imlInstruction->op_r_immS32.registerIndex, (uint32)imlInstruction->op_r_immS32.immS32);
x64Gen_and_reg64Low32_imm32(x64GenContext, imlInstruction->op_r_immS32.regR, (uint32)imlInstruction->op_r_immS32.immS32);
}
else if( imlInstruction->operation == PPCREC_IML_OP_OR )
{
x64Gen_or_reg64Low32_imm32(x64GenContext, imlInstruction->op_r_immS32.registerIndex, (uint32)imlInstruction->op_r_immS32.immS32);
x64Gen_or_reg64Low32_imm32(x64GenContext, imlInstruction->op_r_immS32.regR, (uint32)imlInstruction->op_r_immS32.immS32);
}
else if( imlInstruction->operation == PPCREC_IML_OP_XOR )
{
x64Gen_xor_reg64Low32_imm32(x64GenContext, imlInstruction->op_r_immS32.registerIndex, (uint32)imlInstruction->op_r_immS32.immS32);
x64Gen_xor_reg64Low32_imm32(x64GenContext, imlInstruction->op_r_immS32.regR, (uint32)imlInstruction->op_r_immS32.immS32);
}
else if( imlInstruction->operation == PPCREC_IML_OP_LEFT_ROTATE )
{
if( (imlInstruction->op_r_immS32.immS32&0x80) )
assert_dbg(); // should not happen
x64Gen_rol_reg64Low32_imm8(x64GenContext, imlInstruction->op_r_immS32.registerIndex, (uint8)imlInstruction->op_r_immS32.immS32);
x64Gen_rol_reg64Low32_imm8(x64GenContext, imlInstruction->op_r_immS32.regR, (uint8)imlInstruction->op_r_immS32.immS32);
}
else if( imlInstruction->operation == PPCREC_IML_OP_MFCR )
{
@ -731,9 +731,9 @@ bool PPCRecompilerX64Gen_imlInstruction_r_r_r(PPCRecFunction_t* PPCRecFunction,
if (imlInstruction->operation == PPCREC_IML_OP_ADD)
{
// registerResult = registerOperand1 + registerOperand2
sint32 rRegResult = imlInstruction->op_r_r_r.registerResult;
sint32 rRegOperand1 = imlInstruction->op_r_r_r.registerA;
sint32 rRegOperand2 = imlInstruction->op_r_r_r.registerB;
sint32 rRegResult = imlInstruction->op_r_r_r.regR;
sint32 rRegOperand1 = imlInstruction->op_r_r_r.regA;
sint32 rRegOperand2 = imlInstruction->op_r_r_r.regB;
if( (rRegResult == rRegOperand1) || (rRegResult == rRegOperand2) )
{
// be careful not to overwrite the operand before we use it
@ -751,9 +751,9 @@ bool PPCRecompilerX64Gen_imlInstruction_r_r_r(PPCRecFunction_t* PPCRecFunction,
}
else if( imlInstruction->operation == PPCREC_IML_OP_SUB )
{
sint32 rRegResult = imlInstruction->op_r_r_r.registerResult;
sint32 rRegOperand1 = imlInstruction->op_r_r_r.registerA;
sint32 rRegOperand2 = imlInstruction->op_r_r_r.registerB;
sint32 rRegResult = imlInstruction->op_r_r_r.regR;
sint32 rRegOperand1 = imlInstruction->op_r_r_r.regA;
sint32 rRegOperand2 = imlInstruction->op_r_r_r.regB;
if( rRegOperand1 == rRegOperand2 )
{
// result = operand1 - operand1 -> 0
@ -782,9 +782,9 @@ bool PPCRecompilerX64Gen_imlInstruction_r_r_r(PPCRecFunction_t* PPCRecFunction,
}
else if (imlInstruction->operation == PPCREC_IML_OP_OR || imlInstruction->operation == PPCREC_IML_OP_AND || imlInstruction->operation == PPCREC_IML_OP_XOR)
{
sint32 rRegResult = imlInstruction->op_r_r_r.registerResult;
sint32 rRegA = imlInstruction->op_r_r_r.registerA;
sint32 rRegB = imlInstruction->op_r_r_r.registerB;
sint32 rRegResult = imlInstruction->op_r_r_r.regR;
sint32 rRegA = imlInstruction->op_r_r_r.regA;
sint32 rRegB = imlInstruction->op_r_r_r.regB;
if (rRegResult == rRegB)
std::swap(rRegA, rRegB);
@ -801,9 +801,9 @@ bool PPCRecompilerX64Gen_imlInstruction_r_r_r(PPCRecFunction_t* PPCRecFunction,
else if( imlInstruction->operation == PPCREC_IML_OP_MULTIPLY_SIGNED )
{
// registerResult = registerOperand1 * registerOperand2
sint32 rRegResult = imlInstruction->op_r_r_r.registerResult;
sint32 rRegOperand1 = imlInstruction->op_r_r_r.registerA;
sint32 rRegOperand2 = imlInstruction->op_r_r_r.registerB;
sint32 rRegResult = imlInstruction->op_r_r_r.regR;
sint32 rRegOperand1 = imlInstruction->op_r_r_r.regA;
sint32 rRegOperand2 = imlInstruction->op_r_r_r.regB;
if( (rRegResult == rRegOperand1) || (rRegResult == rRegOperand2) )
{
// be careful not to overwrite the operand before we use it
@ -823,9 +823,9 @@ bool PPCRecompilerX64Gen_imlInstruction_r_r_r(PPCRecFunction_t* PPCRecFunction,
else if( imlInstruction->operation == PPCREC_IML_OP_SLW || imlInstruction->operation == PPCREC_IML_OP_SRW )
{
// registerResult = registerOperand1(rA) >> registerOperand2(rB) (up to 63 bits)
sint32 rRegResult = imlInstruction->op_r_r_r.registerResult;
sint32 rRegOperand1 = imlInstruction->op_r_r_r.registerA;
sint32 rRegOperand2 = imlInstruction->op_r_r_r.registerB;
sint32 rRegResult = imlInstruction->op_r_r_r.regR;
sint32 rRegOperand1 = imlInstruction->op_r_r_r.regA;
sint32 rRegOperand2 = imlInstruction->op_r_r_r.regB;
if (g_CPUFeatures.x86.bmi2 && imlInstruction->operation == PPCREC_IML_OP_SRW)
{
@ -865,9 +865,9 @@ bool PPCRecompilerX64Gen_imlInstruction_r_r_r(PPCRecFunction_t* PPCRecFunction,
}
else if( imlInstruction->operation == PPCREC_IML_OP_LEFT_ROTATE )
{
sint32 rRegResult = imlInstruction->op_r_r_r.registerResult;
sint32 rRegOperand1 = imlInstruction->op_r_r_r.registerA;
sint32 rRegOperand2 = imlInstruction->op_r_r_r.registerB;
sint32 rRegResult = imlInstruction->op_r_r_r.regR;
sint32 rRegOperand1 = imlInstruction->op_r_r_r.regA;
sint32 rRegOperand2 = imlInstruction->op_r_r_r.regB;
// todo: Use BMI2 rotate if available
// check if CL/ECX/RCX is available
if( rRegResult != X86_REG_RCX && rRegOperand1 != X86_REG_RCX && rRegOperand2 != X86_REG_RCX )
@ -906,9 +906,9 @@ bool PPCRecompilerX64Gen_imlInstruction_r_r_r(PPCRecFunction_t* PPCRecFunction,
// since our register allocator doesn't support instruction based fixed phys registers yet
// we'll instead have to temporarily shuffle registers around
sint32 rRegResult = imlInstruction->op_r_r_r.registerResult;
sint32 rRegOperand1 = imlInstruction->op_r_r_r.registerA;
sint32 rRegOperand2 = imlInstruction->op_r_r_r.registerB;
sint32 rRegResult = imlInstruction->op_r_r_r.regR;
sint32 rRegOperand1 = imlInstruction->op_r_r_r.regA;
sint32 rRegOperand2 = imlInstruction->op_r_r_r.regB;
// we use BMI2's shift instructions until the RA can assign fixed registers
if (imlInstruction->operation == PPCREC_IML_OP_RIGHT_SHIFT_S)
@ -981,9 +981,9 @@ bool PPCRecompilerX64Gen_imlInstruction_r_r_r(PPCRecFunction_t* PPCRecFunction,
}
else if( imlInstruction->operation == PPCREC_IML_OP_DIVIDE_SIGNED || imlInstruction->operation == PPCREC_IML_OP_DIVIDE_UNSIGNED )
{
sint32 rRegResult = imlInstruction->op_r_r_r.registerResult;
sint32 rRegOperand1 = imlInstruction->op_r_r_r.registerA;
sint32 rRegOperand2 = imlInstruction->op_r_r_r.registerB;
sint32 rRegResult = imlInstruction->op_r_r_r.regR;
sint32 rRegOperand1 = imlInstruction->op_r_r_r.regA;
sint32 rRegOperand2 = imlInstruction->op_r_r_r.regB;
x64Emit_mov_mem32_reg32(x64GenContext, X86_REG_RSP, (uint32)offsetof(PPCInterpreter_t, temporaryGPR[0]), X86_REG_EAX);
x64Emit_mov_mem32_reg32(x64GenContext, X86_REG_RSP, (uint32)offsetof(PPCInterpreter_t, temporaryGPR[1]), X86_REG_EDX);
@ -1015,9 +1015,9 @@ bool PPCRecompilerX64Gen_imlInstruction_r_r_r(PPCRecFunction_t* PPCRecFunction,
}
else if( imlInstruction->operation == PPCREC_IML_OP_MULTIPLY_HIGH_SIGNED || imlInstruction->operation == PPCREC_IML_OP_MULTIPLY_HIGH_UNSIGNED )
{
sint32 rRegResult = imlInstruction->op_r_r_r.registerResult;
sint32 rRegOperand1 = imlInstruction->op_r_r_r.registerA;
sint32 rRegOperand2 = imlInstruction->op_r_r_r.registerB;
sint32 rRegResult = imlInstruction->op_r_r_r.regR;
sint32 rRegOperand1 = imlInstruction->op_r_r_r.regA;
sint32 rRegOperand2 = imlInstruction->op_r_r_r.regB;
x64Emit_mov_mem32_reg32(x64GenContext, X86_REG_RSP, (uint32)offsetof(PPCInterpreter_t, temporaryGPR[0]), X86_REG_EAX);
x64Emit_mov_mem32_reg32(x64GenContext, X86_REG_RSP, (uint32)offsetof(PPCInterpreter_t, temporaryGPR[1]), X86_REG_EDX);
@ -1095,9 +1095,9 @@ bool PPCRecompilerX64Gen_imlInstruction_r_r_r_carry(PPCRecFunction_t* PPCRecFunc
bool PPCRecompilerX64Gen_imlInstruction_compare(PPCRecFunction_t* PPCRecFunction, ppcImlGenContext_t* ppcImlGenContext, x64GenContext_t* x64GenContext, IMLInstruction* imlInstruction)
{
auto regR = _reg8(imlInstruction->op_compare.registerResult);
auto regA = _reg32(imlInstruction->op_compare.registerOperandA);
auto regB = _reg32(imlInstruction->op_compare.registerOperandB);
auto regR = _reg8(imlInstruction->op_compare.regR);
auto regA = _reg32(imlInstruction->op_compare.regA);
auto regB = _reg32(imlInstruction->op_compare.regB);
X86Cond cond = _x86Cond(imlInstruction->op_compare.cond);
x64GenContext->emitter->XOR_dd(_reg32_from_reg8(regR), _reg32_from_reg8(regR)); // zero bytes unaffected by SETcc
x64GenContext->emitter->CMP_dd(regA, regB);
@ -1107,8 +1107,8 @@ bool PPCRecompilerX64Gen_imlInstruction_compare(PPCRecFunction_t* PPCRecFunction
bool PPCRecompilerX64Gen_imlInstruction_compare_s32(PPCRecFunction_t* PPCRecFunction, ppcImlGenContext_t* ppcImlGenContext, x64GenContext_t* x64GenContext, IMLInstruction* imlInstruction)
{
auto regR = _reg8(imlInstruction->op_compare_s32.registerResult);
auto regA = _reg32(imlInstruction->op_compare_s32.registerOperandA);
auto regR = _reg8(imlInstruction->op_compare_s32.regR);
auto regA = _reg32(imlInstruction->op_compare_s32.regA);
sint32 imm = imlInstruction->op_compare_s32.immS32;
X86Cond cond = _x86Cond(imlInstruction->op_compare_s32.cond);
x64GenContext->emitter->XOR_dd(_reg32_from_reg8(regR), _reg32_from_reg8(regR)); // zero bytes unaffected by SETcc
@ -1119,8 +1119,8 @@ bool PPCRecompilerX64Gen_imlInstruction_compare_s32(PPCRecFunction_t* PPCRecFunc
bool PPCRecompilerX64Gen_imlInstruction_cjump2(PPCRecFunction_t* PPCRecFunction, ppcImlGenContext_t* ppcImlGenContext, x64GenContext_t* x64GenContext, IMLInstruction* imlInstruction, IMLSegment* imlSegment)
{
auto regBool = _reg8(imlInstruction->op_conditionalJump2.registerBool);
bool mustBeTrue = imlInstruction->op_conditionalJump2.mustBeTrue;
auto regBool = _reg8(imlInstruction->op_conditional_jump.registerBool);
bool mustBeTrue = imlInstruction->op_conditional_jump.mustBeTrue;
x64GenContext->emitter->TEST_bb(regBool, regBool);
PPCRecompilerX64Gen_rememberRelocatableOffset(x64GenContext, imlSegment->nextSegmentBranchTaken);
x64GenContext->emitter->Jcc_j32(mustBeTrue ? X86_CONDITION_NZ : X86_CONDITION_Z, 0);
@ -1136,14 +1136,14 @@ bool PPCRecompilerX64Gen_imlInstruction_jump2(PPCRecFunction_t* PPCRecFunction,
bool PPCRecompilerX64Gen_imlInstruction_r_r_s32(PPCRecFunction_t* PPCRecFunction, ppcImlGenContext_t* ppcImlGenContext, x64GenContext_t* x64GenContext, IMLInstruction* imlInstruction)
{
sint32 regResult = imlInstruction->op_r_r_s32.registerResult;
sint32 regOperand = imlInstruction->op_r_r_s32.registerA;
sint32 regResult = imlInstruction->op_r_r_s32.regR;
sint32 regOperand = imlInstruction->op_r_r_s32.regA;
uint32 immS32 = imlInstruction->op_r_r_s32.immS32;
if( imlInstruction->operation == PPCREC_IML_OP_ADD )
{
sint32 rRegResult = imlInstruction->op_r_r_s32.registerResult;
sint32 rRegOperand = imlInstruction->op_r_r_s32.registerA;
sint32 rRegResult = imlInstruction->op_r_r_s32.regR;
sint32 rRegOperand = imlInstruction->op_r_r_s32.regA;
uint32 immU32 = (uint32)imlInstruction->op_r_r_s32.immS32;
if(regResult != regOperand)
x64Gen_mov_reg64_reg64(x64GenContext, regResult, regOperand);
@ -1177,22 +1177,22 @@ bool PPCRecompilerX64Gen_imlInstruction_r_r_s32(PPCRecFunction_t* PPCRecFunction
uint32 sh = (vImm>>16)&0xFF;
uint32 mask = ppc_mask(mb, me);
// copy rS to temporary register
x64Gen_mov_reg64_reg64(x64GenContext, REG_RESV_TEMP, imlInstruction->op_r_r_s32.registerA);
x64Gen_mov_reg64_reg64(x64GenContext, REG_RESV_TEMP, imlInstruction->op_r_r_s32.regA);
// rotate destination register
if( sh )
x64Gen_rol_reg64Low32_imm8(x64GenContext, REG_RESV_TEMP, (uint8)sh&0x1F);
// AND destination register with inverted mask
x64Gen_and_reg64Low32_imm32(x64GenContext, imlInstruction->op_r_r_s32.registerResult, ~mask);
x64Gen_and_reg64Low32_imm32(x64GenContext, imlInstruction->op_r_r_s32.regR, ~mask);
// AND temporary rS register with mask
x64Gen_and_reg64Low32_imm32(x64GenContext, REG_RESV_TEMP, mask);
// OR result with temporary
x64Gen_or_reg64Low32_reg64Low32(x64GenContext, imlInstruction->op_r_r_s32.registerResult, REG_RESV_TEMP);
x64Gen_or_reg64Low32_reg64Low32(x64GenContext, imlInstruction->op_r_r_s32.regR, REG_RESV_TEMP);
}
else if( imlInstruction->operation == PPCREC_IML_OP_MULTIPLY_SIGNED )
{
// registerResult = registerOperand * immS32
sint32 rRegResult = imlInstruction->op_r_r_s32.registerResult;
sint32 rRegOperand = imlInstruction->op_r_r_s32.registerA;
sint32 rRegResult = imlInstruction->op_r_r_s32.regR;
sint32 rRegOperand = imlInstruction->op_r_r_s32.regA;
sint32 immS32 = (uint32)imlInstruction->op_r_r_s32.immS32;
x64Gen_mov_reg64_imm64(x64GenContext, REG_RESV_TEMP, (sint64)immS32); // todo: Optimize
if( rRegResult != rRegOperand )
@ -1203,15 +1203,15 @@ bool PPCRecompilerX64Gen_imlInstruction_r_r_s32(PPCRecFunction_t* PPCRecFunction
imlInstruction->operation == PPCREC_IML_OP_RIGHT_SHIFT_U ||
imlInstruction->operation == PPCREC_IML_OP_RIGHT_SHIFT_S)
{
if( imlInstruction->op_r_r_s32.registerA != imlInstruction->op_r_r_s32.registerResult )
x64Gen_mov_reg64_reg64(x64GenContext, imlInstruction->op_r_r_s32.registerResult, imlInstruction->op_r_r_s32.registerA);
if( imlInstruction->op_r_r_s32.regA != imlInstruction->op_r_r_s32.regR )
x64Gen_mov_reg64_reg64(x64GenContext, imlInstruction->op_r_r_s32.regR, imlInstruction->op_r_r_s32.regA);
if (imlInstruction->operation == PPCREC_IML_OP_LEFT_SHIFT)
x64Gen_shl_reg64Low32_imm8(x64GenContext, imlInstruction->op_r_r_s32.registerResult, imlInstruction->op_r_r_s32.immS32);
x64Gen_shl_reg64Low32_imm8(x64GenContext, imlInstruction->op_r_r_s32.regR, imlInstruction->op_r_r_s32.immS32);
else if (imlInstruction->operation == PPCREC_IML_OP_RIGHT_SHIFT_U)
x64Gen_shr_reg64Low32_imm8(x64GenContext, imlInstruction->op_r_r_s32.registerResult, imlInstruction->op_r_r_s32.immS32);
x64Gen_shr_reg64Low32_imm8(x64GenContext, imlInstruction->op_r_r_s32.regR, imlInstruction->op_r_r_s32.immS32);
else // RIGHT_SHIFT_S
x64Gen_sar_reg64Low32_imm8(x64GenContext, imlInstruction->op_r_r_s32.registerResult, imlInstruction->op_r_r_s32.immS32);
x64Gen_sar_reg64Low32_imm8(x64GenContext, imlInstruction->op_r_r_s32.regR, imlInstruction->op_r_r_s32.immS32);
}
else
{
@ -1272,48 +1272,48 @@ void PPCRecompilerX64Gen_imlInstruction_r_name(PPCRecFunction_t* PPCRecFunction,
uint32 name = imlInstruction->op_r_name.name;
if( name >= PPCREC_NAME_R0 && name < PPCREC_NAME_R0+32 )
{
x64Emit_mov_reg64_mem32(x64GenContext, imlInstruction->op_r_name.registerIndex, X86_REG_RSP, offsetof(PPCInterpreter_t, gpr)+sizeof(uint32)*(name-PPCREC_NAME_R0));
x64Emit_mov_reg64_mem32(x64GenContext, imlInstruction->op_r_name.regR, X86_REG_RSP, offsetof(PPCInterpreter_t, gpr)+sizeof(uint32)*(name-PPCREC_NAME_R0));
}
else if( name >= PPCREC_NAME_SPR0 && name < PPCREC_NAME_SPR0+999 )
{
sint32 sprIndex = (name - PPCREC_NAME_SPR0);
if (sprIndex == SPR_LR)
x64Emit_mov_reg64_mem32(x64GenContext, imlInstruction->op_r_name.registerIndex, X86_REG_RSP, offsetof(PPCInterpreter_t, spr.LR));
x64Emit_mov_reg64_mem32(x64GenContext, imlInstruction->op_r_name.regR, X86_REG_RSP, offsetof(PPCInterpreter_t, spr.LR));
else if (sprIndex == SPR_CTR)
x64Emit_mov_reg64_mem32(x64GenContext, imlInstruction->op_r_name.registerIndex, X86_REG_RSP, offsetof(PPCInterpreter_t, spr.CTR));
x64Emit_mov_reg64_mem32(x64GenContext, imlInstruction->op_r_name.regR, X86_REG_RSP, offsetof(PPCInterpreter_t, spr.CTR));
else if (sprIndex == SPR_XER)
x64Emit_mov_reg64_mem32(x64GenContext, imlInstruction->op_r_name.registerIndex, X86_REG_RSP, offsetof(PPCInterpreter_t, spr.XER));
x64Emit_mov_reg64_mem32(x64GenContext, imlInstruction->op_r_name.regR, X86_REG_RSP, offsetof(PPCInterpreter_t, spr.XER));
else if (sprIndex >= SPR_UGQR0 && sprIndex <= SPR_UGQR7)
{
sint32 memOffset = offsetof(PPCInterpreter_t, spr.UGQR) + sizeof(PPCInterpreter_t::spr.UGQR[0]) * (sprIndex - SPR_UGQR0);
x64Emit_mov_reg64_mem32(x64GenContext, imlInstruction->op_r_name.registerIndex, X86_REG_RSP, memOffset);
x64Emit_mov_reg64_mem32(x64GenContext, imlInstruction->op_r_name.regR, X86_REG_RSP, memOffset);
}
else
assert_dbg();
}
else if (name >= PPCREC_NAME_TEMPORARY && name < PPCREC_NAME_TEMPORARY + 4)
{
x64Emit_mov_reg64_mem32(x64GenContext, imlInstruction->op_r_name.registerIndex, X86_REG_RSP, offsetof(PPCInterpreter_t, temporaryGPR_reg) + sizeof(uint32) * (name - PPCREC_NAME_TEMPORARY));
x64Emit_mov_reg64_mem32(x64GenContext, imlInstruction->op_r_name.regR, X86_REG_RSP, offsetof(PPCInterpreter_t, temporaryGPR_reg) + sizeof(uint32) * (name - PPCREC_NAME_TEMPORARY));
}
else if (name == PPCREC_NAME_XER_CA)
{
x64Emit_movZX_reg64_mem8(x64GenContext, imlInstruction->op_r_name.registerIndex, X86_REG_RSP, offsetof(PPCInterpreter_t, xer_ca));
x64Emit_movZX_reg64_mem8(x64GenContext, imlInstruction->op_r_name.regR, X86_REG_RSP, offsetof(PPCInterpreter_t, xer_ca));
}
else if (name == PPCREC_NAME_XER_SO)
{
x64Emit_movZX_reg64_mem8(x64GenContext, imlInstruction->op_r_name.registerIndex, X86_REG_RSP, offsetof(PPCInterpreter_t, xer_so));
x64Emit_movZX_reg64_mem8(x64GenContext, imlInstruction->op_r_name.regR, X86_REG_RSP, offsetof(PPCInterpreter_t, xer_so));
}
else if (name >= PPCREC_NAME_CR && name <= PPCREC_NAME_CR_LAST)
{
x64Emit_movZX_reg64_mem8(x64GenContext, imlInstruction->op_r_name.registerIndex, X86_REG_RSP, offsetof(PPCInterpreter_t, cr) + (name - PPCREC_NAME_CR));
x64Emit_movZX_reg64_mem8(x64GenContext, imlInstruction->op_r_name.regR, X86_REG_RSP, offsetof(PPCInterpreter_t, cr) + (name - PPCREC_NAME_CR));
}
else if (name == PPCREC_NAME_CPU_MEMRES_EA)
{
x64Emit_mov_reg64_mem32(x64GenContext, imlInstruction->op_r_name.registerIndex, X86_REG_RSP, offsetof(PPCInterpreter_t, reservedMemAddr));
x64Emit_mov_reg64_mem32(x64GenContext, imlInstruction->op_r_name.regR, X86_REG_RSP, offsetof(PPCInterpreter_t, reservedMemAddr));
}
else if (name == PPCREC_NAME_CPU_MEMRES_VAL)
{
x64Emit_mov_reg64_mem32(x64GenContext, imlInstruction->op_r_name.registerIndex, X86_REG_RSP, offsetof(PPCInterpreter_t, reservedMemValue));
x64Emit_mov_reg64_mem32(x64GenContext, imlInstruction->op_r_name.regR, X86_REG_RSP, offsetof(PPCInterpreter_t, reservedMemValue));
}
else
assert_dbg();
@ -1324,48 +1324,48 @@ void PPCRecompilerX64Gen_imlInstruction_name_r(PPCRecFunction_t* PPCRecFunction,
uint32 name = imlInstruction->op_r_name.name;
if( name >= PPCREC_NAME_R0 && name < PPCREC_NAME_R0+32 )
{
x64Emit_mov_mem32_reg64(x64GenContext, X86_REG_RSP, offsetof(PPCInterpreter_t, gpr)+sizeof(uint32)*(name-PPCREC_NAME_R0), imlInstruction->op_r_name.registerIndex);
x64Emit_mov_mem32_reg64(x64GenContext, X86_REG_RSP, offsetof(PPCInterpreter_t, gpr)+sizeof(uint32)*(name-PPCREC_NAME_R0), imlInstruction->op_r_name.regR);
}
else if( name >= PPCREC_NAME_SPR0 && name < PPCREC_NAME_SPR0+999 )
{
uint32 sprIndex = (name - PPCREC_NAME_SPR0);
if (sprIndex == SPR_LR)
x64Emit_mov_mem32_reg64(x64GenContext, X86_REG_RSP, offsetof(PPCInterpreter_t, spr.LR), imlInstruction->op_r_name.registerIndex);
x64Emit_mov_mem32_reg64(x64GenContext, X86_REG_RSP, offsetof(PPCInterpreter_t, spr.LR), imlInstruction->op_r_name.regR);
else if (sprIndex == SPR_CTR)
x64Emit_mov_mem32_reg64(x64GenContext, X86_REG_RSP, offsetof(PPCInterpreter_t, spr.CTR), imlInstruction->op_r_name.registerIndex);
x64Emit_mov_mem32_reg64(x64GenContext, X86_REG_RSP, offsetof(PPCInterpreter_t, spr.CTR), imlInstruction->op_r_name.regR);
else if (sprIndex == SPR_XER)
x64Emit_mov_mem32_reg64(x64GenContext, X86_REG_RSP, offsetof(PPCInterpreter_t, spr.XER), imlInstruction->op_r_name.registerIndex);
x64Emit_mov_mem32_reg64(x64GenContext, X86_REG_RSP, offsetof(PPCInterpreter_t, spr.XER), imlInstruction->op_r_name.regR);
else if (sprIndex >= SPR_UGQR0 && sprIndex <= SPR_UGQR7)
{
sint32 memOffset = offsetof(PPCInterpreter_t, spr.UGQR) + sizeof(PPCInterpreter_t::spr.UGQR[0]) * (sprIndex - SPR_UGQR0);
x64Emit_mov_mem32_reg64(x64GenContext, X86_REG_RSP, memOffset, imlInstruction->op_r_name.registerIndex);
x64Emit_mov_mem32_reg64(x64GenContext, X86_REG_RSP, memOffset, imlInstruction->op_r_name.regR);
}
else
assert_dbg();
}
else if (name >= PPCREC_NAME_TEMPORARY && name < PPCREC_NAME_TEMPORARY + 4)
{
x64Emit_mov_mem32_reg64(x64GenContext, X86_REG_RSP, offsetof(PPCInterpreter_t, temporaryGPR_reg) + sizeof(uint32) * (name - PPCREC_NAME_TEMPORARY), imlInstruction->op_r_name.registerIndex);
x64Emit_mov_mem32_reg64(x64GenContext, X86_REG_RSP, offsetof(PPCInterpreter_t, temporaryGPR_reg) + sizeof(uint32) * (name - PPCREC_NAME_TEMPORARY), imlInstruction->op_r_name.regR);
}
else if (name == PPCREC_NAME_XER_CA)
{
x64GenContext->emitter->MOV_bb_l(X86_REG_RSP, offsetof(PPCInterpreter_t, xer_ca), X86_REG_NONE, 0, _reg8_from_reg32(_reg32(imlInstruction->op_r_name.registerIndex)));
x64GenContext->emitter->MOV_bb_l(X86_REG_RSP, offsetof(PPCInterpreter_t, xer_ca), X86_REG_NONE, 0, _reg8_from_reg32(_reg32(imlInstruction->op_r_name.regR)));
}
else if (name == PPCREC_NAME_XER_SO)
{
x64GenContext->emitter->MOV_bb_l(X86_REG_RSP, offsetof(PPCInterpreter_t, xer_so), X86_REG_NONE, 0, _reg8_from_reg32(_reg32(imlInstruction->op_r_name.registerIndex)));
x64GenContext->emitter->MOV_bb_l(X86_REG_RSP, offsetof(PPCInterpreter_t, xer_so), X86_REG_NONE, 0, _reg8_from_reg32(_reg32(imlInstruction->op_r_name.regR)));
}
else if (name >= PPCREC_NAME_CR && name <= PPCREC_NAME_CR_LAST)
{
x64GenContext->emitter->MOV_bb_l(X86_REG_RSP, offsetof(PPCInterpreter_t, cr) + (name - PPCREC_NAME_CR), X86_REG_NONE, 0, _reg8_from_reg32(_reg32(imlInstruction->op_r_name.registerIndex)));
x64GenContext->emitter->MOV_bb_l(X86_REG_RSP, offsetof(PPCInterpreter_t, cr) + (name - PPCREC_NAME_CR), X86_REG_NONE, 0, _reg8_from_reg32(_reg32(imlInstruction->op_r_name.regR)));
}
else if (name == PPCREC_NAME_CPU_MEMRES_EA)
{
x64Emit_mov_mem32_reg64(x64GenContext, X86_REG_RSP, offsetof(PPCInterpreter_t, reservedMemAddr), imlInstruction->op_r_name.registerIndex);
x64Emit_mov_mem32_reg64(x64GenContext, X86_REG_RSP, offsetof(PPCInterpreter_t, reservedMemAddr), imlInstruction->op_r_name.regR);
}
else if (name == PPCREC_NAME_CPU_MEMRES_VAL)
{
x64Emit_mov_mem32_reg64(x64GenContext, X86_REG_RSP, offsetof(PPCInterpreter_t, reservedMemValue), imlInstruction->op_r_name.registerIndex);
x64Emit_mov_mem32_reg64(x64GenContext, X86_REG_RSP, offsetof(PPCInterpreter_t, reservedMemValue), imlInstruction->op_r_name.regR);
}
else
assert_dbg();

View File

@ -129,9 +129,6 @@ void x64Gen_or_reg64Low8_mem8Reg64(x64GenContext_t* x64GenContext, sint32 dstReg
void x64Gen_and_reg64Low8_mem8Reg64(x64GenContext_t* x64GenContext, sint32 dstRegister, sint32 memRegister64, sint32 memImmS32);
void x64Gen_mov_mem8Reg64_reg64Low8(x64GenContext_t* x64GenContext, sint32 dstRegister, sint32 memRegister64, sint32 memImmS32);
void x64Gen_lock_cmpxchg_mem32Reg64PlusReg64_reg64(x64GenContext_t* x64GenContext, sint32 memRegisterA64, sint32 memRegisterB64, sint32 memImmS32, sint32 srcRegister);
void x64Gen_lock_cmpxchg_mem32Reg64_reg64(x64GenContext_t* x64GenContext, sint32 memRegister64, sint32 memImmS32, sint32 srcRegister);
void x64Gen_add_reg64_reg64(x64GenContext_t* x64GenContext, sint32 destRegister, sint32 srcRegister);
void x64Gen_add_reg64Low32_reg64Low32(x64GenContext_t* x64GenContext, sint32 destRegister, sint32 srcRegister);
void x64Gen_add_reg64_imm32(x64GenContext_t* x64GenContext, sint32 srcRegister, uint32 immU32);
@ -140,9 +137,6 @@ void x64Gen_sub_reg64Low32_reg64Low32(x64GenContext_t* x64GenContext, sint32 des
void x64Gen_sub_reg64Low32_imm32(x64GenContext_t* x64GenContext, sint32 srcRegister, uint32 immU32);
void x64Gen_sub_reg64_imm32(x64GenContext_t* x64GenContext, sint32 srcRegister, uint32 immU32);
void x64Gen_sub_mem32reg64_imm32(x64GenContext_t* x64GenContext, sint32 memRegister, sint32 memImmS32, uint64 immU32);
void x64Gen_sbb_reg64Low32_reg64Low32(x64GenContext_t* x64GenContext, sint32 destRegister, sint32 srcRegister);
void x64Gen_adc_reg64Low32_reg64Low32(x64GenContext_t* x64GenContext, sint32 destRegister, sint32 srcRegister);
void x64Gen_adc_reg64Low32_imm32(x64GenContext_t* x64GenContext, sint32 srcRegister, uint32 immU32);
void x64Gen_dec_mem32(x64GenContext_t* x64GenContext, sint32 memoryRegister, uint32 memoryImmU32);
void x64Gen_imul_reg64Low32_reg64Low32(x64GenContext_t* x64GenContext, sint32 destRegister, sint32 operandRegister);
void x64Gen_idiv_reg64Low32(x64GenContext_t* x64GenContext, sint32 operandRegister);
@ -174,9 +168,7 @@ void x64Gen_not_reg64Low32(x64GenContext_t* x64GenContext, sint32 destRegister);
void x64Gen_neg_reg64Low32(x64GenContext_t* x64GenContext, sint32 destRegister);
void x64Gen_cdq(x64GenContext_t* x64GenContext);
void x64Gen_bswap_reg64(x64GenContext_t* x64GenContext, sint32 destRegister);
void x64Gen_bswap_reg64Lower32bit(x64GenContext_t* x64GenContext, sint32 destRegister);
void x64Gen_bswap_reg64Lower16bit(x64GenContext_t* x64GenContext, sint32 destRegister);
void x64Gen_lzcnt_reg64Low32_reg64Low32(x64GenContext_t* x64GenContext, sint32 destRegister, sint32 srcRegister);
void x64Gen_bsr_reg64Low32_reg64Low32(x64GenContext_t* x64GenContext, sint32 destRegister, sint32 srcRegister);

View File

@ -35,11 +35,11 @@ void PPCRecompilerX64Gen_imlInstruction_fpr_r_name(PPCRecFunction_t* PPCRecFunct
uint32 name = imlInstruction->op_r_name.name;
if( name >= PPCREC_NAME_FPR0 && name < (PPCREC_NAME_FPR0+32) )
{
x64Gen_movupd_xmmReg_memReg128(x64GenContext, imlInstruction->op_r_name.registerIndex, X86_REG_ESP, offsetof(PPCInterpreter_t, fpr)+sizeof(FPR_t)*(name-PPCREC_NAME_FPR0));
x64Gen_movupd_xmmReg_memReg128(x64GenContext, imlInstruction->op_r_name.regR, X86_REG_ESP, offsetof(PPCInterpreter_t, fpr)+sizeof(FPR_t)*(name-PPCREC_NAME_FPR0));
}
else if( name >= PPCREC_NAME_TEMPORARY_FPR0 || name < (PPCREC_NAME_TEMPORARY_FPR0+8) )
{
x64Gen_movupd_xmmReg_memReg128(x64GenContext, imlInstruction->op_r_name.registerIndex, X86_REG_ESP, offsetof(PPCInterpreter_t, temporaryFPR)+sizeof(FPR_t)*(name-PPCREC_NAME_TEMPORARY_FPR0));
x64Gen_movupd_xmmReg_memReg128(x64GenContext, imlInstruction->op_r_name.regR, X86_REG_ESP, offsetof(PPCInterpreter_t, temporaryFPR)+sizeof(FPR_t)*(name-PPCREC_NAME_TEMPORARY_FPR0));
}
else
{
@ -52,11 +52,11 @@ void PPCRecompilerX64Gen_imlInstruction_fpr_name_r(PPCRecFunction_t* PPCRecFunct
uint32 name = imlInstruction->op_r_name.name;
if( name >= PPCREC_NAME_FPR0 && name < (PPCREC_NAME_FPR0+32) )
{
x64Gen_movupd_memReg128_xmmReg(x64GenContext, imlInstruction->op_r_name.registerIndex, X86_REG_ESP, offsetof(PPCInterpreter_t, fpr)+sizeof(FPR_t)*(name-PPCREC_NAME_FPR0));
x64Gen_movupd_memReg128_xmmReg(x64GenContext, imlInstruction->op_r_name.regR, X86_REG_ESP, offsetof(PPCInterpreter_t, fpr)+sizeof(FPR_t)*(name-PPCREC_NAME_FPR0));
}
else if( name >= PPCREC_NAME_TEMPORARY_FPR0 && name < (PPCREC_NAME_TEMPORARY_FPR0+8) )
{
x64Gen_movupd_memReg128_xmmReg(x64GenContext, imlInstruction->op_r_name.registerIndex, X86_REG_ESP, offsetof(PPCInterpreter_t, temporaryFPR)+sizeof(FPR_t)*(name-PPCREC_NAME_TEMPORARY_FPR0));
x64Gen_movupd_memReg128_xmmReg(x64GenContext, imlInstruction->op_r_name.regR, X86_REG_ESP, offsetof(PPCInterpreter_t, temporaryFPR)+sizeof(FPR_t)*(name-PPCREC_NAME_TEMPORARY_FPR0));
}
else
{
@ -101,7 +101,7 @@ void PPCRecompilerX64Gen_imlInstr_psq_load(ppcImlGenContext_t* ppcImlGenContext,
}
// optimized code for ps float load
x64Emit_mov_reg64_mem64(x64GenContext, REG_RESV_TEMP, X86_REG_R13, memReg, memImmS32);
x64Gen_bswap_reg64(x64GenContext, REG_RESV_TEMP);
x64GenContext->emitter->BSWAP_q(REG_RESV_TEMP);
x64Gen_rol_reg64_imm8(x64GenContext, REG_RESV_TEMP, 32); // swap upper and lower DWORD
x64Gen_movq_xmmReg_reg64(x64GenContext, registerXMM, REG_RESV_TEMP);
x64Gen_cvtps2pd_xmmReg_xmmReg(x64GenContext, registerXMM, registerXMM);
@ -343,14 +343,14 @@ bool PPCRecompilerX64Gen_imlInstruction_fpr_load(PPCRecFunction_t* PPCRecFunctio
x64Gen_add_reg64Low32_reg64Low32(x64GenContext, REG_RESV_TEMP, realRegisterMem2);
// load value
x64Emit_mov_reg64_mem64(x64GenContext, REG_RESV_TEMP, X86_REG_R13, REG_RESV_TEMP, imlInstruction->op_storeLoad.immS32+0);
x64Gen_bswap_reg64(x64GenContext, REG_RESV_TEMP);
x64GenContext->emitter->BSWAP_q(REG_RESV_TEMP);
x64Gen_movq_xmmReg_reg64(x64GenContext, REG_RESV_FPR_TEMP, REG_RESV_TEMP);
x64Gen_movsd_xmmReg_xmmReg(x64GenContext, realRegisterXMM, REG_RESV_FPR_TEMP);
}
else
{
x64Emit_mov_reg64_mem64(x64GenContext, REG_RESV_TEMP, X86_REG_R13, realRegisterMem, imlInstruction->op_storeLoad.immS32+0);
x64Gen_bswap_reg64(x64GenContext, REG_RESV_TEMP);
x64GenContext->emitter->BSWAP_q(REG_RESV_TEMP);
x64Gen_movq_xmmReg_reg64(x64GenContext, REG_RESV_FPR_TEMP, REG_RESV_TEMP);
x64Gen_movsd_xmmReg_xmmReg(x64GenContext, realRegisterXMM, REG_RESV_FPR_TEMP);
}
@ -462,7 +462,7 @@ void PPCRecompilerX64Gen_imlInstr_psq_store(ppcImlGenContext_t* ppcImlGenContext
x64Gen_cvtpd2ps_xmmReg_xmmReg(x64GenContext, REG_RESV_FPR_TEMP, registerXMM);
x64Gen_movq_reg64_xmmReg(x64GenContext, REG_RESV_TEMP, REG_RESV_FPR_TEMP);
x64Gen_rol_reg64_imm8(x64GenContext, REG_RESV_TEMP, 32); // swap upper and lower DWORD
x64Gen_bswap_reg64(x64GenContext, REG_RESV_TEMP);
x64GenContext->emitter->BSWAP_q(REG_RESV_TEMP);
x64Gen_mov_mem64Reg64PlusReg64_reg64(x64GenContext, REG_RESV_TEMP, X86_REG_R13, memReg, memImmS32);
return;
}
@ -715,15 +715,15 @@ void PPCRecompilerX64Gen_imlInstruction_fpr_r_r(PPCRecFunction_t* PPCRecFunction
{
if( imlInstruction->operation == PPCREC_IML_OP_FPR_COPY_BOTTOM_TO_BOTTOM_AND_TOP )
{
x64Gen_movddup_xmmReg_xmmReg(x64GenContext, imlInstruction->op_fpr_r_r.registerResult, imlInstruction->op_fpr_r_r.registerOperand);
x64Gen_movddup_xmmReg_xmmReg(x64GenContext, imlInstruction->op_fpr_r_r.regR, imlInstruction->op_fpr_r_r.regA);
}
else if( imlInstruction->operation == PPCREC_IML_OP_FPR_COPY_TOP_TO_BOTTOM_AND_TOP )
{
// VPUNPCKHQDQ
if (imlInstruction->op_fpr_r_r.registerResult == imlInstruction->op_fpr_r_r.registerOperand)
if (imlInstruction->op_fpr_r_r.regR == imlInstruction->op_fpr_r_r.regA)
{
// unpack top to bottom and top
x64Gen_unpckhpd_xmmReg_xmmReg(x64GenContext, imlInstruction->op_fpr_r_r.registerResult, imlInstruction->op_fpr_r_r.registerOperand);
x64Gen_unpckhpd_xmmReg_xmmReg(x64GenContext, imlInstruction->op_fpr_r_r.regR, imlInstruction->op_fpr_r_r.regA);
}
//else if ( hasAVXSupport )
//{
@ -734,142 +734,142 @@ void PPCRecompilerX64Gen_imlInstruction_fpr_r_r(PPCRecFunction_t* PPCRecFunction
else
{
// move top to bottom
x64Gen_movhlps_xmmReg_xmmReg(x64GenContext, imlInstruction->op_fpr_r_r.registerResult, imlInstruction->op_fpr_r_r.registerOperand);
x64Gen_movhlps_xmmReg_xmmReg(x64GenContext, imlInstruction->op_fpr_r_r.regR, imlInstruction->op_fpr_r_r.regA);
// duplicate bottom
x64Gen_movddup_xmmReg_xmmReg(x64GenContext, imlInstruction->op_fpr_r_r.registerResult, imlInstruction->op_fpr_r_r.registerResult);
x64Gen_movddup_xmmReg_xmmReg(x64GenContext, imlInstruction->op_fpr_r_r.regR, imlInstruction->op_fpr_r_r.regR);
}
}
else if( imlInstruction->operation == PPCREC_IML_OP_FPR_COPY_BOTTOM_TO_BOTTOM )
{
x64Gen_movsd_xmmReg_xmmReg(x64GenContext, imlInstruction->op_fpr_r_r.registerResult, imlInstruction->op_fpr_r_r.registerOperand);
x64Gen_movsd_xmmReg_xmmReg(x64GenContext, imlInstruction->op_fpr_r_r.regR, imlInstruction->op_fpr_r_r.regA);
}
else if( imlInstruction->operation == PPCREC_IML_OP_FPR_COPY_BOTTOM_TO_TOP )
{
x64Gen_unpcklpd_xmmReg_xmmReg(x64GenContext, imlInstruction->op_fpr_r_r.registerResult, imlInstruction->op_fpr_r_r.registerOperand);
x64Gen_unpcklpd_xmmReg_xmmReg(x64GenContext, imlInstruction->op_fpr_r_r.regR, imlInstruction->op_fpr_r_r.regA);
}
else if( imlInstruction->operation == PPCREC_IML_OP_FPR_COPY_BOTTOM_AND_TOP_SWAPPED )
{
if( imlInstruction->op_fpr_r_r.registerResult != imlInstruction->op_fpr_r_r.registerOperand )
x64Gen_movaps_xmmReg_xmmReg(x64GenContext, imlInstruction->op_fpr_r_r.registerResult, imlInstruction->op_fpr_r_r.registerOperand);
_swapPS0PS1(x64GenContext, imlInstruction->op_fpr_r_r.registerResult);
if( imlInstruction->op_fpr_r_r.regR != imlInstruction->op_fpr_r_r.regA )
x64Gen_movaps_xmmReg_xmmReg(x64GenContext, imlInstruction->op_fpr_r_r.regR, imlInstruction->op_fpr_r_r.regA);
_swapPS0PS1(x64GenContext, imlInstruction->op_fpr_r_r.regR);
}
else if( imlInstruction->operation == PPCREC_IML_OP_FPR_COPY_TOP_TO_TOP )
{
x64Gen_shufpd_xmmReg_xmmReg_imm8(x64GenContext, imlInstruction->op_fpr_r_r.registerResult, imlInstruction->op_fpr_r_r.registerOperand, 2);
x64Gen_shufpd_xmmReg_xmmReg_imm8(x64GenContext, imlInstruction->op_fpr_r_r.regR, imlInstruction->op_fpr_r_r.regA, 2);
}
else if( imlInstruction->operation == PPCREC_IML_OP_FPR_COPY_TOP_TO_BOTTOM )
{
// use unpckhpd here?
x64Gen_shufpd_xmmReg_xmmReg_imm8(x64GenContext, imlInstruction->op_fpr_r_r.registerResult, imlInstruction->op_fpr_r_r.registerOperand, 3);
_swapPS0PS1(x64GenContext, imlInstruction->op_fpr_r_r.registerResult);
x64Gen_shufpd_xmmReg_xmmReg_imm8(x64GenContext, imlInstruction->op_fpr_r_r.regR, imlInstruction->op_fpr_r_r.regA, 3);
_swapPS0PS1(x64GenContext, imlInstruction->op_fpr_r_r.regR);
}
else if( imlInstruction->operation == PPCREC_IML_OP_FPR_MULTIPLY_BOTTOM )
{
x64Gen_mulsd_xmmReg_xmmReg(x64GenContext, imlInstruction->op_fpr_r_r.registerResult, imlInstruction->op_fpr_r_r.registerOperand);
x64Gen_mulsd_xmmReg_xmmReg(x64GenContext, imlInstruction->op_fpr_r_r.regR, imlInstruction->op_fpr_r_r.regA);
}
else if( imlInstruction->operation == PPCREC_IML_OP_FPR_MULTIPLY_PAIR )
{
x64Gen_mulpd_xmmReg_xmmReg(x64GenContext, imlInstruction->op_fpr_r_r.registerResult, imlInstruction->op_fpr_r_r.registerOperand);
x64Gen_mulpd_xmmReg_xmmReg(x64GenContext, imlInstruction->op_fpr_r_r.regR, imlInstruction->op_fpr_r_r.regA);
}
else if( imlInstruction->operation == PPCREC_IML_OP_FPR_DIVIDE_BOTTOM )
{
x64Gen_divsd_xmmReg_xmmReg(x64GenContext, imlInstruction->op_fpr_r_r.registerResult, imlInstruction->op_fpr_r_r.registerOperand);
x64Gen_divsd_xmmReg_xmmReg(x64GenContext, imlInstruction->op_fpr_r_r.regR, imlInstruction->op_fpr_r_r.regA);
}
else if (imlInstruction->operation == PPCREC_IML_OP_FPR_DIVIDE_PAIR)
{
x64Gen_divpd_xmmReg_xmmReg(x64GenContext, imlInstruction->op_fpr_r_r.registerResult, imlInstruction->op_fpr_r_r.registerOperand);
x64Gen_divpd_xmmReg_xmmReg(x64GenContext, imlInstruction->op_fpr_r_r.regR, imlInstruction->op_fpr_r_r.regA);
}
else if( imlInstruction->operation == PPCREC_IML_OP_FPR_ADD_BOTTOM )
{
x64Gen_addsd_xmmReg_xmmReg(x64GenContext, imlInstruction->op_fpr_r_r.registerResult, imlInstruction->op_fpr_r_r.registerOperand);
x64Gen_addsd_xmmReg_xmmReg(x64GenContext, imlInstruction->op_fpr_r_r.regR, imlInstruction->op_fpr_r_r.regA);
}
else if( imlInstruction->operation == PPCREC_IML_OP_FPR_ADD_PAIR )
{
x64Gen_addpd_xmmReg_xmmReg(x64GenContext, imlInstruction->op_fpr_r_r.registerResult, imlInstruction->op_fpr_r_r.registerOperand);
x64Gen_addpd_xmmReg_xmmReg(x64GenContext, imlInstruction->op_fpr_r_r.regR, imlInstruction->op_fpr_r_r.regA);
}
else if( imlInstruction->operation == PPCREC_IML_OP_FPR_SUB_PAIR )
{
x64Gen_subpd_xmmReg_xmmReg(x64GenContext, imlInstruction->op_fpr_r_r.registerResult, imlInstruction->op_fpr_r_r.registerOperand);
x64Gen_subpd_xmmReg_xmmReg(x64GenContext, imlInstruction->op_fpr_r_r.regR, imlInstruction->op_fpr_r_r.regA);
}
else if( imlInstruction->operation == PPCREC_IML_OP_FPR_SUB_BOTTOM )
{
x64Gen_subsd_xmmReg_xmmReg(x64GenContext, imlInstruction->op_fpr_r_r.registerResult, imlInstruction->op_fpr_r_r.registerOperand);
x64Gen_subsd_xmmReg_xmmReg(x64GenContext, imlInstruction->op_fpr_r_r.regR, imlInstruction->op_fpr_r_r.regA);
}
else if( imlInstruction->operation == PPCREC_IML_OP_ASSIGN )
{
x64Gen_movaps_xmmReg_xmmReg(x64GenContext, imlInstruction->op_fpr_r_r.registerResult, imlInstruction->op_fpr_r_r.registerOperand);
x64Gen_movaps_xmmReg_xmmReg(x64GenContext, imlInstruction->op_fpr_r_r.regR, imlInstruction->op_fpr_r_r.regA);
}
else if( imlInstruction->operation == PPCREC_IML_OP_FPR_BOTTOM_FCTIWZ )
{
x64Gen_cvttsd2si_xmmReg_xmmReg(x64GenContext, REG_RESV_TEMP, imlInstruction->op_fpr_r_r.registerOperand);
x64Gen_cvttsd2si_xmmReg_xmmReg(x64GenContext, REG_RESV_TEMP, imlInstruction->op_fpr_r_r.regA);
x64Gen_mov_reg64Low32_reg64Low32(x64GenContext, REG_RESV_TEMP, REG_RESV_TEMP);
// move to FPR register
x64Gen_movq_xmmReg_reg64(x64GenContext, imlInstruction->op_fpr_r_r.registerResult, REG_RESV_TEMP);
x64Gen_movq_xmmReg_reg64(x64GenContext, imlInstruction->op_fpr_r_r.regR, REG_RESV_TEMP);
}
else if( imlInstruction->operation == PPCREC_IML_OP_FPR_BOTTOM_FRES_TO_BOTTOM_AND_TOP )
{
// move register to XMM15
x64Gen_movsd_xmmReg_xmmReg(x64GenContext, REG_RESV_FPR_TEMP, imlInstruction->op_fpr_r_r.registerOperand);
x64Gen_movsd_xmmReg_xmmReg(x64GenContext, REG_RESV_FPR_TEMP, imlInstruction->op_fpr_r_r.regA);
// call assembly routine to calculate accurate FRES result in XMM15
x64Gen_mov_reg64_imm64(x64GenContext, REG_RESV_TEMP, (uint64)recompiler_fres);
x64Gen_call_reg64(x64GenContext, REG_RESV_TEMP);
// copy result to bottom and top half of result register
x64Gen_movddup_xmmReg_xmmReg(x64GenContext, imlInstruction->op_fpr_r_r.registerResult, REG_RESV_FPR_TEMP);
x64Gen_movddup_xmmReg_xmmReg(x64GenContext, imlInstruction->op_fpr_r_r.regR, REG_RESV_FPR_TEMP);
}
else if (imlInstruction->operation == PPCREC_IML_OP_FPR_BOTTOM_RECIPROCAL_SQRT)
{
// move register to XMM15
x64Gen_movsd_xmmReg_xmmReg(x64GenContext, REG_RESV_FPR_TEMP, imlInstruction->op_fpr_r_r.registerOperand);
x64Gen_movsd_xmmReg_xmmReg(x64GenContext, REG_RESV_FPR_TEMP, imlInstruction->op_fpr_r_r.regA);
// call assembly routine to calculate accurate FRSQRTE result in XMM15
x64Gen_mov_reg64_imm64(x64GenContext, REG_RESV_TEMP, (uint64)recompiler_frsqrte);
x64Gen_call_reg64(x64GenContext, REG_RESV_TEMP);
// copy result to bottom of result register
x64Gen_movsd_xmmReg_xmmReg(x64GenContext, imlInstruction->op_fpr_r_r.registerResult, REG_RESV_FPR_TEMP);
x64Gen_movsd_xmmReg_xmmReg(x64GenContext, imlInstruction->op_fpr_r_r.regR, REG_RESV_FPR_TEMP);
}
else if( imlInstruction->operation == PPCREC_IML_OP_FPR_NEGATE_PAIR )
{
// copy register
if( imlInstruction->op_fpr_r_r.registerResult != imlInstruction->op_fpr_r_r.registerOperand )
if( imlInstruction->op_fpr_r_r.regR != imlInstruction->op_fpr_r_r.regA )
{
x64Gen_movaps_xmmReg_xmmReg(x64GenContext, imlInstruction->op_fpr_r_r.registerResult, imlInstruction->op_fpr_r_r.registerOperand);
x64Gen_movaps_xmmReg_xmmReg(x64GenContext, imlInstruction->op_fpr_r_r.regR, imlInstruction->op_fpr_r_r.regA);
}
// toggle sign bits
x64Gen_xorps_xmmReg_mem128Reg64(x64GenContext, imlInstruction->op_fpr_r_r.registerResult, REG_RESV_RECDATA, offsetof(PPCRecompilerInstanceData_t, _x64XMM_xorNegateMaskPair));
x64Gen_xorps_xmmReg_mem128Reg64(x64GenContext, imlInstruction->op_fpr_r_r.regR, REG_RESV_RECDATA, offsetof(PPCRecompilerInstanceData_t, _x64XMM_xorNegateMaskPair));
}
else if( imlInstruction->operation == PPCREC_IML_OP_FPR_ABS_PAIR )
{
// copy register
if( imlInstruction->op_fpr_r_r.registerResult != imlInstruction->op_fpr_r_r.registerOperand )
if( imlInstruction->op_fpr_r_r.regR != imlInstruction->op_fpr_r_r.regA )
{
x64Gen_movaps_xmmReg_xmmReg(x64GenContext, imlInstruction->op_fpr_r_r.registerResult, imlInstruction->op_fpr_r_r.registerOperand);
x64Gen_movaps_xmmReg_xmmReg(x64GenContext, imlInstruction->op_fpr_r_r.regR, imlInstruction->op_fpr_r_r.regA);
}
// set sign bit to 0
x64Gen_andps_xmmReg_mem128Reg64(x64GenContext, imlInstruction->op_fpr_r_r.registerResult, REG_RESV_RECDATA, offsetof(PPCRecompilerInstanceData_t, _x64XMM_andAbsMaskPair));
x64Gen_andps_xmmReg_mem128Reg64(x64GenContext, imlInstruction->op_fpr_r_r.regR, REG_RESV_RECDATA, offsetof(PPCRecompilerInstanceData_t, _x64XMM_andAbsMaskPair));
}
else if( imlInstruction->operation == PPCREC_IML_OP_FPR_FRES_PAIR || imlInstruction->operation == PPCREC_IML_OP_FPR_FRSQRTE_PAIR)
{
// calculate bottom half of result
x64Gen_movsd_xmmReg_xmmReg(x64GenContext, REG_RESV_FPR_TEMP, imlInstruction->op_fpr_r_r.registerOperand);
x64Gen_movsd_xmmReg_xmmReg(x64GenContext, REG_RESV_FPR_TEMP, imlInstruction->op_fpr_r_r.regA);
if(imlInstruction->operation == PPCREC_IML_OP_FPR_FRES_PAIR)
x64Gen_mov_reg64_imm64(x64GenContext, REG_RESV_TEMP, (uint64)recompiler_fres);
else
x64Gen_mov_reg64_imm64(x64GenContext, REG_RESV_TEMP, (uint64)recompiler_frsqrte);
x64Gen_call_reg64(x64GenContext, REG_RESV_TEMP); // calculate fres result in xmm15
x64Gen_movsd_xmmReg_xmmReg(x64GenContext, imlInstruction->op_fpr_r_r.registerResult, REG_RESV_FPR_TEMP);
x64Gen_movsd_xmmReg_xmmReg(x64GenContext, imlInstruction->op_fpr_r_r.regR, REG_RESV_FPR_TEMP);
// calculate top half of result
// todo - this top to bottom copy can be optimized?
x64Gen_shufpd_xmmReg_xmmReg_imm8(x64GenContext, REG_RESV_FPR_TEMP, imlInstruction->op_fpr_r_r.registerOperand, 3);
x64Gen_shufpd_xmmReg_xmmReg_imm8(x64GenContext, REG_RESV_FPR_TEMP, imlInstruction->op_fpr_r_r.regA, 3);
x64Gen_shufpd_xmmReg_xmmReg_imm8(x64GenContext, REG_RESV_FPR_TEMP, REG_RESV_FPR_TEMP, 1); // swap top and bottom
x64Gen_call_reg64(x64GenContext, REG_RESV_TEMP); // calculate fres result in xmm15
x64Gen_unpcklpd_xmmReg_xmmReg(x64GenContext, imlInstruction->op_fpr_r_r.registerResult, REG_RESV_FPR_TEMP); // copy bottom to top
x64Gen_unpcklpd_xmmReg_xmmReg(x64GenContext, imlInstruction->op_fpr_r_r.regR, REG_RESV_FPR_TEMP); // copy bottom to top
}
else
{
@ -884,76 +884,76 @@ void PPCRecompilerX64Gen_imlInstruction_fpr_r_r_r(PPCRecFunction_t* PPCRecFuncti
{
if (imlInstruction->operation == PPCREC_IML_OP_FPR_MULTIPLY_BOTTOM)
{
if (imlInstruction->op_fpr_r_r_r.registerResult == imlInstruction->op_fpr_r_r_r.registerOperandA)
if (imlInstruction->op_fpr_r_r_r.regR == imlInstruction->op_fpr_r_r_r.regA)
{
x64Gen_mulsd_xmmReg_xmmReg(x64GenContext, imlInstruction->op_fpr_r_r_r.registerResult, imlInstruction->op_fpr_r_r_r.registerOperandB);
x64Gen_mulsd_xmmReg_xmmReg(x64GenContext, imlInstruction->op_fpr_r_r_r.regR, imlInstruction->op_fpr_r_r_r.regB);
}
else if (imlInstruction->op_fpr_r_r_r.registerResult == imlInstruction->op_fpr_r_r_r.registerOperandB)
else if (imlInstruction->op_fpr_r_r_r.regR == imlInstruction->op_fpr_r_r_r.regB)
{
x64Gen_mulsd_xmmReg_xmmReg(x64GenContext, imlInstruction->op_fpr_r_r_r.registerResult, imlInstruction->op_fpr_r_r_r.registerOperandA);
x64Gen_mulsd_xmmReg_xmmReg(x64GenContext, imlInstruction->op_fpr_r_r_r.regR, imlInstruction->op_fpr_r_r_r.regA);
}
else
{
x64Gen_movsd_xmmReg_xmmReg(x64GenContext, imlInstruction->op_fpr_r_r_r.registerResult, imlInstruction->op_fpr_r_r_r.registerOperandA);
x64Gen_mulsd_xmmReg_xmmReg(x64GenContext, imlInstruction->op_fpr_r_r_r.registerResult, imlInstruction->op_fpr_r_r_r.registerOperandB);
x64Gen_movsd_xmmReg_xmmReg(x64GenContext, imlInstruction->op_fpr_r_r_r.regR, imlInstruction->op_fpr_r_r_r.regA);
x64Gen_mulsd_xmmReg_xmmReg(x64GenContext, imlInstruction->op_fpr_r_r_r.regR, imlInstruction->op_fpr_r_r_r.regB);
}
}
else if (imlInstruction->operation == PPCREC_IML_OP_FPR_ADD_BOTTOM)
{
// todo: Use AVX 3-operand VADDSD if available
if (imlInstruction->op_fpr_r_r_r.registerResult == imlInstruction->op_fpr_r_r_r.registerOperandA)
if (imlInstruction->op_fpr_r_r_r.regR == imlInstruction->op_fpr_r_r_r.regA)
{
x64Gen_addsd_xmmReg_xmmReg(x64GenContext, imlInstruction->op_fpr_r_r_r.registerResult, imlInstruction->op_fpr_r_r_r.registerOperandB);
x64Gen_addsd_xmmReg_xmmReg(x64GenContext, imlInstruction->op_fpr_r_r_r.regR, imlInstruction->op_fpr_r_r_r.regB);
}
else if (imlInstruction->op_fpr_r_r_r.registerResult == imlInstruction->op_fpr_r_r_r.registerOperandB)
else if (imlInstruction->op_fpr_r_r_r.regR == imlInstruction->op_fpr_r_r_r.regB)
{
x64Gen_addsd_xmmReg_xmmReg(x64GenContext, imlInstruction->op_fpr_r_r_r.registerResult, imlInstruction->op_fpr_r_r_r.registerOperandA);
x64Gen_addsd_xmmReg_xmmReg(x64GenContext, imlInstruction->op_fpr_r_r_r.regR, imlInstruction->op_fpr_r_r_r.regA);
}
else
{
x64Gen_movaps_xmmReg_xmmReg(x64GenContext, imlInstruction->op_fpr_r_r_r.registerResult, imlInstruction->op_fpr_r_r_r.registerOperandA);
x64Gen_addsd_xmmReg_xmmReg(x64GenContext, imlInstruction->op_fpr_r_r_r.registerResult, imlInstruction->op_fpr_r_r_r.registerOperandB);
x64Gen_movaps_xmmReg_xmmReg(x64GenContext, imlInstruction->op_fpr_r_r_r.regR, imlInstruction->op_fpr_r_r_r.regA);
x64Gen_addsd_xmmReg_xmmReg(x64GenContext, imlInstruction->op_fpr_r_r_r.regR, imlInstruction->op_fpr_r_r_r.regB);
}
}
else if (imlInstruction->operation == PPCREC_IML_OP_FPR_SUB_PAIR)
{
// registerResult = registerOperandA - registerOperandB
if( imlInstruction->op_fpr_r_r_r.registerResult == imlInstruction->op_fpr_r_r_r.registerOperandA )
if( imlInstruction->op_fpr_r_r_r.regR == imlInstruction->op_fpr_r_r_r.regA )
{
x64Gen_subpd_xmmReg_xmmReg(x64GenContext, imlInstruction->op_fpr_r_r_r.registerResult, imlInstruction->op_fpr_r_r_r.registerOperandB);
x64Gen_subpd_xmmReg_xmmReg(x64GenContext, imlInstruction->op_fpr_r_r_r.regR, imlInstruction->op_fpr_r_r_r.regB);
}
else if (g_CPUFeatures.x86.avx)
{
x64Gen_avx_VSUBPD_xmm_xmm_xmm(x64GenContext, imlInstruction->op_fpr_r_r_r.registerResult, imlInstruction->op_fpr_r_r_r.registerOperandA, imlInstruction->op_fpr_r_r_r.registerOperandB);
x64Gen_avx_VSUBPD_xmm_xmm_xmm(x64GenContext, imlInstruction->op_fpr_r_r_r.regR, imlInstruction->op_fpr_r_r_r.regA, imlInstruction->op_fpr_r_r_r.regB);
}
else if( imlInstruction->op_fpr_r_r_r.registerResult == imlInstruction->op_fpr_r_r_r.registerOperandB )
else if( imlInstruction->op_fpr_r_r_r.regR == imlInstruction->op_fpr_r_r_r.regB )
{
x64Gen_movaps_xmmReg_xmmReg(x64GenContext, REG_RESV_FPR_TEMP, imlInstruction->op_fpr_r_r_r.registerOperandA);
x64Gen_subpd_xmmReg_xmmReg(x64GenContext, REG_RESV_FPR_TEMP, imlInstruction->op_fpr_r_r_r.registerOperandB);
x64Gen_movaps_xmmReg_xmmReg(x64GenContext, imlInstruction->op_fpr_r_r_r.registerResult, REG_RESV_FPR_TEMP);
x64Gen_movaps_xmmReg_xmmReg(x64GenContext, REG_RESV_FPR_TEMP, imlInstruction->op_fpr_r_r_r.regA);
x64Gen_subpd_xmmReg_xmmReg(x64GenContext, REG_RESV_FPR_TEMP, imlInstruction->op_fpr_r_r_r.regB);
x64Gen_movaps_xmmReg_xmmReg(x64GenContext, imlInstruction->op_fpr_r_r_r.regR, REG_RESV_FPR_TEMP);
}
else
{
x64Gen_movaps_xmmReg_xmmReg(x64GenContext, imlInstruction->op_fpr_r_r_r.registerResult, imlInstruction->op_fpr_r_r_r.registerOperandA);
x64Gen_subpd_xmmReg_xmmReg(x64GenContext, imlInstruction->op_fpr_r_r_r.registerResult, imlInstruction->op_fpr_r_r_r.registerOperandB);
x64Gen_movaps_xmmReg_xmmReg(x64GenContext, imlInstruction->op_fpr_r_r_r.regR, imlInstruction->op_fpr_r_r_r.regA);
x64Gen_subpd_xmmReg_xmmReg(x64GenContext, imlInstruction->op_fpr_r_r_r.regR, imlInstruction->op_fpr_r_r_r.regB);
}
}
else if( imlInstruction->operation == PPCREC_IML_OP_FPR_SUB_BOTTOM )
{
if( imlInstruction->op_fpr_r_r_r.registerResult == imlInstruction->op_fpr_r_r_r.registerOperandA )
if( imlInstruction->op_fpr_r_r_r.regR == imlInstruction->op_fpr_r_r_r.regA )
{
x64Gen_subsd_xmmReg_xmmReg(x64GenContext, imlInstruction->op_fpr_r_r_r.registerResult, imlInstruction->op_fpr_r_r_r.registerOperandB);
x64Gen_subsd_xmmReg_xmmReg(x64GenContext, imlInstruction->op_fpr_r_r_r.regR, imlInstruction->op_fpr_r_r_r.regB);
}
else if( imlInstruction->op_fpr_r_r_r.registerResult == imlInstruction->op_fpr_r_r_r.registerOperandB )
else if( imlInstruction->op_fpr_r_r_r.regR == imlInstruction->op_fpr_r_r_r.regB )
{
x64Gen_movsd_xmmReg_xmmReg(x64GenContext, REG_RESV_FPR_TEMP, imlInstruction->op_fpr_r_r_r.registerOperandA);
x64Gen_subsd_xmmReg_xmmReg(x64GenContext, REG_RESV_FPR_TEMP, imlInstruction->op_fpr_r_r_r.registerOperandB);
x64Gen_movsd_xmmReg_xmmReg(x64GenContext, imlInstruction->op_fpr_r_r_r.registerResult, REG_RESV_FPR_TEMP);
x64Gen_movsd_xmmReg_xmmReg(x64GenContext, REG_RESV_FPR_TEMP, imlInstruction->op_fpr_r_r_r.regA);
x64Gen_subsd_xmmReg_xmmReg(x64GenContext, REG_RESV_FPR_TEMP, imlInstruction->op_fpr_r_r_r.regB);
x64Gen_movsd_xmmReg_xmmReg(x64GenContext, imlInstruction->op_fpr_r_r_r.regR, REG_RESV_FPR_TEMP);
}
else
{
x64Gen_movsd_xmmReg_xmmReg(x64GenContext, imlInstruction->op_fpr_r_r_r.registerResult, imlInstruction->op_fpr_r_r_r.registerOperandA);
x64Gen_subsd_xmmReg_xmmReg(x64GenContext, imlInstruction->op_fpr_r_r_r.registerResult, imlInstruction->op_fpr_r_r_r.registerOperandB);
x64Gen_movsd_xmmReg_xmmReg(x64GenContext, imlInstruction->op_fpr_r_r_r.regR, imlInstruction->op_fpr_r_r_r.regA);
x64Gen_subsd_xmmReg_xmmReg(x64GenContext, imlInstruction->op_fpr_r_r_r.regR, imlInstruction->op_fpr_r_r_r.regB);
}
}
else
@ -970,27 +970,27 @@ void PPCRecompilerX64Gen_imlInstruction_fpr_r_r_r_r(PPCRecFunction_t* PPCRecFunc
// todo: Investigate if there are other optimizations possible if the operand registers overlap
// generic case
// 1) move frA bottom to frTemp bottom and top
x64Gen_movddup_xmmReg_xmmReg(x64GenContext, REG_RESV_FPR_TEMP, imlInstruction->op_fpr_r_r_r_r.registerOperandA);
x64Gen_movddup_xmmReg_xmmReg(x64GenContext, REG_RESV_FPR_TEMP, imlInstruction->op_fpr_r_r_r_r.regA);
// 2) add frB (both halfs, lower half is overwritten in the next step)
x64Gen_addpd_xmmReg_xmmReg(x64GenContext, REG_RESV_FPR_TEMP, imlInstruction->op_fpr_r_r_r_r.registerOperandB);
x64Gen_addpd_xmmReg_xmmReg(x64GenContext, REG_RESV_FPR_TEMP, imlInstruction->op_fpr_r_r_r_r.regB);
// 3) Interleave top of frTemp and frC
x64Gen_unpckhpd_xmmReg_xmmReg(x64GenContext, REG_RESV_FPR_TEMP, imlInstruction->op_fpr_r_r_r_r.registerOperandC);
x64Gen_unpckhpd_xmmReg_xmmReg(x64GenContext, REG_RESV_FPR_TEMP, imlInstruction->op_fpr_r_r_r_r.regC);
// todo: We can optimize the REG_RESV_FPR_TEMP -> resultReg copy operation away when the result register does not overlap with any of the operand registers
x64Gen_movaps_xmmReg_xmmReg(x64GenContext, imlInstruction->op_fpr_r_r_r_r.registerResult, REG_RESV_FPR_TEMP);
x64Gen_movaps_xmmReg_xmmReg(x64GenContext, imlInstruction->op_fpr_r_r_r_r.regR, REG_RESV_FPR_TEMP);
}
else if( imlInstruction->operation == PPCREC_IML_OP_FPR_SUM1 )
{
// todo: Investigate if there are other optimizations possible if the operand registers overlap
// 1) move frA bottom to frTemp bottom and top
x64Gen_movddup_xmmReg_xmmReg(x64GenContext, REG_RESV_FPR_TEMP, imlInstruction->op_fpr_r_r_r_r.registerOperandA);
x64Gen_movddup_xmmReg_xmmReg(x64GenContext, REG_RESV_FPR_TEMP, imlInstruction->op_fpr_r_r_r_r.regA);
// 2) add frB (both halfs, lower half is overwritten in the next step)
x64Gen_addpd_xmmReg_xmmReg(x64GenContext, REG_RESV_FPR_TEMP, imlInstruction->op_fpr_r_r_r_r.registerOperandB);
x64Gen_addpd_xmmReg_xmmReg(x64GenContext, REG_RESV_FPR_TEMP, imlInstruction->op_fpr_r_r_r_r.regB);
// 3) Copy bottom from frC
x64Gen_movsd_xmmReg_xmmReg(x64GenContext, REG_RESV_FPR_TEMP, imlInstruction->op_fpr_r_r_r_r.registerOperandC);
x64Gen_movsd_xmmReg_xmmReg(x64GenContext, REG_RESV_FPR_TEMP, imlInstruction->op_fpr_r_r_r_r.regC);
//// 4) Swap bottom and top half
//x64Gen_shufpd_xmmReg_xmmReg_imm8(x64GenContext, REG_RESV_FPR_TEMP, REG_RESV_FPR_TEMP, 1);
// todo: We can optimize the REG_RESV_FPR_TEMP -> resultReg copy operation away when the result register does not overlap with any of the operand registers
x64Gen_movaps_xmmReg_xmmReg(x64GenContext, imlInstruction->op_fpr_r_r_r_r.registerResult, REG_RESV_FPR_TEMP);
x64Gen_movaps_xmmReg_xmmReg(x64GenContext, imlInstruction->op_fpr_r_r_r_r.regR, REG_RESV_FPR_TEMP);
//float s0 = (float)hCPU->fpr[frC].fp0;
//float s1 = (float)(hCPU->fpr[frA].fp0 + hCPU->fpr[frB].fp1);
@ -999,48 +999,48 @@ void PPCRecompilerX64Gen_imlInstruction_fpr_r_r_r_r(PPCRecFunction_t* PPCRecFunc
}
else if( imlInstruction->operation == PPCREC_IML_OP_FPR_SELECT_BOTTOM )
{
x64Gen_comisd_xmmReg_mem64Reg64(x64GenContext, imlInstruction->op_fpr_r_r_r_r.registerOperandA, REG_RESV_RECDATA, offsetof(PPCRecompilerInstanceData_t, _x64XMM_constDouble0_0));
x64Gen_comisd_xmmReg_mem64Reg64(x64GenContext, imlInstruction->op_fpr_r_r_r_r.regA, REG_RESV_RECDATA, offsetof(PPCRecompilerInstanceData_t, _x64XMM_constDouble0_0));
sint32 jumpInstructionOffset1 = x64GenContext->emitter->GetWriteIndex();
x64Gen_jmpc_near(x64GenContext, X86_CONDITION_UNSIGNED_BELOW, 0);
// select C
x64Gen_movsd_xmmReg_xmmReg(x64GenContext, imlInstruction->op_fpr_r_r_r_r.registerResult, imlInstruction->op_fpr_r_r_r_r.registerOperandC);
x64Gen_movsd_xmmReg_xmmReg(x64GenContext, imlInstruction->op_fpr_r_r_r_r.regR, imlInstruction->op_fpr_r_r_r_r.regC);
sint32 jumpInstructionOffset2 = x64GenContext->emitter->GetWriteIndex();
x64Gen_jmpc_near(x64GenContext, X86_CONDITION_NONE, 0);
// select B
PPCRecompilerX64Gen_redirectRelativeJump(x64GenContext, jumpInstructionOffset1, x64GenContext->emitter->GetWriteIndex());
x64Gen_movsd_xmmReg_xmmReg(x64GenContext, imlInstruction->op_fpr_r_r_r_r.registerResult, imlInstruction->op_fpr_r_r_r_r.registerOperandB);
x64Gen_movsd_xmmReg_xmmReg(x64GenContext, imlInstruction->op_fpr_r_r_r_r.regR, imlInstruction->op_fpr_r_r_r_r.regB);
// end
PPCRecompilerX64Gen_redirectRelativeJump(x64GenContext, jumpInstructionOffset2, x64GenContext->emitter->GetWriteIndex());
}
else if( imlInstruction->operation == PPCREC_IML_OP_FPR_SELECT_PAIR )
{
// select bottom
x64Gen_comisd_xmmReg_mem64Reg64(x64GenContext, imlInstruction->op_fpr_r_r_r_r.registerOperandA, REG_RESV_RECDATA, offsetof(PPCRecompilerInstanceData_t, _x64XMM_constDouble0_0));
x64Gen_comisd_xmmReg_mem64Reg64(x64GenContext, imlInstruction->op_fpr_r_r_r_r.regA, REG_RESV_RECDATA, offsetof(PPCRecompilerInstanceData_t, _x64XMM_constDouble0_0));
sint32 jumpInstructionOffset1_bottom = x64GenContext->emitter->GetWriteIndex();
x64Gen_jmpc_near(x64GenContext, X86_CONDITION_UNSIGNED_BELOW, 0);
// select C bottom
x64Gen_movsd_xmmReg_xmmReg(x64GenContext, imlInstruction->op_fpr_r_r_r_r.registerResult, imlInstruction->op_fpr_r_r_r_r.registerOperandC);
x64Gen_movsd_xmmReg_xmmReg(x64GenContext, imlInstruction->op_fpr_r_r_r_r.regR, imlInstruction->op_fpr_r_r_r_r.regC);
sint32 jumpInstructionOffset2_bottom = x64GenContext->emitter->GetWriteIndex();
x64Gen_jmpc_near(x64GenContext, X86_CONDITION_NONE, 0);
// select B bottom
PPCRecompilerX64Gen_redirectRelativeJump(x64GenContext, jumpInstructionOffset1_bottom, x64GenContext->emitter->GetWriteIndex());
x64Gen_movsd_xmmReg_xmmReg(x64GenContext, imlInstruction->op_fpr_r_r_r_r.registerResult, imlInstruction->op_fpr_r_r_r_r.registerOperandB);
x64Gen_movsd_xmmReg_xmmReg(x64GenContext, imlInstruction->op_fpr_r_r_r_r.regR, imlInstruction->op_fpr_r_r_r_r.regB);
// end
PPCRecompilerX64Gen_redirectRelativeJump(x64GenContext, jumpInstructionOffset2_bottom, x64GenContext->emitter->GetWriteIndex());
// select top
x64Gen_movhlps_xmmReg_xmmReg(x64GenContext, REG_RESV_FPR_TEMP, imlInstruction->op_fpr_r_r_r_r.registerOperandA); // copy top to bottom (todo: May cause stall?)
x64Gen_movhlps_xmmReg_xmmReg(x64GenContext, REG_RESV_FPR_TEMP, imlInstruction->op_fpr_r_r_r_r.regA); // copy top to bottom (todo: May cause stall?)
x64Gen_comisd_xmmReg_mem64Reg64(x64GenContext, REG_RESV_FPR_TEMP, REG_RESV_RECDATA, offsetof(PPCRecompilerInstanceData_t, _x64XMM_constDouble0_0));
sint32 jumpInstructionOffset1_top = x64GenContext->emitter->GetWriteIndex();
x64Gen_jmpc_near(x64GenContext, X86_CONDITION_UNSIGNED_BELOW, 0);
// select C top
//x64Gen_movsd_xmmReg_xmmReg(x64GenContext, imlInstruction->op_fpr_r_r_r_r.registerResult, imlInstruction->op_fpr_r_r_r_r.registerOperandC);
x64Gen_shufpd_xmmReg_xmmReg_imm8(x64GenContext, imlInstruction->op_fpr_r_r_r_r.registerResult, imlInstruction->op_fpr_r_r_r_r.registerOperandC, 2);
x64Gen_shufpd_xmmReg_xmmReg_imm8(x64GenContext, imlInstruction->op_fpr_r_r_r_r.regR, imlInstruction->op_fpr_r_r_r_r.regC, 2);
sint32 jumpInstructionOffset2_top = x64GenContext->emitter->GetWriteIndex();
x64Gen_jmpc_near(x64GenContext, X86_CONDITION_NONE, 0);
// select B top
PPCRecompilerX64Gen_redirectRelativeJump(x64GenContext, jumpInstructionOffset1_top, x64GenContext->emitter->GetWriteIndex());
//x64Gen_movsd_xmmReg_xmmReg(x64GenContext, imlInstruction->op_fpr_r_r_r_r.registerResult, imlInstruction->op_fpr_r_r_r_r.registerOperandB);
x64Gen_shufpd_xmmReg_xmmReg_imm8(x64GenContext, imlInstruction->op_fpr_r_r_r_r.registerResult, imlInstruction->op_fpr_r_r_r_r.registerOperandB, 2);
x64Gen_shufpd_xmmReg_xmmReg_imm8(x64GenContext, imlInstruction->op_fpr_r_r_r_r.regR, imlInstruction->op_fpr_r_r_r_r.regB, 2);
// end
PPCRecompilerX64Gen_redirectRelativeJump(x64GenContext, jumpInstructionOffset2_top, x64GenContext->emitter->GetWriteIndex());
}
@ -1052,36 +1052,36 @@ void PPCRecompilerX64Gen_imlInstruction_fpr_r(PPCRecFunction_t* PPCRecFunction,
{
if( imlInstruction->operation == PPCREC_IML_OP_FPR_NEGATE_BOTTOM )
{
x64Gen_xorps_xmmReg_mem128Reg64(x64GenContext, imlInstruction->op_fpr_r.registerResult, REG_RESV_RECDATA, offsetof(PPCRecompilerInstanceData_t, _x64XMM_xorNegateMaskBottom));
x64Gen_xorps_xmmReg_mem128Reg64(x64GenContext, imlInstruction->op_fpr_r.regR, REG_RESV_RECDATA, offsetof(PPCRecompilerInstanceData_t, _x64XMM_xorNegateMaskBottom));
}
else if( imlInstruction->operation == PPCREC_IML_OP_FPR_ABS_BOTTOM )
{
x64Gen_andps_xmmReg_mem128Reg64(x64GenContext, imlInstruction->op_fpr_r.registerResult, REG_RESV_RECDATA, offsetof(PPCRecompilerInstanceData_t, _x64XMM_andAbsMaskBottom));
x64Gen_andps_xmmReg_mem128Reg64(x64GenContext, imlInstruction->op_fpr_r.regR, REG_RESV_RECDATA, offsetof(PPCRecompilerInstanceData_t, _x64XMM_andAbsMaskBottom));
}
else if( imlInstruction->operation == PPCREC_IML_OP_FPR_NEGATIVE_ABS_BOTTOM )
{
x64Gen_orps_xmmReg_mem128Reg64(x64GenContext, imlInstruction->op_fpr_r.registerResult, REG_RESV_RECDATA, offsetof(PPCRecompilerInstanceData_t, _x64XMM_xorNegateMaskBottom));
x64Gen_orps_xmmReg_mem128Reg64(x64GenContext, imlInstruction->op_fpr_r.regR, REG_RESV_RECDATA, offsetof(PPCRecompilerInstanceData_t, _x64XMM_xorNegateMaskBottom));
}
else if( imlInstruction->operation == PPCREC_IML_OP_FPR_ROUND_TO_SINGLE_PRECISION_BOTTOM )
{
// convert to 32bit single
x64Gen_cvtsd2ss_xmmReg_xmmReg(x64GenContext, imlInstruction->op_fpr_r.registerResult, imlInstruction->op_fpr_r.registerResult);
x64Gen_cvtsd2ss_xmmReg_xmmReg(x64GenContext, imlInstruction->op_fpr_r.regR, imlInstruction->op_fpr_r.regR);
// convert back to 64bit double
x64Gen_cvtss2sd_xmmReg_xmmReg(x64GenContext, imlInstruction->op_fpr_r.registerResult, imlInstruction->op_fpr_r.registerResult);
x64Gen_cvtss2sd_xmmReg_xmmReg(x64GenContext, imlInstruction->op_fpr_r.regR, imlInstruction->op_fpr_r.regR);
}
else if( imlInstruction->operation == PPCREC_IML_OP_FPR_ROUND_TO_SINGLE_PRECISION_PAIR )
{
// convert to 32bit singles
x64Gen_cvtpd2ps_xmmReg_xmmReg(x64GenContext, imlInstruction->op_fpr_r.registerResult, imlInstruction->op_fpr_r.registerResult);
x64Gen_cvtpd2ps_xmmReg_xmmReg(x64GenContext, imlInstruction->op_fpr_r.regR, imlInstruction->op_fpr_r.regR);
// convert back to 64bit doubles
x64Gen_cvtps2pd_xmmReg_xmmReg(x64GenContext, imlInstruction->op_fpr_r.registerResult, imlInstruction->op_fpr_r.registerResult);
x64Gen_cvtps2pd_xmmReg_xmmReg(x64GenContext, imlInstruction->op_fpr_r.regR, imlInstruction->op_fpr_r.regR);
}
else if (imlInstruction->operation == PPCREC_IML_OP_FPR_EXPAND_BOTTOM32_TO_BOTTOM64_AND_TOP64)
{
// convert bottom to 64bit double
x64Gen_cvtss2sd_xmmReg_xmmReg(x64GenContext, imlInstruction->op_fpr_r.registerResult, imlInstruction->op_fpr_r.registerResult);
x64Gen_cvtss2sd_xmmReg_xmmReg(x64GenContext, imlInstruction->op_fpr_r.regR, imlInstruction->op_fpr_r.regR);
// copy to top half
x64Gen_movddup_xmmReg_xmmReg(x64GenContext, imlInstruction->op_fpr_r.registerResult, imlInstruction->op_fpr_r.registerResult);
x64Gen_movddup_xmmReg_xmmReg(x64GenContext, imlInstruction->op_fpr_r.regR, imlInstruction->op_fpr_r.regR);
}
else
{

View File

@ -612,40 +612,6 @@ void x64Gen_mov_mem8Reg64_reg64Low8(x64GenContext_t* x64GenContext, sint32 dstRe
_x64_op_reg64Low_mem8Reg64(x64GenContext, dstRegister, memRegister64, memImmS32, 0x88);
}
void x64Gen_lock_cmpxchg_mem32Reg64PlusReg64_reg64(x64GenContext_t* x64GenContext, sint32 memRegisterA64, sint32 memRegisterB64, sint32 memImmS32, sint32 srcRegister)
{
// LOCK CMPXCHG DWORD [<reg64> + <reg64> + <imm64>], <srcReg64> (low dword)
x64Gen_writeU8(x64GenContext, 0xF0); // LOCK prefix
if( srcRegister >= 8 || memRegisterA64 >= 8|| memRegisterB64 >= 8 )
x64Gen_writeU8(x64GenContext, 0x40+((srcRegister>=8)?4:0)+((memRegisterA64>=8)?1:0)+((memRegisterB64>=8)?2:0));
x64Gen_writeU8(x64GenContext, 0x0F);
x64Gen_writeU8(x64GenContext, 0xB1);
_x64Gen_writeMODRMDeprecated(x64GenContext, srcRegister, memRegisterA64, memRegisterB64, memImmS32);
}
void x64Gen_lock_cmpxchg_mem32Reg64_reg64(x64GenContext_t* x64GenContext, sint32 memRegister64, sint32 memImmS32, sint32 srcRegister)
{
// LOCK CMPXCHG DWORD [<reg64> + <imm64>], <srcReg64> (low dword)
x64Gen_writeU8(x64GenContext, 0xF0); // LOCK prefix
if( srcRegister >= 8 || memRegister64 >= 8 )
x64Gen_writeU8(x64GenContext, 0x40+((srcRegister>=8)?4:0)+((memRegister64>=8)?1:0));
x64Gen_writeU8(x64GenContext, 0x0F);
x64Gen_writeU8(x64GenContext, 0xB1);
if( memImmS32 == 0 )
{
x64Gen_writeU8(x64GenContext, 0x45+(srcRegister&7)*8);
x64Gen_writeU8(x64GenContext, 0x00);
}
else
assert_dbg();
}
void x64Gen_add_reg64_reg64(x64GenContext_t* x64GenContext, sint32 destRegister, sint32 srcRegister)
{
// ADD <destReg>, <srcReg>
@ -812,59 +778,6 @@ void x64Gen_sub_mem32reg64_imm32(x64GenContext_t* x64GenContext, sint32 memRegis
}
}
void x64Gen_sbb_reg64Low32_reg64Low32(x64GenContext_t* x64GenContext, sint32 destRegister, sint32 srcRegister)
{
// SBB <destReg64_low32>, <srcReg64_low32>
if( destRegister >= 8 && srcRegister >= 8 )
x64Gen_writeU8(x64GenContext, 0x45);
else if( srcRegister >= 8 )
x64Gen_writeU8(x64GenContext, 0x44);
else if( destRegister >= 8 )
x64Gen_writeU8(x64GenContext, 0x41);
x64Gen_writeU8(x64GenContext, 0x19);
x64Gen_writeU8(x64GenContext, 0xC0+(srcRegister&7)*8+(destRegister&7));
}
void x64Gen_adc_reg64Low32_reg64Low32(x64GenContext_t* x64GenContext, sint32 destRegister, sint32 srcRegister)
{
// ADC <destReg64_low32>, <srcReg64_low32>
if( destRegister >= 8 && srcRegister >= 8 )
x64Gen_writeU8(x64GenContext, 0x45);
else if( srcRegister >= 8 )
x64Gen_writeU8(x64GenContext, 0x44);
else if( destRegister >= 8 )
x64Gen_writeU8(x64GenContext, 0x41);
x64Gen_writeU8(x64GenContext, 0x11);
x64Gen_writeU8(x64GenContext, 0xC0+(srcRegister&7)*8+(destRegister&7));
}
void x64Gen_adc_reg64Low32_imm32(x64GenContext_t* x64GenContext, sint32 srcRegister, uint32 immU32)
{
sint32 immS32 = (sint32)immU32;
if( srcRegister >= 8 )
x64Gen_writeU8(x64GenContext, 0x41);
if( immS32 >= -128 && immS32 <= 127 )
{
x64Gen_writeU8(x64GenContext, 0x83);
x64Gen_writeU8(x64GenContext, 0xD0+(srcRegister&7));
x64Gen_writeU8(x64GenContext, (uint8)immS32);
}
else
{
if( srcRegister == X86_REG_RAX )
{
// special EAX short form
x64Gen_writeU8(x64GenContext, 0x15);
}
else
{
x64Gen_writeU8(x64GenContext, 0x81);
x64Gen_writeU8(x64GenContext, 0xD0+(srcRegister&7));
}
x64Gen_writeU32(x64GenContext, immU32);
}
}
void x64Gen_dec_mem32(x64GenContext_t* x64GenContext, sint32 memoryRegister, uint32 memoryImmU32)
{
// DEC dword [<reg64>+imm]
@ -1295,16 +1208,6 @@ void x64Gen_cdq(x64GenContext_t* x64GenContext)
x64Gen_writeU8(x64GenContext, 0x99);
}
void x64Gen_bswap_reg64(x64GenContext_t* x64GenContext, sint32 destRegister)
{
if( destRegister >= 8 )
x64Gen_writeU8(x64GenContext, 0x41|8);
else
x64Gen_writeU8(x64GenContext, 0x40|8);
x64Gen_writeU8(x64GenContext, 0x0F);
x64Gen_writeU8(x64GenContext, 0xC8+(destRegister&7));
}
void x64Gen_bswap_reg64Lower32bit(x64GenContext_t* x64GenContext, sint32 destRegister)
{
if( destRegister >= 8 )
@ -1313,16 +1216,6 @@ void x64Gen_bswap_reg64Lower32bit(x64GenContext_t* x64GenContext, sint32 destReg
x64Gen_writeU8(x64GenContext, 0xC8+(destRegister&7));
}
void x64Gen_bswap_reg64Lower16bit(x64GenContext_t* x64GenContext, sint32 destRegister)
{
assert_dbg(); // do not use this instruction, it's result is always undefined. Instead use ROL <reg16>, 8
//x64Gen_writeU8(x64GenContext, 0x66);
//if( destRegister >= 8 )
// x64Gen_writeU8(x64GenContext, 0x41);
//x64Gen_writeU8(x64GenContext, 0x0F);
//x64Gen_writeU8(x64GenContext, 0xC8+(destRegister&7));
}
void x64Gen_lzcnt_reg64Low32_reg64Low32(x64GenContext_t* x64GenContext, sint32 destRegister, sint32 srcRegister)
{
// SSE4

View File

@ -18,7 +18,6 @@ void IMLAnalyzer_GetCRTracking(IMLInstruction* imlInstruction, PPCRecCRTracking_
// todo - rename
bool PPCRecompiler_reduceNumberOfFPRRegisters(struct ppcImlGenContext_t* ppcImlGenContext);
bool PPCRecompiler_manageFPRRegisters(struct ppcImlGenContext_t* ppcImlGenContext);
void PPCRecompiler_removeRedundantCRUpdates(struct ppcImlGenContext_t* ppcImlGenContext);
void PPCRecompiler_optimizeDirectFloatCopies(struct ppcImlGenContext_t* ppcImlGenContext);
void PPCRecompiler_optimizeDirectIntegerCopies(struct ppcImlGenContext_t* ppcImlGenContext);
void PPCRecompiler_optimizePSQLoadAndStore(struct ppcImlGenContext_t* ppcImlGenContext);

View File

@ -31,7 +31,7 @@ bool IMLAnalyzer_IsTightFiniteLoop(IMLSegment* imlSegment)
{
if (instIt.type == PPCREC_IML_TYPE_R_S32 && (instIt.operation == PPCREC_IML_OP_ADD || instIt.operation == PPCREC_IML_OP_SUB) )
{
list_modifiedRegisters.addUnique(instIt.op_r_immS32.registerIndex);
list_modifiedRegisters.addUnique(instIt.op_r_immS32.regR);
}
}
if (list_modifiedRegisters.count > 0)

View File

@ -195,9 +195,9 @@ void IMLDebug_DumpSegment(ppcImlGenContext_t* ctx, IMLSegment* imlSegment, bool
while ((sint32)strOutput.getLen() < lineOffsetParameters)
strOutput.add(" ");
IMLDebug_AppendRegisterParam(strOutput, inst.op_r_name.registerIndex);
IMLDebug_AppendRegisterParam(strOutput, inst.op_r_name.regR);
strOutput.addFmt("name_{} (", inst.op_r_name.registerIndex, inst.op_r_name.name);
strOutput.addFmt("name_{} (", inst.op_r_name.regR, inst.op_r_name.name);
if (inst.op_r_name.name >= PPCREC_NAME_R0 && inst.op_r_name.name < (PPCREC_NAME_R0 + 999))
{
strOutput.addFmt("r{}", inst.op_r_name.name - PPCREC_NAME_R0);
@ -227,17 +227,17 @@ void IMLDebug_DumpSegment(ppcImlGenContext_t* ctx, IMLSegment* imlSegment, bool
strOutput.addFmt("{}", IMLDebug_GetOpcodeName(&inst));
while ((sint32)strOutput.getLen() < lineOffsetParameters)
strOutput.add(" ");
IMLDebug_AppendRegisterParam(strOutput, inst.op_r_r.registerResult);
IMLDebug_AppendRegisterParam(strOutput, inst.op_r_r.registerA, true);
IMLDebug_AppendRegisterParam(strOutput, inst.op_r_r.regR);
IMLDebug_AppendRegisterParam(strOutput, inst.op_r_r.regA, true);
}
else if (inst.type == PPCREC_IML_TYPE_R_R_R)
{
strOutput.addFmt("{}", IMLDebug_GetOpcodeName(&inst));
while ((sint32)strOutput.getLen() < lineOffsetParameters)
strOutput.add(" ");
IMLDebug_AppendRegisterParam(strOutput, inst.op_r_r_r.registerResult);
IMLDebug_AppendRegisterParam(strOutput, inst.op_r_r_r.registerA);
IMLDebug_AppendRegisterParam(strOutput, inst.op_r_r_r.registerB, true);
IMLDebug_AppendRegisterParam(strOutput, inst.op_r_r_r.regR);
IMLDebug_AppendRegisterParam(strOutput, inst.op_r_r_r.regA);
IMLDebug_AppendRegisterParam(strOutput, inst.op_r_r_r.regB, true);
}
else if (inst.type == PPCREC_IML_TYPE_R_R_R_CARRY)
{
@ -254,30 +254,30 @@ void IMLDebug_DumpSegment(ppcImlGenContext_t* ctx, IMLSegment* imlSegment, bool
strOutput.add("CMP ");
while ((sint32)strOutput.getLen() < lineOffsetParameters)
strOutput.add(" ");
IMLDebug_AppendRegisterParam(strOutput, inst.op_compare.registerOperandA);
IMLDebug_AppendRegisterParam(strOutput, inst.op_compare.registerOperandB);
IMLDebug_AppendRegisterParam(strOutput, inst.op_compare.regA);
IMLDebug_AppendRegisterParam(strOutput, inst.op_compare.regB);
strOutput.addFmt(", {}", IMLDebug_GetConditionName(inst.op_compare.cond));
strOutput.add(" -> ");
IMLDebug_AppendRegisterParam(strOutput, inst.op_compare.registerResult, true);
IMLDebug_AppendRegisterParam(strOutput, inst.op_compare.regR, true);
}
else if (inst.type == PPCREC_IML_TYPE_COMPARE_S32)
{
strOutput.add("CMP ");
while ((sint32)strOutput.getLen() < lineOffsetParameters)
strOutput.add(" ");
IMLDebug_AppendRegisterParam(strOutput, inst.op_compare_s32.registerOperandA);
IMLDebug_AppendRegisterParam(strOutput, inst.op_compare_s32.regA);
strOutput.addFmt("{}", inst.op_compare_s32.immS32);
strOutput.addFmt(", {}", IMLDebug_GetConditionName(inst.op_compare_s32.cond));
strOutput.add(" -> ");
IMLDebug_AppendRegisterParam(strOutput, inst.op_compare_s32.registerResult, true);
IMLDebug_AppendRegisterParam(strOutput, inst.op_compare_s32.regR, true);
}
else if (inst.type == PPCREC_IML_TYPE_CONDITIONAL_JUMP)
{
strOutput.add("CJUMP2 ");
while ((sint32)strOutput.getLen() < lineOffsetParameters)
strOutput.add(" ");
IMLDebug_AppendRegisterParam(strOutput, inst.op_conditionalJump2.registerBool, true);
if (!inst.op_conditionalJump2.mustBeTrue)
IMLDebug_AppendRegisterParam(strOutput, inst.op_conditional_jump.registerBool, true);
if (!inst.op_conditional_jump.mustBeTrue)
strOutput.add("(inverted)");
}
else if (inst.type == PPCREC_IML_TYPE_JUMP)
@ -290,8 +290,8 @@ void IMLDebug_DumpSegment(ppcImlGenContext_t* ctx, IMLSegment* imlSegment, bool
while ((sint32)strOutput.getLen() < lineOffsetParameters)
strOutput.add(" ");
IMLDebug_AppendRegisterParam(strOutput, inst.op_r_r_s32.registerResult);
IMLDebug_AppendRegisterParam(strOutput, inst.op_r_r_s32.registerA);
IMLDebug_AppendRegisterParam(strOutput, inst.op_r_r_s32.regR);
IMLDebug_AppendRegisterParam(strOutput, inst.op_r_r_s32.regA);
IMLDebug_AppendS32Param(strOutput, inst.op_r_r_s32.immS32, true);
}
else if (inst.type == PPCREC_IML_TYPE_R_R_S32_CARRY)
@ -311,7 +311,7 @@ void IMLDebug_DumpSegment(ppcImlGenContext_t* ctx, IMLSegment* imlSegment, bool
while ((sint32)strOutput.getLen() < lineOffsetParameters)
strOutput.add(" ");
IMLDebug_AppendRegisterParam(strOutput, inst.op_r_immS32.registerIndex);
IMLDebug_AppendRegisterParam(strOutput, inst.op_r_immS32.regR);
IMLDebug_AppendS32Param(strOutput, inst.op_r_immS32.immS32, true);
}
else if (inst.type == PPCREC_IML_TYPE_LOAD || inst.type == PPCREC_IML_TYPE_STORE ||
@ -391,7 +391,7 @@ void IMLDebug_DumpSegment(ppcImlGenContext_t* ctx, IMLSegment* imlSegment, bool
}
else if (inst.type == PPCREC_IML_TYPE_FPR_R_NAME)
{
strOutput.addFmt("fpr_t{} = name_{} (", inst.op_r_name.registerIndex, inst.op_r_name.name);
strOutput.addFmt("fpr_t{} = name_{} (", inst.op_r_name.regR, inst.op_r_name.name);
if (inst.op_r_name.name >= PPCREC_NAME_FPR0 && inst.op_r_name.name < (PPCREC_NAME_FPR0 + 999))
{
strOutput.addFmt("fpr{}", inst.op_r_name.name - PPCREC_NAME_FPR0);
@ -417,7 +417,7 @@ void IMLDebug_DumpSegment(ppcImlGenContext_t* ctx, IMLSegment* imlSegment, bool
}
else
strOutput.add("ukn");
strOutput.addFmt(") = fpr_t{}", inst.op_r_name.registerIndex);
strOutput.addFmt(") = fpr_t{}", inst.op_r_name.regR);
}
else if (inst.type == PPCREC_IML_TYPE_FPR_LOAD)
{
@ -444,17 +444,17 @@ void IMLDebug_DumpSegment(ppcImlGenContext_t* ctx, IMLSegment* imlSegment, bool
else if (inst.type == PPCREC_IML_TYPE_FPR_R_R)
{
strOutput.addFmt("{:>6} ", IMLDebug_GetOpcodeName(&inst));
strOutput.addFmt("fpr{:02}, fpr{:02}", inst.op_fpr_r_r.registerResult, inst.op_fpr_r_r.registerOperand);
strOutput.addFmt("fpr{:02}, fpr{:02}", inst.op_fpr_r_r.regR, inst.op_fpr_r_r.regA);
}
else if (inst.type == PPCREC_IML_TYPE_FPR_R_R_R_R)
{
strOutput.addFmt("{:>6} ", IMLDebug_GetOpcodeName(&inst));
strOutput.addFmt("fpr{:02}, fpr{:02}, fpr{:02}, fpr{:02}", inst.op_fpr_r_r_r_r.registerResult, inst.op_fpr_r_r_r_r.registerOperandA, inst.op_fpr_r_r_r_r.registerOperandB, inst.op_fpr_r_r_r_r.registerOperandC);
strOutput.addFmt("fpr{:02}, fpr{:02}, fpr{:02}, fpr{:02}", inst.op_fpr_r_r_r_r.regR, inst.op_fpr_r_r_r_r.regA, inst.op_fpr_r_r_r_r.regB, inst.op_fpr_r_r_r_r.regC);
}
else if (inst.type == PPCREC_IML_TYPE_FPR_R_R_R)
{
strOutput.addFmt("{:>6} ", IMLDebug_GetOpcodeName(&inst));
strOutput.addFmt("fpr{:02}, fpr{:02}, fpr{:02}", inst.op_fpr_r_r_r.registerResult, inst.op_fpr_r_r_r.registerOperandA, inst.op_fpr_r_r_r.registerOperandB);
strOutput.addFmt("fpr{:02}, fpr{:02}, fpr{:02}", inst.op_fpr_r_r_r.regR, inst.op_fpr_r_r_r.regA, inst.op_fpr_r_r_r.regB);
}
else if (inst.type == PPCREC_IML_TYPE_CJUMP_CYCLE_CHECK)
{
@ -462,7 +462,7 @@ void IMLDebug_DumpSegment(ppcImlGenContext_t* ctx, IMLSegment* imlSegment, bool
}
else if (inst.type == PPCREC_IML_TYPE_CONDITIONAL_R_S32)
{
strOutput.addFmt("t{} ", inst.op_conditional_r_s32.registerIndex);
strOutput.addFmt("t{} ", inst.op_conditional_r_s32.regR);
bool displayAsHex = false;
if (inst.operation == PPCREC_IML_OP_ASSIGN)
{

View File

@ -6,31 +6,31 @@
void IMLInstruction::CheckRegisterUsage(IMLUsedRegisters* registersUsed) const
{
registersUsed->readNamedReg1 = -1;
registersUsed->readNamedReg2 = -1;
registersUsed->readNamedReg3 = -1;
registersUsed->writtenNamedReg1 = -1;
registersUsed->writtenNamedReg2 = -1;
registersUsed->readFPR1 = -1;
registersUsed->readFPR2 = -1;
registersUsed->readFPR3 = -1;
registersUsed->readFPR4 = -1;
registersUsed->writtenFPR1 = -1;
registersUsed->readGPR1 = IMLREG_INVALID;
registersUsed->readGPR2 = IMLREG_INVALID;
registersUsed->readGPR3 = IMLREG_INVALID;
registersUsed->writtenGPR1 = IMLREG_INVALID;
registersUsed->writtenGPR2 = IMLREG_INVALID;
registersUsed->readFPR1 = IMLREG_INVALID;
registersUsed->readFPR2 = IMLREG_INVALID;
registersUsed->readFPR3 = IMLREG_INVALID;
registersUsed->readFPR4 = IMLREG_INVALID;
registersUsed->writtenFPR1 = IMLREG_INVALID;
if (type == PPCREC_IML_TYPE_R_NAME)
{
registersUsed->writtenNamedReg1 = op_r_name.registerIndex;
registersUsed->writtenGPR1 = op_r_name.regR;
}
else if (type == PPCREC_IML_TYPE_NAME_R)
{
registersUsed->readNamedReg1 = op_r_name.registerIndex;
registersUsed->readGPR1 = op_r_name.regR;
}
else if (type == PPCREC_IML_TYPE_R_R)
{
if (operation == PPCREC_IML_OP_DCBZ)
{
// both operands are read only
registersUsed->readNamedReg1 = op_r_r.registerResult;
registersUsed->readNamedReg2 = op_r_r.registerA;
registersUsed->readGPR1 = op_r_r.regR;
registersUsed->readGPR2 = op_r_r.regA;
}
else if (
operation == PPCREC_IML_OP_OR ||
@ -38,9 +38,9 @@ void IMLInstruction::CheckRegisterUsage(IMLUsedRegisters* registersUsed) const
operation == PPCREC_IML_OP_XOR)
{
// 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;
registersUsed->writtenGPR1 = op_r_r.regR;
registersUsed->readGPR1 = op_r_r.regR;
registersUsed->readGPR2 = op_r_r.regA;
}
else if (
operation == PPCREC_IML_OP_ASSIGN ||
@ -52,8 +52,8 @@ void IMLInstruction::CheckRegisterUsage(IMLUsedRegisters* registersUsed) const
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;
registersUsed->writtenGPR1 = op_r_r.regR;
registersUsed->readGPR1 = op_r_r.regA;
}
else
cemu_assert_unimplemented();
@ -63,7 +63,7 @@ void IMLInstruction::CheckRegisterUsage(IMLUsedRegisters* registersUsed) const
if (operation == PPCREC_IML_OP_MTCRF)
{
// operand register is read only
registersUsed->readNamedReg1 = op_r_immS32.registerIndex;
registersUsed->readGPR1 = op_r_immS32.regR;
}
else if (operation == PPCREC_IML_OP_ADD || // deprecated
operation == PPCREC_IML_OP_SUB ||
@ -73,14 +73,14 @@ void IMLInstruction::CheckRegisterUsage(IMLUsedRegisters* registersUsed) const
operation == PPCREC_IML_OP_LEFT_ROTATE)
{
// operand register is read and write
registersUsed->readNamedReg1 = op_r_immS32.registerIndex;
registersUsed->writtenNamedReg1 = op_r_immS32.registerIndex;
registersUsed->readGPR1 = op_r_immS32.regR;
registersUsed->writtenGPR1 = op_r_immS32.regR;
}
else
{
// operand register is write only
// todo - use explicit lists, avoid default cases
registersUsed->writtenNamedReg1 = op_r_immS32.registerIndex;
registersUsed->writtenGPR1 = op_r_immS32.regR;
}
}
else if (type == PPCREC_IML_TYPE_CONDITIONAL_R_S32)
@ -88,8 +88,8 @@ void IMLInstruction::CheckRegisterUsage(IMLUsedRegisters* registersUsed) const
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;
registersUsed->readGPR1 = op_conditional_r_s32.regR;
registersUsed->writtenGPR1 = op_conditional_r_s32.regR;
}
else
cemu_assert_unimplemented();
@ -99,26 +99,26 @@ void IMLInstruction::CheckRegisterUsage(IMLUsedRegisters* registersUsed) const
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;
registersUsed->writtenGPR1 = op_r_r_s32.regR;
registersUsed->readGPR1 = op_r_r_s32.regR;
registersUsed->readGPR2 = op_r_r_s32.regA;
}
else
{
// result is write only and operand is read only
registersUsed->writtenNamedReg1 = op_r_r_s32.registerResult;
registersUsed->readNamedReg1 = op_r_r_s32.registerA;
registersUsed->writtenGPR1 = op_r_r_s32.regR;
registersUsed->readGPR1 = op_r_r_s32.regA;
}
}
else if (type == PPCREC_IML_TYPE_R_R_S32_CARRY)
{
registersUsed->writtenNamedReg1 = op_r_r_s32_carry.regR;
registersUsed->readNamedReg1 = op_r_r_s32_carry.regA;
registersUsed->writtenGPR1 = op_r_r_s32_carry.regR;
registersUsed->readGPR1 = op_r_r_s32_carry.regA;
// some operations read carry
switch (operation)
{
case PPCREC_IML_OP_ADD_WITH_CARRY:
registersUsed->readNamedReg2 = op_r_r_s32_carry.regCarry;
registersUsed->readGPR2 = op_r_r_s32_carry.regCarry;
break;
case PPCREC_IML_OP_ADD:
break;
@ -126,25 +126,25 @@ void IMLInstruction::CheckRegisterUsage(IMLUsedRegisters* registersUsed) const
cemu_assert_unimplemented();
}
// carry is always written
registersUsed->writtenNamedReg2 = op_r_r_s32_carry.regCarry;
registersUsed->writtenGPR2 = op_r_r_s32_carry.regCarry;
}
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;
registersUsed->writtenGPR1 = op_r_r_r.regR;
registersUsed->readGPR1 = op_r_r_r.regA;
registersUsed->readGPR2 = op_r_r_r.regB;
}
else if (type == PPCREC_IML_TYPE_R_R_R_CARRY)
{
registersUsed->writtenNamedReg1 = op_r_r_r_carry.regR;
registersUsed->readNamedReg1 = op_r_r_r_carry.regA;
registersUsed->readNamedReg2 = op_r_r_r_carry.regB;
registersUsed->writtenGPR1 = op_r_r_r_carry.regR;
registersUsed->readGPR1 = op_r_r_r_carry.regA;
registersUsed->readGPR2 = op_r_r_r_carry.regB;
// some operations read carry
switch (operation)
{
case PPCREC_IML_OP_ADD_WITH_CARRY:
registersUsed->readNamedReg3 = op_r_r_r_carry.regCarry;
registersUsed->readGPR3 = op_r_r_r_carry.regCarry;
break;
case PPCREC_IML_OP_ADD:
break;
@ -152,7 +152,7 @@ void IMLInstruction::CheckRegisterUsage(IMLUsedRegisters* registersUsed) const
cemu_assert_unimplemented();
}
// carry is always written
registersUsed->writtenNamedReg2 = op_r_r_r_carry.regCarry;
registersUsed->writtenGPR2 = op_r_r_r_carry.regCarry;
}
else if (type == PPCREC_IML_TYPE_CJUMP_CYCLE_CHECK)
{
@ -170,25 +170,25 @@ void IMLInstruction::CheckRegisterUsage(IMLUsedRegisters* registersUsed) const
}
else if (operation == PPCREC_IML_MACRO_B_TO_REG)
{
registersUsed->readNamedReg1 = op_macro.param;
registersUsed->readGPR1 = op_macro.param;
}
else
cemu_assert_unimplemented();
}
else if (type == PPCREC_IML_TYPE_COMPARE)
{
registersUsed->readNamedReg1 = op_compare.registerOperandA;
registersUsed->readNamedReg2 = op_compare.registerOperandB;
registersUsed->writtenNamedReg1 = op_compare.registerResult;
registersUsed->readGPR1 = op_compare.regA;
registersUsed->readGPR2 = op_compare.regB;
registersUsed->writtenGPR1 = op_compare.regR;
}
else if (type == PPCREC_IML_TYPE_COMPARE_S32)
{
registersUsed->readNamedReg1 = op_compare_s32.registerOperandA;
registersUsed->writtenNamedReg1 = op_compare_s32.registerResult;
registersUsed->readGPR1 = op_compare_s32.regA;
registersUsed->writtenGPR1 = op_compare_s32.regR;
}
else if (type == PPCREC_IML_TYPE_CONDITIONAL_JUMP)
{
registersUsed->readNamedReg1 = op_conditionalJump2.registerBool;
registersUsed->readGPR1 = op_conditional_jump.registerBool;
}
else if (type == PPCREC_IML_TYPE_JUMP)
{
@ -196,48 +196,48 @@ void IMLInstruction::CheckRegisterUsage(IMLUsedRegisters* registersUsed) const
}
else if (type == PPCREC_IML_TYPE_LOAD)
{
registersUsed->writtenNamedReg1 = op_storeLoad.registerData;
registersUsed->writtenGPR1 = op_storeLoad.registerData;
if (op_storeLoad.registerMem != PPC_REC_INVALID_REGISTER)
registersUsed->readNamedReg1 = op_storeLoad.registerMem;
registersUsed->readGPR1 = op_storeLoad.registerMem;
}
else if (type == PPCREC_IML_TYPE_LOAD_INDEXED)
{
registersUsed->writtenNamedReg1 = op_storeLoad.registerData;
registersUsed->writtenGPR1 = op_storeLoad.registerData;
if (op_storeLoad.registerMem != PPC_REC_INVALID_REGISTER)
registersUsed->readNamedReg1 = op_storeLoad.registerMem;
registersUsed->readGPR1 = op_storeLoad.registerMem;
if (op_storeLoad.registerMem2 != PPC_REC_INVALID_REGISTER)
registersUsed->readNamedReg2 = op_storeLoad.registerMem2;
registersUsed->readGPR2 = op_storeLoad.registerMem2;
}
else if (type == PPCREC_IML_TYPE_STORE)
{
registersUsed->readNamedReg1 = op_storeLoad.registerData;
registersUsed->readGPR1 = op_storeLoad.registerData;
if (op_storeLoad.registerMem != PPC_REC_INVALID_REGISTER)
registersUsed->readNamedReg2 = op_storeLoad.registerMem;
registersUsed->readGPR2 = op_storeLoad.registerMem;
}
else if (type == PPCREC_IML_TYPE_STORE_INDEXED)
{
registersUsed->readNamedReg1 = op_storeLoad.registerData;
registersUsed->readGPR1 = op_storeLoad.registerData;
if (op_storeLoad.registerMem != PPC_REC_INVALID_REGISTER)
registersUsed->readNamedReg2 = op_storeLoad.registerMem;
registersUsed->readGPR2 = op_storeLoad.registerMem;
if (op_storeLoad.registerMem2 != PPC_REC_INVALID_REGISTER)
registersUsed->readNamedReg3 = op_storeLoad.registerMem2;
registersUsed->readGPR3 = op_storeLoad.registerMem2;
}
else if (type == PPCREC_IML_TYPE_ATOMIC_CMP_STORE)
{
registersUsed->readNamedReg1 = op_atomic_compare_store.regEA;
registersUsed->readNamedReg2 = op_atomic_compare_store.regCompareValue;
registersUsed->readNamedReg3 = op_atomic_compare_store.regWriteValue;
registersUsed->writtenNamedReg1 = op_atomic_compare_store.regBoolOut;
registersUsed->readGPR1 = op_atomic_compare_store.regEA;
registersUsed->readGPR2 = op_atomic_compare_store.regCompareValue;
registersUsed->readGPR3 = op_atomic_compare_store.regWriteValue;
registersUsed->writtenGPR1 = op_atomic_compare_store.regBoolOut;
}
else if (type == PPCREC_IML_TYPE_FPR_R_NAME)
{
// fpr operation
registersUsed->writtenFPR1 = op_r_name.registerIndex;
registersUsed->writtenFPR1 = op_r_name.regR;
}
else if (type == PPCREC_IML_TYPE_FPR_NAME_R)
{
// fpr operation
registersUsed->readFPR1 = op_r_name.registerIndex;
registersUsed->readFPR1 = op_r_name.regR;
}
else if (type == PPCREC_IML_TYPE_FPR_LOAD)
{
@ -245,14 +245,14 @@ void IMLInstruction::CheckRegisterUsage(IMLUsedRegisters* registersUsed) const
registersUsed->writtenFPR1 = op_storeLoad.registerData;
// address is in gpr register
if (op_storeLoad.registerMem != PPC_REC_INVALID_REGISTER)
registersUsed->readNamedReg1 = op_storeLoad.registerMem;
registersUsed->readGPR1 = 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;
registersUsed->readGPR2 = op_storeLoad.registerGQR;
break;
case PPCREC_FPR_LD_MODE_DOUBLE_INTO_PS0:
// PS1 remains the same
@ -282,16 +282,16 @@ void IMLInstruction::CheckRegisterUsage(IMLUsedRegisters* registersUsed) const
registersUsed->writtenFPR1 = op_storeLoad.registerData;
// address is in gpr registers
if (op_storeLoad.registerMem != PPC_REC_INVALID_REGISTER)
registersUsed->readNamedReg1 = op_storeLoad.registerMem;
registersUsed->readGPR1 = op_storeLoad.registerMem;
if (op_storeLoad.registerMem2 != PPC_REC_INVALID_REGISTER)
registersUsed->readNamedReg2 = op_storeLoad.registerMem2;
registersUsed->readGPR2 = 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;
registersUsed->readGPR3 = op_storeLoad.registerGQR;
break;
case PPCREC_FPR_LD_MODE_DOUBLE_INTO_PS0:
// PS1 remains the same
@ -319,14 +319,14 @@ void IMLInstruction::CheckRegisterUsage(IMLUsedRegisters* registersUsed) const
// fpr store operation
registersUsed->readFPR1 = op_storeLoad.registerData;
if (op_storeLoad.registerMem != PPC_REC_INVALID_REGISTER)
registersUsed->readNamedReg1 = op_storeLoad.registerMem;
registersUsed->readGPR1 = 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;
registersUsed->readGPR2 = op_storeLoad.registerGQR;
break;
default:
cemu_assert_debug(op_storeLoad.registerGQR == PPC_REC_INVALID_REGISTER);
@ -339,16 +339,16 @@ void IMLInstruction::CheckRegisterUsage(IMLUsedRegisters* registersUsed) const
registersUsed->readFPR1 = op_storeLoad.registerData;
// address is in gpr registers
if (op_storeLoad.registerMem != PPC_REC_INVALID_REGISTER)
registersUsed->readNamedReg1 = op_storeLoad.registerMem;
registersUsed->readGPR1 = op_storeLoad.registerMem;
if (op_storeLoad.registerMem2 != PPC_REC_INVALID_REGISTER)
registersUsed->readNamedReg2 = op_storeLoad.registerMem2;
registersUsed->readGPR2 = 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;
registersUsed->readGPR3 = op_storeLoad.registerGQR;
break;
default:
cemu_assert_debug(op_storeLoad.registerGQR == PPC_REC_INVALID_REGISTER);
@ -369,8 +369,8 @@ void IMLInstruction::CheckRegisterUsage(IMLUsedRegisters* registersUsed) const
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;
registersUsed->readFPR1 = op_fpr_r_r.regA;
registersUsed->writtenFPR1 = op_fpr_r_r.regR;
}
else if (
operation == PPCREC_IML_OP_FPR_COPY_BOTTOM_TO_BOTTOM ||
@ -383,9 +383,9 @@ void IMLInstruction::CheckRegisterUsage(IMLUsedRegisters* registersUsed) const
)
{
// 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;
registersUsed->readFPR1 = op_fpr_r_r.regA;
registersUsed->readFPR4 = op_fpr_r_r.regR;
registersUsed->writtenFPR1 = op_fpr_r_r.regR;
}
else if (operation == PPCREC_IML_OP_FPR_MULTIPLY_BOTTOM ||
operation == PPCREC_IML_OP_FPR_MULTIPLY_PAIR ||
@ -397,9 +397,9 @@ void IMLInstruction::CheckRegisterUsage(IMLUsedRegisters* registersUsed) const
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;
registersUsed->readFPR1 = op_fpr_r_r.regA;
registersUsed->readFPR2 = op_fpr_r_r.regR;
registersUsed->writtenFPR1 = op_fpr_r_r.regR;
}
else if (operation == PPCREC_IML_OP_FPR_FCMPU_BOTTOM ||
@ -407,8 +407,8 @@ void IMLInstruction::CheckRegisterUsage(IMLUsedRegisters* registersUsed) const
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;
registersUsed->readFPR1 = op_fpr_r_r.regA;
registersUsed->readFPR2 = op_fpr_r_r.regR;
}
else
cemu_assert_unimplemented();
@ -416,16 +416,16 @@ void IMLInstruction::CheckRegisterUsage(IMLUsedRegisters* registersUsed) const
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;
registersUsed->readFPR1 = op_fpr_r_r_r.regA;
registersUsed->readFPR2 = op_fpr_r_r_r.regB;
registersUsed->writtenFPR1 = op_fpr_r_r_r.regR;
// 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;
registersUsed->readFPR4 = op_fpr_r_r_r.regR;
break;
case PPCREC_IML_OP_FPR_SUB_PAIR:
break;
@ -436,15 +436,15 @@ void IMLInstruction::CheckRegisterUsage(IMLUsedRegisters* registersUsed) const
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;
registersUsed->readFPR1 = op_fpr_r_r_r_r.regA;
registersUsed->readFPR2 = op_fpr_r_r_r_r.regB;
registersUsed->readFPR3 = op_fpr_r_r_r_r.regC;
registersUsed->writtenFPR1 = op_fpr_r_r_r_r.regR;
// handle partially written result
switch (operation)
{
case PPCREC_IML_OP_FPR_SELECT_BOTTOM:
registersUsed->readFPR4 = op_fpr_r_r_r_r.registerResult;
registersUsed->readFPR4 = op_fpr_r_r_r_r.regR;
break;
case PPCREC_IML_OP_FPR_SUM0:
case PPCREC_IML_OP_FPR_SUM1:
@ -464,15 +464,15 @@ void IMLInstruction::CheckRegisterUsage(IMLUsedRegisters* registersUsed) const
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;
registersUsed->readFPR1 = op_fpr_r.regR;
registersUsed->writtenFPR1 = op_fpr_r.regR;
}
else
cemu_assert_unimplemented();
}
else if (type == PPCREC_IML_TYPE_FPR_COMPARE)
{
registersUsed->writtenNamedReg1 = op_fpr_compare.regR;
registersUsed->writtenGPR1 = op_fpr_compare.regR;
registersUsed->readFPR1 = op_fpr_compare.regA;
registersUsed->readFPR2 = op_fpr_compare.regB;
}
@ -511,29 +511,29 @@ void IMLInstruction::RewriteGPR(const std::unordered_map<IMLReg, IMLReg>& transl
{
if (type == PPCREC_IML_TYPE_R_NAME)
{
op_r_name.registerIndex = replaceRegisterMultiple(op_r_name.registerIndex, translationTable);
op_r_name.regR = replaceRegisterMultiple(op_r_name.regR, translationTable);
}
else if (type == PPCREC_IML_TYPE_NAME_R)
{
op_r_name.registerIndex = replaceRegisterMultiple(op_r_name.registerIndex, translationTable);
op_r_name.regR = replaceRegisterMultiple(op_r_name.regR, translationTable);
}
else if (type == PPCREC_IML_TYPE_R_R)
{
op_r_r.registerResult = replaceRegisterMultiple(op_r_r.registerResult, translationTable);
op_r_r.registerA = replaceRegisterMultiple(op_r_r.registerA, translationTable);
op_r_r.regR = replaceRegisterMultiple(op_r_r.regR, translationTable);
op_r_r.regA = replaceRegisterMultiple(op_r_r.regA, translationTable);
}
else if (type == PPCREC_IML_TYPE_R_S32)
{
op_r_immS32.registerIndex = replaceRegisterMultiple(op_r_immS32.registerIndex, translationTable);
op_r_immS32.regR = replaceRegisterMultiple(op_r_immS32.regR, translationTable);
}
else if (type == PPCREC_IML_TYPE_CONDITIONAL_R_S32)
{
op_conditional_r_s32.registerIndex = replaceRegisterMultiple(op_conditional_r_s32.registerIndex, translationTable);
op_conditional_r_s32.regR = replaceRegisterMultiple(op_conditional_r_s32.regR, translationTable);
}
else if (type == PPCREC_IML_TYPE_R_R_S32)
{
op_r_r_s32.registerResult = replaceRegisterMultiple(op_r_r_s32.registerResult, translationTable);
op_r_r_s32.registerA = replaceRegisterMultiple(op_r_r_s32.registerA, translationTable);
op_r_r_s32.regR = replaceRegisterMultiple(op_r_r_s32.regR, translationTable);
op_r_r_s32.regA = replaceRegisterMultiple(op_r_r_s32.regA, translationTable);
}
else if (type == PPCREC_IML_TYPE_R_R_S32_CARRY)
{
@ -543,9 +543,9 @@ void IMLInstruction::RewriteGPR(const std::unordered_map<IMLReg, IMLReg>& transl
}
else if (type == PPCREC_IML_TYPE_R_R_R)
{
op_r_r_r.registerResult = replaceRegisterMultiple(op_r_r_r.registerResult, translationTable);
op_r_r_r.registerA = replaceRegisterMultiple(op_r_r_r.registerA, translationTable);
op_r_r_r.registerB = replaceRegisterMultiple(op_r_r_r.registerB, translationTable);
op_r_r_r.regR = replaceRegisterMultiple(op_r_r_r.regR, translationTable);
op_r_r_r.regA = replaceRegisterMultiple(op_r_r_r.regA, translationTable);
op_r_r_r.regB = replaceRegisterMultiple(op_r_r_r.regB, translationTable);
}
else if (type == PPCREC_IML_TYPE_R_R_R_CARRY)
{
@ -556,18 +556,18 @@ void IMLInstruction::RewriteGPR(const std::unordered_map<IMLReg, IMLReg>& transl
}
else if (type == PPCREC_IML_TYPE_COMPARE)
{
op_compare.registerResult = replaceRegisterMultiple(op_compare.registerResult, translationTable);
op_compare.registerOperandA = replaceRegisterMultiple(op_compare.registerOperandA, translationTable);
op_compare.registerOperandB = replaceRegisterMultiple(op_compare.registerOperandB, translationTable);
op_compare.regR = replaceRegisterMultiple(op_compare.regR, translationTable);
op_compare.regA = replaceRegisterMultiple(op_compare.regA, translationTable);
op_compare.regB = replaceRegisterMultiple(op_compare.regB, translationTable);
}
else if (type == PPCREC_IML_TYPE_COMPARE_S32)
{
op_compare_s32.registerResult = replaceRegisterMultiple(op_compare_s32.registerResult, translationTable);
op_compare_s32.registerOperandA = replaceRegisterMultiple(op_compare_s32.registerOperandA, translationTable);
op_compare_s32.regR = replaceRegisterMultiple(op_compare_s32.regR, translationTable);
op_compare_s32.regA = replaceRegisterMultiple(op_compare_s32.regA, translationTable);
}
else if (type == PPCREC_IML_TYPE_CONDITIONAL_JUMP)
{
op_conditionalJump2.registerBool = replaceRegisterMultiple(op_conditionalJump2.registerBool, translationTable);
op_conditional_jump.registerBool = replaceRegisterMultiple(op_conditional_jump.registerBool, translationTable);
}
else if (type == PPCREC_IML_TYPE_CJUMP_CYCLE_CHECK || type == PPCREC_IML_TYPE_JUMP)
{
@ -775,11 +775,11 @@ void IMLInstruction::ReplaceFPRs(sint32 fprRegisterSearched[4], sint32 fprRegist
}
else if (type == PPCREC_IML_TYPE_FPR_R_NAME)
{
op_r_name.registerIndex = replaceRegisterMultiple(op_r_name.registerIndex, fprRegisterSearched, fprRegisterReplaced);
op_r_name.regR = replaceRegisterMultiple(op_r_name.regR, fprRegisterSearched, fprRegisterReplaced);
}
else if (type == PPCREC_IML_TYPE_FPR_NAME_R)
{
op_r_name.registerIndex = replaceRegisterMultiple(op_r_name.registerIndex, fprRegisterSearched, fprRegisterReplaced);
op_r_name.regR = replaceRegisterMultiple(op_r_name.regR, fprRegisterSearched, fprRegisterReplaced);
}
else if (type == PPCREC_IML_TYPE_FPR_LOAD)
{
@ -799,25 +799,25 @@ void IMLInstruction::ReplaceFPRs(sint32 fprRegisterSearched[4], sint32 fprRegist
}
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);
op_fpr_r_r.regR = replaceRegisterMultiple(op_fpr_r_r.regR, fprRegisterSearched, fprRegisterReplaced);
op_fpr_r_r.regA = replaceRegisterMultiple(op_fpr_r_r.regA, 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);
op_fpr_r_r_r.regR = replaceRegisterMultiple(op_fpr_r_r_r.regR, fprRegisterSearched, fprRegisterReplaced);
op_fpr_r_r_r.regA = replaceRegisterMultiple(op_fpr_r_r_r.regA, fprRegisterSearched, fprRegisterReplaced);
op_fpr_r_r_r.regB = replaceRegisterMultiple(op_fpr_r_r_r.regB, fprRegisterSearched, fprRegisterReplaced);
}
else if (type == PPCREC_IML_TYPE_FPR_R_R_R_R)
{
op_fpr_r_r_r_r.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);
op_fpr_r_r_r_r.regR = replaceRegisterMultiple(op_fpr_r_r_r_r.regR, fprRegisterSearched, fprRegisterReplaced);
op_fpr_r_r_r_r.regA = replaceRegisterMultiple(op_fpr_r_r_r_r.regA, fprRegisterSearched, fprRegisterReplaced);
op_fpr_r_r_r_r.regB = replaceRegisterMultiple(op_fpr_r_r_r_r.regB, fprRegisterSearched, fprRegisterReplaced);
op_fpr_r_r_r_r.regC = replaceRegisterMultiple(op_fpr_r_r_r_r.regC, fprRegisterSearched, fprRegisterReplaced);
}
else if (type == PPCREC_IML_TYPE_FPR_R)
{
op_fpr_r.registerResult = replaceRegisterMultiple(op_fpr_r.registerResult, fprRegisterSearched, fprRegisterReplaced);
op_fpr_r.regR = replaceRegisterMultiple(op_fpr_r.regR, fprRegisterSearched, fprRegisterReplaced);
}
else if (type == PPCREC_IML_TYPE_FPR_COMPARE)
{
@ -894,11 +894,11 @@ void IMLInstruction::ReplaceFPR(sint32 fprRegisterSearched, sint32 fprRegisterRe
}
else if (type == PPCREC_IML_TYPE_FPR_R_NAME)
{
op_r_name.registerIndex = replaceRegister(op_r_name.registerIndex, fprRegisterSearched, fprRegisterReplaced);
op_r_name.regR = replaceRegister(op_r_name.regR, fprRegisterSearched, fprRegisterReplaced);
}
else if (type == PPCREC_IML_TYPE_FPR_NAME_R)
{
op_r_name.registerIndex = replaceRegister(op_r_name.registerIndex, fprRegisterSearched, fprRegisterReplaced);
op_r_name.regR = replaceRegister(op_r_name.regR, fprRegisterSearched, fprRegisterReplaced);
}
else if (type == PPCREC_IML_TYPE_FPR_LOAD)
{
@ -918,25 +918,25 @@ void IMLInstruction::ReplaceFPR(sint32 fprRegisterSearched, sint32 fprRegisterRe
}
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);
op_fpr_r_r.regR = replaceRegister(op_fpr_r_r.regR, fprRegisterSearched, fprRegisterReplaced);
op_fpr_r_r.regA = replaceRegister(op_fpr_r_r.regA, 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);
op_fpr_r_r_r.regR = replaceRegister(op_fpr_r_r_r.regR, fprRegisterSearched, fprRegisterReplaced);
op_fpr_r_r_r.regA = replaceRegister(op_fpr_r_r_r.regA, fprRegisterSearched, fprRegisterReplaced);
op_fpr_r_r_r.regB = replaceRegister(op_fpr_r_r_r.regB, fprRegisterSearched, fprRegisterReplaced);
}
else if (type == PPCREC_IML_TYPE_FPR_R_R_R_R)
{
op_fpr_r_r_r_r.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);
op_fpr_r_r_r_r.regR = replaceRegister(op_fpr_r_r_r_r.regR, fprRegisterSearched, fprRegisterReplaced);
op_fpr_r_r_r_r.regA = replaceRegister(op_fpr_r_r_r_r.regA, fprRegisterSearched, fprRegisterReplaced);
op_fpr_r_r_r_r.regB = replaceRegister(op_fpr_r_r_r_r.regB, fprRegisterSearched, fprRegisterReplaced);
op_fpr_r_r_r_r.regC = replaceRegister(op_fpr_r_r_r_r.regC, fprRegisterSearched, fprRegisterReplaced);
}
else if (type == PPCREC_IML_TYPE_FPR_R)
{
op_fpr_r.registerResult = replaceRegister(op_fpr_r.registerResult, fprRegisterSearched, fprRegisterReplaced);
op_fpr_r.regR = replaceRegister(op_fpr_r.regR, fprRegisterSearched, fprRegisterReplaced);
}
else
{

View File

@ -1,5 +1,10 @@
#pragma once
using IMLReg = uint8;
inline constexpr IMLReg IMLREG_INVALID = (IMLReg)-1;
using IMLName = uint32;
enum
{
PPCREC_IML_OP_ASSIGN, // '=' operator
@ -65,8 +70,6 @@ enum
PPCREC_IML_OP_FPR_SUM1,
// working towards defining ops per-form
// R_R_R only
// R_R_S32 only
@ -110,9 +113,6 @@ enum class IMLCondition : uint8
UNSIGNED_GT,
UNSIGNED_LT,
SIGNED_OVERFLOW,
SIGNED_NOVERFLOW,
// floating point conditions
UNORDERED_GT, // a > b, false if either is NaN
UNORDERED_LT, // a < b, false if either is NaN
@ -171,7 +171,7 @@ enum
PPCREC_IML_TYPE_FPR_COMPARE, // r* = r* CMP[cond] r*
};
enum
enum // IMLName
{
PPCREC_NAME_NONE,
PPCREC_NAME_TEMPORARY = 1000,
@ -230,15 +230,16 @@ enum
struct IMLUsedRegisters
{
// GPR
union
{
struct
{
sint16 readNamedReg1;
sint16 readNamedReg2;
sint16 readNamedReg3;
sint16 writtenNamedReg1;
sint16 writtenNamedReg2;
IMLReg readGPR1;
IMLReg readGPR2;
IMLReg readGPR3;
IMLReg writtenGPR1;
IMLReg writtenGPR2;
};
};
// FPR
@ -247,59 +248,58 @@ struct IMLUsedRegisters
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;
IMLReg readFPR1;
IMLReg readFPR2;
IMLReg readFPR3;
IMLReg readFPR4;
IMLReg writtenFPR1;
};
//sint16 fpr[4];
};
bool IsRegWritten(sint16 imlReg) const // GPRs
bool IsGPRWritten(IMLReg imlReg) const
{
cemu_assert_debug(imlReg >= 0);
return writtenNamedReg1 == imlReg || writtenNamedReg2 == imlReg;
cemu_assert_debug(imlReg != IMLREG_INVALID);
return writtenGPR1 == imlReg || writtenGPR2 == imlReg;
}
template<typename Fn>
void ForEachWrittenGPR(Fn F)
void ForEachWrittenGPR(Fn F) const
{
if (writtenNamedReg1 >= 0)
F(writtenNamedReg1);
if (writtenNamedReg2 >= 0)
F(writtenNamedReg2);
if (writtenGPR1 != IMLREG_INVALID)
F(writtenGPR1);
if (writtenGPR2 != IMLREG_INVALID)
F(writtenGPR2);
}
template<typename Fn>
void ForEachReadGPR(Fn F)
void ForEachReadGPR(Fn F) const
{
if (readNamedReg1 >= 0)
F(readNamedReg1);
if (readNamedReg2 >= 0)
F(readNamedReg2);
if (readNamedReg3 >= 0)
F(readNamedReg3);
if (readGPR1 != IMLREG_INVALID)
F(readGPR1);
if (readGPR2 != IMLREG_INVALID)
F(readGPR2);
if (readGPR3 != IMLREG_INVALID)
F(readGPR3);
}
template<typename Fn>
void ForEachAccessedGPR(Fn F)
void ForEachAccessedGPR(Fn F) const
{
if (readNamedReg1 >= 0)
F(readNamedReg1, false);
if (readNamedReg2 >= 0)
F(readNamedReg2, false);
if (readNamedReg3 >= 0)
F(readNamedReg3, false);
if (writtenNamedReg1 >= 0)
F(writtenNamedReg1, true);
if (writtenNamedReg2 >= 0)
F(writtenNamedReg2, true);
if (readGPR1 != IMLREG_INVALID)
F(readGPR1, false);
if (readGPR2 != IMLREG_INVALID)
F(readGPR2, false);
if (readGPR3 != IMLREG_INVALID)
F(readGPR3, false);
if (writtenGPR1 != IMLREG_INVALID)
F(writtenGPR1, true);
if (writtenGPR2 != IMLREG_INVALID)
F(writtenGPR2, true);
}
bool HasFPRReg(sint16 imlReg) const
{
cemu_assert_debug(imlReg >= 0);
cemu_assert_debug(imlReg != IMLREG_INVALID);
if (readFPR1 == imlReg)
return true;
if (readFPR2 == imlReg)
@ -314,10 +314,6 @@ struct IMLUsedRegisters
}
};
using IMLReg = uint8;
inline constexpr IMLReg IMLREG_INVALID = (IMLReg)-1;
struct IMLInstruction
{
uint8 type;
@ -330,14 +326,14 @@ struct IMLInstruction
}padding;
struct
{
uint8 registerResult;
uint8 registerA;
IMLReg regR;
IMLReg regA;
}op_r_r;
struct
{
uint8 registerResult;
uint8 registerA;
uint8 registerB;
IMLReg regR;
IMLReg regA;
IMLReg regB;
}op_r_r_r;
struct
{
@ -348,25 +344,25 @@ struct IMLInstruction
}op_r_r_r_carry;
struct
{
uint8 registerResult;
uint8 registerA;
IMLReg regR;
IMLReg regA;
sint32 immS32;
}op_r_r_s32;
struct
{
IMLReg regR;
IMLReg regA;
sint32 immS32;
IMLReg regCarry;
sint32 immS32;
}op_r_r_s32_carry;
struct
{
uint8 registerIndex;
uint32 name;
IMLReg regR;
IMLName name;
}op_r_name; // alias op_name_r
struct
{
uint8 registerIndex;
IMLReg regR;
sint32 immS32;
}op_r_immS32;
struct
@ -377,10 +373,10 @@ struct IMLInstruction
}op_macro;
struct
{
uint8 registerData;
uint8 registerMem;
uint8 registerMem2;
uint8 registerGQR;
IMLReg registerData;
IMLReg registerMem;
IMLReg registerMem2;
IMLReg registerGQR;
uint8 copyWidth;
struct
{
@ -393,28 +389,25 @@ struct IMLInstruction
}op_storeLoad;
struct
{
uint8 registerResult;
uint8 registerOperand;
uint8 flags;
IMLReg regR;
IMLReg regA;
}op_fpr_r_r;
struct
{
uint8 registerResult;
uint8 registerOperandA;
uint8 registerOperandB;
uint8 flags;
IMLReg regR;
IMLReg regA;
IMLReg regB;
}op_fpr_r_r_r;
struct
{
uint8 registerResult;
uint8 registerOperandA;
uint8 registerOperandB;
uint8 registerOperandC;
uint8 flags;
IMLReg regR;
IMLReg regA;
IMLReg regB;
IMLReg regC;
}op_fpr_r_r_r_r;
struct
{
uint8 registerResult;
IMLReg regR;
}op_fpr_r;
struct
{
@ -425,41 +418,35 @@ struct IMLInstruction
}op_fpr_compare;
struct
{
uint8 crD; // crBitIndex (result)
uint8 crA; // crBitIndex
uint8 crB; // crBitIndex
}op_cr;
struct
{
uint8 registerResult; // stores the boolean result of the comparison
uint8 registerOperandA;
uint8 registerOperandB;
IMLReg regR; // stores the boolean result of the comparison
IMLReg regA;
IMLReg regB;
IMLCondition cond;
}op_compare;
struct
{
uint8 registerResult; // stores the boolean result of the comparison
uint8 registerOperandA;
IMLReg regR; // stores the boolean result of the comparison
IMLReg regA;
sint32 immS32;
IMLCondition cond;
}op_compare_s32;
struct
{
uint8 registerBool;
IMLReg registerBool;
bool mustBeTrue;
}op_conditionalJump2;
}op_conditional_jump;
struct
{
IMLReg regEA;
IMLReg regCompareValue;
IMLReg regWriteValue;
IMLReg regBoolOut; // boolean 0/1
IMLReg regBoolOut;
}op_atomic_compare_store;
// conditional operations (emitted if supported by target platform)
struct
{
// r_s32
uint8 registerIndex;
uint8 regR;
sint32 immS32;
// condition
uint8 crRegisterIndex;
@ -514,15 +501,15 @@ struct IMLInstruction
{
this->type = PPCREC_IML_TYPE_R_R;
this->operation = operation;
this->op_r_r.registerResult = registerResult;
this->op_r_r.registerA = registerA;
this->op_r_r.regR = registerResult;
this->op_r_r.regA = registerA;
}
void make_r_s32(uint32 operation, uint8 registerIndex, sint32 immS32)
{
this->type = PPCREC_IML_TYPE_R_S32;
this->operation = operation;
this->op_r_immS32.registerIndex = registerIndex;
this->op_r_immS32.regR = registerIndex;
this->op_r_immS32.immS32 = immS32;
}
@ -530,9 +517,9 @@ struct IMLInstruction
{
this->type = PPCREC_IML_TYPE_R_R_R;
this->operation = operation;
this->op_r_r_r.registerResult = registerResult;
this->op_r_r_r.registerA = registerA;
this->op_r_r_r.registerB = registerB;
this->op_r_r_r.regR = registerResult;
this->op_r_r_r.regA = registerA;
this->op_r_r_r.regB = registerB;
}
void make_r_r_r_carry(uint32 operation, uint8 registerResult, uint8 registerA, uint8 registerB, uint8 registerCarry)
@ -549,8 +536,8 @@ struct IMLInstruction
{
this->type = PPCREC_IML_TYPE_R_R_S32;
this->operation = operation;
this->op_r_r_s32.registerResult = registerResult;
this->op_r_r_s32.registerA = registerA;
this->op_r_r_s32.regR = registerResult;
this->op_r_r_s32.regA = registerA;
this->op_r_r_s32.immS32 = immS32;
}
@ -568,9 +555,9 @@ struct IMLInstruction
{
this->type = PPCREC_IML_TYPE_COMPARE;
this->operation = -999;
this->op_compare.registerResult = registerResult;
this->op_compare.registerOperandA = registerA;
this->op_compare.registerOperandB = registerB;
this->op_compare.regR = registerResult;
this->op_compare.regA = registerA;
this->op_compare.regB = registerB;
this->op_compare.cond = cond;
}
@ -578,8 +565,8 @@ struct IMLInstruction
{
this->type = PPCREC_IML_TYPE_COMPARE_S32;
this->operation = -999;
this->op_compare_s32.registerResult = registerResult;
this->op_compare_s32.registerOperandA = registerA;
this->op_compare_s32.regR = registerResult;
this->op_compare_s32.regA = registerA;
this->op_compare_s32.immS32 = immS32;
this->op_compare_s32.cond = cond;
}
@ -588,8 +575,8 @@ struct IMLInstruction
{
this->type = PPCREC_IML_TYPE_CONDITIONAL_JUMP;
this->operation = -999;
this->op_conditionalJump2.registerBool = registerBool;
this->op_conditionalJump2.mustBeTrue = mustBeTrue;
this->op_conditional_jump.registerBool = registerBool;
this->op_conditional_jump.mustBeTrue = mustBeTrue;
}
void make_jump()

View File

@ -6,6 +6,15 @@
#include "../PPCRecompilerIml.h"
#include "../BackendX64/BackendX64.h"
bool _RegExceedsFPRSpace(IMLReg r)
{
if (r == IMLREG_INVALID)
return false;
if ((uint32)r >= PPC_X64_FPR_USABLE_REGISTERS)
return true;
return false;
}
bool PPCRecompiler_reduceNumberOfFPRRegisters(ppcImlGenContext_t* ppcImlGenContext)
{
// only xmm0 to xmm14 may be used, xmm15 is reserved
@ -21,7 +30,7 @@ bool PPCRecompiler_reduceNumberOfFPRRegisters(ppcImlGenContext_t* ppcImlGenConte
IMLInstruction& imlInstructionItr = segIt->imlList[imlIndex];
if( imlInstructionItr.type == PPCREC_IML_TYPE_FPR_R_NAME || imlInstructionItr.type == PPCREC_IML_TYPE_FPR_NAME_R )
{
if( imlInstructionItr.op_r_name.registerIndex >= PPC_X64_FPR_USABLE_REGISTERS )
if(_RegExceedsFPRSpace(imlInstructionItr.op_r_name.regR))
{
imlInstructionItr.make_no_op();
}
@ -39,93 +48,96 @@ bool PPCRecompiler_reduceNumberOfFPRRegisters(ppcImlGenContext_t* ppcImlGenConte
while( true )
{
segIt->imlList[imlIndex].CheckRegisterUsage(&registersUsed);
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 )
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
sint32 fprToReplace = -1;
if( registersUsed.readFPR1 >= PPC_X64_FPR_USABLE_REGISTERS )
if(_RegExceedsFPRSpace(registersUsed.readFPR1) )
fprToReplace = registersUsed.readFPR1;
else if( registersUsed.readFPR2 >= PPC_X64_FPR_USABLE_REGISTERS )
else if(_RegExceedsFPRSpace(registersUsed.readFPR2) )
fprToReplace = registersUsed.readFPR2;
else if (registersUsed.readFPR3 >= PPC_X64_FPR_USABLE_REGISTERS)
else if (_RegExceedsFPRSpace(registersUsed.readFPR3))
fprToReplace = registersUsed.readFPR3;
else if (registersUsed.readFPR4 >= PPC_X64_FPR_USABLE_REGISTERS)
else if (_RegExceedsFPRSpace(registersUsed.readFPR4))
fprToReplace = registersUsed.readFPR4;
else if( registersUsed.writtenFPR1 >= PPC_X64_FPR_USABLE_REGISTERS )
else if(_RegExceedsFPRSpace(registersUsed.writtenFPR1) )
fprToReplace = registersUsed.writtenFPR1;
// generate mask of useable registers
uint8 useableRegisterMask = 0x7F; // lowest bit is fpr register 0
if( registersUsed.readFPR1 != -1 )
useableRegisterMask &= ~(1<<(registersUsed.readFPR1));
if( registersUsed.readFPR2 != -1 )
useableRegisterMask &= ~(1<<(registersUsed.readFPR2));
if (registersUsed.readFPR3 != -1)
useableRegisterMask &= ~(1 << (registersUsed.readFPR3));
if (registersUsed.readFPR4 != -1)
useableRegisterMask &= ~(1 << (registersUsed.readFPR4));
if( registersUsed.writtenFPR1 != -1 )
useableRegisterMask &= ~(1<<(registersUsed.writtenFPR1));
// get highest unused register index (0-6 range)
sint32 unusedRegisterIndex = -1;
for(sint32 f=0; f<PPC_X64_FPR_USABLE_REGISTERS; f++)
if (fprToReplace >= 0)
{
if( useableRegisterMask&(1<<f) )
// generate mask of useable registers
uint8 useableRegisterMask = 0x7F; // lowest bit is fpr register 0
if (registersUsed.readFPR1 != -1)
useableRegisterMask &= ~(1 << (registersUsed.readFPR1));
if (registersUsed.readFPR2 != -1)
useableRegisterMask &= ~(1 << (registersUsed.readFPR2));
if (registersUsed.readFPR3 != -1)
useableRegisterMask &= ~(1 << (registersUsed.readFPR3));
if (registersUsed.readFPR4 != -1)
useableRegisterMask &= ~(1 << (registersUsed.readFPR4));
if (registersUsed.writtenFPR1 != -1)
useableRegisterMask &= ~(1 << (registersUsed.writtenFPR1));
// get highest unused register index (0-6 range)
sint32 unusedRegisterIndex = -1;
for (sint32 f = 0; f < PPC_X64_FPR_USABLE_REGISTERS; f++)
{
unusedRegisterIndex = f;
if (useableRegisterMask & (1 << f))
{
unusedRegisterIndex = f;
}
}
}
if( unusedRegisterIndex == -1 )
assert_dbg();
// determine if the placeholder register is actually used (if not we must not load/store it)
uint32 unusedRegisterName = ppcImlGenContext->mappedFPRRegister[unusedRegisterIndex];
bool replacedRegisterIsUsed = true;
if( unusedRegisterName >= PPCREC_NAME_FPR0 && unusedRegisterName < (PPCREC_NAME_FPR0+32) )
{
replacedRegisterIsUsed = segIt->ppcFPRUsed[unusedRegisterName-PPCREC_NAME_FPR0];
}
// replace registers that are out of range
segIt->imlList[imlIndex].ReplaceFPR(fprToReplace, unusedRegisterIndex);
// add load/store name after instruction
PPCRecompiler_pushBackIMLInstructions(segIt, imlIndex+1, 2);
// add load/store before current instruction
PPCRecompiler_pushBackIMLInstructions(segIt, imlIndex, 2);
// name_unusedRegister = unusedRegister
IMLInstruction* imlInstructionItr = segIt->imlList.data() + (imlIndex + 0);
memset(imlInstructionItr, 0x00, sizeof(IMLInstruction));
if (replacedRegisterIsUsed)
{
imlInstructionItr->type = PPCREC_IML_TYPE_FPR_NAME_R;
imlInstructionItr->operation = PPCREC_IML_OP_ASSIGN;
imlInstructionItr->op_r_name.registerIndex = unusedRegisterIndex;
imlInstructionItr->op_r_name.name = ppcImlGenContext->mappedFPRRegister[unusedRegisterIndex];
}
else
imlInstructionItr->make_no_op();
imlInstructionItr = segIt->imlList.data() + (imlIndex + 1);
memset(imlInstructionItr, 0x00, sizeof(IMLInstruction));
imlInstructionItr->type = PPCREC_IML_TYPE_FPR_R_NAME;
imlInstructionItr->operation = PPCREC_IML_OP_ASSIGN;
imlInstructionItr->op_r_name.registerIndex = unusedRegisterIndex;
imlInstructionItr->op_r_name.name = ppcImlGenContext->mappedFPRRegister[fprToReplace];
// name_gprToReplace = unusedRegister
imlInstructionItr = segIt->imlList.data() + (imlIndex + 3);
memset(imlInstructionItr, 0x00, sizeof(IMLInstruction));
imlInstructionItr->type = PPCREC_IML_TYPE_FPR_NAME_R;
imlInstructionItr->operation = PPCREC_IML_OP_ASSIGN;
imlInstructionItr->op_r_name.registerIndex = unusedRegisterIndex;
imlInstructionItr->op_r_name.name = ppcImlGenContext->mappedFPRRegister[fprToReplace];
// unusedRegister = name_unusedRegister
imlInstructionItr = segIt->imlList.data() + (imlIndex + 4);
memset(imlInstructionItr, 0x00, sizeof(IMLInstruction));
if (replacedRegisterIsUsed)
{
if (unusedRegisterIndex == -1)
assert_dbg();
// determine if the placeholder register is actually used (if not we must not load/store it)
uint32 unusedRegisterName = ppcImlGenContext->mappedFPRRegister[unusedRegisterIndex];
bool replacedRegisterIsUsed = true;
if (unusedRegisterName >= PPCREC_NAME_FPR0 && unusedRegisterName < (PPCREC_NAME_FPR0 + 32))
{
replacedRegisterIsUsed = segIt->ppcFPRUsed[unusedRegisterName - PPCREC_NAME_FPR0];
}
// replace registers that are out of range
segIt->imlList[imlIndex].ReplaceFPR(fprToReplace, unusedRegisterIndex);
// add load/store name after instruction
PPCRecompiler_pushBackIMLInstructions(segIt, imlIndex + 1, 2);
// add load/store before current instruction
PPCRecompiler_pushBackIMLInstructions(segIt, imlIndex, 2);
// name_unusedRegister = unusedRegister
IMLInstruction* imlInstructionItr = segIt->imlList.data() + (imlIndex + 0);
memset(imlInstructionItr, 0x00, sizeof(IMLInstruction));
if (replacedRegisterIsUsed)
{
imlInstructionItr->type = PPCREC_IML_TYPE_FPR_NAME_R;
imlInstructionItr->operation = PPCREC_IML_OP_ASSIGN;
imlInstructionItr->op_r_name.regR = unusedRegisterIndex;
imlInstructionItr->op_r_name.name = ppcImlGenContext->mappedFPRRegister[unusedRegisterIndex];
}
else
imlInstructionItr->make_no_op();
imlInstructionItr = segIt->imlList.data() + (imlIndex + 1);
memset(imlInstructionItr, 0x00, sizeof(IMLInstruction));
imlInstructionItr->type = PPCREC_IML_TYPE_FPR_R_NAME;
imlInstructionItr->operation = PPCREC_IML_OP_ASSIGN;
imlInstructionItr->op_r_name.registerIndex = unusedRegisterIndex;
imlInstructionItr->op_r_name.name = ppcImlGenContext->mappedFPRRegister[unusedRegisterIndex];
imlInstructionItr->op_r_name.regR = unusedRegisterIndex;
imlInstructionItr->op_r_name.name = ppcImlGenContext->mappedFPRRegister[fprToReplace];
// name_gprToReplace = unusedRegister
imlInstructionItr = segIt->imlList.data() + (imlIndex + 3);
memset(imlInstructionItr, 0x00, sizeof(IMLInstruction));
imlInstructionItr->type = PPCREC_IML_TYPE_FPR_NAME_R;
imlInstructionItr->operation = PPCREC_IML_OP_ASSIGN;
imlInstructionItr->op_r_name.regR = unusedRegisterIndex;
imlInstructionItr->op_r_name.name = ppcImlGenContext->mappedFPRRegister[fprToReplace];
// unusedRegister = name_unusedRegister
imlInstructionItr = segIt->imlList.data() + (imlIndex + 4);
memset(imlInstructionItr, 0x00, sizeof(IMLInstruction));
if (replacedRegisterIsUsed)
{
imlInstructionItr->type = PPCREC_IML_TYPE_FPR_R_NAME;
imlInstructionItr->operation = PPCREC_IML_OP_ASSIGN;
imlInstructionItr->op_r_name.regR = unusedRegisterIndex;
imlInstructionItr->op_r_name.name = ppcImlGenContext->mappedFPRRegister[unusedRegisterIndex];
}
else
imlInstructionItr->make_no_op();
}
else
imlInstructionItr->make_no_op();
}
else
break;
@ -207,9 +219,9 @@ bool PPCRecompiler_manageFPRRegistersForSegment(ppcImlGenContext_t* ppcImlGenCon
if (idxInst.IsSuffixInstruction())
break;
idxInst.CheckRegisterUsage(&registersUsed);
sint32 fprMatch[4];
sint32 fprMatch[4]; // should be IMLReg, but this code is being dropped soon anyway
sint32 fprReplace[4];
fprMatch[0] = -1;
fprMatch[0] = -1; // should be IMLREG_INVALID
fprMatch[1] = -1;
fprMatch[2] = -1;
fprMatch[3] = -1;
@ -233,7 +245,7 @@ bool PPCRecompiler_manageFPRRegistersForSegment(ppcImlGenContext_t* ppcImlGenCon
virtualFpr = registersUsed.readFPR4;
else if (f == 4)
virtualFpr = registersUsed.writtenFPR1;
if( virtualFpr < 0 )
if(virtualFpr == IMLREG_INVALID)
continue;
cemu_assert_debug(virtualFpr < 64);
// check if this virtual FPR is already loaded in any real register
@ -257,7 +269,7 @@ bool PPCRecompiler_manageFPRRegistersForSegment(ppcImlGenContext_t* ppcImlGenCon
memset(imlInstructionTemp, 0x00, sizeof(IMLInstruction));
imlInstructionTemp->type = PPCREC_IML_TYPE_FPR_NAME_R;
imlInstructionTemp->operation = PPCREC_IML_OP_ASSIGN;
imlInstructionTemp->op_r_name.registerIndex = (uint8)(unloadRegMapping - rCtx.currentMapping);
imlInstructionTemp->op_r_name.regR = (uint8)(unloadRegMapping - rCtx.currentMapping);
imlInstructionTemp->op_r_name.name = ppcImlGenContext->mappedFPRRegister[unloadRegMapping->virtualReg];
idx++;
// update mapping
@ -273,7 +285,7 @@ bool PPCRecompiler_manageFPRRegistersForSegment(ppcImlGenContext_t* ppcImlGenCon
memset(imlInstructionTemp, 0x00, sizeof(IMLInstruction));
imlInstructionTemp->type = PPCREC_IML_TYPE_FPR_R_NAME;
imlInstructionTemp->operation = PPCREC_IML_OP_ASSIGN;
imlInstructionTemp->op_r_name.registerIndex = (uint8)(regMapping-rCtx.currentMapping);
imlInstructionTemp->op_r_name.regR = (uint8)(regMapping-rCtx.currentMapping);
imlInstructionTemp->op_r_name.name = ppcImlGenContext->mappedFPRRegister[virtualFpr];
idx++;
// update mapping
@ -333,7 +345,7 @@ bool PPCRecompiler_manageFPRRegistersForSegment(ppcImlGenContext_t* ppcImlGenCon
memset(imlInstructionTemp, 0x00, sizeof(IMLInstruction));
imlInstructionTemp->type = PPCREC_IML_TYPE_FPR_NAME_R;
imlInstructionTemp->operation = PPCREC_IML_OP_ASSIGN;
imlInstructionTemp->op_r_name.registerIndex = i;
imlInstructionTemp->op_r_name.regR = i;
imlInstructionTemp->op_r_name.name = ppcImlGenContext->mappedFPRRegister[rCtx.currentMapping[i].virtualReg];
idx++;
}
@ -357,15 +369,15 @@ bool PPCRecompiler_manageFPRRegisters(ppcImlGenContext_t* ppcImlGenContext)
*/
bool PPCRecompiler_trackRedundantNameLoadInstruction(ppcImlGenContext_t* ppcImlGenContext, IMLSegment* imlSegment, sint32 startIndex, IMLInstruction* nameStoreInstruction, sint32 scanDepth)
{
sint16 registerIndex = nameStoreInstruction->op_r_name.registerIndex;
IMLReg registerIndex = nameStoreInstruction->op_r_name.regR;
for(size_t i=startIndex; i<imlSegment->imlList.size(); i++)
{
IMLInstruction* imlInstruction = imlSegment->imlList.data() + i;
IMLUsedRegisters registersUsed;
imlInstruction->CheckRegisterUsage(&registersUsed);
if( registersUsed.readNamedReg1 == registerIndex || registersUsed.readNamedReg2 == registerIndex || registersUsed.readNamedReg3 == registerIndex )
if( registersUsed.readGPR1 == registerIndex || registersUsed.readGPR2 == registerIndex || registersUsed.readGPR3 == registerIndex )
return false;
if (registersUsed.IsRegWritten(registerIndex))
if (registersUsed.IsGPRWritten(registerIndex))
return true;
}
// todo: Scan next segment(s)
@ -377,7 +389,7 @@ bool PPCRecompiler_trackRedundantNameLoadInstruction(ppcImlGenContext_t* ppcImlG
*/
bool PPCRecompiler_trackRedundantFPRNameLoadInstruction(ppcImlGenContext_t* ppcImlGenContext, IMLSegment* imlSegment, sint32 startIndex, IMLInstruction* nameStoreInstruction, sint32 scanDepth)
{
sint16 registerIndex = nameStoreInstruction->op_r_name.registerIndex;
sint16 registerIndex = nameStoreInstruction->op_r_name.regR;
for(size_t i=startIndex; i<imlSegment->imlList.size(); i++)
{
IMLInstruction* imlInstruction = imlSegment->imlList.data() + i;
@ -397,13 +409,13 @@ bool PPCRecompiler_trackRedundantFPRNameLoadInstruction(ppcImlGenContext_t* ppcI
*/
bool PPCRecompiler_trackRedundantNameStoreInstruction(ppcImlGenContext_t* ppcImlGenContext, IMLSegment* imlSegment, sint32 startIndex, IMLInstruction* nameStoreInstruction, sint32 scanDepth)
{
sint16 registerIndex = nameStoreInstruction->op_r_name.registerIndex;
sint16 registerIndex = nameStoreInstruction->op_r_name.regR;
for(sint32 i=startIndex; i>=0; i--)
{
IMLInstruction* imlInstruction = imlSegment->imlList.data() + i;
IMLUsedRegisters registersUsed;
imlInstruction->CheckRegisterUsage(&registersUsed);
if( registersUsed.IsRegWritten(registerIndex) )
if( registersUsed.IsGPRWritten(registerIndex) )
{
if( imlSegment->imlList[i].type == PPCREC_IML_TYPE_R_NAME )
return true;
@ -456,7 +468,7 @@ bool PPCRecompiler_trackOverwrittenNameStoreInstruction(ppcImlGenContext_t* ppcI
*/
bool PPCRecompiler_trackRedundantFPRNameStoreInstruction(ppcImlGenContext_t* ppcImlGenContext, IMLSegment* imlSegment, sint32 startIndex, IMLInstruction* nameStoreInstruction, sint32 scanDepth)
{
sint16 registerIndex = nameStoreInstruction->op_r_name.registerIndex;
sint16 registerIndex = nameStoreInstruction->op_r_name.regR;
for(sint32 i=startIndex; i>=0; i--)
{
IMLInstruction* imlInstruction = imlSegment->imlList.data() + i;
@ -473,228 +485,6 @@ bool PPCRecompiler_trackRedundantFPRNameStoreInstruction(ppcImlGenContext_t* ppc
return false;
}
uint32 _PPCRecompiler_getCROverwriteMask(ppcImlGenContext_t* ppcImlGenContext, IMLSegment* imlSegment, uint32 currentOverwriteMask, uint32 currentReadMask, uint32 scanDepth)
{
// is any bit overwritten but not read?
uint32 overwriteMask = imlSegment->crBitsWritten&~imlSegment->crBitsInput;
currentOverwriteMask |= overwriteMask;
// next segment
if( imlSegment->nextSegmentIsUncertain == false && scanDepth < 3 )
{
uint32 nextSegmentOverwriteMask = 0;
if( imlSegment->nextSegmentBranchTaken && imlSegment->nextSegmentBranchNotTaken )
{
uint32 mask0 = _PPCRecompiler_getCROverwriteMask(ppcImlGenContext, imlSegment->nextSegmentBranchTaken, 0, 0, scanDepth+1);
uint32 mask1 = _PPCRecompiler_getCROverwriteMask(ppcImlGenContext, imlSegment->nextSegmentBranchNotTaken, 0, 0, scanDepth+1);
nextSegmentOverwriteMask = mask0&mask1;
}
else if( imlSegment->nextSegmentBranchNotTaken)
{
nextSegmentOverwriteMask = _PPCRecompiler_getCROverwriteMask(ppcImlGenContext, imlSegment->nextSegmentBranchNotTaken, 0, 0, scanDepth+1);
}
nextSegmentOverwriteMask &= ~imlSegment->crBitsRead;
currentOverwriteMask |= nextSegmentOverwriteMask;
}
else if (imlSegment->nextSegmentIsUncertain)
{
if (ppcImlGenContext->segmentList2.size() >= 5)
{
return 7; // for more complex functions we assume that CR is not passed on (hack)
}
}
return currentOverwriteMask;
}
/*
* Returns a mask of all CR bits that are overwritten (written but not read) in the segment and all it's following segments
* If the write state of a CR bit cannot be determined, it is returned as 0 (not overwritten)
*/
uint32 PPCRecompiler_getCROverwriteMask(ppcImlGenContext_t* ppcImlGenContext, IMLSegment* imlSegment)
{
__debugbreak(); // deprecated
if (imlSegment->nextSegmentIsUncertain)
{
return 0;
}
if( imlSegment->nextSegmentBranchTaken && imlSegment->nextSegmentBranchNotTaken )
{
uint32 mask0 = _PPCRecompiler_getCROverwriteMask(ppcImlGenContext, imlSegment->nextSegmentBranchTaken, 0, 0, 0);
uint32 mask1 = _PPCRecompiler_getCROverwriteMask(ppcImlGenContext, imlSegment->nextSegmentBranchNotTaken, 0, 0, 0);
return mask0&mask1; // only return bits that are overwritten in both branches
}
else if( imlSegment->nextSegmentBranchNotTaken )
{
uint32 mask = _PPCRecompiler_getCROverwriteMask(ppcImlGenContext, imlSegment->nextSegmentBranchNotTaken, 0, 0, 0);
return mask;
}
else
{
// not implemented
}
return 0;
}
void PPCRecompiler_removeRedundantCRUpdates(ppcImlGenContext_t* ppcImlGenContext)
{
__debugbreak(); // deprecated
//for (IMLSegment* segIt : ppcImlGenContext->segmentList2)
//{
// for(IMLInstruction& instIt : segIt->imlList)
// {
// if (instIt.type == PPCREC_IML_TYPE_CJUMP)
// {
// if (instIt.op_conditionalJump.condition != PPCREC_JUMP_CONDITION_NONE)
// {
// uint32 crBitFlag = 1 << (instIt.op_conditionalJump.crRegisterIndex * 4 + instIt.op_conditionalJump.crBitIndex);
// segIt->crBitsInput |= (crBitFlag&~segIt->crBitsWritten); // flag bits that have not already been written
// segIt->crBitsRead |= (crBitFlag);
// }
// }
// else if (instIt.type == PPCREC_IML_TYPE_CONDITIONAL_R_S32)
// {
// uint32 crBitFlag = 1 << (instIt.op_conditional_r_s32.crRegisterIndex * 4 + instIt.op_conditional_r_s32.crBitIndex);
// segIt->crBitsInput |= (crBitFlag&~segIt->crBitsWritten); // flag bits that have not already been written
// segIt->crBitsRead |= (crBitFlag);
// }
// else if (instIt.type == PPCREC_IML_TYPE_R_S32 && instIt.operation == PPCREC_IML_OP_MFCR)
// {
// segIt->crBitsRead |= 0xFFFFFFFF;
// }
// else if (instIt.type == PPCREC_IML_TYPE_R_S32 && instIt.operation == PPCREC_IML_OP_MTCRF)
// {
// segIt->crBitsWritten |= ppc_MTCRFMaskToCRBitMask((uint32)instIt.op_r_immS32.immS32);
// }
// else if( instIt.type == PPCREC_IML_TYPE_CR )
// {
// if (instIt.operation == PPCREC_IML_OP_CR_CLEAR ||
// instIt.operation == PPCREC_IML_OP_CR_SET)
// {
// uint32 crBitFlag = 1 << (instIt.op_cr.crD);
// segIt->crBitsWritten |= (crBitFlag & ~segIt->crBitsWritten);
// }
// else if (instIt.operation == PPCREC_IML_OP_CR_OR ||
// instIt.operation == PPCREC_IML_OP_CR_ORC ||
// instIt.operation == PPCREC_IML_OP_CR_AND ||
// instIt.operation == PPCREC_IML_OP_CR_ANDC)
// {
// uint32 crBitFlag = 1 << (instIt.op_cr.crD);
// segIt->crBitsWritten |= (crBitFlag & ~segIt->crBitsWritten);
// crBitFlag = 1 << (instIt.op_cr.crA);
// segIt->crBitsRead |= (crBitFlag & ~segIt->crBitsRead);
// crBitFlag = 1 << (instIt.op_cr.crB);
// segIt->crBitsRead |= (crBitFlag & ~segIt->crBitsRead);
// }
// else
// cemu_assert_unimplemented();
// }
// else if (IMLAnalyzer_CanTypeWriteCR(&instIt) && instIt.crRegister >= 0 && instIt.crRegister <= 7)
// {
// segIt->crBitsWritten |= (0xF<<(instIt.crRegister*4));
// }
// else if( (instIt.type == PPCREC_IML_TYPE_STORE || instIt.type == PPCREC_IML_TYPE_STORE_INDEXED) && instIt.op_storeLoad.copyWidth == PPC_REC_STORE_STWCX_MARKER )
// {
// // overwrites CR0
// segIt->crBitsWritten |= (0xF<<0);
// }
// }
//}
//// flag instructions that write to CR where we can ignore individual CR bits
//for (IMLSegment* segIt : ppcImlGenContext->segmentList2)
//{
// for (IMLInstruction& instIt : segIt->imlList)
// {
// if (IMLAnalyzer_CanTypeWriteCR(&instIt) && instIt.crRegister >= 0 && instIt.crRegister <= 7)
// {
// uint32 crBitFlags = 0xF<<((uint32)instIt.crRegister*4);
// uint32 crOverwriteMask = PPCRecompiler_getCROverwriteMask(ppcImlGenContext, segIt);
// uint32 crIgnoreMask = crOverwriteMask & ~segIt->crBitsRead;
// instIt.crIgnoreMask = crIgnoreMask;
// }
// }
//}
}
//bool PPCRecompiler_checkIfGPRIsModifiedInRange(ppcImlGenContext_t* ppcImlGenContext, IMLSegment* imlSegment, sint32 startIndex, sint32 endIndex, sint32 vreg)
//{
// IMLUsedRegisters registersUsed;
// for (sint32 i = startIndex; i <= endIndex; i++)
// {
// IMLInstruction* imlInstruction = imlSegment->imlList.data() + i;
// imlInstruction->CheckRegisterUsage(&registersUsed);
// if (registersUsed.IsRegWritten(vreg))
// return true;
// }
// return false;
//}
//sint32 PPCRecompiler_scanBackwardsForReusableRegister(ppcImlGenContext_t* ppcImlGenContext, IMLSegment* startSegment, sint32 startIndex, sint32 name)
//{
// // current segment
// sint32 currentIndex = startIndex;
// IMLSegment* currentSegment = startSegment;
// sint32 segmentIterateCount = 0;
// sint32 foundRegister = -1;
// while (true)
// {
// // stop scanning if segment is enterable
// if (currentSegment->isEnterable)
// return -1;
// while (currentIndex >= 0)
// {
// if (currentSegment->imlList[currentIndex].type == PPCREC_IML_TYPE_NAME_R && currentSegment->imlList[currentIndex].op_r_name.name == name)
// {
// foundRegister = currentSegment->imlList[currentIndex].op_r_name.registerIndex;
// break;
// }
// // previous instruction
// currentIndex--;
// }
// if (foundRegister >= 0)
// break;
// // continue at previous segment (if there is only one)
// if (segmentIterateCount >= 1)
// return -1;
// if (currentSegment->list_prevSegments.size() != 1)
// return -1;
// currentSegment = currentSegment->list_prevSegments[0];
// currentIndex = currentSegment->imlList.size() - 1;
// segmentIterateCount++;
// }
// // scan again to make sure the register is not modified inbetween
// currentIndex = startIndex;
// currentSegment = startSegment;
// segmentIterateCount = 0;
// IMLUsedRegisters registersUsed;
// while (true)
// {
// while (currentIndex >= 0)
// {
// // check if register is modified
// currentSegment->imlList[currentIndex].CheckRegisterUsage(&registersUsed);
// if (registersUsed.IsRegWritten(foundRegister))
// return -1;
// // check if end of scan reached
// if (currentSegment->imlList[currentIndex].type == PPCREC_IML_TYPE_NAME_R && currentSegment->imlList[currentIndex].op_r_name.name == name)
// {
// return foundRegister;
// }
// // previous instruction
// currentIndex--;
// }
// // continue at previous segment (if there is only one)
// if (segmentIterateCount >= 1)
// return -1;
// if (currentSegment->list_prevSegments.size() != 1)
// return -1;
// currentSegment = currentSegment->list_prevSegments[0];
// currentIndex = currentSegment->imlList.size() - 1;
// segmentIterateCount++;
// }
// return -1;
//}
void PPCRecompiler_optimizeDirectFloatCopiesScanForward(ppcImlGenContext_t* ppcImlGenContext, IMLSegment* imlSegment, sint32 imlIndexLoad, sint32 fprIndex)
{
IMLInstruction* imlInstructionLoad = imlSegment->imlList.data() + imlIndexLoad;
@ -820,13 +610,13 @@ void PPCRecompiler_optimizeDirectIntegerCopiesScanForward(ppcImlGenContext_t* pp
}
// check if GPR is accessed
imlInstruction->CheckRegisterUsage(&registersUsed);
if (registersUsed.readNamedReg1 == gprIndex ||
registersUsed.readNamedReg2 == gprIndex ||
registersUsed.readNamedReg3 == gprIndex)
if (registersUsed.readGPR1 == gprIndex ||
registersUsed.readGPR2 == gprIndex ||
registersUsed.readGPR3 == gprIndex)
{
break;
}
if (registersUsed.IsRegWritten(gprIndex))
if (registersUsed.IsGPRWritten(gprIndex))
return; // GPR overwritten, we don't need to byte swap anymore
}
if (foundMatch)

View File

@ -132,7 +132,7 @@ void PPCRecRA_insertGPRLoadInstruction(IMLSegment* imlSegment, sint32 insertInde
memset(imlInstructionItr, 0x00, sizeof(IMLInstruction));
imlInstructionItr->type = PPCREC_IML_TYPE_R_NAME;
imlInstructionItr->operation = PPCREC_IML_OP_ASSIGN;
imlInstructionItr->op_r_name.registerIndex = registerIndex;
imlInstructionItr->op_r_name.regR = registerIndex;
imlInstructionItr->op_r_name.name = registerName;
}
@ -145,7 +145,7 @@ void PPCRecRA_insertGPRLoadInstructions(IMLSegment* imlSegment, sint32 insertInd
IMLInstruction* imlInstructionItr = imlSegment->imlList.data() + (insertIndex + i);
imlInstructionItr->type = PPCREC_IML_TYPE_R_NAME;
imlInstructionItr->operation = PPCREC_IML_OP_ASSIGN;
imlInstructionItr->op_r_name.registerIndex = (uint8)loadList[i].registerIndex;
imlInstructionItr->op_r_name.regR = (uint8)loadList[i].registerIndex;
imlInstructionItr->op_r_name.name = (uint32)loadList[i].registerName;
}
}
@ -157,7 +157,7 @@ void PPCRecRA_insertGPRStoreInstruction(IMLSegment* imlSegment, sint32 insertInd
memset(imlInstructionItr, 0x00, sizeof(IMLInstruction));
imlInstructionItr->type = PPCREC_IML_TYPE_NAME_R;
imlInstructionItr->operation = PPCREC_IML_OP_ASSIGN;
imlInstructionItr->op_r_name.registerIndex = registerIndex;
imlInstructionItr->op_r_name.regR = registerIndex;
imlInstructionItr->op_r_name.name = registerName;
}
@ -171,7 +171,7 @@ void PPCRecRA_insertGPRStoreInstructions(IMLSegment* imlSegment, sint32 insertIn
memset(imlInstructionItr, 0x00, sizeof(IMLInstruction));
imlInstructionItr->type = PPCREC_IML_TYPE_NAME_R;
imlInstructionItr->operation = PPCREC_IML_OP_ASSIGN;
imlInstructionItr->op_r_name.registerIndex = (uint8)storeList[i].registerIndex;
imlInstructionItr->op_r_name.regR = (uint8)storeList[i].registerIndex;
imlInstructionItr->op_r_name.name = (uint32)storeList[i].registerName;
}
}

View File

@ -62,7 +62,7 @@ void PPCRecompilerImlGen_generateNewInstruction_conditional_r_s32(ppcImlGenConte
imlInstruction->type = PPCREC_IML_TYPE_CONDITIONAL_R_S32;
imlInstruction->operation = operation;
// r_s32 operation
imlInstruction->op_conditional_r_s32.registerIndex = registerIndex;
imlInstruction->op_conditional_r_s32.regR = registerIndex;
imlInstruction->op_conditional_r_s32.immS32 = immS32;
// condition
imlInstruction->op_conditional_r_s32.crRegisterIndex = crRegisterIndex;

View File

@ -70,9 +70,8 @@ void PPCRecompilerImlGen_generateNewInstruction_fpr_r_r(ppcImlGenContext_t* ppcI
IMLInstruction* imlInstruction = PPCRecompilerImlGen_generateNewEmptyInstruction(ppcImlGenContext);
imlInstruction->type = PPCREC_IML_TYPE_FPR_R_R;
imlInstruction->operation = operation;
imlInstruction->op_fpr_r_r.registerResult = registerResult;
imlInstruction->op_fpr_r_r.registerOperand = registerOperand;
imlInstruction->op_fpr_r_r.flags = 0;
imlInstruction->op_fpr_r_r.regR = registerResult;
imlInstruction->op_fpr_r_r.regA = registerOperand;
}
void PPCRecompilerImlGen_generateNewInstruction_fpr_r_r_r(ppcImlGenContext_t* ppcImlGenContext, sint32 operation, uint8 registerResult, uint8 registerOperand1, uint8 registerOperand2, sint32 crRegister=PPC_REC_INVALID_REGISTER)
@ -81,10 +80,9 @@ void PPCRecompilerImlGen_generateNewInstruction_fpr_r_r_r(ppcImlGenContext_t* pp
IMLInstruction* imlInstruction = PPCRecompilerImlGen_generateNewEmptyInstruction(ppcImlGenContext);
imlInstruction->type = PPCREC_IML_TYPE_FPR_R_R_R;
imlInstruction->operation = operation;
imlInstruction->op_fpr_r_r_r.registerResult = registerResult;
imlInstruction->op_fpr_r_r_r.registerOperandA = registerOperand1;
imlInstruction->op_fpr_r_r_r.registerOperandB = registerOperand2;
imlInstruction->op_fpr_r_r_r.flags = 0;
imlInstruction->op_fpr_r_r_r.regR = registerResult;
imlInstruction->op_fpr_r_r_r.regA = registerOperand1;
imlInstruction->op_fpr_r_r_r.regB = registerOperand2;
}
void PPCRecompilerImlGen_generateNewInstruction_fpr_r_r_r_r(ppcImlGenContext_t* ppcImlGenContext, sint32 operation, uint8 registerResult, uint8 registerOperandA, uint8 registerOperandB, uint8 registerOperandC, sint32 crRegister=PPC_REC_INVALID_REGISTER)
@ -93,11 +91,10 @@ void PPCRecompilerImlGen_generateNewInstruction_fpr_r_r_r_r(ppcImlGenContext_t*
IMLInstruction* imlInstruction = PPCRecompilerImlGen_generateNewEmptyInstruction(ppcImlGenContext);
imlInstruction->type = PPCREC_IML_TYPE_FPR_R_R_R_R;
imlInstruction->operation = operation;
imlInstruction->op_fpr_r_r_r_r.registerResult = registerResult;
imlInstruction->op_fpr_r_r_r_r.registerOperandA = registerOperandA;
imlInstruction->op_fpr_r_r_r_r.registerOperandB = registerOperandB;
imlInstruction->op_fpr_r_r_r_r.registerOperandC = registerOperandC;
imlInstruction->op_fpr_r_r_r_r.flags = 0;
imlInstruction->op_fpr_r_r_r_r.regR = registerResult;
imlInstruction->op_fpr_r_r_r_r.regA = registerOperandA;
imlInstruction->op_fpr_r_r_r_r.regB = registerOperandB;
imlInstruction->op_fpr_r_r_r_r.regC = registerOperandC;
}
void PPCRecompilerImlGen_generateNewInstruction_fpr_r(ppcImlGenContext_t* ppcImlGenContext, IMLInstruction* imlInstruction, sint32 operation, uint8 registerResult, sint32 crRegister)
@ -107,7 +104,7 @@ void PPCRecompilerImlGen_generateNewInstruction_fpr_r(ppcImlGenContext_t* ppcIml
imlInstruction = PPCRecompilerImlGen_generateNewEmptyInstruction(ppcImlGenContext);
imlInstruction->type = PPCREC_IML_TYPE_FPR_R;
imlInstruction->operation = operation;
imlInstruction->op_fpr_r.registerResult = registerResult;
imlInstruction->op_fpr_r.regR = registerResult;
}
/*