Merge branch 'aram-dma-fixes'

This branch fixes the ARAM DMA state tracking and makes external exceptions
timing more accurate.

Fixes WWE: Day of Reckoning 1 and 2 (issue 617)
Fixes Knockout Kings 2003 (issue 4904)
Fixes Spider-Man (GC)
This commit is contained in:
Pierre Bourdon 2012-06-19 06:45:05 +02:00
commit 540010055e
7 changed files with 45 additions and 11 deletions

View File

@ -436,10 +436,6 @@ void Write16(const u16 _Value, const u32 _Address)
if (tmpControl.ARAM) g_dspState.DSPControl.ARAM = 0; if (tmpControl.ARAM) g_dspState.DSPControl.ARAM = 0;
if (tmpControl.DSP) g_dspState.DSPControl.DSP = 0; if (tmpControl.DSP) g_dspState.DSPControl.DSP = 0;
// Tracking DMAState fixes Knockout Kings 2003 in DSP HLE mode
if (GetDSPEmulator()->IsLLE())
g_dspState.DSPControl.DMAState = 0; // keep g_ARAM DMA State zero
// unknown // unknown
g_dspState.DSPControl.unk3 = tmpControl.unk3; g_dspState.DSPControl.unk3 = tmpControl.unk3;
g_dspState.DSPControl.pad = tmpControl.pad; g_dspState.DSPControl.pad = tmpControl.pad;
@ -701,9 +697,9 @@ void Do_ARAM_DMA()
// seems like a good estimate // seems like a good estimate
CoreTiming::ScheduleEvent_Threadsafe(g_arDMA.Cnt.count >> 1, et_GenerateDSPInterrupt, INT_ARAM | (1<<16)); CoreTiming::ScheduleEvent_Threadsafe(g_arDMA.Cnt.count >> 1, et_GenerateDSPInterrupt, INT_ARAM | (1<<16));
// Emulating the DMA wait time fixes Knockout Kings 2003 in DSP HLE mode // Set the "DMA in progress" flag. It will be cleared when the interrupt will
if (!GetDSPEmulator()->IsLLE()) // be triggered, after the simulated delay.
g_dspState.DSPControl.DMAState = 1; g_dspState.DSPControl.DMAState = 1;
// 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

@ -234,6 +234,7 @@ void Interpreter::mtmsr(UGeckoInstruction _inst)
{ {
// Privileged? // Privileged?
MSR = m_GPR[_inst.RS]; MSR = m_GPR[_inst.RS];
PowerPC::CheckExceptions();
m_EndBlock = true; m_EndBlock = true;
} }

View File

@ -303,7 +303,8 @@ void Jit64::Cleanup()
void Jit64::WriteExit(u32 destination, int exit_num) void Jit64::WriteExit(u32 destination, int exit_num)
{ {
Cleanup(); Cleanup();
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));
//If nobody has taken care of this yet (this can be removed when all branches are done) //If nobody has taken care of this yet (this can be removed when all branches are done)
JitBlock *b = js.curBlock; JitBlock *b = js.curBlock;

View File

@ -122,7 +122,25 @@ void Jit64::mtmsr(UGeckoInstruction inst)
gpr.UnlockAll(); gpr.UnlockAll();
gpr.Flush(FLUSH_ALL); gpr.Flush(FLUSH_ALL);
fpr.Flush(FLUSH_ALL); fpr.Flush(FLUSH_ALL);
// If some exceptions are pending and EE are now enabled, force checking
// external exceptions when going out of mtmsr in order to execute delayed
// interrupts as soon as possible.
MOV(32, R(EAX), M(&MSR));
TEST(32, R(EAX), Imm32(0x8000));
FixupBranch eeDisabled = J_CC(CC_Z);
MOV(32, R(EAX), M((void*)&PowerPC::ppcState.Exceptions));
TEST(32, R(EAX), R(EAX));
FixupBranch noExceptionsPending = J_CC(CC_Z);
MOV(32, M(&PC), Imm32(js.compilerPC + 4));
WriteExternalExceptionExit();
SetJumpTarget(eeDisabled);
SetJumpTarget(noExceptionsPending);
WriteExit(js.compilerPC + 4, 0); WriteExit(js.compilerPC + 4, 0);
js.firstFPInstructionFound = false; js.firstFPInstructionFound = false;
} }

View File

@ -276,8 +276,8 @@ public:
InstLoc EmitLoadMSR() { InstLoc EmitLoadMSR() {
return FoldZeroOp(LoadMSR, 0); return FoldZeroOp(LoadMSR, 0);
} }
InstLoc EmitStoreMSR(InstLoc val) { InstLoc EmitStoreMSR(InstLoc val, InstLoc pc) {
return FoldUOp(StoreMSR, val); return FoldBiOp(StoreMSR, val, pc);
} }
InstLoc EmitStoreFPRF(InstLoc value) { InstLoc EmitStoreFPRF(InstLoc value) {
return FoldUOp(StoreFPRF, value); return FoldUOp(StoreFPRF, value);

View File

@ -994,8 +994,26 @@ static void DoWriteCode(IRBuilder* ibuild, JitIL* Jit, bool UseProfile, bool Mak
break; break;
} }
case StoreMSR: { case StoreMSR: {
unsigned InstLoc = ibuild->GetImmValue(getOp2(I));
regStoreInstToConstLoc(RI, 32, getOp1(I), &MSR); regStoreInstToConstLoc(RI, 32, getOp1(I), &MSR);
regNormalRegClear(RI, I); regNormalRegClear(RI, I);
// If some exceptions are pending and EE are now enabled, force checking
// external exceptions when going out of mtmsr in order to execute delayed
// interrupts as soon as possible.
Jit->MOV(32, R(EAX), M(&MSR));
Jit->TEST(32, R(EAX), Imm32(0x8000));
FixupBranch eeDisabled = Jit->J_CC(CC_Z);
Jit->MOV(32, R(EAX), M((void*)&PowerPC::ppcState.Exceptions));
Jit->TEST(32, R(EAX), R(EAX));
FixupBranch noExceptionsPending = Jit->J_CC(CC_Z);
Jit->MOV(32, M(&PC), Imm32(InstLoc + 4));
Jit->WriteExceptionExit(); // TODO: Implement WriteExternalExceptionExit for JitIL
Jit->SetJumpTarget(eeDisabled);
Jit->SetJumpTarget(noExceptionsPending);
break; break;
} }
case StoreGQR: { case StoreGQR: {

View File

@ -106,7 +106,7 @@ void JitIL::mfspr(UGeckoInstruction inst)
// -------------- // --------------
void JitIL::mtmsr(UGeckoInstruction inst) void JitIL::mtmsr(UGeckoInstruction inst)
{ {
ibuild.EmitStoreMSR(ibuild.EmitLoadGReg(inst.RS)); ibuild.EmitStoreMSR(ibuild.EmitLoadGReg(inst.RS), ibuild.EmitIntConst(js.compilerPC));
ibuild.EmitBranchUncond(ibuild.EmitIntConst(js.compilerPC + 4)); ibuild.EmitBranchUncond(ibuild.EmitIntConst(js.compilerPC + 4));
} }
// ============== // ==============