Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- Index: Source/Core/Common/Src/Atomic_GCC.h
- ===================================================================
- --- Source/Core/Common/Src/Atomic_GCC.h (revision 6314)
- +++ Source/Core/Common/Src/Atomic_GCC.h (working copy)
- @@ -41,10 +41,14 @@
- __sync_add_and_fetch(&target, value);
- }
- -inline void AtomicAnd(volatile u32& target, u32 value) {
- - __sync_and_and_fetch(&target, value);
- +inline void * AtomicCompareExchange(void *& dest, void * value, void * comp) {
- + return __sync_val_compare_and_swap(&dest, comp, value);
- }
- +inline u32 AtomicAnd(volatile u32& target, u32 value) {
- + return __sync_fetch_and_and(&target, value);
- +}
- +
- inline void AtomicDecrement(volatile u32& target) {
- __sync_add_and_fetch(&target, -1);
- }
- @@ -61,8 +65,8 @@
- return src;
- }
- -inline void AtomicOr(volatile u32& target, u32 value) {
- - __sync_or_and_fetch(&target, value);
- +inline u32 AtomicOr(volatile u32& target, u32 value) {
- + return __sync_fetch_and_or(&target, value);
- }
- inline void AtomicStore(volatile u32& dest, u32 value) {
- Index: Source/Core/Common/Src/Atomic_Win32.h
- ===================================================================
- --- Source/Core/Common/Src/Atomic_Win32.h (revision 6314)
- +++ Source/Core/Common/Src/Atomic_Win32.h (working copy)
- @@ -47,10 +47,14 @@
- InterlockedExchangeAdd((volatile LONG*)&target, (LONG)value);
- }
- -inline void AtomicAnd(volatile u32& target, u32 value) {
- - _InterlockedAnd((volatile LONG*)&target, (LONG)value);
- +inline void * AtomicCompareExchange(void * & dest, void * value, void * comp) {
- + return InterlockedCompareExchangePointer(&dest, value, comp);
- }
- +inline u32 AtomicAnd(volatile u32& target, u32 value) {
- + return (u32)_InterlockedAnd((volatile LONG*)&target, (LONG)value);
- +}
- +
- inline void AtomicIncrement(volatile u32& target) {
- InterlockedIncrement((volatile LONG*)&target);
- }
- @@ -68,8 +72,8 @@
- return result;
- }
- -inline void AtomicOr(volatile u32& target, u32 value) {
- - _InterlockedOr((volatile LONG*)&target, (LONG)value);
- +inline u32 AtomicOr(volatile u32& target, u32 value) {
- + return (u32)_InterlockedOr((volatile LONG*)&target, (LONG)value);
- }
- inline void AtomicStore(volatile u32& dest, u32 value) {
- Index: Source/Core/Core/Src/CoreTiming.cpp
- ===================================================================
- --- Source/Core/Core/Src/CoreTiming.cpp (revision 6314)
- +++ Source/Core/Core/Src/CoreTiming.cpp (working copy)
- @@ -42,7 +42,6 @@
- s64 time;
- u64 userdata;
- int type;
- - bool fifoWait;
- // Event *next;
- };
- @@ -66,7 +65,7 @@
- Common::CriticalSection externalEventSection;
- -void (*advanceCallback)(int cyclesExecuted) = NULL;
- +void (*advanceCallback)(s64 cyclesExecuted) = NULL;
- Event* GetNewEvent()
- {
- @@ -178,7 +177,6 @@
- p.Do(ev->time);
- p.Do(ev->type);
- p.Do(ev->userdata);
- - p.Do(ev->fifoWait);
- ev->next = 0;
- prev = ev;
- ev = ev->next;
- @@ -196,7 +194,6 @@
- p.Do(ev->time);
- p.Do(ev->type);
- p.Do(ev->userdata);
- - p.Do(ev->fifoWait);
- ev = ev->next;
- }
- more_events = 0;
- @@ -219,7 +216,7 @@
- // This is to be called when outside threads, such as the graphics thread, wants to
- // schedule things to be executed on the main thread.
- -void ScheduleEvent_Threadsafe(int cyclesIntoFuture, int event_type, u64 userdata, bool fifoWait)
- +void ScheduleEvent_Threadsafe(s64 cyclesIntoFuture, int event_type, u64 userdata)
- {
- externalEventSection.Enter();
- Event *ne = GetNewTsEvent();
- @@ -227,13 +224,16 @@
- ne->type = event_type;
- ne->next = 0;
- ne->userdata = userdata;
- - ne->fifoWait = fifoWait;
- if(!tsFirst)
- tsFirst = ne;
- if(tsLast)
- tsLast->next = ne;
- tsLast = ne;
- externalEventSection.Leave();
- +
- + // Tell PowerPC to synchronize with new timing data if required
- + if (cyclesIntoFuture < downcount)
- + PowerPC::Synchronize();
- }
- // Same as ScheduleEvent_Threadsafe(0, ...) EXCEPT if we are already on the main thread
- @@ -247,7 +247,7 @@
- externalEventSection.Leave();
- }
- else
- - ScheduleEvent_Threadsafe(0, event_type, userdata, false);
- + ScheduleEvent_Threadsafe(0, event_type, userdata);
- }
- void ClearPendingEvents()
- @@ -281,17 +281,20 @@
- // This must be run ONLY from within the cpu thread
- // cyclesIntoFuture may be VERY inaccurate if called from anything else
- // than Advance
- -void ScheduleEvent(int cyclesIntoFuture, int event_type, u64 userdata)
- +void ScheduleEvent(s64 cyclesIntoFuture, int event_type, u64 userdata)
- {
- Event *ne = GetNewEvent();
- ne->userdata = userdata;
- ne->type = event_type;
- ne->time = globalTimer + cyclesIntoFuture;
- - ne->fifoWait = false;
- AddEventToQueue(ne);
- +
- + // Tell PowerPC to synchronize with new timing data
- + if (cyclesIntoFuture < downcount)
- + PowerPC::Synchronize();
- }
- -void RegisterAdvanceCallback(void (*callback)(int cyclesExecuted))
- +void RegisterAdvanceCallback(void (*callback)(s64 cyclesExecuted))
- {
- advanceCallback = callback;
- }
- @@ -394,30 +397,6 @@
- maxSliceLength = MAX_SLICE_LENGTH;
- }
- -
- -//This raise only the events required while the fifo is processing data
- -void ProcessFifoWaitEvents()
- -{
- - MoveEvents();
- -
- - while (first)
- - {
- - if ((first->time <= globalTimer) && first->fifoWait)
- - {
- -
- - Event* evt = first;
- - first = first->next;
- - event_types[evt->type].callback(evt->userdata, (int)(globalTimer - evt->time));
- - FreeEvent(evt);
- - }
- - else
- - {
- - break;
- - }
- - }
- -
- -}
- -
- void MoveEvents()
- {
- @@ -444,47 +423,44 @@
- }
- -void Advance()
- +void AdvanceCycles(s64 cyclesExecuted)
- {
- -
- - MoveEvents();
- -
- - int cyclesExecuted = slicelength - downcount;
- globalTimer += cyclesExecuted;
- - downcount = slicelength;
- -
- - while (first)
- +
- + while (first && (first->time <= globalTimer))
- {
- - if (first->time <= globalTimer)
- - {
- // LOG(GEKKO, "[Scheduler] %s (%lld, %lld) ",
- // first->name ? first->name : "?", (u64)globalTimer, (u64)first->time);
- - Event* evt = first;
- - first = first->next;
- - event_types[evt->type].callback(evt->userdata, (int)(globalTimer - evt->time));
- - FreeEvent(evt);
- - }
- - else
- - {
- - break;
- - }
- + Event* evt = first;
- + first = first->next;
- + event_types[evt->type].callback(evt->userdata, (int)(globalTimer - evt->time));
- + FreeEvent(evt);
- }
- - if (!first)
- + if (!first)
- {
- - WARN_LOG(POWERPC, "WARNING - no events in queue. Setting downcount to 10000");
- - downcount += 10000;
- + WARN_LOG(POWERPC, "WARNING - no events in queue. Setting slicelength to maxSliceLength;");
- + slicelength = maxSliceLength;
- }
- else
- {
- slicelength = (int)(first->time - globalTimer);
- if (slicelength > maxSliceLength)
- slicelength = maxSliceLength;
- - downcount = slicelength;
- }
- + downcount = slicelength;
- +
- if (advanceCallback)
- advanceCallback(cyclesExecuted);
- }
- +void Advance()
- +{
- + MoveEvents();
- +
- + int cyclesExecuted = slicelength - downcount;
- + AdvanceCycles(cyclesExecuted);
- +}
- +
- void LogPendingEvents()
- {
- Event *ptr = first;
- @@ -498,20 +474,24 @@
- void Idle()
- {
- //DEBUG_LOG(POWERPC, "Idle");
- -
- - //When the FIFO is processing data we must not advance because in this way
- - //the VI will be desynchronized. So, We are waiting until the FIFO finish and
- - //while we process only the events required by the FIFO.
- - while (CPluginManager::GetInstance().GetVideo()->Video_IsFifoBusy())
- +
- + // Get asynchronous events
- + MoveEvents();
- +
- + // Idle until the next scheduled event (if it occurs before the end of the current time slice)
- + // Otherwise, idle until the end of the current time slice
- + if (first && ((first->time - globalTimer) < slicelength))
- {
- - ProcessFifoWaitEvents();
- - Common::YieldCPU();
- + s64 cycles = first->time - globalTimer;
- + if (cycles > downcount)
- + idledCycles += cycles - downcount;
- + AdvanceCycles(cycles);
- }
- -
- - idledCycles += downcount;
- - downcount = 0;
- -
- - Advance();
- + else
- + {
- + idledCycles += downcount;
- + AdvanceCycles(slicelength);
- + }
- }
- std::string GetScheduledEventsSummary()
- Index: Source/Core/Core/Src/CoreTiming.h
- ===================================================================
- --- Source/Core/Core/Src/CoreTiming.h (revision 6314)
- +++ Source/Core/Core/Src/CoreTiming.h (working copy)
- @@ -56,8 +56,8 @@
- // userdata MAY NOT CONTAIN POINTERS. userdata might get written and reloaded from disk,
- // when we implement state saves.
- -void ScheduleEvent(int cyclesIntoFuture, int event_type, u64 userdata=0);
- -void ScheduleEvent_Threadsafe(int cyclesIntoFuture, int event_type, u64 userdata=0, bool fifoWait=false);
- +void ScheduleEvent(s64 cyclesIntoFuture, int event_type, u64 userdata=0);
- +void ScheduleEvent_Threadsafe(s64 cyclesIntoFuture, int event_type, u64 userdata=0);
- void ScheduleEvent_Threadsafe_Immediate(int event_type, u64 userdata=0);
- // We only permit one event of each type in the queue at a time.
- @@ -67,7 +67,6 @@
- bool IsScheduled(int event_type);
- void Advance();
- void MoveEvents();
- -void ProcessFifoWaitEvents();
- // Pretend that the main CPU has executed enough cycles to reach the next event.
- void Idle();
- Index: Source/Core/Core/Src/HW/MemmapFunctions.cpp
- ===================================================================
- --- Source/Core/Core/Src/HW/MemmapFunctions.cpp (revision 6314)
- +++ Source/Core/Core/Src/HW/MemmapFunctions.cpp (working copy)
- @@ -602,7 +602,7 @@
- PowerPC::ppcState.spr[SPR_DAR] = _EffectiveAddress;
- - Common::AtomicOr(PowerPC::ppcState.Exceptions, EXCEPTION_DSI);
- + PowerPC::SetException(EXCEPTION_DSI, true);
- }
- @@ -611,7 +611,7 @@
- // Address of instruction could not be translated
- NPC = _EffectiveAddress;
- - Common::AtomicOr(PowerPC::ppcState.Exceptions, EXCEPTION_ISI);
- + PowerPC::SetException(EXCEPTION_ISI, true);
- }
- Index: Source/Core/Core/Src/HW/ProcessorInterface.cpp
- ===================================================================
- --- Source/Core/Core/Src/HW/ProcessorInterface.cpp (revision 6314)
- +++ Source/Core/Core/Src/HW/ProcessorInterface.cpp (working copy)
- @@ -57,6 +57,8 @@
- u32 m_FlipperRev;
- u32 m_Unknown;
- +int et_UpdateException;
- +void UpdateExceptionCallback(u64 userdata, int cyclesLate);
- // ID and callback for scheduling reset button presses/releases
- static int toggleResetButton;
- @@ -100,6 +102,7 @@
- m_InterruptCause = INT_CAUSE_RST_BUTTON | INT_CAUSE_VI;
- toggleResetButton = CoreTiming::RegisterEvent("ToggleResetButton", &ToggleResetButtonCallback);
- + et_UpdateException = CoreTiming::RegisterEvent("UpdateException", &UpdateExceptionCallback);
- }
- void Read32(u32& _uReturnValue, const u32 _iAddress)
- @@ -201,12 +204,14 @@
- }
- }
- +void UpdateExceptionCallback(u64 userdata, int cyclesLate)
- +{
- + PowerPC::SetException(EXCEPTION_EXTERNAL_INT, !!userdata);
- +}
- +
- void UpdateException()
- {
- - if ((m_InterruptCause & m_InterruptMask) != 0)
- - Common::AtomicOr(PowerPC::ppcState.Exceptions, EXCEPTION_EXTERNAL_INT);
- - else
- - Common::AtomicAnd(PowerPC::ppcState.Exceptions, ~EXCEPTION_EXTERNAL_INT);
- + CoreTiming::ScheduleEvent_Threadsafe(0, et_UpdateException, ((m_InterruptCause & m_InterruptMask) != 0));
- }
- static const char *Debug_GetInterruptName(u32 _causemask)
- Index: Source/Core/Core/Src/HW/SystemTimers.cpp
- ===================================================================
- --- Source/Core/Core/Src/HW/SystemTimers.cpp (revision 6314)
- +++ Source/Core/Core/Src/HW/SystemTimers.cpp (working copy)
- @@ -194,7 +194,7 @@
- void DecrementerCallback(u64 userdata, int cyclesLate)
- {
- PowerPC::ppcState.spr[SPR_DEC] = 0xFFFFFFFF;
- - Common::AtomicOr(PowerPC::ppcState.Exceptions, EXCEPTION_DECREMENTER);
- + PowerPC::SetException(EXCEPTION_DECREMENTER, true);
- }
- void DecrementerSet()
- Index: Source/Core/Core/Src/PowerPC/Interpreter/Interpreter.cpp
- ===================================================================
- --- Source/Core/Core/Src/PowerPC/Interpreter/Interpreter.cpp (revision 6314)
- +++ Source/Core/Core/Src/PowerPC/Interpreter/Interpreter.cpp (working copy)
- @@ -140,7 +140,7 @@
- }
- else
- {
- - Common::AtomicOr(PowerPC::ppcState.Exceptions, EXCEPTION_FPU_UNAVAILABLE);
- + PowerPC::SetException(EXCEPTION_FPU_UNAVAILABLE, true);
- PowerPC::CheckExceptions();
- m_EndBlock = true;
- }
- Index: Source/Core/Core/Src/PowerPC/Interpreter/Interpreter_Branch.cpp
- ===================================================================
- --- Source/Core/Core/Src/PowerPC/Interpreter/Interpreter_Branch.cpp (revision 6314)
- +++ Source/Core/Core/Src/PowerPC/Interpreter/Interpreter_Branch.cpp (working copy)
- @@ -135,7 +135,7 @@
- // We do it anyway, though :P
- void Interpreter::sc(UGeckoInstruction _inst)
- {
- - Common::AtomicOr(PowerPC::ppcState.Exceptions, EXCEPTION_SYSCALL);
- + PowerPC::SetException(EXCEPTION_SYSCALL, true);
- PowerPC::CheckExceptions();
- m_EndBlock = true;
- }
- Index: Source/Core/Core/Src/PowerPC/Interpreter/Interpreter_Integer.cpp
- ===================================================================
- --- Source/Core/Core/Src/PowerPC/Interpreter/Interpreter_Integer.cpp (revision 6314)
- +++ Source/Core/Core/Src/PowerPC/Interpreter/Interpreter_Integer.cpp (working copy)
- @@ -175,7 +175,7 @@
- || (((u32)a <(u32)b) && (TO & 0x02))
- || (((u32)a >(u32)b) && (TO & 0x01)))
- {
- - Common::AtomicOr(PowerPC::ppcState.Exceptions, EXCEPTION_PROGRAM);
- + PowerPC::SetException(EXCEPTION_PROGRAM, true);
- PowerPC::CheckExceptions();
- m_EndBlock = true; // Dunno about this
- }
- @@ -403,7 +403,7 @@
- || (((u32)a <(u32)b) && (TO & 0x02))
- || (((u32)a >(u32)b) && (TO & 0x01)))
- {
- - Common::AtomicOr(PowerPC::ppcState.Exceptions, EXCEPTION_PROGRAM);
- + PowerPC::SetException(EXCEPTION_PROGRAM, true);
- PowerPC::CheckExceptions();
- m_EndBlock = true; // Dunno about this
- }
- Index: Source/Core/Core/Src/PowerPC/Interpreter/Interpreter_LoadStore.cpp
- ===================================================================
- --- Source/Core/Core/Src/PowerPC/Interpreter/Interpreter_LoadStore.cpp (revision 6314)
- +++ Source/Core/Core/Src/PowerPC/Interpreter/Interpreter_LoadStore.cpp (working copy)
- @@ -406,10 +406,10 @@
- if (!(PowerPC::ppcState.spr[SPR_EAR] & 0x80000000))
- {
- - Common::AtomicOr(PowerPC::ppcState.Exceptions, EXCEPTION_DSI);
- + PowerPC::SetException(EXCEPTION_DSI, true);
- }
- if (EA & 3)
- - Common::AtomicOr(PowerPC::ppcState.Exceptions, EXCEPTION_ALIGNMENT);
- + PowerPC::SetException(EXCEPTION_ALIGNMENT, true);
- // _assert_msg_(POWERPC,0,"eciwx - fill r%i with word @ %08x from device %02x",
- // _inst.RS, EA, PowerPC::ppcState.spr[SPR_EAR] & 0x1f);
- @@ -428,10 +428,10 @@
- if (!(PowerPC::ppcState.spr[SPR_EAR] & 0x80000000))
- {
- - Common::AtomicOr(PowerPC::ppcState.Exceptions, EXCEPTION_DSI);
- + PowerPC::SetException(EXCEPTION_DSI, true);
- }
- if (EA & 3)
- - Common::AtomicOr(PowerPC::ppcState.Exceptions, EXCEPTION_ALIGNMENT);
- + PowerPC::SetException(EXCEPTION_ALIGNMENT, true);
- // _assert_msg_(POWERPC,0,"ecowx - send stw request (%08x@%08x) to device %02x",
- // m_GPR[_inst.RS], EA, PowerPC::ppcState.spr[SPR_EAR] & 0x1f);
- Index: Source/Core/Core/Src/PowerPC/Interpreter/Interpreter_SystemRegisters.cpp
- ===================================================================
- --- Source/Core/Core/Src/PowerPC/Interpreter/Interpreter_SystemRegisters.cpp (revision 6314)
- +++ Source/Core/Core/Src/PowerPC/Interpreter/Interpreter_SystemRegisters.cpp (working copy)
- @@ -425,7 +425,7 @@
- if (!(oldValue >> 31) && (m_GPR[_inst.RD]>>31)) //top bit from 0 to 1
- {
- PanicAlert("Interesting - Software triggered Decrementer exception");
- - Common::AtomicOr(PowerPC::ppcState.Exceptions, EXCEPTION_DECREMENTER);
- + PowerPC::SetException(EXCEPTION_DECREMENTER, true);
- }
- SystemTimers::DecrementerSet();
- break;
- Index: Source/Core/Core/Src/PowerPC/Jit64/Jit.cpp
- ===================================================================
- --- Source/Core/Core/Src/PowerPC/Jit64/Jit.cpp (revision 6314)
- +++ Source/Core/Core/Src/PowerPC/Jit64/Jit.cpp (working copy)
- @@ -23,6 +23,7 @@
- #endif
- #include "Common.h"
- +#include "Atomic.h"
- #include "x64Emitter.h"
- #include "ABI.h"
- #include "Thunk.h"
- @@ -207,8 +208,25 @@
- blocks.Init();
- asm_routines.Init();
- +
- + pNextDispatcher = asm_routines.dispatcherDefault;
- }
- +void Jit64::Synchronize()
- +{
- + // Set the next dispatcher so that it will call CoreTiming::Advance()
- + // This is useful when a new CoreTiming event has been scheduled before the end of the current time slice.
- + pNextDispatcher = asm_routines.doTiming;
- +}
- +
- +void Jit64::OnExceptionUpdated()
- +{
- + // Set the next dispatcher so that it will check for exception.
- + // It won't be replaced if the previous value is not set to the default dispatcher.
- + // This will prevent Synchronize requests from being discarded
- + Common::AtomicCompareExchange((void *&)pNextDispatcher, (void *)asm_routines.dispatcherException, (void *)asm_routines.dispatcherDefault);
- +}
- +
- void Jit64::ClearCache()
- {
- blocks.Clear();
- @@ -299,7 +317,7 @@
- void Jit64::WriteExit(u32 destination, int exit_num)
- {
- Cleanup();
- - SUB(32, M(&CoreTiming::downcount), js.downcountAmount > 127 ? Imm32(js.downcountAmount) : Imm8(js.downcountAmount));
- + SUB(32, M((void *)&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)
- JitBlock *b = js.curBlock;
- @@ -317,7 +335,17 @@
- else
- {
- MOV(32, M(&PC), Imm32(destination));
- - JMP(asm_routines.dispatcher, true);
- +#ifdef _M_X64
- + LEA(64, RAX, M((void *)asm_routines.dispatcherDefault));
- + LOCK();
- + XCHG(64, M((void *)&pNextDispatcher), R(RAX));
- + JMPptr(R(RAX));
- +#else
- + LEA(32, EAX, M((void *)asm_routines.dispatcherDefault));
- + LOCK();
- + XCHG(32, M((void *)&pNextDispatcher), R(EAX));
- + JMPptr(R(EAX));
- +#endif
- }
- }
- @@ -325,23 +353,31 @@
- {
- MOV(32, M(&PC), R(EAX));
- Cleanup();
- - SUB(32, M(&CoreTiming::downcount), js.downcountAmount > 127 ? Imm32(js.downcountAmount) : Imm8(js.downcountAmount));
- - JMP(asm_routines.dispatcher, true);
- + SUB(32, M((void *)&CoreTiming::downcount), js.downcountAmount > 127 ? Imm32(js.downcountAmount) : Imm8(js.downcountAmount));
- +#ifdef _M_X64
- + LEA(64, RAX, M((void *)asm_routines.dispatcherDefault));
- + LOCK();
- + XCHG(64, M((void *)&pNextDispatcher), R(RAX));
- + JMPptr(R(RAX));
- +#else
- + LEA(32, EAX, M((void *)asm_routines.dispatcherDefault));
- + LOCK();
- + XCHG(32, M((void *)&pNextDispatcher), R(EAX));
- + JMPptr(R(EAX));
- +#endif
- }
- void Jit64::WriteRfiExitDestInEAX()
- {
- MOV(32, M(&PC), R(EAX));
- - Cleanup();
- - SUB(32, M(&CoreTiming::downcount), js.downcountAmount > 127 ? Imm32(js.downcountAmount) : Imm8(js.downcountAmount));
- - JMP(asm_routines.testExceptions, true);
- + WriteExceptionExit();
- }
- void Jit64::WriteExceptionExit()
- {
- Cleanup();
- - SUB(32, M(&CoreTiming::downcount), js.downcountAmount > 127 ? Imm32(js.downcountAmount) : Imm8(js.downcountAmount));
- - JMP(asm_routines.testExceptions, true);
- + SUB(32, M((void *)&CoreTiming::downcount), js.downcountAmount > 127 ? Imm32(js.downcountAmount) : Imm8(js.downcountAmount));
- + JMP(asm_routines.dispatcherException, true);
- }
- void STACKALIGN Jit64::Run()
- @@ -433,6 +469,7 @@
- js.curBlock = b;
- js.block_flags = 0;
- js.cancel = false;
- + js.downcountAmount = 0;
- // Analyze the block, collect all instructions it is made of (including inlining,
- // if that is enabled), reorder instructions for optimal performance, and join joinable instructions.
- @@ -469,8 +506,15 @@
- // This block uses FPU - needs to add FP exception bailout
- TEST(32, M(&PowerPC::ppcState.msr), Imm32(1 << 13)); //Test FP enabled bit
- FixupBranch b1 = J_CC(CC_NZ);
- +
- + // Raise FPU Unavailable exception
- + LOCK();
- + OR(32, M((void *)&PowerPC::ppcState.Exceptions), Imm32(EXCEPTION_FPU_UNAVAILABLE));
- +
- + // If a FPU exception occurs, the exception handler will read
- + // from PC. Update PC with the latest value in case that happens.
- MOV(32, M(&PC), Imm32(js.blockStart));
- - JMP(asm_routines.fpException, true);
- + WriteExceptionExit();
- SetJumpTarget(b1);
- }
- @@ -497,7 +541,6 @@
- gpr.Start(js.gpa);
- fpr.Start(js.fpa);
- - js.downcountAmount = 0;
- if (!Core::g_CoreStartupParameter.bEnableDebugging)
- {
- for (int i = 0; i < size_of_merged_addresses; ++i)
- @@ -555,11 +598,14 @@
- TEST(32, M(&PowerPC::ppcState.msr), Imm32(1 << 13)); // Test FP enabled bit
- FixupBranch b1 = J_CC(CC_NZ);
- + // Raise FPU Unavailable exception
- + LOCK();
- + OR(32, M((void *)&PowerPC::ppcState.Exceptions), Imm32(EXCEPTION_FPU_UNAVAILABLE));
- +
- // If a FPU exception occurs, the exception handler will read
- // from PC. Update PC with the latest value in case that happens.
- MOV(32, M(&PC), Imm32(ops[i].address));
- - SUB(32, M(&CoreTiming::downcount), js.downcountAmount > 127 ? Imm32(js.downcountAmount) : Imm8(js.downcountAmount));
- - JMP(asm_routines.fpException, true);
- + WriteExceptionExit();
- SetJumpTarget(b1);
- }
- @@ -604,6 +650,7 @@
- {
- // Address of instruction could not be translated
- MOV(32, M(&NPC), Imm32(js.compilerPC));
- + LOCK();
- OR(32, M((void *)&PowerPC::ppcState.Exceptions), Imm32(EXCEPTION_ISI));
- // Remove the invalid instruction from the icache, forcing a recompile
- Index: Source/Core/Core/Src/PowerPC/Jit64/Jit.h
- ===================================================================
- --- Source/Core/Core/Src/PowerPC/Jit64/Jit.h (revision 6314)
- +++ Source/Core/Core/Src/PowerPC/Jit64/Jit.h (working copy)
- @@ -99,6 +99,9 @@
- PPCAnalyst::CodeBuffer code_buffer;
- Jit64AsmRoutineManager asm_routines;
- + // Address of the next dispatcher to call at the end of the current JIT block
- + const u8 * volatile pNextDispatcher;
- +
- public:
- Jit64() : code_buffer(32000) {}
- ~Jit64() {}
- @@ -119,9 +122,10 @@
- void ClearCache();
- - const u8 *GetDispatcher() {
- - return asm_routines.dispatcher;
- - }
- + void Synchronize();
- +
- + void OnExceptionUpdated();
- +
- const CommonAsmRoutines *GetAsmRoutines() {
- return &asm_routines;
- }
- Index: Source/Core/Core/Src/PowerPC/Jit64/Jit_LoadStore.cpp
- ===================================================================
- --- Source/Core/Core/Src/PowerPC/Jit64/Jit_LoadStore.cpp (revision 6314)
- +++ Source/Core/Core/Src/PowerPC/Jit64/Jit_LoadStore.cpp (working copy)
- @@ -119,44 +119,57 @@
- // IMHO those Idles should always be skipped and replaced by a more controllable "native" Idle methode
- // ... maybe the throttle one already do that :p
- // if (CommandProcessor::AllowIdleSkipping() && PixelEngine::AllowIdleSkipping())
- - if (SConfig::GetInstance().m_LocalCoreStartupParameter.bSkipIdle &&
- - inst.OPCD == 32 &&
- - (inst.hex & 0xFFFF0000) == 0x800D0000 &&
- - (Memory::ReadUnchecked_U32(js.compilerPC + 4) == 0x28000000 ||
- - (SConfig::GetInstance().m_LocalCoreStartupParameter.bWii && Memory::ReadUnchecked_U32(js.compilerPC + 4) == 0x2C000000)) &&
- - Memory::ReadUnchecked_U32(js.compilerPC + 8) == 0x4182fff8)
- + if (SConfig::GetInstance().m_LocalCoreStartupParameter.bSkipIdle && (inst.OPCD == 32 /* lwz */))
- {
- - // TODO(LinesPrower):
- - // - Rewrite this!
- - // It seems to be ugly and inefficient, but I don't know JIT stuff enough to make it right
- - // It only demonstrates the idea
- + u32 compareInst = Memory::ReadUnchecked_U32(js.compilerPC + 4);
- + if ((((compareInst & 0xFC600000) == 0x2C000000) /* cmpi */ ||
- + ((compareInst & 0xFC600000) == 0x28000000) /* cmpli */) &&
- + (((compareInst & 0x001F0000) >> 16) == d))
- + {
- + int CRField = (compareInst & 0x03800000) >> 23;
- + u32 branchInst = Memory::ReadUnchecked_U32(js.compilerPC + 8);
- + if ((branchInst & 0xFE80FFFF) == 0x4080FFF8) /* bcx */
- + {
- + int CRBit = (branchInst & 0x001F0000) >> 16;
- + if (((CRBit / 4) == CRField) && ((CRBit % 4) != 3))
- + {
- + s32 offset = (s32)(s16)inst.SIMM_16;
- + gpr.Lock(d);
- + SafeLoadToEAX(gpr.R(a), accessSize, offset, signExtend);
- + gpr.KillImmediate(d, false, true);
- + MOV(32, gpr.R(d), R(EAX));
- + gpr.UnlockAll();
- +
- + gpr.Flush(FLUSH_ALL);
- + fpr.Flush(FLUSH_ALL);
- - // do our job at first
- - s32 offset = (s32)(s16)inst.SIMM_16;
- - gpr.Lock(d);
- - SafeLoadToEAX(gpr.R(a), accessSize, offset, signExtend);
- - gpr.KillImmediate(d, false, true);
- - MOV(32, gpr.R(d), R(EAX));
- - gpr.UnlockAll();
- -
- - gpr.Flush(FLUSH_ALL);
- + CRBit %= 4;
- + FixupBranch noIdle;
- + if ((compareInst & 0xFC600000) == 0x2C000000) /* cmpi */
- + {
- + CMP(32, R(EAX), Imm32((u32)(s32)(s16)(compareInst & 0x0000FFFF)));
- + if (CRBit == 0) noIdle = J_CC(((branchInst & 0x01000000) != 0) ? CC_NL : CC_L);
- + else if (CRBit == 1) noIdle = J_CC(((branchInst & 0x01000000) != 0) ? CC_NG : CC_G);
- + else if (CRBit == 2) noIdle = J_CC(((branchInst & 0x01000000) != 0) ? CC_NE : CC_E);
- + }
- + else if((compareInst & 0xFC600000) == 0x28000000) /* cmpli */
- + {
- + CMP(32, R(EAX), Imm32((u32)(compareInst & 0x0000FFFF)));
- + if (CRBit == 0) noIdle = J_CC(((branchInst & 0x01000000) != 0) ? CC_NB : CC_B);
- + else if (CRBit == 1) noIdle = J_CC(((branchInst & 0x01000000) != 0) ? CC_NA : CC_A);
- + else if (CRBit == 2) noIdle = J_CC(((branchInst & 0x01000000) != 0) ? CC_NE : CC_E);
- + }
- +
- + ABI_CallFunctionC((void *)&PowerPC::OnIdle, PowerPC::ppcState.gpr[a] + (s32)(s16)inst.SIMM_16);
- - // if it's still 0, we can wait until the next event
- - TEST(32, R(EAX), R(EAX));
- - FixupBranch noIdle = J_CC(CC_NZ);
- -
- - gpr.Flush(FLUSH_ALL);
- - fpr.Flush(FLUSH_ALL);
- - ABI_CallFunctionC((void *)&PowerPC::OnIdle, PowerPC::ppcState.gpr[a] + (s32)(s16)inst.SIMM_16);
- -
- - // ! we must continue executing of the loop after exception handling, maybe there is still 0 in r0
- - //MOV(32, M(&PowerPC::ppcState.pc), Imm32(js.compilerPC));
- - JMP(asm_routines.testExceptions, true);
- -
- - SetJumpTarget(noIdle);
- -
- - //js.compilerPC += 8;
- - return;
- + MOV(32, M(&PowerPC::ppcState.pc), Imm32(js.compilerPC));
- + WriteExceptionExit();
- +
- + SetJumpTarget(noIdle);
- + return;
- + }
- + }
- + }
- }
- // Determine whether this instruction updates inst.RA
- Index: Source/Core/Core/Src/PowerPC/Jit64/JitAsm.cpp
- ===================================================================
- --- Source/Core/Core/Src/PowerPC/Jit64/JitAsm.cpp (revision 6314)
- +++ Source/Core/Core/Src/PowerPC/Jit64/JitAsm.cpp (working copy)
- @@ -70,11 +70,10 @@
- MOV(64, R(R15), Imm64((u64)jit->GetBlockCache()->GetCodePointers())); //It's below 2GB so 32 bits are good enough
- #endif
- - const u8 *outerLoop = GetCodePtr();
- ABI_CallFunction(reinterpret_cast<void *>(&CoreTiming::Advance));
- FixupBranch skipToRealDispatch = J(); //skip the sync and compare first time
- - dispatcher = GetCodePtr();
- + dispatcherDefault = GetCodePtr();
- // The result of slice decrementation should be in flags if somebody jumped here
- // IMPORTANT - We jump on negative, not carry!!!
- FixupBranch bail = J_CC(CC_BE, true);
- @@ -191,24 +190,19 @@
- #endif
- JMP(dispatcherNoCheck); // no point in special casing this
- - //FP blocks test for FPU available, jump here if false
- - fpException = AlignCode4();
- - LOCK();
- - OR(32, M((void *)&PowerPC::ppcState.Exceptions), Imm32(EXCEPTION_FPU_UNAVAILABLE));
- - ABI_CallFunction(reinterpret_cast<void *>(&PowerPC::CheckExceptions));
- - MOV(32, R(EAX), M(&NPC));
- - MOV(32, M(&PC), R(EAX));
- - JMP(dispatcher, true);
- + dispatcherException = GetCodePtr();
- + FixupBranch skipTiming = J_CC(CC_NBE);
- SetJumpTarget(bail);
- doTiming = GetCodePtr();
- ABI_CallFunction(reinterpret_cast<void *>(&CoreTiming::Advance));
- -
- +
- + SetJumpTarget(skipTiming);
- testExceptions = GetCodePtr();
- + MOV(32, R(EAX), M(&PC));
- TEST(32, M((void *)&PowerPC::ppcState.Exceptions), Imm32(0xFFFFFFFF));
- FixupBranch skipExceptions = J_CC(CC_Z);
- - MOV(32, R(EAX), M(&PC));
- MOV(32, M(&NPC), R(EAX));
- ABI_CallFunction(reinterpret_cast<void *>(&PowerPC::CheckExceptions));
- MOV(32, R(EAX), M(&NPC));
- @@ -216,17 +210,12 @@
- SetJumpTarget(skipExceptions);
- TEST(32, M((void*)PowerPC::GetStatePtr()), Imm32(0xFFFFFFFF));
- - J_CC(CC_Z, outerLoop, true);
- + J_CC(CC_Z, dispatcherPcInEAX, true);
- //Landing pad for drec space
- ABI_PopAllCalleeSavedRegsAndAdjustStack();
- RET();
- - breakpointBailout = GetCodePtr();
- - //Landing pad for drec space
- - ABI_PopAllCalleeSavedRegsAndAdjustStack();
- - RET();
- -
- GenerateCommon();
- }
- Index: Source/Core/Core/Src/PowerPC/Jit64IL/IR_X86.cpp
- ===================================================================
- --- Source/Core/Core/Src/PowerPC/Jit64IL/IR_X86.cpp (revision 6314)
- +++ Source/Core/Core/Src/PowerPC/Jit64IL/IR_X86.cpp (working copy)
- @@ -705,7 +705,7 @@
- RI.Jit->MOV(32, M(&PC), R(EAX));
- }
- RI.Jit->Cleanup();
- - RI.Jit->SUB(32, M(&CoreTiming::downcount), Imm32(RI.Jit->js.downcountAmount));
- + RI.Jit->SUB(32, M((void *)&CoreTiming::downcount), Imm32(RI.Jit->js.downcountAmount));
- RI.Jit->JMP(((JitIL *)jit)->asm_routines.doReJit, true);
- return;
- }
- @@ -1864,11 +1864,14 @@
- Jit->TEST(32, M(&PowerPC::ppcState.msr), Imm32(1 << 13)); // Test FP enabled bit
- FixupBranch b1 = Jit->J_CC(CC_NZ);
- + // Raise FPU Unavailable exception
- + Jit->LOCK();
- + Jit->OR(32, M((void *)&PowerPC::ppcState.Exceptions), Imm32(EXCEPTION_FPU_UNAVAILABLE));
- +
- // If a FPU exception occurs, the exception handler will read
- // from PC. Update PC with the latest value in case that happens.
- Jit->MOV(32, M(&PC), Imm32(InstLoc));
- - Jit->SUB(32, M(&CoreTiming::downcount), Jit->js.downcountAmount > 127 ? Imm32(Jit->js.downcountAmount) : Imm8(Jit->js.downcountAmount));
- - Jit->JMP(Jit->asm_routines.fpException, true);
- + Jit->WriteExceptionExit();
- Jit->SetJumpTarget(b1);
- break;
- }
- @@ -1889,6 +1892,7 @@
- // Address of instruction could not be translated
- Jit->MOV(32, M(&NPC), Imm32(InstLoc));
- + Jit->LOCK();
- Jit->OR(32, M((void *)&PowerPC::ppcState.Exceptions), Imm32(EXCEPTION_ISI));
- // Remove the invalid instruction from the icache, forcing a recompile
- Index: Source/Core/Core/Src/PowerPC/Jit64IL/JitIL.cpp
- ===================================================================
- --- Source/Core/Core/Src/PowerPC/Jit64IL/JitIL.cpp (revision 6314)
- +++ Source/Core/Core/Src/PowerPC/Jit64IL/JitIL.cpp (working copy)
- @@ -18,6 +18,7 @@
- #include <map>
- #include "Common.h"
- +#include "Atomic.h"
- #include "x64Emitter.h"
- #include "ABI.h"
- #include "Thunk.h"
- @@ -194,8 +195,25 @@
- blocks.Init();
- asm_routines.Init();
- +
- + pNextDispatcher = asm_routines.dispatcherDefault;
- }
- +void JitIL::Synchronize()
- +{
- + // Set the next dispatcher so that it will call CoreTiming::Advance()
- + // This is useful when a new CoreTiming event has been scheduled before the end of the current time slice.
- + pNextDispatcher = asm_routines.doTiming;
- +}
- +
- +void JitIL::OnExceptionUpdated()
- +{
- + // Set the next dispatcher so that it will check for exception.
- + // It won't be replaced if the previous value is not set to the default dispatcher.
- + // This will prevent Synchronize requests from being discarded
- + Common::AtomicCompareExchange((void *&)pNextDispatcher, (void *)asm_routines.dispatcherException, (void *)asm_routines.dispatcherDefault);
- +}
- +
- void JitIL::ClearCache()
- {
- blocks.Clear();
- @@ -292,7 +310,7 @@
- void JitIL::WriteExit(u32 destination, int exit_num)
- {
- Cleanup();
- - SUB(32, M(&CoreTiming::downcount), js.downcountAmount > 127 ? Imm32(js.downcountAmount) : Imm8(js.downcountAmount));
- + SUB(32, M((void *)&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)
- JitBlock *b = js.curBlock;
- @@ -310,7 +328,17 @@
- else
- {
- MOV(32, M(&PC), Imm32(destination));
- - JMP(asm_routines.dispatcher, true);
- +#ifdef _M_X64
- + LEA(64, RAX, M((void *)asm_routines.dispatcherDefault));
- + LOCK();
- + XCHG(64, M((void *)&pNextDispatcher), R(RAX));
- + JMPptr(R(RAX));
- +#else
- + LEA(32, EAX, M((void *)asm_routines.dispatcherDefault));
- + LOCK();
- + XCHG(32, M((void *)&pNextDispatcher), R(EAX));
- + JMPptr(R(EAX));
- +#endif
- }
- }
- @@ -318,23 +346,31 @@
- {
- MOV(32, M(&PC), arg);
- Cleanup();
- - SUB(32, M(&CoreTiming::downcount), js.downcountAmount > 127 ? Imm32(js.downcountAmount) : Imm8(js.downcountAmount));
- - JMP(asm_routines.dispatcher, true);
- + SUB(32, M((void *)&CoreTiming::downcount), js.downcountAmount > 127 ? Imm32(js.downcountAmount) : Imm8(js.downcountAmount));
- +#ifdef _M_X64
- + LEA(64, RAX, M((void *)asm_routines.dispatcherDefault));
- + LOCK();
- + XCHG(64, M((void *)&pNextDispatcher), R(RAX));
- + JMPptr(R(RAX));
- +#else
- + LEA(32, EAX, M((void *)asm_routines.dispatcherDefault));
- + LOCK();
- + XCHG(32, M((void *)&pNextDispatcher), R(EAX));
- + JMPptr(R(EAX));
- +#endif
- }
- void JitIL::WriteRfiExitDestInOpArg(const Gen::OpArg& arg)
- {
- MOV(32, M(&PC), arg);
- - Cleanup();
- - SUB(32, M(&CoreTiming::downcount), js.downcountAmount > 127 ? Imm32(js.downcountAmount) : Imm8(js.downcountAmount));
- - JMP(asm_routines.testExceptions, true);
- + WriteExceptionExit();
- }
- void JitIL::WriteExceptionExit()
- {
- Cleanup();
- - SUB(32, M(&CoreTiming::downcount), js.downcountAmount > 127 ? Imm32(js.downcountAmount) : Imm8(js.downcountAmount));
- - JMP(asm_routines.testExceptions, true);
- + SUB(32, M((void *)&CoreTiming::downcount), js.downcountAmount > 127 ? Imm32(js.downcountAmount) : Imm8(js.downcountAmount));
- + JMP(asm_routines.dispatcherException, true);
- }
- void STACKALIGN JitIL::Run()
- @@ -425,6 +461,7 @@
- js.fifoBytesThisBlock = 0;
- js.curBlock = b;
- js.cancel = false;
- + js.downcountAmount = 0;
- // Analyze the block, collect all instructions it is made of (including inlining,
- // if that is enabled), reorder instructions for optimal performance, and join joinable instructions.
- @@ -460,8 +497,13 @@
- // This block uses FPU - needs to add FP exception bailout
- TEST(32, M(&PowerPC::ppcState.msr), Imm32(1 << 13)); //Test FP enabled bit
- FixupBranch b1 = J_CC(CC_NZ);
- +
- + // Raise FPU Unavailable exception
- + LOCK();
- + OR(32, M((void *)&PowerPC::ppcState.Exceptions), Imm32(EXCEPTION_FPU_UNAVAILABLE));
- +
- MOV(32, M(&PC), Imm32(js.blockStart));
- - JMP(asm_routines.fpException, true);
- + WriteExceptionExit();
- SetJumpTarget(b1);
- }
- @@ -471,7 +513,6 @@
- // instruction processed by the JIT routines)
- ibuild.Reset();
- - js.downcountAmount = 0;
- if (!Core::g_CoreStartupParameter.bEnableDebugging)
- {
- for (int i = 0; i < size_of_merged_addresses; ++i)
- Index: Source/Core/Core/Src/PowerPC/Jit64IL/JitIL.h
- ===================================================================
- --- Source/Core/Core/Src/PowerPC/Jit64IL/JitIL.h (revision 6314)
- +++ Source/Core/Core/Src/PowerPC/Jit64IL/JitIL.h (working copy)
- @@ -69,6 +69,9 @@
- public:
- JitILAsmRoutineManager asm_routines;
- + // Address of the next dispatcher to call at the end of the current JIT block
- + const u8 * volatile pNextDispatcher;
- +
- JitIL() : code_buffer(32000) {}
- ~JitIL() {}
- @@ -87,9 +90,11 @@
- void Trace();
- void ClearCache();
- - const u8 *GetDispatcher() {
- - return asm_routines.dispatcher; // asm_routines.dispatcher
- - }
- +
- + void Synchronize();
- +
- + void OnExceptionUpdated();
- +
- const CommonAsmRoutines *GetAsmRoutines() {
- return &asm_routines;
- }
- Index: Source/Core/Core/Src/PowerPC/Jit64IL/JitILAsm.cpp
- ===================================================================
- --- Source/Core/Core/Src/PowerPC/Jit64IL/JitILAsm.cpp (revision 6314)
- +++ Source/Core/Core/Src/PowerPC/Jit64IL/JitILAsm.cpp (working copy)
- @@ -71,11 +71,10 @@
- #endif
- // INT3();
- - const u8 *outerLoop = GetCodePtr();
- ABI_CallFunction(reinterpret_cast<void *>(&CoreTiming::Advance));
- FixupBranch skipToRealDispatch = J(); //skip the sync and compare first time
- - dispatcher = GetCodePtr();
- + dispatcherDefault = GetCodePtr();
- //This is the place for CPUCompare!
- //The result of slice decrement should be in flags if somebody jumped here
- @@ -193,26 +192,20 @@
- #endif
- JMP(dispatcherNoCheck); // no point in special casing this
- - //FP blocks test for FPU available, jump here if false
- - fpException = AlignCode4();
- - MOV(32, R(EAX), M(&PC));
- - MOV(32, M(&NPC), R(EAX));
- - LOCK();
- - OR(32, M((void *)&PowerPC::ppcState.Exceptions), Imm32(EXCEPTION_FPU_UNAVAILABLE));
- - ABI_CallFunction(reinterpret_cast<void *>(&PowerPC::CheckExceptions));
- - MOV(32, R(EAX), M(&NPC));
- - MOV(32, M(&PC), R(EAX));
- - JMP(dispatcher, true);
- + dispatcherException = GetCodePtr();
- + FixupBranch skipTiming = J_CC(CC_NBE);
- +
- SetJumpTarget(bail);
- doTiming = GetCodePtr();
- ABI_CallFunction(reinterpret_cast<void *>(&CoreTiming::Advance));
- + SetJumpTarget(skipTiming);
- testExceptions = GetCodePtr();
- + MOV(32, R(EAX), M(&PC));
- TEST(32, M((void *)&PowerPC::ppcState.Exceptions), Imm32(0xFFFFFFFF));
- FixupBranch skipExceptions = J_CC(CC_Z);
- - MOV(32, R(EAX), M(&PC));
- MOV(32, M(&NPC), R(EAX));
- ABI_CallFunction(reinterpret_cast<void *>(&PowerPC::CheckExceptions));
- MOV(32, R(EAX), M(&NPC));
- @@ -220,16 +213,11 @@
- SetJumpTarget(skipExceptions);
- TEST(32, M((void*)PowerPC::GetStatePtr()), Imm32(0xFFFFFFFF));
- - J_CC(CC_Z, outerLoop, true);
- + J_CC(CC_Z, dispatcherPcInEAX, true);
- //Landing pad for drec space
- ABI_PopAllCalleeSavedRegsAndAdjustStack();
- RET();
- - breakpointBailout = GetCodePtr();
- - //Landing pad for drec space
- - ABI_PopAllCalleeSavedRegsAndAdjustStack();
- - RET();
- -
- GenerateCommon();
- }
- @@ -250,8 +238,8 @@
- ABI_AlignStack(0);
- CALL(reinterpret_cast<void *>(&ProfiledReJit));
- ABI_RestoreStack(0);
- - SUB(32, M(&CoreTiming::downcount), Imm8(0));
- - JMP(dispatcher, true);
- + SUB(32, M((void *)&CoreTiming::downcount), Imm8(0));
- + JMP(dispatcherDefault, true);
- GenQuantizedLoads();
- GenQuantizedStores();
- Index: Source/Core/Core/Src/PowerPC/JitCommon/JitAsmCommon.h
- ===================================================================
- --- Source/Core/Core/Src/PowerPC/JitCommon/JitAsmCommon.h (revision 6314)
- +++ Source/Core/Core/Src/PowerPC/JitCommon/JitAsmCommon.h (working copy)
- @@ -40,17 +40,14 @@
- const u8 *enterCode;
- - const u8 *dispatcher;
- + const u8 *dispatcherDefault;
- const u8 *dispatcherNoCheck;
- const u8 *dispatcherPcInEAX;
- + const u8 *dispatcherException;
- - const u8 *fpException;
- const u8 *testExceptions;
- - const u8 *dispatchPcInEAX;
- const u8 *doTiming;
- - const u8 *breakpointBailout;
- -
- // In: array index: GQR to use.
- // In: ECX: Address to read from.
- // Out: XMM0: Bottom two 32-bit slots hold the read value,
- Index: Source/Core/Core/Src/PowerPC/JitCommon/JitBase.h
- ===================================================================
- --- Source/Core/Core/Src/PowerPC/JitCommon/JitBase.h (revision 6314)
- +++ Source/Core/Core/Src/PowerPC/JitCommon/JitBase.h (working copy)
- @@ -89,6 +89,9 @@
- const u8 *BackPatch(u8 *codePtr, int accessType, u32 em_address, void *ctx);
- virtual const CommonAsmRoutines *GetAsmRoutines() = 0;
- +
- + virtual void Synchronize() = 0;
- + virtual void OnExceptionUpdated() = 0;
- };
- extern JitBase *jit;
- Index: Source/Core/Core/Src/PowerPC/JitCommon/JitCache.cpp
- ===================================================================
- --- Source/Core/Core/Src/PowerPC/JitCommon/JitCache.cpp (revision 6314)
- +++ Source/Core/Core/Src/PowerPC/JitCommon/JitCache.cpp (working copy)
- @@ -380,7 +380,7 @@
- // Spurious entrances from previously linked blocks can only come through checkedEntry
- XEmitter emit((u8 *)b.checkedEntry);
- emit.MOV(32, M(&PC), Imm32(b.originalAddress));
- - emit.JMP(jit->GetAsmRoutines()->dispatcher, true);
- + emit.JMP(jit->GetAsmRoutines()->dispatcherNoCheck, true);
- // this is not needed really
- /*
- emit.SetCodePtr((u8 *)blockCodePointers[blocknum]);
- Index: Source/Core/Core/Src/PowerPC/PowerPC.cpp
- ===================================================================
- --- Source/Core/Core/Src/PowerPC/PowerPC.cpp (revision 6314)
- +++ Source/Core/Core/Src/PowerPC/PowerPC.cpp (working copy)
- @@ -270,6 +270,25 @@
- Host_UpdateDisasmDialog();
- }
- +void Synchronize()
- +{
- + if (jit)
- + jit->Synchronize();
- +}
- +
- +void SetException(u32 exception, bool active)
- +{
- + if (active)
- + {
- + if ((Common::AtomicOr(ppcState.Exceptions, exception) & exception) == 0)
- + if (jit) jit->OnExceptionUpdated(); // Notify JIT compiler when a new exception is raised
- + }
- + else
- + {
- + Common::AtomicAnd(ppcState.Exceptions, ~exception);
- + }
- +}
- +
- void CheckExceptions()
- {
- // Read volatile data once
- @@ -400,6 +419,10 @@
- ERROR_LOG(POWERPC, "Unknown EXTERNAL INTERRUPT exception: Exceptions == %08x", exceptions);
- }
- }
- +
- + // Force the JIT to check for the remaining exception at the end of the next block
- + if (jit && ppcState.Exceptions)
- + jit->OnExceptionUpdated();
- }
- void CheckBreakPoints()
- @@ -414,9 +437,9 @@
- void OnIdle(u32 _uThreadAddr)
- {
- - u32 nextThread = Memory::Read_U32(_uThreadAddr);
- + //u32 nextThread = Memory::Read_U32(_uThreadAddr);
- //do idle skipping
- - if (nextThread == 0)
- + //if (nextThread == 0)
- CoreTiming::Idle();
- }
- Index: Source/Core/Core/Src/PowerPC/PowerPC.h
- ===================================================================
- --- Source/Core/Core/Src/PowerPC/PowerPC.h (revision 6314)
- +++ Source/Core/Core/Src/PowerPC/PowerPC.h (working copy)
- @@ -115,6 +115,11 @@
- void OnIdle(u32 _uThreadAddr);
- void OnIdleIL();
- +// Force the CPU emulation to synchronize with CoreTiming events (only required for JIT cores)
- +void Synchronize();
- +
- +void SetException(u32 exception, bool active);
- +
- // Easy register access macros.
- #define HID0 ((UReg_HID0&)PowerPC::ppcState.spr[SPR_HID0])
- #define HID2 ((UReg_HID2&)PowerPC::ppcState.spr[SPR_HID2])
- Index: Source/Core/DolphinWX/Src/ISOProperties.cpp
- ===================================================================
- --- Source/Core/DolphinWX/Src/ISOProperties.cpp (revision 6314)
- +++ Source/Core/DolphinWX/Src/ISOProperties.cpp (working copy)
- @@ -342,10 +342,6 @@
- arrayStringFor_Hack.Add(_("Skies of Arcadia"));
- Hack = new wxChoice(m_GameConfig, ID_HACK, wxDefaultPosition, wxDefaultSize, arrayStringFor_Hack, 0, wxDefaultValidator);
- - WMTightnessText = new wxStaticText(m_GameConfig, ID_WMTIGHTNESS_TEXT, wxT("Watermark tightness: "), wxDefaultPosition, wxDefaultSize);
- - WMTightness = new wxTextCtrl(m_GameConfig, ID_WMTIGHTNESS, wxT(""), wxDefaultPosition, wxDefaultSize, 0, wxTextValidator(wxFILTER_NUMERIC));
- - WMTightness->SetToolTip(wxT("Change this if you get lots of FIFO overflow errors. Reasonable values range from 0 to 1000."));
- -
- // Emulation State
- sEmuState = new wxBoxSizer(wxHORIZONTAL);
- EmuStateText = new wxStaticText(m_GameConfig, ID_EMUSTATE_TEXT, _("Emulation State: "), wxDefaultPosition, wxDefaultSize);
- @@ -383,8 +379,6 @@
- wxFlexGridSizer* fifosizer = new wxFlexGridSizer(2, 2, 0, 0);
- fifosizer->Add(Hacktext, 0, wxLEFT, 5);
- fifosizer->Add(Hack, 0, wxEXPAND|wxLEFT, 5);
- - fifosizer->Add(WMTightnessText, 0, wxLEFT, 5);
- - fifosizer->Add(WMTightness, 0, wxEXPAND|wxLEFT, 5);
- sbVideoOverrides->Add(fifosizer);
- sbGameConfig->Add(sbCoreOverrides, 0, wxEXPAND);
- @@ -913,11 +907,6 @@
- else
- DListCache->Set3StateValue(wxCHK_UNDETERMINED);
- - if (GameIni.Get("Video", "FIFOWatermarkTightness", &sTemp))
- - WMTightness->SetValue(wxString(sTemp.c_str(), *wxConvCurrent));
- - else
- - WMTightness->SetValue(wxT("50"));
- -
- GameIni.Get("Video", "ProjectionHack", &iTemp, -1);
- Hack->SetSelection(iTemp);
- @@ -1034,15 +1023,6 @@
- else
- GameIni.Set("Video", "ProjectionHack", Hack->GetSelection());
- - if (WMTightness->GetValue().size() == 0)
- - GameIni.DeleteKey("Video", "FIFOWatermarkTightness");
- - else
- - {
- - long val;
- - WMTightness->GetValue().ToLong(&val);
- - GameIni.Set("Video", "FIFOWatermarkTightness", (int)val);
- - }
- -
- if (EmuState->GetSelection() == -1)
- GameIni.DeleteKey("EmuState", "EmulationStateId");
- else
- Index: Source/Core/DolphinWX/Src/ISOProperties.h
- ===================================================================
- --- Source/Core/DolphinWX/Src/ISOProperties.h (revision 6314)
- +++ Source/Core/DolphinWX/Src/ISOProperties.h (working copy)
- @@ -96,8 +96,6 @@
- wxStaticText *Hacktext;
- wxArrayString arrayStringFor_Hack;
- wxChoice *Hack;
- - wxStaticText *WMTightnessText;
- - wxTextCtrl *WMTightness;
- wxButton *EditConfig;
- wxStaticText *EmuStateText;
- @@ -182,8 +180,6 @@
- ID_DLISTCACHE,
- ID_HACK_TEXT,
- ID_HACK,
- - ID_WMTIGHTNESS_TEXT,
- - ID_WMTIGHTNESS,
- ID_ENABLEPROGRESSIVESCAN,
- ID_ENABLEWIDESCREEN,
- ID_EDITCONFIG,
- Index: Source/Core/VideoCommon/Src/CommandProcessor.cpp
- ===================================================================
- --- Source/Core/VideoCommon/Src/CommandProcessor.cpp (revision 6314)
- +++ Source/Core/VideoCommon/Src/CommandProcessor.cpp (working copy)
- @@ -98,8 +98,6 @@
- UCPCtrlReg m_CPCtrlReg;
- UCPClearReg m_CPClearReg;
- -u32 HiWatermark_Tighter;
- -
- int m_bboxleft;
- int m_bboxtop;
- int m_bboxright;
- @@ -133,7 +131,6 @@
- p.Do(m_bboxbottom);
- p.Do(m_tokenReg);
- p.Do(fifo);
- - p.Do(HiWatermark_Tighter);
- }
- //inline void WriteLow (u32& _reg, u16 lowbits) {_reg = (_reg & 0xFFFF0000) | lowbits;}
- @@ -404,12 +401,6 @@
- Common::AtomicStore(fifo.bFF_Breakpoint, false);
- - if (tmpCtrl.FifoUnderflowIntEnable)
- - Common::AtomicStore(fifo.CPReadIdle, false);
- -
- - if (tmpCtrl.FifoOverflowIntEnable)
- - m_CPStatusReg.OverflowHiWatermark = false;
- -
- UpdateInterrupts();
- // If the new fifo is being attached We make sure there wont be SetFinish event pending.
- @@ -502,8 +493,6 @@
- break;
- case FIFO_HI_WATERMARK_HI:
- WriteHigh((u32 &)fifo.CPHiWatermark, _Value);
- - // Tune this when you see lots of FIFO overflown by GatherPipe
- - HiWatermark_Tighter = fifo.CPHiWatermark - 32 * g_ActiveConfig.iFIFOWatermarkTightness;
- DEBUG_LOG(COMMANDPROCESSOR,"\t write to FIFO_HI_WATERMARK_HI : %04x", _Value);
- break;
- @@ -615,8 +604,7 @@
- CatchUpGPU();
- }
- - // The interrupt latency in Dolphin is much longer than Hardware, so we must be more vigilant on Watermark
- - if (!m_CPStatusReg.OverflowHiWatermark && fifo.CPReadWriteDistance >= HiWatermark_Tighter)
- + if (!m_CPStatusReg.OverflowHiWatermark && fifo.CPReadWriteDistance >= fifo.CPHiWatermark)
- {
- m_CPStatusReg.OverflowHiWatermark = true;
- if (m_CPCtrlReg.FifoOverflowIntEnable)
- @@ -693,7 +681,7 @@
- void UpdateInterruptsFromVideoPlugin()
- {
- - g_VideoInitialize.pScheduleEvent_Threadsafe(0, et_UpdateInterrupts, 0, true);
- + g_VideoInitialize.pScheduleEvent_Threadsafe(0, et_UpdateInterrupts, 0);
- }
- void SetFifoIdleFromVideoPlugin()
- Index: Source/Core/VideoCommon/Src/PixelEngine.cpp
- ===================================================================
- --- Source/Core/VideoCommon/Src/PixelEngine.cpp (revision 6314)
- +++ Source/Core/VideoCommon/Src/PixelEngine.cpp (working copy)
- @@ -343,7 +343,7 @@
- // This seems smelly...
- CommandProcessor::IncrementGPWDToken(); // for DC watchdog hack since PEToken seems to be a frame-finish too
- g_VideoInitialize.pScheduleEvent_Threadsafe(
- - 0, et_SetTokenOnMainThread, _token | (_bSetTokenAcknowledge << 16), true);
- + 0, et_SetTokenOnMainThread, _token | (_bSetTokenAcknowledge << 16));
- }
- else // set token value
- {
- @@ -362,7 +362,7 @@
- {
- CommandProcessor::IncrementGPWDToken(); // for DC watchdog hack
- g_VideoInitialize.pScheduleEvent_Threadsafe(
- - 0, et_SetFinishOnMainThread, 0, true);
- + 0, et_SetFinishOnMainThread, 0);
- INFO_LOG(PIXELENGINE, "VIDEO Set Finish");
- }
- Index: Source/Core/VideoCommon/Src/VideoConfig.cpp
- ===================================================================
- --- Source/Core/VideoCommon/Src/VideoConfig.cpp (revision 6314)
- +++ Source/Core/VideoCommon/Src/VideoConfig.cpp (working copy)
- @@ -97,7 +97,6 @@
- iniFile.Get("Hacks", "EFBCopyDisableHotKey", &bOSDHotKey, 0);
- iniFile.Get("Hacks", "EFBToTextureEnable", &bCopyEFBToTexture, false);
- iniFile.Get("Hacks", "EFBScaledCopy", &bCopyEFBScaled, true);
- - iniFile.Get("Hacks", "FIFOWatermarkTightness", &iFIFOWatermarkTightness, 50);
- iniFile.Get("Hacks", "ProjectionHack", &iPhackvalue, 0);
- iniFile.Get("Hardware", "Adapter", &iAdapter, 0);
- @@ -145,8 +144,6 @@
- iniFile.Get("Video", "UseXFB", &bUseXFB);
- if (iniFile.Exists("Video", "UseRealXFB"))
- iniFile.Get("Video", "UseRealXFB", &bUseRealXFB);
- - if (iniFile.Exists("Video", "FIFOWatermarkTightness"))
- - iniFile.Get("Video", "FIFOWatermarkTightness", &iFIFOWatermarkTightness);
- if (iniFile.Exists("Video", "ProjectionHack"))
- iniFile.Get("Video", "ProjectionHack", &iPhackvalue);
- if (iniFile.Exists("Video", "UseNativeMips"))
- Index: Source/Core/VideoCommon/Src/VideoConfig.h
- ===================================================================
- --- Source/Core/VideoCommon/Src/VideoConfig.h (revision 6314)
- +++ Source/Core/VideoCommon/Src/VideoConfig.h (working copy)
- @@ -122,7 +122,6 @@
- bool bCopyEFBScaled;
- bool bSafeTextureCache;
- int iSafeTextureCache_ColorSamples;
- - int iFIFOWatermarkTightness;
- int iPhackvalue;
- bool bPhackvalue1, bPhackvalue2;
- float fhackvalue1, fhackvalue2;
- Index: Source/Plugins/Plugin_VideoSoftware/Src/CommandProcessor.cpp
- ===================================================================
- --- Source/Plugins/Plugin_VideoSoftware/Src/CommandProcessor.cpp (revision 6314)
- +++ Source/Plugins/Plugin_VideoSoftware/Src/CommandProcessor.cpp (working copy)
- @@ -322,7 +322,7 @@
- void UpdateInterruptsFromVideoPlugin(u64 userdata)
- {
- - g_VideoInitialize.pScheduleEvent_Threadsafe(0, et_UpdateInterrupts, userdata, true);
- + g_VideoInitialize.pScheduleEvent_Threadsafe(0, et_UpdateInterrupts, userdata);
- }
- void ReadFifo()
- Index: Source/Plugins/Plugin_VideoSoftware/Src/PixelEngine.cpp
- ===================================================================
- --- Source/Plugins/Plugin_VideoSoftware/Src/PixelEngine.cpp (revision 6314)
- +++ Source/Plugins/Plugin_VideoSoftware/Src/PixelEngine.cpp (working copy)
- @@ -155,7 +155,7 @@
- if (_bSetTokenAcknowledge) // set token INT
- {
- g_VideoInitialize.pScheduleEvent_Threadsafe(
- - 0, et_SetTokenOnMainThread, _token | (_bSetTokenAcknowledge << 16), true);
- + 0, et_SetTokenOnMainThread, _token | (_bSetTokenAcknowledge << 16));
- }
- }
- @@ -164,7 +164,7 @@
- void SetFinish()
- {
- g_VideoInitialize.pScheduleEvent_Threadsafe(
- - 0, et_SetFinishOnMainThread, 0, true);
- + 0, et_SetFinishOnMainThread, 0);
- INFO_LOG(PIXELENGINE, "VIDEO Set Finish");
- }
- Index: Source/PluginSpecs/pluginspecs_video.h
- ===================================================================
- --- Source/PluginSpecs/pluginspecs_video.h (revision 6314)
- +++ Source/PluginSpecs/pluginspecs_video.h (working copy)
- @@ -13,7 +13,7 @@
- typedef void (*TSetInterrupt)(u32 _causemask, bool _bSet);
- typedef int (*TRegisterEvent)(const char *name, TimedCallback callback);
- -typedef void (*TScheduleEvent_Threadsafe)(int cyclesIntoFuture, int event_type, u64 userdata, bool fifoWait);
- +typedef void (*TScheduleEvent_Threadsafe)(s64 cyclesIntoFuture, int event_type, u64 userdata);
- typedef void (*TRemoveEvent)(int event_type);
- typedef unsigned char* (*TGetMemoryPointer)(const unsigned int _iAddress);
- typedef void (*TVideoLog)(const char* _pMessage, int _bBreak);
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement