Compile the ARAM DMA exception checks into the JIT block in a similar style to FIFO writes. This ensures that the ARAM DMA is handled soon after the DMA completes. Fixes issue 7122 and issue 7342.

This commit is contained in:
skidau 2014-09-06 18:59:38 +10:00
parent 23e2301223
commit d09e2abb0d
3 changed files with 27 additions and 16 deletions

View File

@ -38,6 +38,7 @@
#include "Core/HW/MMIO.h" #include "Core/HW/MMIO.h"
#include "Core/HW/ProcessorInterface.h" #include "Core/HW/ProcessorInterface.h"
#include "Core/PowerPC/PowerPC.h" #include "Core/PowerPC/PowerPC.h"
#include "Core/PowerPC/JitCommon/JitBase.h"
namespace DSP namespace DSP
{ {
@ -441,6 +442,21 @@ static void UpdateInterrupts()
bool ints_set = (((g_dspState.DSPControl.Hex >> 1) & g_dspState.DSPControl.Hex & (INT_DSP | INT_ARAM | INT_AID)) != 0); bool ints_set = (((g_dspState.DSPControl.Hex >> 1) & g_dspState.DSPControl.Hex & (INT_DSP | INT_ARAM | INT_AID)) != 0);
ProcessorInterface::SetInterrupt(ProcessorInterface::INT_CAUSE_DSP, ints_set); ProcessorInterface::SetInterrupt(ProcessorInterface::INT_CAUSE_DSP, ints_set);
if ((g_dspState.DSPControl.Hex >> 1) & g_dspState.DSPControl.Hex & (INT_DSP | INT_ARAM | INT_AID))
{
if (jit && PC != 0 && (jit->js.dspARAMAddresses.find(PC)) == (jit->js.dspARAMAddresses.end()) && (g_dspState.DSPControl.ARAM & g_dspState.DSPControl.ARAM_mask))
{
int type = GetOpInfo(Memory::ReadUnchecked_U32(PC))->type;
if (type == OPTYPE_STORE || type == OPTYPE_STOREFP || (type == OPTYPE_PS && GetOpInfo(Memory::ReadUnchecked_U32(PC))->opname == "psq_st"))
{
jit->js.dspARAMAddresses.insert(PC);
// Invalidate the JIT block so that it gets recompiled with the external exception check included.
jit->GetBlockCache()->InvalidateICache(PC, 4);
}
}
}
} }
static void GenerateDSPInterrupt(u64 DSPIntType, int cyclesLate) static void GenerateDSPInterrupt(u64 DSPIntType, int cyclesLate)
@ -518,25 +534,11 @@ static void Do_ARAM_DMA()
g_dspState.DSPControl.DMAState = 1; g_dspState.DSPControl.DMAState = 1;
if (g_arDMA.Cnt.count == 32) if (g_arDMA.Cnt.count == 32)
{ {
// Beyond Good and Evil (GGEE41) sends count 32
// Lost Kingdoms 2 needs the exception check here in DSP HLE mode
CompleteARAM(0, 0); CompleteARAM(0, 0);
CoreTiming::ForceExceptionCheck(100);
} }
else else
{ {
CoreTiming::ScheduleEvent_Threadsafe(0, et_CompleteARAM); CoreTiming::ScheduleEvent_Threadsafe(0, et_CompleteARAM);
// Force an early exception check on large transfers. Fixes RE2 audio.
// NFS:HP2 (<= 6144)
// Viewtiful Joe (<= 6144)
// Sonic Mega Collection (> 2048)
// Paper Mario battles (> 32)
// Mario Super Baseball (> 32)
// Knockout Kings 2003 loading (> 32)
// WWE DOR (> 32)
if (g_arDMA.Cnt.count > 2048 && g_arDMA.Cnt.count <= 6144)
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

View File

@ -697,7 +697,8 @@ const u8* Jit64::DoJit(u32 em_address, PPCAnalyst::CodeBuffer *code_buf, JitBloc
} }
// Add an external exception check if the instruction writes to the FIFO. // Add an external exception check if the instruction writes to the FIFO.
if (jit->js.fifoWriteAddresses.find(ops[i].address) != jit->js.fifoWriteAddresses.end()) if (jit->js.fifoWriteAddresses.find(ops[i].address) != jit->js.fifoWriteAddresses.end() ||
jit->js.dspARAMAddresses.find(ops[i].address) != jit->js.dspARAMAddresses.end())
{ {
TEST(32, PPCSTATE(Exceptions), Imm32(EXCEPTION_ISI | EXCEPTION_PROGRAM | EXCEPTION_SYSCALL | EXCEPTION_FPU_UNAVAILABLE | EXCEPTION_DSI | EXCEPTION_ALIGNMENT)); TEST(32, PPCSTATE(Exceptions), Imm32(EXCEPTION_ISI | EXCEPTION_PROGRAM | EXCEPTION_SYSCALL | EXCEPTION_FPU_UNAVAILABLE | EXCEPTION_DSI | EXCEPTION_ALIGNMENT));
FixupBranch clearInt = J_CC(CC_NZ); FixupBranch clearInt = J_CC(CC_NZ);
@ -707,7 +708,14 @@ const u8* Jit64::DoJit(u32 em_address, PPCAnalyst::CodeBuffer *code_buf, JitBloc
SetJumpTarget(extException); SetJumpTarget(extException);
TEST(32, PPCSTATE(msr), Imm32(0x0008000)); TEST(32, PPCSTATE(msr), Imm32(0x0008000));
FixupBranch noExtIntEnable = J_CC(CC_Z, true); FixupBranch noExtIntEnable = J_CC(CC_Z, true);
if (jit->js.fifoWriteAddresses.find(ops[i].address) != jit->js.fifoWriteAddresses.end())
{
TEST(32, M((void *)&ProcessorInterface::m_InterruptCause), Imm32(ProcessorInterface::INT_CAUSE_CP | ProcessorInterface::INT_CAUSE_PE_TOKEN | ProcessorInterface::INT_CAUSE_PE_FINISH)); TEST(32, M((void *)&ProcessorInterface::m_InterruptCause), Imm32(ProcessorInterface::INT_CAUSE_CP | ProcessorInterface::INT_CAUSE_PE_TOKEN | ProcessorInterface::INT_CAUSE_PE_FINISH));
}
else
{
TEST(32, M((void *)&ProcessorInterface::m_InterruptCause), Imm32(ProcessorInterface::INT_CAUSE_DSP));
}
FixupBranch noCPInt = J_CC(CC_Z, true); FixupBranch noCPInt = J_CC(CC_Z, true);
gpr.Flush(FLUSH_MAINTAIN_STATE); gpr.Flush(FLUSH_MAINTAIN_STATE);

View File

@ -97,6 +97,7 @@ protected:
JitBlock *curBlock; JitBlock *curBlock;
std::unordered_set<u32> fifoWriteAddresses; std::unordered_set<u32> fifoWriteAddresses;
std::unordered_set<u32> dspARAMAddresses;
}; };
PPCAnalyst::CodeBlock code_block; PPCAnalyst::CodeBlock code_block;