mirror of
https://github.com/izzy2lost/dolphin.git
synced 2026-06-19 01:16:48 -07:00
@@ -76,9 +76,9 @@ inline double ForceDouble(double d)
|
||||
|
||||
inline double Force25Bit(double d)
|
||||
{
|
||||
u64 di = *(u64*)&d;
|
||||
di = (di & 0xFFFFFFFFF8000000ULL) + (di & 0x8000000);
|
||||
return *(double*)&di;
|
||||
MathUtil::IntDouble x(d);
|
||||
x.i = (x.i & 0xFFFFFFFFF8000000ULL) + (x.i & 0x8000000);
|
||||
return x.d;
|
||||
}
|
||||
|
||||
// these functions allow globally modify operations behaviour
|
||||
|
||||
@@ -623,12 +623,13 @@ const u8* Jit64::DoJit(u32 em_address, PPCAnalyst::CodeBuffer *code_buf, JitBloc
|
||||
CMP(32, PPCSTATE(spr[SPR_GQR0 + gqr]), Imm8(0));
|
||||
FixupBranch failure = J_CC(CC_NZ, true);
|
||||
SwitchToFarCode();
|
||||
SetJumpTarget(failure);
|
||||
MOV(32, PPCSTATE(pc), Imm32(js.blockStart));
|
||||
ABI_PushRegistersAndAdjustStack({}, 0);
|
||||
ABI_CallFunctionC((void *)&JitInterface::CompileExceptionCheck, (u32)JitInterface::ExceptionType::EXCEPTIONS_PAIRED_QUANTIZE);
|
||||
ABI_PopRegistersAndAdjustStack({}, 0);
|
||||
JMP(asm_routines.dispatcher, true);
|
||||
SetJumpTarget(failure);
|
||||
MOV(32, PPCSTATE(pc), Imm32(js.blockStart));
|
||||
ABI_PushRegistersAndAdjustStack({}, 0);
|
||||
ABI_CallFunctionC((void *)&JitInterface::CompileExceptionCheck,
|
||||
(u32)JitInterface::ExceptionType::EXCEPTIONS_PAIRED_QUANTIZE);
|
||||
ABI_PopRegistersAndAdjustStack({}, 0);
|
||||
JMP(asm_routines.dispatcher, true);
|
||||
SwitchToNearCode();
|
||||
js.assumeNoPairedQuantize = true;
|
||||
}
|
||||
@@ -684,19 +685,21 @@ const u8* Jit64::DoJit(u32 em_address, PPCAnalyst::CodeBuffer *code_buf, JitBloc
|
||||
{
|
||||
TEST(32, PPCSTATE(Exceptions), Imm32(EXCEPTION_EXTERNAL_INT));
|
||||
FixupBranch extException = J_CC(CC_NZ, true);
|
||||
|
||||
SwitchToFarCode();
|
||||
SetJumpTarget(extException);
|
||||
TEST(32, PPCSTATE(msr), Imm32(0x0008000));
|
||||
FixupBranch noExtIntEnable = J_CC(CC_Z, true);
|
||||
TEST(32, M(&ProcessorInterface::m_InterruptCause), Imm32(ProcessorInterface::INT_CAUSE_CP | ProcessorInterface::INT_CAUSE_PE_TOKEN | ProcessorInterface::INT_CAUSE_PE_FINISH));
|
||||
FixupBranch noCPInt = J_CC(CC_Z, true);
|
||||
SetJumpTarget(extException);
|
||||
TEST(32, PPCSTATE(msr), Imm32(0x0008000));
|
||||
FixupBranch noExtIntEnable = J_CC(CC_Z, true);
|
||||
TEST(32, M(&ProcessorInterface::m_InterruptCause), Imm32(ProcessorInterface::INT_CAUSE_CP |
|
||||
ProcessorInterface::INT_CAUSE_PE_TOKEN |
|
||||
ProcessorInterface::INT_CAUSE_PE_FINISH));
|
||||
FixupBranch noCPInt = J_CC(CC_Z, true);
|
||||
|
||||
gpr.Flush(FLUSH_MAINTAIN_STATE);
|
||||
fpr.Flush(FLUSH_MAINTAIN_STATE);
|
||||
|
||||
MOV(32, PPCSTATE(pc), Imm32(ops[i].address));
|
||||
WriteExternalExceptionExit();
|
||||
gpr.Flush(FLUSH_MAINTAIN_STATE);
|
||||
fpr.Flush(FLUSH_MAINTAIN_STATE);
|
||||
|
||||
MOV(32, PPCSTATE(pc), Imm32(ops[i].address));
|
||||
WriteExternalExceptionExit();
|
||||
SwitchToNearCode();
|
||||
|
||||
SetJumpTarget(noCPInt);
|
||||
@@ -731,18 +734,19 @@ const u8* Jit64::DoJit(u32 em_address, PPCAnalyst::CodeBuffer *code_buf, JitBloc
|
||||
//This instruction uses FPU - needs to add FP exception bailout
|
||||
TEST(32, PPCSTATE(msr), Imm32(1 << 13)); // Test FP enabled bit
|
||||
FixupBranch b1 = J_CC(CC_Z, true);
|
||||
|
||||
SwitchToFarCode();
|
||||
SetJumpTarget(b1);
|
||||
gpr.Flush(FLUSH_MAINTAIN_STATE);
|
||||
fpr.Flush(FLUSH_MAINTAIN_STATE);
|
||||
|
||||
// If a FPU exception occurs, the exception handler will read
|
||||
// from PC. Update PC with the latest value in case that happens.
|
||||
MOV(32, PPCSTATE(pc), Imm32(ops[i].address));
|
||||
OR(32, PPCSTATE(Exceptions), Imm32(EXCEPTION_FPU_UNAVAILABLE));
|
||||
WriteExceptionExit();
|
||||
SetJumpTarget(b1);
|
||||
gpr.Flush(FLUSH_MAINTAIN_STATE);
|
||||
fpr.Flush(FLUSH_MAINTAIN_STATE);
|
||||
|
||||
// If a FPU exception occurs, the exception handler will read
|
||||
// from PC. Update PC with the latest value in case that happens.
|
||||
MOV(32, PPCSTATE(pc), Imm32(ops[i].address));
|
||||
OR(32, PPCSTATE(Exceptions), Imm32(EXCEPTION_FPU_UNAVAILABLE));
|
||||
WriteExceptionExit();
|
||||
SwitchToNearCode();
|
||||
|
||||
js.firstFPInstructionFound = true;
|
||||
}
|
||||
|
||||
@@ -802,29 +806,29 @@ const u8* Jit64::DoJit(u32 em_address, PPCAnalyst::CodeBuffer *code_buf, JitBloc
|
||||
}
|
||||
|
||||
SwitchToFarCode();
|
||||
if (!js.fastmemLoadStore)
|
||||
{
|
||||
exceptionHandlerAtLoc[js.fastmemLoadStore] = nullptr;
|
||||
SetJumpTarget(js.fixupExceptionHandler ? js.exceptionHandler : memException);
|
||||
}
|
||||
else
|
||||
{
|
||||
exceptionHandlerAtLoc[js.fastmemLoadStore] = GetWritableCodePtr();
|
||||
}
|
||||
if (!js.fastmemLoadStore)
|
||||
{
|
||||
exceptionHandlerAtLoc[js.fastmemLoadStore] = nullptr;
|
||||
SetJumpTarget(js.fixupExceptionHandler ? js.exceptionHandler : memException);
|
||||
}
|
||||
else
|
||||
{
|
||||
exceptionHandlerAtLoc[js.fastmemLoadStore] = GetWritableCodePtr();
|
||||
}
|
||||
|
||||
BitSet32 gprToFlush = BitSet32::AllTrue(32);
|
||||
BitSet32 fprToFlush = BitSet32::AllTrue(32);
|
||||
if (js.revertGprLoad >= 0)
|
||||
gprToFlush[js.revertGprLoad] = false;
|
||||
if (js.revertFprLoad >= 0)
|
||||
fprToFlush[js.revertFprLoad] = false;
|
||||
gpr.Flush(FLUSH_MAINTAIN_STATE, gprToFlush);
|
||||
fpr.Flush(FLUSH_MAINTAIN_STATE, fprToFlush);
|
||||
BitSet32 gprToFlush = BitSet32::AllTrue(32);
|
||||
BitSet32 fprToFlush = BitSet32::AllTrue(32);
|
||||
if (js.revertGprLoad >= 0)
|
||||
gprToFlush[js.revertGprLoad] = false;
|
||||
if (js.revertFprLoad >= 0)
|
||||
fprToFlush[js.revertFprLoad] = false;
|
||||
gpr.Flush(FLUSH_MAINTAIN_STATE, gprToFlush);
|
||||
fpr.Flush(FLUSH_MAINTAIN_STATE, fprToFlush);
|
||||
|
||||
// If a memory exception occurs, the exception handler will read
|
||||
// from PC. Update PC with the latest value in case that happens.
|
||||
MOV(32, PPCSTATE(pc), Imm32(ops[i].address));
|
||||
WriteExceptionExit();
|
||||
// If a memory exception occurs, the exception handler will read
|
||||
// from PC. Update PC with the latest value in case that happens.
|
||||
MOV(32, PPCSTATE(pc), Imm32(ops[i].address));
|
||||
WriteExceptionExit();
|
||||
SwitchToNearCode();
|
||||
}
|
||||
|
||||
|
||||
@@ -133,7 +133,7 @@ public:
|
||||
// Generates a branch that will check if a given bit of a CR register part
|
||||
// is set or not.
|
||||
Gen::FixupBranch JumpIfCRFieldBit(int field, int bit, bool jump_if_set = true);
|
||||
void SetFPRFIfNeeded(UGeckoInstruction inst, Gen::X64Reg xmm);
|
||||
void SetFPRFIfNeeded(Gen::X64Reg xmm);
|
||||
|
||||
void MultiplyImmediate(u32 imm, int a, int d, bool overflow);
|
||||
|
||||
@@ -240,7 +240,7 @@ public:
|
||||
void subfic(UGeckoInstruction inst);
|
||||
void subfx(UGeckoInstruction inst);
|
||||
|
||||
void twx(UGeckoInstruction inst);
|
||||
void twX(UGeckoInstruction inst);
|
||||
|
||||
void lXXx(UGeckoInstruction inst);
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -49,14 +49,14 @@ void Jit64::fp_tri_op(int d, int a, int b, bool reversible, bool single, void (X
|
||||
MOVDDUP(fpr.RX(d), fpr.R(d));
|
||||
}
|
||||
}
|
||||
SetFPRFIfNeeded(inst, fpr.RX(d));
|
||||
SetFPRFIfNeeded(fpr.RX(d));
|
||||
fpr.UnlockAll();
|
||||
}
|
||||
|
||||
// We can avoid calculating FPRF if it's not needed; every float operation resets it, so
|
||||
// if it's going to be clobbered in a future instruction before being read, we can just
|
||||
// not calculate it.
|
||||
void Jit64::SetFPRFIfNeeded(UGeckoInstruction inst, X64Reg xmm)
|
||||
void Jit64::SetFPRFIfNeeded(X64Reg xmm)
|
||||
{
|
||||
// As far as we know, the games that use this flag only need FPRF for fmul and fmadd, but
|
||||
// FPRF is fast enough in JIT that we might as well just enable it for every float instruction
|
||||
@@ -230,7 +230,7 @@ void Jit64::fmaddXX(UGeckoInstruction inst)
|
||||
{
|
||||
MOVSD(fpr.RX(d), R(XMM0));
|
||||
}
|
||||
SetFPRFIfNeeded(inst, fpr.RX(d));
|
||||
SetFPRFIfNeeded(fpr.RX(d));
|
||||
fpr.UnlockAll();
|
||||
}
|
||||
|
||||
@@ -497,7 +497,7 @@ void Jit64::frspx(UGeckoInstruction inst)
|
||||
MOVAPD(fpr.RX(d), fpr.R(b));
|
||||
ForceSinglePrecisionS(fpr.RX(d), fpr.RX(d));
|
||||
MOVDDUP(fpr.RX(d), fpr.R(d));
|
||||
SetFPRFIfNeeded(inst, fpr.RX(d));
|
||||
SetFPRFIfNeeded(fpr.RX(d));
|
||||
fpr.UnlockAll();
|
||||
}
|
||||
|
||||
@@ -515,7 +515,7 @@ void Jit64::frsqrtex(UGeckoInstruction inst)
|
||||
MOVAPD(XMM0, fpr.R(b));
|
||||
CALL((void *)asm_routines.frsqrte);
|
||||
MOVSD(fpr.R(d), XMM0);
|
||||
SetFPRFIfNeeded(inst, fpr.RX(d));
|
||||
SetFPRFIfNeeded(fpr.RX(d));
|
||||
fpr.UnlockAll();
|
||||
gpr.UnlockAllX();
|
||||
}
|
||||
@@ -534,7 +534,7 @@ void Jit64::fresx(UGeckoInstruction inst)
|
||||
MOVAPD(XMM0, fpr.R(b));
|
||||
CALL((void *)asm_routines.fres);
|
||||
MOVSD(fpr.R(d), XMM0);
|
||||
SetFPRFIfNeeded(inst, fpr.RX(d));
|
||||
SetFPRFIfNeeded(fpr.RX(d));
|
||||
fpr.UnlockAll();
|
||||
gpr.UnlockAllX();
|
||||
}
|
||||
|
||||
@@ -1161,7 +1161,6 @@ void Jit64::divwux(UGeckoInstruction inst)
|
||||
{
|
||||
GenerateConstantOverflow(true);
|
||||
}
|
||||
//MOV(32, R(RAX), gpr.R(d));
|
||||
FixupBranch end = J();
|
||||
SetJumpTarget(not_div_by_zero);
|
||||
DIV(32, gpr.R(b));
|
||||
@@ -1849,7 +1848,7 @@ void Jit64::cntlzwx(UGeckoInstruction inst)
|
||||
gpr.UnlockAll();
|
||||
}
|
||||
|
||||
void Jit64::twx(UGeckoInstruction inst)
|
||||
void Jit64::twX(UGeckoInstruction inst)
|
||||
{
|
||||
INSTRUCTION_START
|
||||
JITDISABLE(bJITIntegerOff);
|
||||
|
||||
@@ -336,15 +336,15 @@ void Jit64::dcbz(UGeckoInstruction inst)
|
||||
// Should this code ever run? I can't find any games that use DCBZ on non-physical addresses, but
|
||||
// supposedly there are, at least for some MMU titles. Let's be careful and support it to be sure.
|
||||
SwitchToFarCode();
|
||||
SetJumpTarget(slow);
|
||||
MOV(32, M(&PC), Imm32(jit->js.compilerPC));
|
||||
BitSet32 registersInUse = CallerSavedRegistersInUse();
|
||||
ABI_PushRegistersAndAdjustStack(registersInUse, 0);
|
||||
ABI_CallFunctionR((void *)&PowerPC::ClearCacheLine, RSCRATCH);
|
||||
ABI_PopRegistersAndAdjustStack(registersInUse, 0);
|
||||
FixupBranch exit = J(true);
|
||||
|
||||
SetJumpTarget(slow);
|
||||
MOV(32, M(&PC), Imm32(jit->js.compilerPC));
|
||||
BitSet32 registersInUse = CallerSavedRegistersInUse();
|
||||
ABI_PushRegistersAndAdjustStack(registersInUse, 0);
|
||||
ABI_CallFunctionR((void *)&PowerPC::ClearCacheLine, RSCRATCH);
|
||||
ABI_PopRegistersAndAdjustStack(registersInUse, 0);
|
||||
FixupBranch exit = J(true);
|
||||
SwitchToNearCode();
|
||||
|
||||
// Mask out the address so we don't write to MEM1 out of bounds
|
||||
// FIXME: Work out why the AGP disc writes out of bounds
|
||||
if (!SConfig::GetInstance().m_LocalCoreStartupParameter.bWii)
|
||||
|
||||
@@ -114,7 +114,7 @@ void Jit64::tri_op(int d, int a, int b, bool reversible, void (XEmitter::*avxOp)
|
||||
avx_op(avxOp, sseOp, fpr.RX(d), fpr.R(a), fpr.R(b), true, reversible);
|
||||
}
|
||||
ForceSinglePrecisionP(fpr.RX(d), fpr.RX(d));
|
||||
SetFPRFIfNeeded(inst, fpr.RX(d));
|
||||
SetFPRFIfNeeded(fpr.RX(d));
|
||||
fpr.UnlockAll();
|
||||
}
|
||||
|
||||
@@ -174,7 +174,7 @@ void Jit64::ps_sum(UGeckoInstruction inst)
|
||||
}
|
||||
fpr.BindToRegister(d, false);
|
||||
ForceSinglePrecisionP(fpr.RX(d), XMM0);
|
||||
SetFPRFIfNeeded(inst, fpr.RX(d));
|
||||
SetFPRFIfNeeded(fpr.RX(d));
|
||||
fpr.UnlockAll();
|
||||
}
|
||||
|
||||
@@ -206,7 +206,7 @@ void Jit64::ps_muls(UGeckoInstruction inst)
|
||||
MULPD(XMM0, fpr.R(a));
|
||||
fpr.BindToRegister(d, false);
|
||||
ForceSinglePrecisionP(fpr.RX(d), XMM0);
|
||||
SetFPRFIfNeeded(inst, fpr.RX(d));
|
||||
SetFPRFIfNeeded(fpr.RX(d));
|
||||
fpr.UnlockAll();
|
||||
}
|
||||
|
||||
@@ -265,7 +265,7 @@ void Jit64::ps_rsqrte(UGeckoInstruction inst)
|
||||
MOVLHPS(fpr.RX(d), XMM0);
|
||||
|
||||
ForceSinglePrecisionP(fpr.RX(d), fpr.RX(d));
|
||||
SetFPRFIfNeeded(inst, fpr.RX(d));
|
||||
SetFPRFIfNeeded(fpr.RX(d));
|
||||
fpr.UnlockAll();
|
||||
gpr.UnlockAllX();
|
||||
}
|
||||
@@ -292,7 +292,7 @@ void Jit64::ps_res(UGeckoInstruction inst)
|
||||
MOVLHPS(fpr.RX(d), XMM0);
|
||||
|
||||
ForceSinglePrecisionP(fpr.RX(d), fpr.RX(d));
|
||||
SetFPRFIfNeeded(inst, fpr.RX(d));
|
||||
SetFPRFIfNeeded(fpr.RX(d));
|
||||
fpr.UnlockAll();
|
||||
gpr.UnlockAllX();
|
||||
}
|
||||
@@ -387,7 +387,7 @@ void Jit64::ps_maddXX(UGeckoInstruction inst)
|
||||
|
||||
fpr.BindToRegister(d, false);
|
||||
ForceSinglePrecisionP(fpr.RX(d), XMM0);
|
||||
SetFPRFIfNeeded(inst, fpr.RX(d));
|
||||
SetFPRFIfNeeded(fpr.RX(d));
|
||||
fpr.UnlockAll();
|
||||
}
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -20,11 +20,8 @@ void Jit(u32 em_address)
|
||||
|
||||
u32 Helper_Mask(u8 mb, u8 me)
|
||||
{
|
||||
return (((mb > me) ?
|
||||
~(((u32)-1 >> mb) ^ ((me >= 31) ? 0 : (u32) -1 >> (me + 1)))
|
||||
:
|
||||
(((u32)-1 >> mb) ^ ((me >= 31) ? 0 : (u32) -1 >> (me + 1))))
|
||||
);
|
||||
u32 mask = ((u32)-1 >> mb) ^ (me >= 31 ? 0 : (u32)-1 >> (me + 1));
|
||||
return mb > me ? ~mask : mask;
|
||||
}
|
||||
|
||||
void LogGeneratedX86(int size, PPCAnalyst::CodeBuffer *code_buffer, const u8 *normalEntry, JitBlock *b)
|
||||
@@ -45,11 +42,7 @@ void LogGeneratedX86(int size, PPCAnalyst::CodeBuffer *code_buffer, const u8 *no
|
||||
while ((u8*)disasmPtr < end)
|
||||
{
|
||||
char sptr[1000] = "";
|
||||
#if _ARCH_64
|
||||
disasmPtr += x64disasm.disasm64(disasmPtr, disasmPtr, (u8*)disasmPtr, sptr);
|
||||
#else
|
||||
disasmPtr += x64disasm.disasm32(disasmPtr, disasmPtr, (u8*)disasmPtr, sptr);
|
||||
#endif
|
||||
DEBUG_LOG(DYNA_REC,"IR_X86 x86: %s", sptr);
|
||||
}
|
||||
|
||||
|
||||
@@ -895,22 +895,22 @@ void EmuCodeBlock::ConvertDoubleToSingle(X64Reg dst, X64Reg src)
|
||||
CVTSD2SS(dst, R(src));
|
||||
|
||||
SwitchToFarCode();
|
||||
SetJumpTarget(nanConversion);
|
||||
MOVQ_xmm(R(RSCRATCH), src);
|
||||
// Put the quiet bit into CF.
|
||||
BT(64, R(RSCRATCH), Imm8(51));
|
||||
CVTSD2SS(dst, R(src));
|
||||
FixupBranch continue1 = J_CC(CC_C, true);
|
||||
// Clear the quiet bit of the SNaN, which was 0 (signalling) but got set to 1 (quiet) by conversion.
|
||||
ANDPS(dst, M(&single_qnan_bit));
|
||||
FixupBranch continue2 = J(true);
|
||||
SetJumpTarget(nanConversion);
|
||||
MOVQ_xmm(R(RSCRATCH), src);
|
||||
// Put the quiet bit into CF.
|
||||
BT(64, R(RSCRATCH), Imm8(51));
|
||||
CVTSD2SS(dst, R(src));
|
||||
FixupBranch continue1 = J_CC(CC_C, true);
|
||||
// Clear the quiet bit of the SNaN, which was 0 (signalling) but got set to 1 (quiet) by conversion.
|
||||
ANDPS(dst, M(&single_qnan_bit));
|
||||
FixupBranch continue2 = J(true);
|
||||
|
||||
SetJumpTarget(denormalConversion);
|
||||
MOVSD(M(&temp64), src);
|
||||
FLD(64, M(&temp64));
|
||||
FSTP(32, M(&temp32));
|
||||
MOVSS(dst, M(&temp32));
|
||||
FixupBranch continue3 = J(true);
|
||||
SetJumpTarget(denormalConversion);
|
||||
MOVSD(M(&temp64), src);
|
||||
FLD(64, M(&temp64));
|
||||
FSTP(32, M(&temp32));
|
||||
MOVSS(dst, M(&temp32));
|
||||
FixupBranch continue3 = J(true);
|
||||
SwitchToNearCode();
|
||||
|
||||
SetJumpTarget(continue1);
|
||||
@@ -941,11 +941,11 @@ void EmuCodeBlock::ConvertSingleToDouble(X64Reg dst, X64Reg src, bool src_is_gpr
|
||||
FixupBranch nanConversion = J_CC(CC_P, true);
|
||||
|
||||
SwitchToFarCode();
|
||||
SetJumpTarget(nanConversion);
|
||||
TEST(32, R(gprsrc), Imm32(0x00400000));
|
||||
FixupBranch continue1 = J_CC(CC_NZ, true);
|
||||
ANDPD(dst, M(&double_qnan_bit));
|
||||
FixupBranch continue2 = J(true);
|
||||
SetJumpTarget(nanConversion);
|
||||
TEST(32, R(gprsrc), Imm32(0x00400000));
|
||||
FixupBranch continue1 = J_CC(CC_NZ, true);
|
||||
ANDPD(dst, M(&double_qnan_bit));
|
||||
FixupBranch continue2 = J(true);
|
||||
SwitchToNearCode();
|
||||
|
||||
SetJumpTarget(continue1);
|
||||
|
||||
@@ -71,7 +71,6 @@ enum
|
||||
OPTYPE_SINGLEFP,
|
||||
OPTYPE_LOADPS ,
|
||||
OPTYPE_STOREPS ,
|
||||
OPTYPE_FPU ,
|
||||
OPTYPE_PS ,
|
||||
OPTYPE_DCACHE ,
|
||||
OPTYPE_ICACHE ,
|
||||
|
||||
Reference in New Issue
Block a user