Use faster CheckGatherPipe from JIT.

We don't need to profile explicit calls to CheckGatherPipe: we aleady know
where they are. Skip profiling, and explciitly insert an exception check.

While I'm here, get rid of unused code in JitIL.
This commit is contained in:
magumagu
2015-01-30 15:45:51 -08:00
parent a277172b49
commit 5a3f75f5cf
6 changed files with 76 additions and 64 deletions

View File

@ -55,37 +55,50 @@ void ResetGatherPipe()
m_gatherPipeCount = 0; m_gatherPipeCount = 0;
} }
static void UpdateGatherPipe()
{
u32 cnt;
u8* curMem = Memory::GetPointer(ProcessorInterface::Fifo_CPUWritePointer);
for (cnt = 0; m_gatherPipeCount >= GATHER_PIPE_SIZE; cnt += GATHER_PIPE_SIZE)
{
// copy the GatherPipe
memcpy(curMem, m_gatherPipe + cnt, GATHER_PIPE_SIZE);
m_gatherPipeCount -= GATHER_PIPE_SIZE;
// increase the CPUWritePointer
if (ProcessorInterface::Fifo_CPUWritePointer == ProcessorInterface::Fifo_CPUEnd)
{
ProcessorInterface::Fifo_CPUWritePointer = ProcessorInterface::Fifo_CPUBase;
curMem = Memory::GetPointer(ProcessorInterface::Fifo_CPUWritePointer);
}
else
{
curMem += GATHER_PIPE_SIZE;
ProcessorInterface::Fifo_CPUWritePointer += GATHER_PIPE_SIZE;
}
g_video_backend->Video_GatherPipeBursted();
}
// move back the spill bytes
memmove(m_gatherPipe, m_gatherPipe + cnt, m_gatherPipeCount);
}
void FastCheckGatherPipe()
{
if (m_gatherPipeCount >= GATHER_PIPE_SIZE)
{
UpdateGatherPipe();
}
}
void CheckGatherPipe() void CheckGatherPipe()
{ {
if (m_gatherPipeCount >= GATHER_PIPE_SIZE) if (m_gatherPipeCount >= GATHER_PIPE_SIZE)
{ {
u32 cnt; UpdateGatherPipe();
u8* curMem = Memory::GetPointer(ProcessorInterface::Fifo_CPUWritePointer);
for (cnt = 0; m_gatherPipeCount >= GATHER_PIPE_SIZE; cnt += GATHER_PIPE_SIZE)
{
// copy the GatherPipe
memcpy(curMem, m_gatherPipe + cnt, GATHER_PIPE_SIZE);
m_gatherPipeCount -= GATHER_PIPE_SIZE;
// increase the CPUWritePointer // Profile where slow FIFO writes are occurring.
if (ProcessorInterface::Fifo_CPUWritePointer == ProcessorInterface::Fifo_CPUEnd)
{
ProcessorInterface::Fifo_CPUWritePointer = ProcessorInterface::Fifo_CPUBase;
curMem = Memory::GetPointer(ProcessorInterface::Fifo_CPUWritePointer);
}
else
{
curMem += GATHER_PIPE_SIZE;
ProcessorInterface::Fifo_CPUWritePointer += GATHER_PIPE_SIZE;
}
g_video_backend->Video_GatherPipeBursted();
}
// move back the spill bytes
memmove(m_gatherPipe, m_gatherPipe + cnt, m_gatherPipeCount);
// Profile where the FIFO writes are occurring.
JitInterface::CompileExceptionCheck(JitInterface::ExceptionType::EXCEPTIONS_FIFO_WRITE); JitInterface::CompileExceptionCheck(JitInterface::ExceptionType::EXCEPTIONS_FIFO_WRITE);
} }
} }

View File

@ -27,6 +27,7 @@ void DoState(PointerWrap &p);
// ResetGatherPipe // ResetGatherPipe
void ResetGatherPipe(); void ResetGatherPipe();
void CheckGatherPipe(); void CheckGatherPipe();
void FastCheckGatherPipe();
bool IsEmpty(); bool IsEmpty();

View File

@ -300,7 +300,7 @@ bool Jit64::Cleanup()
if (jo.optimizeGatherPipe && js.fifoBytesThisBlock > 0) if (jo.optimizeGatherPipe && js.fifoBytesThisBlock > 0)
{ {
ABI_PushRegistersAndAdjustStack({}, 0); ABI_PushRegistersAndAdjustStack({}, 0);
ABI_CallFunction((void *)&GPFifo::CheckGatherPipe); ABI_CallFunction((void *)&GPFifo::FastCheckGatherPipe);
ABI_PopRegistersAndAdjustStack({}, 0); ABI_PopRegistersAndAdjustStack({}, 0);
did_something = true; did_something = true;
} }
@ -665,14 +665,44 @@ const u8* Jit64::DoJit(u32 em_address, PPCAnalyst::CodeBuffer *code_buf, JitBloc
js.isLastInstruction = true; js.isLastInstruction = true;
} }
// Gather pipe writes using a non-immediate address are discovered by profiling.
bool gatherPipeIntCheck = jit->js.fifoWriteAddresses.find(ops[i].address) != jit->js.fifoWriteAddresses.end();
// Gather pipe writes using an immediate address are explicitly tracked.
if (jo.optimizeGatherPipe && js.fifoBytesThisBlock >= 32) if (jo.optimizeGatherPipe && js.fifoBytesThisBlock >= 32)
{ {
js.fifoBytesThisBlock -= 32; js.fifoBytesThisBlock -= 32;
MOV(32, PPCSTATE(pc), Imm32(jit->js.compilerPC)); // Helps external systems know which instruction triggered the write
BitSet32 registersInUse = CallerSavedRegistersInUse(); BitSet32 registersInUse = CallerSavedRegistersInUse();
ABI_PushRegistersAndAdjustStack(registersInUse, 0); ABI_PushRegistersAndAdjustStack(registersInUse, 0);
ABI_CallFunction((void *)&GPFifo::CheckGatherPipe); ABI_CallFunction((void *)&GPFifo::FastCheckGatherPipe);
ABI_PopRegistersAndAdjustStack(registersInUse, 0); ABI_PopRegistersAndAdjustStack(registersInUse, 0);
gatherPipeIntCheck = true;
}
// Gather pipe writes can generate an exception; add an exception check.
// TODO: This doesn't really match hardware; the CP interrupt is
// asynchronous.
if (gatherPipeIntCheck)
{
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);
gpr.Flush(FLUSH_MAINTAIN_STATE);
fpr.Flush(FLUSH_MAINTAIN_STATE);
MOV(32, PPCSTATE(pc), Imm32(ops[i].address));
WriteExternalExceptionExit();
SwitchToNearCode();
SetJumpTarget(noCPInt);
SetJumpTarget(noExtIntEnable);
} }
u32 function = HLE::GetFunctionIndex(ops[i].address); u32 function = HLE::GetFunctionIndex(ops[i].address);
@ -718,33 +748,6 @@ const u8* Jit64::DoJit(u32 em_address, PPCAnalyst::CodeBuffer *code_buf, JitBloc
js.firstFPInstructionFound = true; js.firstFPInstructionFound = true;
} }
// Add an external exception check if the instruction writes to the FIFO.
if (jit->js.fifoWriteAddresses.find(ops[i].address) != jit->js.fifoWriteAddresses.end())
{
TEST(32, PPCSTATE(Exceptions), Imm32(EXCEPTION_ISI | EXCEPTION_PROGRAM | EXCEPTION_SYSCALL | EXCEPTION_FPU_UNAVAILABLE | EXCEPTION_DSI | EXCEPTION_ALIGNMENT));
FixupBranch clearInt = J_CC(CC_NZ);
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);
gpr.Flush(FLUSH_MAINTAIN_STATE);
fpr.Flush(FLUSH_MAINTAIN_STATE);
MOV(32, PPCSTATE(pc), Imm32(ops[i].address));
WriteExternalExceptionExit();
SwitchToNearCode();
SetJumpTarget(noCPInt);
SetJumpTarget(noExtIntEnable);
SetJumpTarget(clearInt);
}
if (SConfig::GetInstance().m_LocalCoreStartupParameter.bEnableDebugging && breakpoints.IsAddressBreakPoint(ops[i].address) && GetState() != CPU_STEPPING) if (SConfig::GetInstance().m_LocalCoreStartupParameter.bEnableDebugging && breakpoints.IsAddressBreakPoint(ops[i].address) && GetState() != CPU_STEPPING)
{ {
// Turn off block linking if there are breakpoints so that the Step Over command does not link this block. // Turn off block linking if there are breakpoints so that the Step Over command does not link this block.

View File

@ -361,11 +361,6 @@ static void ImHere()
void JitIL::Cleanup() void JitIL::Cleanup()
{ {
if (jo.optimizeGatherPipe && js.fifoBytesThisBlock > 0)
{
ABI_CallFunction((void *)&GPFifo::CheckGatherPipe);
}
// SPEED HACK: MMCR0/MMCR1 should be checked at run-time, not at compile time. // SPEED HACK: MMCR0/MMCR1 should be checked at run-time, not at compile time.
if (MMCR0.Hex || MMCR1.Hex) if (MMCR0.Hex || MMCR1.Hex)
ABI_CallFunctionCCC((void *)&PowerPC::UpdatePerformanceMonitor, js.downcountAmount, jit->js.numLoadStoreInst, jit->js.numFloatingPointInst); ABI_CallFunctionCCC((void *)&PowerPC::UpdatePerformanceMonitor, js.downcountAmount, jit->js.numLoadStoreInst, jit->js.numFloatingPointInst);

View File

@ -123,7 +123,7 @@ void JitArm::Cleanup()
if (jo.optimizeGatherPipe && js.fifoBytesThisBlock > 0) if (jo.optimizeGatherPipe && js.fifoBytesThisBlock > 0)
{ {
PUSH(4, R0, R1, R2, R3); PUSH(4, R0, R1, R2, R3);
QuickCallFunction(R14, (void*)&GPFifo::CheckGatherPipe); QuickCallFunction(R14, (void*)&GPFifo::FastCheckGatherPipe);
POP(4, R0, R1, R2, R3); POP(4, R0, R1, R2, R3);
} }
} }
@ -465,7 +465,7 @@ const u8* JitArm::DoJit(u32 em_address, PPCAnalyst::CodeBuffer *code_buf, JitBlo
{ {
js.fifoBytesThisBlock -= 32; js.fifoBytesThisBlock -= 32;
PUSH(4, R0, R1, R2, R3); PUSH(4, R0, R1, R2, R3);
QuickCallFunction(R14, (void*)&GPFifo::CheckGatherPipe); QuickCallFunction(R14, (void*)&GPFifo::FastCheckGatherPipe);
POP(4, R0, R1, R2, R3); POP(4, R0, R1, R2, R3);
} }

View File

@ -292,7 +292,7 @@ const u8* JitArm64::DoJit(u32 em_address, PPCAnalyst::CodeBuffer *code_buf, JitB
regs_in_use[W30] = 0; regs_in_use[W30] = 0;
ABI_PushRegisters(regs_in_use); ABI_PushRegisters(regs_in_use);
MOVI2R(X30, (u64)&GPFifo::CheckGatherPipe); MOVI2R(X30, (u64)&GPFifo::FastCheckGatherPipe);
BLR(X30); BLR(X30);
ABI_PopRegisters(regs_in_use); ABI_PopRegisters(regs_in_use);
gpr.Unlock(W30); gpr.Unlock(W30);