Merge branch 'Fast-EE'

* Fast-EE:
  Forced the exception check only for ARAM DMA transfers. Removed the Eternal Darkness boot hack and replaced it with an exception check.
  Reverted rd76ca5783743 as it was made obsolete by r1d550f4496e4.
  Removed the tracking of the FIFO Writes as it was made obsolete by r1d550f4496e4.
  Forced the external exception check to occur sooner by changing the downcount.
This commit is contained in:
skidau 2013-03-26 08:24:21 +11:00
commit b00201dcbd
11 changed files with 22 additions and 81 deletions

View File

@ -413,6 +413,15 @@ void SetMaximumSlice(int maximumSliceLength)
maxSliceLength = maximumSliceLength; maxSliceLength = maximumSliceLength;
} }
void ForceExceptionCheck(int cycles)
{
if (downcount > cycles)
{
slicelength -= (downcount - cycles); // Account for cycles already executed by adjusting the slicelength
downcount = cycles;
}
}
void ResetSliceLength() void ResetSliceLength()
{ {
maxSliceLength = MAX_SLICE_LENGTH; maxSliceLength = MAX_SLICE_LENGTH;
@ -468,7 +477,6 @@ void MoveEvents()
void Advance() void Advance()
{ {
MoveEvents(); MoveEvents();
int cyclesExecuted = slicelength - downcount; int cyclesExecuted = slicelength - downcount;

View File

@ -92,6 +92,8 @@ void SetFakeTBStartValue(u64 val);
u64 GetFakeTBStartTicks(); u64 GetFakeTBStartTicks();
void SetFakeTBStartTicks(u64 val); void SetFakeTBStartTicks(u64 val);
void ForceExceptionCheck(int cycles);
extern int downcount; extern int downcount;
extern int slicelength; extern int slicelength;

View File

@ -696,6 +696,10 @@ void Do_ARAM_DMA()
g_dspState.DSPControl.DMAState = 1; g_dspState.DSPControl.DMAState = 1;
CoreTiming::ScheduleEvent_Threadsafe(0, et_GenerateDSPInterrupt, INT_ARAM | (1<<16)); CoreTiming::ScheduleEvent_Threadsafe(0, et_GenerateDSPInterrupt, INT_ARAM | (1<<16));
// Force an early exception check. Fixes RE2 audio.
if (g_arDMA.Cnt.count == 4096)
CoreTiming::ForceExceptionCheck(100);
// Real hardware DMAs in 32byte chunks, but we can get by with 8byte chunks // Real hardware DMAs in 32byte chunks, but we can get by with 8byte chunks
if (g_arDMA.Cnt.dir) if (g_arDMA.Cnt.dir)
{ {

View File

@ -96,20 +96,6 @@ void STACKALIGN CheckGatherPipe()
// move back the spill bytes // move back the spill bytes
memmove(m_gatherPipe, m_gatherPipe + cnt, m_gatherPipeCount); memmove(m_gatherPipe, m_gatherPipe + cnt, m_gatherPipeCount);
// Profile where the FIFO writes are occurring.
if (jit && PC != 0 && (jit->js.fifoWriteAddresses.find(PC)) == (jit->js.fifoWriteAddresses.end()))
{
// Log only stores, fp stores and ps stores, filtering out other instructions arrived via optimizeGatherPipe
int type = GetOpInfo(Memory::ReadUnchecked_U32(PC))->type;
if (type == OPTYPE_STORE || type == OPTYPE_STOREFP || (type == OPTYPE_PS && !strcmp(GetOpInfo(Memory::ReadUnchecked_U32(PC))->opname, "psq_st")))
{
jit->js.fifoWriteAddresses.insert(PC);
// Invalidate the JIT block so that it gets recompiled with the external exception check included.
jit->GetBlockCache()->InvalidateICache(PC, 4);
}
}
} }
} }

View File

@ -341,7 +341,7 @@ void Jit64::WriteRfiExitDestInEAX()
Cleanup(); Cleanup();
ABI_CallFunction(reinterpret_cast<void *>(&PowerPC::CheckExceptions)); ABI_CallFunction(reinterpret_cast<void *>(&PowerPC::CheckExceptions));
SUB(32, M(&CoreTiming::downcount), js.downcountAmount > 127 ? Imm32(js.downcountAmount) : Imm8(js.downcountAmount)); SUB(32, M(&CoreTiming::downcount), js.downcountAmount > 127 ? Imm32(js.downcountAmount) : Imm8(js.downcountAmount));
JMP(asm_routines.outerLoop, true); JMP(asm_routines.dispatcher, true);
} }
void Jit64::WriteExceptionExit() void Jit64::WriteExceptionExit()
@ -611,30 +611,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())
{
gpr.Flush(FLUSH_ALL);
fpr.Flush(FLUSH_ALL);
TEST(32, M((void *)&PowerPC::ppcState.Exceptions), Imm32(EXCEPTION_ISI | EXCEPTION_PROGRAM | EXCEPTION_SYSCALL | EXCEPTION_FPU_UNAVAILABLE | EXCEPTION_DSI | EXCEPTION_ALIGNMENT));
FixupBranch clearInt = J_CC(CC_NZ, true);
TEST(32, M((void *)&PowerPC::ppcState.Exceptions), Imm32(EXCEPTION_EXTERNAL_INT));
FixupBranch noExtException = J_CC(CC_Z, true);
TEST(32, M((void *)&PowerPC::ppcState.msr), Imm32(0x0008000));
FixupBranch noExtIntEnable = J_CC(CC_Z, true);
TEST(32, M((void *)&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);
MOV(32, M(&PC), Imm32(ops[i].address));
WriteExternalExceptionExit();
SetJumpTarget(noCPInt);
SetJumpTarget(noExtIntEnable);
SetJumpTarget(noExtException);
SetJumpTarget(clearInt);
}
if (Core::g_CoreStartupParameter.bEnableDebugging && breakpoints.IsAddressBreakPoint(ops[i].address) && GetState() != CPU_STEPPING) if (Core::g_CoreStartupParameter.bEnableDebugging && breakpoints.IsAddressBreakPoint(ops[i].address) && GetState() != CPU_STEPPING)
{ {
gpr.Flush(FLUSH_ALL); gpr.Flush(FLUSH_ALL);

View File

@ -1269,7 +1269,7 @@ static const unsigned alwaysUsedList[] = {
Store16, Store32, StoreSingle, StoreDouble, StorePaired, StoreFReg, FDCmpCR, Store16, Store32, StoreSingle, StoreDouble, StorePaired, StoreFReg, FDCmpCR,
BlockStart, BlockEnd, IdleBranch, BranchCond, BranchUncond, ShortIdleLoop, BlockStart, BlockEnd, IdleBranch, BranchCond, BranchUncond, ShortIdleLoop,
SystemCall, InterpreterBranch, RFIExit, FPExceptionCheck, SystemCall, InterpreterBranch, RFIExit, FPExceptionCheck,
DSIExceptionCheck, ISIException, ExtExceptionCheck, BreakPointCheck, DSIExceptionCheck, ISIException, BreakPointCheck,
Int3, Tramp, Nop Int3, Tramp, Nop
}; };
static const unsigned extra8RegList[] = { static const unsigned extra8RegList[] = {

View File

@ -168,7 +168,7 @@ enum Opcode {
// used for exception checking, at least until someone // used for exception checking, at least until someone
// has a better idea of integrating it // has a better idea of integrating it
FPExceptionCheck, DSIExceptionCheck, FPExceptionCheck, DSIExceptionCheck,
ISIException, ExtExceptionCheck, BreakPointCheck, ISIException, BreakPointCheck,
// "Opcode" representing a register too far away to // "Opcode" representing a register too far away to
// reference directly; this is a size optimization // reference directly; this is a size optimization
Tramp, Tramp,
@ -411,9 +411,6 @@ public:
InstLoc EmitISIException(InstLoc dest) { InstLoc EmitISIException(InstLoc dest) {
return EmitUOp(ISIException, dest); return EmitUOp(ISIException, dest);
} }
InstLoc EmitExtExceptionCheck(InstLoc pc) {
return EmitUOp(ExtExceptionCheck, pc);
}
InstLoc EmitBreakPointCheck(InstLoc pc) { InstLoc EmitBreakPointCheck(InstLoc pc) {
return EmitUOp(BreakPointCheck, pc); return EmitUOp(BreakPointCheck, pc);
} }

View File

@ -762,7 +762,6 @@ static void DoWriteCode(IRBuilder* ibuild, JitIL* Jit, bool UseProfile, bool Mak
case FPExceptionCheck: case FPExceptionCheck:
case DSIExceptionCheck: case DSIExceptionCheck:
case ISIException: case ISIException:
case ExtExceptionCheck:
case BreakPointCheck: case BreakPointCheck:
case Int3: case Int3:
case Tramp: case Tramp:
@ -1941,27 +1940,6 @@ static void DoWriteCode(IRBuilder* ibuild, JitIL* Jit, bool UseProfile, bool Mak
Jit->WriteExceptionExit(); Jit->WriteExceptionExit();
break; break;
} }
case ExtExceptionCheck: {
unsigned InstLoc = ibuild->GetImmValue(getOp1(I));
Jit->TEST(32, M((void *)&PowerPC::ppcState.Exceptions), Imm32(EXCEPTION_ISI | EXCEPTION_PROGRAM | EXCEPTION_SYSCALL | EXCEPTION_FPU_UNAVAILABLE | EXCEPTION_DSI | EXCEPTION_ALIGNMENT));
FixupBranch clearInt = Jit->J_CC(CC_NZ);
Jit->TEST(32, M((void *)&PowerPC::ppcState.Exceptions), Imm32(EXCEPTION_EXTERNAL_INT));
FixupBranch noExtException = Jit->J_CC(CC_Z);
Jit->TEST(32, M((void *)&PowerPC::ppcState.msr), Imm32(0x0008000));
FixupBranch noExtIntEnable = Jit->J_CC(CC_Z);
Jit->TEST(32, M((void *)&ProcessorInterface::m_InterruptCause), Imm32(ProcessorInterface::INT_CAUSE_CP | ProcessorInterface::INT_CAUSE_PE_TOKEN | ProcessorInterface::INT_CAUSE_PE_FINISH));
FixupBranch noCPInt = Jit->J_CC(CC_Z);
Jit->MOV(32, M(&PC), Imm32(InstLoc));
Jit->WriteExceptionExit();
Jit->SetJumpTarget(noCPInt);
Jit->SetJumpTarget(noExtIntEnable);
Jit->SetJumpTarget(noExtException);
Jit->SetJumpTarget(clearInt);
break;
}
case BreakPointCheck: { case BreakPointCheck: {
unsigned InstLoc = ibuild->GetImmValue(getOp1(I)); unsigned InstLoc = ibuild->GetImmValue(getOp1(I));

View File

@ -679,11 +679,6 @@ const u8* JitIL::DoJit(u32 em_address, PPCAnalyst::CodeBuffer *code_buf, JitBloc
ibuild.EmitFPExceptionCheck(ibuild.EmitIntConst(ops[i].address)); ibuild.EmitFPExceptionCheck(ibuild.EmitIntConst(ops[i].address));
} }
if (jit->js.fifoWriteAddresses.find(js.compilerPC) != jit->js.fifoWriteAddresses.end())
{
ibuild.EmitExtExceptionCheck(ibuild.EmitIntConst(ops[i].address));
}
if (Core::g_CoreStartupParameter.bEnableDebugging && breakpoints.IsAddressBreakPoint(ops[i].address) && GetState() != CPU_STEPPING) if (Core::g_CoreStartupParameter.bEnableDebugging && breakpoints.IsAddressBreakPoint(ops[i].address) && GetState() != CPU_STEPPING)
{ {
ibuild.EmitBreakPointCheck(ibuild.EmitIntConst(ops[i].address)); ibuild.EmitBreakPointCheck(ibuild.EmitIntConst(ops[i].address));

View File

@ -74,8 +74,6 @@ protected:
u8* rewriteStart; u8* rewriteStart;
JitBlock *curBlock; JitBlock *curBlock;
std::set<u32> fifoWriteAddresses;
}; };
public: public:

View File

@ -144,7 +144,7 @@ void Init()
isHiWatermarkActive = false; isHiWatermarkActive = false;
isLoWatermarkActive = false; isLoWatermarkActive = false;
et_UpdateInterrupts = CoreTiming::RegisterEvent("UpdateInterrupts", UpdateInterrupts_Wrapper); et_UpdateInterrupts = CoreTiming::RegisterEvent("CPInterrupt", UpdateInterrupts_Wrapper);
} }
void Read16(u16& _rReturnValue, const u32 _Address) void Read16(u16& _rReturnValue, const u32 _Address)
@ -642,14 +642,11 @@ void SetCpStatusRegister()
void SetCpControlRegister() void SetCpControlRegister()
{ {
// If the new fifo is being attached We make sure there wont be SetFinish event pending. // If the new fifo is being attached, force an exception check
// This protection fix eternal darkness booting, because the second SetFinish event when it is booting // This fixes the hang while booting Eternal Darkness
// seems invalid or has a bug and hang the game.
if (!fifo.bFF_GPReadEnable && m_CPCtrlReg.GPReadEnable && !m_CPCtrlReg.BPEnable) if (!fifo.bFF_GPReadEnable && m_CPCtrlReg.GPReadEnable && !m_CPCtrlReg.BPEnable)
{ {
ProcessFifoEvents(); CoreTiming::ForceExceptionCheck(0);
PixelEngine::ResetSetFinish();
} }
fifo.bFF_BPInt = m_CPCtrlReg.BPInt; fifo.bFF_BPInt = m_CPCtrlReg.BPInt;