Merge branch 'master' into GLSL-master

Conflicts:
	.gitignore
This commit is contained in:
degasus committed 2013-03-12 11:28:56 +01:00
commit 382be2aabd
87 files changed
+23862 -38775

No files matched your search

+4 -1
View File
@@ -55,7 +55,7 @@ namespace BootManager
struct ConfigCache
{
bool valid, bCPUThread, bSkipIdle, bEnableFPRF, bMMU, bDCBZOFF,
bVBeam, bFastDiscSpeed, bMergeBlocks, bDSPHLE, bHLE_BS2;
bVBeam, bSyncGPU, bFastDiscSpeed, bMergeBlocks, bDSPHLE, bHLE_BS2;
int iTLBHack, iCPUCore;
std::string strBackend;
};
@@ -95,6 +95,7 @@ bool BootCore(const std::string& _rFilename)
config_cache.bDCBZOFF = StartUp.bDCBZOFF;
config_cache.iTLBHack = StartUp.iTLBHack;
config_cache.bVBeam = StartUp.bVBeam;
config_cache.bSyncGPU = StartUp.bSyncGPU;
config_cache.bFastDiscSpeed = StartUp.bFastDiscSpeed;
config_cache.bMergeBlocks = StartUp.bMergeBlocks;
config_cache.bDSPHLE = StartUp.bDSPHLE;
@@ -109,6 +110,7 @@ bool BootCore(const std::string& _rFilename)
game_ini.Get("Core", "TLBHack", &StartUp.iTLBHack, StartUp.iTLBHack);
game_ini.Get("Core", "DCBZ", &StartUp.bDCBZOFF, StartUp.bDCBZOFF);
game_ini.Get("Core", "VBeam", &StartUp.bVBeam, StartUp.bVBeam);
game_ini.Get("Core", "SyncGPU", &StartUp.bSyncGPU, StartUp.bSyncGPU);
game_ini.Get("Core", "FastDiscSpeed", &StartUp.bFastDiscSpeed, StartUp.bFastDiscSpeed);
game_ini.Get("Core", "BlockMerging", &StartUp.bMergeBlocks, StartUp.bMergeBlocks);
game_ini.Get("Core", "DSPHLE", &StartUp.bDSPHLE, StartUp.bDSPHLE);
@@ -168,6 +170,7 @@ void Stop()
StartUp.bDCBZOFF = config_cache.bDCBZOFF;
StartUp.iTLBHack = config_cache.iTLBHack;
StartUp.bVBeam = config_cache.bVBeam;
StartUp.bSyncGPU = config_cache.bSyncGPU;
StartUp.bFastDiscSpeed = config_cache.bFastDiscSpeed;
StartUp.bMergeBlocks = config_cache.bMergeBlocks;
StartUp.bDSPHLE = config_cache.bDSPHLE;
+2 -1
View File
@@ -404,6 +404,7 @@ void SConfig::LoadSettings()
ini.Get("Core", "MMU", &m_LocalCoreStartupParameter.bMMU, false);
ini.Get("Core", "TLBHack", &m_LocalCoreStartupParameter.iTLBHack, 0);
ini.Get("Core", "VBeam", &m_LocalCoreStartupParameter.bVBeam, false);
ini.Get("Core", "SyncGPU", &m_LocalCoreStartupParameter.bSyncGPU, false);
ini.Get("Core", "FastDiscSpeed", &m_LocalCoreStartupParameter.bFastDiscSpeed, false);
ini.Get("Core", "DCBZ", &m_LocalCoreStartupParameter.bDCBZOFF, false);
ini.Get("Core", "FrameLimit", &m_Framelimit, 1); // auto frame limit by default
@@ -413,7 +414,7 @@ void SConfig::LoadSettings()
ini.Get("Core", "GFXBackend", &m_LocalCoreStartupParameter.m_strVideoBackend, "");
// Movie
ini.Get("General", "PauseMovie", &m_PauseMovie, false);
ini.Get("Movie", "PauseMovie", &m_PauseMovie, false);
ini.Get("Movie", "Author", &m_strMovieAuthor, "");
// DSP
+2 -1
View File
@@ -50,7 +50,7 @@ SCoreStartupParameter::SCoreStartupParameter()
bDPL2Decoder(false), iLatency(14),
bRunCompareServer(false), bRunCompareClient(false),
bMMU(false), bDCBZOFF(false), iTLBHack(0), bVBeam(false),
bFastDiscSpeed(false),
bSyncGPU(false), bFastDiscSpeed(false),
SelectedLanguage(0), bWii(false),
bConfirmStop(false), bHideCursor(false),
bAutoHideCursor(false), bUsePanicHandlers(true), bOnScreenDisplayMessages(true),
@@ -78,6 +78,7 @@ void SCoreStartupParameter::LoadDefaults()
bDCBZOFF = false;
iTLBHack = 0;
bVBeam = false;
bSyncGPU = false;
bFastDiscSpeed = false;
bMergeBlocks = false;
SelectedLanguage = 0;
+1
View File
@@ -116,6 +116,7 @@ struct SCoreStartupParameter
bool bDCBZOFF;
int iTLBHack;
bool bVBeam;
bool bSyncGPU;
bool bFastDiscSpeed;
int SelectedLanguage;
+21 -6
View File
@@ -145,6 +145,8 @@ static void GenerateAudioInterrupt();
static void UpdateInterrupts();
static void IncreaseSampleCount(const u32 _uAmount);
void ReadStreamBlock(s16* _pPCM);
u64 GetAIPeriod();
int et_AI;
void Init()
{
@@ -159,6 +161,8 @@ void Init()
g_AISSampleRate = 48000;
g_AIDSampleRate = 32000;
et_AI = CoreTiming::RegisterEvent("AICallback", Update);
}
void Shutdown()
@@ -178,11 +182,8 @@ void Read32(u32& _rReturnValue, const u32 _Address)
break;
case AI_SAMPLE_COUNTER:
Update(0, 0);
_rReturnValue = m_SampleCounter;
// HACK - AI SRC init will do while (oldval == sample_counter) {}
// in order to pass this, we need to increment the counter whenever read
if (m_Control.PSTAT)
m_SampleCounter++;
break;
case AI_INTERRUPT_TIMING:
@@ -236,6 +237,9 @@ void Write32(const u32 _Value, const u32 _Address)
// Tell Drive Interface to start/stop streaming
DVDInterface::g_bStream = tmpAICtrl.PSTAT;
CoreTiming::RemoveEvent(et_AI);
CoreTiming::ScheduleEvent(((int)GetAIPeriod() / 2), et_AI);
}
// AI Interrupt
@@ -271,6 +275,8 @@ void Write32(const u32 _Value, const u32 _Address)
case AI_INTERRUPT_TIMING:
m_InterruptTiming = _Value;
CoreTiming::RemoveEvent(et_AI);
CoreTiming::ScheduleEvent(((int)GetAIPeriod() / 2), et_AI);
DEBUG_LOG(AUDIO_INTERFACE, "Set interrupt: %08x samples", m_InterruptTiming);
break;
@@ -448,7 +454,7 @@ unsigned int GetAIDSampleRate()
return g_AIDSampleRate;
}
void Update()
void Update(u64 userdata, int cyclesLate)
{
if (m_Control.PSTAT)
{
@@ -458,8 +464,17 @@ void Update()
const u32 Samples = static_cast<u32>(Diff / g_CPUCyclesPerSample);
g_LastCPUTime += Samples * g_CPUCyclesPerSample;
IncreaseSampleCount(Samples);
}
}
CoreTiming::ScheduleEvent(((int)GetAIPeriod() / 2) - cyclesLate, et_AI);
}
}
u64 GetAIPeriod()
{
u64 period = g_CPUCyclesPerSample * m_InterruptTiming;
if (period == 0)
period = 32000 * g_CPUCyclesPerSample;
return period;
}
} // end of namespace AudioInterface
+1 -1
View File
@@ -31,7 +31,7 @@ void Init();
void Shutdown();
void DoState(PointerWrap &p);
void Update();
void Update(u64 userdata, int cyclesLate);
// Called by DSP emulator
void Callback_GetSampleRate(unsigned int &_AISampleRate, unsigned int &_DACSampleRate);
+5 -6
View File
@@ -436,10 +436,6 @@ void Write16(const u16 _Value, const u32 _Address)
if (tmpControl.ARAM) g_dspState.DSPControl.ARAM = 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
g_dspState.DSPControl.unk3 = tmpControl.unk3;
g_dspState.DSPControl.pad = tmpControl.pad;
@@ -691,7 +687,7 @@ void UpdateAudioDMA()
{
// Send silence. Yeah, it's a bit of a waste to sample rate convert
// silence. or hm. Maybe we shouldn't do this :)
//dsp_emulator->DSP_SendAIBuffer(0, AudioInterface::GetAIDSampleRate());
dsp_emulator->DSP_SendAIBuffer(0, AudioInterface::GetAIDSampleRate());
}
}
@@ -701,7 +697,10 @@ void Do_ARAM_DMA()
if (!GetDSPEmulator()->IsLLE())
g_dspState.DSPControl.DMAState = 1;
GenerateDSPInterrupt(INT_ARAM, true);
if (g_arDMA.Cnt.dir || g_arDMA.Cnt.count > 10240)
CoreTiming::ScheduleEvent_Threadsafe(0, et_GenerateDSPInterrupt, INT_ARAM | (1<<16));
else
GenerateDSPInterrupt(INT_ARAM);
// Real hardware DMAs in 32byte chunks, but we can get by with 8byte chunks
if (g_arDMA.Cnt.dir)
+2 -7
View File
@@ -32,11 +32,7 @@
#include "../Movie.h"
// Disc transfer rate measured in bytes per second
static const u32 DISC_TRANSFER_RATE_GC = 3125 * 1024;
static const u32 DISC_TRANSFER_RATE_WII = 7926 * 1024;
// Disc access time measured in milliseconds
static const u32 DISC_ACCESS_TIME_MS = 128;
static const u32 DISC_TRANSFER_RATE_GC = 4 * 1024 * 1024;
namespace DVDInterface
{
@@ -501,8 +497,7 @@ void Write32(const u32 _iValue, const u32 _iAddress)
if (!SConfig::GetInstance().m_LocalCoreStartupParameter.bFastDiscSpeed)
{
u64 ticksUntilTC = m_DILENGTH.Length *
(SystemTimers::GetTicksPerSecond() / (SConfig::GetInstance().m_LocalCoreStartupParameter.bWii?DISC_TRANSFER_RATE_WII:DISC_TRANSFER_RATE_GC)) +
(SystemTimers::GetTicksPerSecond() * DISC_ACCESS_TIME_MS / 1000);
(SystemTimers::GetTicksPerSecond() / (SConfig::GetInstance().m_LocalCoreStartupParameter.bWii ? 1 : DISC_TRANSFER_RATE_GC));
CoreTiming::ScheduleEvent((int)ticksUntilTC, tc);
}
else
+9 -5
View File
@@ -25,9 +25,9 @@
#define EXI_WRITE 1
#define EXI_READWRITE 2
#include "ProcessorInterface.h"
#include "../PowerPC/PowerPC.h"
#include "CoreTiming.h"
CEXIChannel::CEXIChannel(u32 ChannelId) :
m_DMAMemoryAddress(0),
@@ -45,6 +45,8 @@ CEXIChannel::CEXIChannel(u32 ChannelId) :
for (int i = 0; i < NUM_DEVICES; i++)
m_pDevices[i] = EXIDevice_Create(EXIDEVICE_NONE, m_ChannelId);
updateInterrupts = CoreTiming::RegisterEvent("EXIInterrupt", UpdateInterrupts);
}
CEXIChannel::~CEXIChannel()
@@ -88,12 +90,12 @@ void CEXIChannel::AddDevice(IEXIDevice* pDevice, const int device_num, bool noti
if (m_ChannelId != 2)
{
m_Status.EXTINT = 1;
UpdateInterrupts();
CoreTiming::ScheduleEvent_Threadsafe_Immediate(updateInterrupts, 0);
}
}
}
void CEXIChannel::UpdateInterrupts()
void CEXIChannel::UpdateInterrupts(u64 userdata, int cyclesLate)
{
ExpansionInterface::UpdateInterrupts();
}
@@ -149,7 +151,9 @@ void CEXIChannel::Read32(u32& _uReturnValue, const u32 _iRegister)
if (m_ChannelId == 2)
m_Status.EXT = 0;
else
{
m_Status.EXT = GetDevice(1)->IsPresent() ? 1 : 0;
}
_uReturnValue = m_Status.Hex;
break;
@@ -213,7 +217,7 @@ void CEXIChannel::Write32(const u32 _iValue, const u32 _iRegister)
if (pDevice != NULL)
pDevice->SetCS(m_Status.CHIP_SELECT);
UpdateInterrupts();
CoreTiming::ScheduleEvent_Threadsafe_Immediate(updateInterrupts, 0);
}
break;
@@ -264,7 +268,7 @@ void CEXIChannel::Write32(const u32 _iValue, const u32 _iRegister)
if(!m_Control.TSTART) // completed !
{
m_Status.TCINT = 1;
UpdateInterrupts();
CoreTiming::ScheduleEvent_Threadsafe_Immediate(updateInterrupts, 0);
}
}
break;
+3 -1
View File
@@ -110,6 +110,9 @@ private:
// Since channels operate a bit differently from each other
u32 m_ChannelId;
int updateInterrupts;
static void UpdateInterrupts(u64 userdata, int cyclesLate);
public:
// get device
IEXIDevice* GetDevice(const u8 _CHIP_SELECT);
@@ -129,7 +132,6 @@ public:
void Update();
bool IsCausingInterrupt();
void UpdateInterrupts();
void DoState(PointerWrap &p);
void PauseAndLock(bool doLock, bool unpauseOnUnlock);
@@ -47,6 +47,14 @@ void CEXIMemoryCard::FlushCallback(u64 userdata, int cyclesLate)
pThis->Flush();
}
void CEXIMemoryCard::CmdDoneCallback(u64 userdata, int cyclesLate)
{
int card_index = (int)userdata;
CEXIMemoryCard* pThis = (CEXIMemoryCard*)ExpansionInterface::FindDevice(EXIDEVICE_MEMORYCARD, card_index);
if (pThis)
pThis->CmdDone();
}
CEXIMemoryCard::CEXIMemoryCard(const int index)
: card_index(index)
, m_bDirty(false)
@@ -56,7 +64,8 @@ CEXIMemoryCard::CEXIMemoryCard(const int index)
m_strFilename = "Movie.raw";
// we're potentially leaking events here, since there's no UnregisterEvent until emu shutdown, but I guess it's inconsequential
et_this_card = CoreTiming::RegisterEvent((card_index == 0) ? "memcardA" : "memcardB", FlushCallback);
et_this_card = CoreTiming::RegisterEvent((card_index == 0) ? "memcardFlushA" : "memcardFlushB", FlushCallback);
et_cmd_done = CoreTiming::RegisterEvent((card_index == 0) ? "memcardDoneA" : "memcardDoneB", CmdDoneCallback);
interruptSwitch = 0;
m_bInterruptSet = 0;
@@ -178,6 +187,21 @@ bool CEXIMemoryCard::IsPresent()
return true;
}
void CEXIMemoryCard::CmdDone()
{
status |= MC_STATUS_READY;
status &= ~MC_STATUS_BUSY;
m_bInterruptSet = 1;
m_bDirty = true;
}
void CEXIMemoryCard::CmdDoneLater(u64 cycles)
{
CoreTiming::RemoveEvent(et_cmd_done);
CoreTiming::ScheduleEvent(cycles, et_cmd_done, (u64)card_index);
}
void CEXIMemoryCard::SetCS(int cs)
{
// So that memory card won't be invalidated during flushing
@@ -201,11 +225,7 @@ void CEXIMemoryCard::SetCS(int cs)
//???
status |= MC_STATUS_READY;
status &= ~MC_STATUS_BUSY;
m_bInterruptSet = 1;
m_bDirty = true;
CmdDoneLater(5000);
}
break;
@@ -232,11 +252,7 @@ void CEXIMemoryCard::SetCS(int cs)
address = (address & ~0x1FF) | ((address+1) & 0x1FF);
}
status |= MC_STATUS_READY;
status &= ~MC_STATUS_BUSY;
m_bInterruptSet = 1;
m_bDirty = true;
CmdDoneLater(5000);
}
// Page written to memory card, not just to buffer - let's schedule a flush 0.5b cycles into the future (1 sec)
+10 -1
View File
@@ -47,9 +47,18 @@ private:
// through the userdata parameter, so that it can then call Flush on the right card.
static void FlushCallback(u64 userdata, int cyclesLate);
// Scheduled when a command that required delayed end signaling is done.
static void CmdDoneCallback(u64 userdata, int cyclesLate);
// Flushes the memory card contents to disk.
void Flush(bool exiting = false);
// Signals that the command that was previously executed is now done.
void CmdDone();
// Variant of CmdDone which schedules an event later in the future to complete the command.
void CmdDoneLater(u64 cycles);
enum
{
cmdNintendoID = 0x00,
@@ -71,7 +80,7 @@ private:
std::string m_strFilename;
int card_index;
int et_this_card;
int et_this_card, et_cmd_done;
//! memory card state
// STATE_TO_SAVE
+9 -4
View File
@@ -98,12 +98,17 @@ void STACKALIGN CheckGatherPipe()
memmove(m_gatherPipe, m_gatherPipe + cnt, m_gatherPipeCount);
// Profile where the FIFO writes are occurring.
if (jit && (jit->js.fifoWriteAddresses.find(PC)) == (jit->js.fifoWriteAddresses.end()))
if (jit && PC != 0 && (jit->js.fifoWriteAddresses.find(PC)) == (jit->js.fifoWriteAddresses.end()))
{
jit->js.fifoWriteAddresses.insert(PC);
// 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 && 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);
// Invalidate the JIT block so that it gets recompiled with the external exception check included.
jit->GetBlockCache()->InvalidateICache(PC, 4);
}
}
}
}
@@ -99,7 +99,7 @@ void Init()
m_ResetCode = 0x80000000; // Cold reset
m_InterruptCause = INT_CAUSE_RST_BUTTON | INT_CAUSE_VI;
toggleResetButton = CoreTiming::RegisterEvent("ToggleResetButton", &ToggleResetButtonCallback);
toggleResetButton = CoreTiming::RegisterEvent("ToggleResetButton", ToggleResetButtonCallback);
}
void Read16(u16& _uReturnValue, const u32 _iAddress)
@@ -69,6 +69,19 @@ int CSIDevice_GCController::RunBuffer(u8* _pBuffer, int _iLength)
*(u32*)&_pBuffer[0] = SI_GC_CONTROLLER;
break;
case CMD_DIRECT:
{
INFO_LOG(SERIALINTERFACE, "PAD - Direct (Length: %d)", _iLength);
u32 high, low;
GetData(high, low);
for (int i = 0; i < (_iLength - 1) / 2; i++)
{
_pBuffer[0 + i] = (high >> (i * 8)) & 0xff;
_pBuffer[4 + i] = (low >> (i * 8)) & 0xff;
}
}
break;
case CMD_ORIGIN:
{
INFO_LOG(SERIALINTERFACE, "PAD - Get Origin");
@@ -96,7 +109,7 @@ int CSIDevice_GCController::RunBuffer(u8* _pBuffer, int _iLength)
default:
{
ERROR_LOG(SERIALINTERFACE, "unknown SI command (0x%x)", command);
PanicAlert("SI: Unknown command");
PanicAlert("SI: Unknown command (0x%x)", command);
}
break;
}
@@ -31,6 +31,7 @@ private:
enum EBufferCommands
{
CMD_RESET = 0x00,
CMD_DIRECT = 0x40,
CMD_ORIGIN = 0x41,
CMD_RECALIBRATE = 0x42,
};
+18 -15
View File
@@ -74,6 +74,7 @@ IPC_HLE_PERIOD: For the Wiimote this is the call schedule:
#include "Thread.h"
#include "Timer.h"
#include "VideoBackendBase.h"
#include "CommandProcessor.h"
namespace SystemTimers
@@ -109,7 +110,7 @@ enum
int et_Dec;
int et_VI;
int et_SI;
int et_AI;
int et_CP;
int et_AudioDMA;
int et_DSP;
int et_IPC_HLE;
@@ -118,15 +119,15 @@ int et_PatchEngine; // PatchEngine updates every 1/60th of a second by default
// These are badly educated guesses
// Feel free to experiment. Set these in Init below.
int
// This one should simply be determined by the increasing counter in AI.
AI_PERIOD,
// These shouldn't be period controlled either, most likely.
DSP_PERIOD,
// This is a fixed value, don't change it
AUDIO_DMA_PERIOD,
// Regulates the speed of the Command Processor
CP_PERIOD,
// This is completely arbitrary. If we find that we need lower latency, we can just
// increase this number.
IPC_HLE_PERIOD;
@@ -143,12 +144,6 @@ u32 ConvertMillisecondsToTicks(u32 _Milliseconds)
return GetTicksPerSecond() / 1000 * _Milliseconds;
}
void AICallback(u64 userdata, int cyclesLate)
{
AudioInterface::Update();
CoreTiming::ScheduleEvent(AI_PERIOD - cyclesLate, et_AI);
}
// DSP/CPU timeslicing.
void DSPCallback(u64 userdata, int cyclesLate)
{
@@ -187,6 +182,12 @@ void SICallback(u64 userdata, int cyclesLate)
CoreTiming::ScheduleEvent(SerialInterface::GetTicksToNextSIPoll() - cyclesLate, et_SI);
}
void CPCallback(u64 userdata, int cyclesLate)
{
CommandProcessor::Update();
CoreTiming::ScheduleEvent(CP_PERIOD - cyclesLate, et_CP);
}
void DecrementerCallback(u64 userdata, int cyclesLate)
{
PowerPC::ppcState.spr[SPR_DEC] = 0xFFFFFFFF;
@@ -266,12 +267,12 @@ void Init()
if (DSP::GetDSPEmulator()->IsLLE())
DSP_PERIOD = 12000; // TO BE TWEAKED
// This is the biggest question mark.
AI_PERIOD = GetTicksPerSecond() / 80;
// System internal sample rate is fixed at 32KHz * 4 (16bit Stereo) / 32 bytes DMA
AUDIO_DMA_PERIOD = CPU_CORE_CLOCK / (AudioInterface::GetAIDSampleRate() * 4 / 32);
// Emulated gekko <-> flipper bus speed ratio (cpu clock / flipper clock)
CP_PERIOD = GetTicksPerSecond() / 10000;
Common::Timer::IncreaseResolution();
// store and convert localtime at boot to timebase ticks
CoreTiming::SetFakeTBStartValue((u64)(CPU_CORE_CLOCK / TIMER_RATIO) * (u64)CEXIIPL::GetGCTime());
@@ -281,19 +282,21 @@ void Init()
CoreTiming::SetFakeDecStartTicks(CoreTiming::GetTicks());
et_Dec = CoreTiming::RegisterEvent("DecCallback", DecrementerCallback);
et_AI = CoreTiming::RegisterEvent("AICallback", AICallback);
et_VI = CoreTiming::RegisterEvent("VICallback", VICallback);
et_SI = CoreTiming::RegisterEvent("SICallback", SICallback);
if (SConfig::GetInstance().m_LocalCoreStartupParameter.bSyncGPU)
et_CP = CoreTiming::RegisterEvent("CPCallback", CPCallback);
et_DSP = CoreTiming::RegisterEvent("DSPCallback", DSPCallback);
et_AudioDMA = CoreTiming::RegisterEvent("AudioDMACallback", AudioDMACallback);
et_IPC_HLE = CoreTiming::RegisterEvent("IPC_HLE_UpdateCallback", IPC_HLE_UpdateCallback);
et_PatchEngine = CoreTiming::RegisterEvent("PatchEngine", PatchEngineCallback);
CoreTiming::ScheduleEvent(AI_PERIOD, et_AI);
CoreTiming::ScheduleEvent(VideoInterface::GetTicksPerLine(), et_VI);
CoreTiming::ScheduleEvent(DSP_PERIOD, et_DSP);
CoreTiming::ScheduleEvent(VideoInterface::GetTicksPerFrame(), et_SI);
CoreTiming::ScheduleEvent(AUDIO_DMA_PERIOD, et_AudioDMA);
if (SConfig::GetInstance().m_LocalCoreStartupParameter.bSyncGPU)
CoreTiming::ScheduleEvent(CP_PERIOD, et_CP);
CoreTiming::ScheduleEvent(VideoInterface::GetTicksPerFrame(), et_PatchEngine);
+1 -1
View File
@@ -1043,7 +1043,7 @@ bool PlayWiimote(int wiimote, u8 *data, const WiimoteEmu::ReportFeatures& rptf,
if (size != sizeInMovie)
{
PanicAlertT("Fatal desync. Aborting playback. (Error in PlayWiimote: %u != %u, byte %u.)%s", (u32)sizeInMovie, (u32)size, (u32)g_currentByte, (g_numPads & 0xF)?" Try re-creating the recording with all GameCube controllers disabled (in Configure > Gamecube > Device Settings).":"");
PanicAlertT("Fatal desync. Aborting playback. (Error in PlayWiimote: %u != %u, byte %u.)%s", (u32)sizeInMovie, (u32)size, (u32)g_currentByte, (g_numPads & 0xF)?" Try re-creating the recording with all GameCube controllers disabled (in Configure > Gamecube > Device Settings), or restarting Dolphin (Dolphin currently must be restarted every time before playing back a wiimote movie).":"");
EndPlayInput(!g_bReadOnly);
return false;
}
@@ -193,6 +193,7 @@ void Interpreter::mtmsr(UGeckoInstruction _inst)
{
// Privileged?
MSR = m_GPR[_inst.RS];
PowerPC::CheckExceptions();
m_EndBlock = true;
}
+5 -1
View File
@@ -291,7 +291,9 @@ static void ImHere()
void Jit64::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.
if (MMCR0.Hex || MMCR1.Hex)
@@ -301,7 +303,8 @@ void Jit64::Cleanup()
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(&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;
@@ -561,6 +564,7 @@ const u8* Jit64::DoJit(u32 em_address, PPCAnalyst::CodeBuffer *code_buf, JitBloc
if (jo.optimizeGatherPipe && js.fifoBytesThisBlock >= 32)
{
js.fifoBytesThisBlock -= 32;
MOV(32, M(&PC), Imm32(jit->js.compilerPC)); // Helps external systems know which instruction triggered the write
ABI_CallFunction(thunks.ProtectFunction((void *)&GPFifo::CheckGatherPipe, 0));
}
@@ -302,6 +302,7 @@ void Jit64::stX(UGeckoInstruction inst)
addr += offset;
if ((addr & 0xFFFFF000) == 0xCC008000 && jo.optimizeGatherPipe)
{
MOV(32, M(&PC), Imm32(jit->js.compilerPC)); // Helps external systems know which instruction triggered the write
gpr.FlushLockX(ABI_PARAM1);
MOV(32, R(ABI_PARAM1), gpr.R(s));
if (update)
@@ -329,6 +330,7 @@ void Jit64::stX(UGeckoInstruction inst)
}
else
{
MOV(32, M(&PC), Imm32(jit->js.compilerPC)); // Helps external systems know which instruction triggered the write
switch (accessSize)
{
case 32: ABI_CallFunctionAC(thunks.ProtectFunction(true ? ((void *)&Memory::Write_U32) : ((void *)&Memory::Write_U32_Swap), 2), gpr.R(s), addr); break;
@@ -42,6 +42,7 @@ const u8 GC_ALIGNED16(pbswapShuffle2x4[16]) = {3, 2, 1, 0, 7, 6, 5, 4, 8, 9, 10,
#if 0
static void WriteDual32(u64 value, u32 address)
{
MOV(32, M(&PC), Imm32(jit->js.compilerPC)); // Helps external systems know which instruction triggered the write
Memory::Write_U32((u32)(value >> 32), address);
Memory::Write_U32((u32)value, address + 4);
}
@@ -28,6 +28,7 @@
#include "Jit.h"
#include "JitRegCache.h"
#include "HW/ProcessorInterface.h"
void Jit64::mtspr(UGeckoInstruction inst)
{
@@ -122,7 +123,29 @@ void Jit64::mtmsr(UGeckoInstruction inst)
gpr.UnlockAll();
gpr.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.
TEST(32, M(&MSR), Imm32(0x8000));
FixupBranch eeDisabled = J_CC(CC_Z);
TEST(32, M((void*)&PowerPC::ppcState.Exceptions), Imm32(EXCEPTION_EXTERNAL_INT | EXCEPTION_PERFORMANCE_MONITOR | EXCEPTION_DECREMENTER));
FixupBranch noExceptionsPending = J_CC(CC_Z);
// Check if a CP interrupt is waiting and keep the GPU emulation in sync (issue 4336)
TEST(32, M((void *)&ProcessorInterface::m_InterruptCause), Imm32(ProcessorInterface::INT_CAUSE_CP));
FixupBranch cpInt = J_CC(CC_NZ);
MOV(32, M(&PC), Imm32(js.compilerPC + 4));
WriteExternalExceptionExit();
SetJumpTarget(cpInt);
SetJumpTarget(noExceptionsPending);
SetJumpTarget(eeDisabled);
WriteExit(js.compilerPC + 4, 0);
js.firstFPInstructionFound = false;
}
+2 -2
View File
@@ -276,8 +276,8 @@ public:
InstLoc EmitLoadMSR() {
return FoldZeroOp(LoadMSR, 0);
}
InstLoc EmitStoreMSR(InstLoc val) {
return FoldUOp(StoreMSR, val);
InstLoc EmitStoreMSR(InstLoc val, InstLoc pc) {
return FoldBiOp(StoreMSR, val, pc);
}
InstLoc EmitStoreFPRF(InstLoc value) {
return FoldUOp(StoreFPRF, value);
@@ -994,8 +994,26 @@ static void DoWriteCode(IRBuilder* ibuild, JitIL* Jit, bool UseProfile, bool Mak
break;
}
case StoreMSR: {
unsigned InstLoc = ibuild->GetImmValue(getOp2(I));
regStoreInstToConstLoc(RI, 32, getOp1(I), &MSR);
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;
}
case StoreGQR: {
@@ -389,7 +389,9 @@ static void ImHere()
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.
if (MMCR0.Hex || MMCR1.Hex)
@@ -106,7 +106,7 @@ void JitIL::mfspr(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));
}
// ==============
+10 -9
View File
@@ -148,20 +148,20 @@ void JitArm::DoDownCount()
if(js.downcountAmount < 255) // We can enlarge this if we used rotations
{
SUBS(rB, rB, js.downcountAmount);
STR(rA, rB);
STR(rB, rA);
}
else
{
ARMReg rC = gpr.GetReg(false);
MOVI2R(rC, js.downcountAmount);
SUBS(rB, rB, rC);
STR(rA, rB);
STR(rB, rA);
}
gpr.Unlock(rA, rB);
}
void JitArm::WriteExitDestInR(ARMReg Reg)
{
STR(R9, Reg, PPCSTATE_OFF(pc));
STR(Reg, R9, PPCSTATE_OFF(pc));
Cleanup();
DoDownCount();
MOVI2R(Reg, (u32)asm_routines.dispatcher);
@@ -170,7 +170,7 @@ void JitArm::WriteExitDestInR(ARMReg Reg)
}
void JitArm::WriteRfiExitDestInR(ARMReg Reg)
{
STR(R9, Reg, PPCSTATE_OFF(pc));
STR(Reg, R9, PPCSTATE_OFF(pc));
Cleanup();
DoDownCount();
@@ -209,7 +209,7 @@ void JitArm::WriteExit(u32 destination, int exit_num)
{
ARMReg A = gpr.GetReg(false);
MOVI2R(A, destination);
STR(R9, A, PPCSTATE_OFF(pc));
STR(A, R9, PPCSTATE_OFF(pc));
MOVI2R(A, (u32)asm_routines.dispatcher);
B(A);
}
@@ -361,8 +361,9 @@ const u8* JitArm::DoJit(u32 em_address, PPCAnalyst::CodeBuffer *code_buf, JitBlo
// Downcount flag check, Only valid for linked blocks
{
FixupBranch skip = B_CC(CC_PL);
ARMABI_MOVI2M((u32)&PC, js.blockStart);
ARMReg rA = gpr.GetReg(false);
MOVI2R(rA, js.blockStart);
STR(rA, R9, PPCSTATE_OFF(pc));
MOVI2R(rA, (u32)asm_routines.doTiming);
B(rA);
SetJumpTarget(skip);
@@ -384,7 +385,7 @@ const u8* JitArm::DoJit(u32 em_address, PPCAnalyst::CodeBuffer *code_buf, JitBlo
LDR(A, R9, PPCSTATE_OFF(msr));
TST(A, Shift);
FixupBranch b1 = B_CC(CC_NEQ);
STR(R9, C, PPCSTATE_OFF(pc));
STR(C, R9, PPCSTATE_OFF(pc));
MOVI2R(A, (u32)asm_routines.fpException);
B(A);
SetJumpTarget(b1);
@@ -397,7 +398,7 @@ const u8* JitArm::DoJit(u32 em_address, PPCAnalyst::CodeBuffer *code_buf, JitBlo
MOVI2R(rA, (u32)&b->runCount); // Load in to register
LDR(rB, rA); // Load the actual value in to R11.
ADD(rB, rB, 1); // Add one to the value
STR(rA, rB); // Now store it back in the memory location
STR(rB, rA); // Now store it back in the memory location
// get start tic
PROFILER_QUERY_PERFORMANCE_COUNTER(&b->ticStart);
gpr.Unlock(rA, rB);
@@ -461,7 +462,7 @@ const u8* JitArm::DoJit(u32 em_address, PPCAnalyst::CodeBuffer *code_buf, JitBlo
MOVI2R(RA, (u32)&opinfo->runCount);
LDR(RB, RA);
ADD(RB, RB, 1);
STR(RA, RB);
STR(RB, RA);
gpr.Unlock(RA, RB);
}
if (!ops[i].skip)
@@ -23,6 +23,7 @@
// locating performance issues.
#include "../JitInterface.h"
#include "Jit.h"
#include "JitArmCache.h"
@@ -38,7 +39,7 @@ using namespace ArmGen;
ARMXEmitter emit((u8 *)location);
emit.MOVI2R(R11, address);
emit.MOVI2R(R12, (u32)jit->GetAsmRoutines()->dispatcher);
emit.STR(R9, R11, PPCSTATE_OFF(pc));
emit.STR(R11, R9, PPCSTATE_OFF(pc));
emit.B(R12);
}
@@ -48,11 +48,12 @@ void JitArm::sc(UGeckoInstruction inst)
gpr.Flush();
fpr.Flush();
ARMABI_MOVI2M((u32)&PC, js.compilerPC + 4); // Destroys R12 and R14
ARMReg rA = gpr.GetReg();
MOVI2R(rA, js.compilerPC + 4);
STR(rA, R9, PPCSTATE_OFF(pc));
LDR(rA, R9, PPCSTATE_OFF(Exceptions));
ORR(rA, rA, EXCEPTION_SYSCALL);
STR(R9, rA, PPCSTATE_OFF(Exceptions));
STR(rA, R9, PPCSTATE_OFF(Exceptions));
gpr.Unlock(rA);
WriteExceptionExit();
@@ -84,14 +85,14 @@ void JitArm::rfi(UGeckoInstruction inst)
LDR(rD, R9, PPCSTATE_OFF(msr));
AND(rD, rD, rB); // rD = Masked MSR
STR(R9, rD, PPCSTATE_OFF(msr));
STR(rD, R9, PPCSTATE_OFF(msr));
LDR(rB, R9, PPCSTATE_OFF(spr[SPR_SRR1])); // rB contains SRR1 here
AND(rB, rB, rC); // rB contains masked SRR1 here
ORR(rB, rD, rB); // rB = Masked MSR OR masked SRR1
STR(R9, rB, PPCSTATE_OFF(msr)); // STR rB in to rA
STR(rB, R9, PPCSTATE_OFF(msr)); // STR rB in to rA
LDR(rA, R9, PPCSTATE_OFF(spr[SPR_SRR0]));
@@ -117,7 +118,7 @@ void JitArm::bx(UGeckoInstruction inst)
ARMReg rA = gpr.GetReg(false);
u32 Jumpto = js.compilerPC + 4;
MOVI2R(rA, Jumpto);
STR(R9, rA, PPCSTATE_OFF(spr[SPR_LR]));
STR(rA, R9, PPCSTATE_OFF(spr[SPR_LR]));
//ARMABI_MOVI2M((u32)&LR, js.compilerPC + 4);
}
// If this is not the last instruction of a block,
@@ -168,7 +169,7 @@ void JitArm::bcx(UGeckoInstruction inst)
{
LDR(rB, R9, PPCSTATE_OFF(spr[SPR_CTR]));
SUBS(rB, rB, 1);
STR(R9, rB, PPCSTATE_OFF(spr[SPR_CTR]));
STR(rB, R9, PPCSTATE_OFF(spr[SPR_CTR]));
//SUB(32, M(&CTR), Imm8(1));
if (inst.BO & BO_BRANCH_IF_CTR_0)
@@ -193,7 +194,7 @@ void JitArm::bcx(UGeckoInstruction inst)
{
u32 Jumpto = js.compilerPC + 4;
MOVI2R(rB, Jumpto);
STR(R9, rB, PPCSTATE_OFF(spr[SPR_LR]));
STR(rB, R9, PPCSTATE_OFF(spr[SPR_LR]));
//ARMABI_MOVI2M((u32)&LR, js.compilerPC + 4); // Careful, destroys R14, R12
}
gpr.Unlock(rA, rB);
@@ -235,7 +236,7 @@ void JitArm::bcctrx(UGeckoInstruction inst)
{
u32 Jumpto = js.compilerPC + 4;
MOVI2R(rA, Jumpto);
STR(R9, rA, PPCSTATE_OFF(spr[SPR_LR]));
STR(rA, R9, PPCSTATE_OFF(spr[SPR_LR]));
// ARMABI_MOVI2M((u32)&LR, js.compilerPC + 4);
}
MVN(rB, 0x3); // 0xFFFFFFFC
@@ -269,7 +270,7 @@ void JitArm::bcctrx(UGeckoInstruction inst)
if (inst.LK_3){
u32 Jumpto = js.compilerPC + 4;
MOVI2R(rB, Jumpto);
STR(R9, rB, PPCSTATE_OFF(spr[SPR_LR]));
STR(rB, R9, PPCSTATE_OFF(spr[SPR_LR]));
//ARMABI_MOVI2M((u32)&LR, js.compilerPC + 4);
}
gpr.Unlock(rB); // rA gets unlocked in WriteExitDestInR
@@ -290,7 +291,7 @@ void JitArm::bclrx(UGeckoInstruction inst)
ARMReg rA = gpr.GetReg(false);
u32 Jumpto = js.compilerPC + 4;
MOVI2R(rA, Jumpto);
STR(R9, rA, PPCSTATE_OFF(spr[SPR_LR]));
STR(rA, R9, PPCSTATE_OFF(spr[SPR_LR]));
// ARMABI_MOVI2M((u32)&LR, js.compilerPC + 4);
}
return;
@@ -305,7 +306,7 @@ void JitArm::bclrx(UGeckoInstruction inst)
{
LDR(rB, R9, PPCSTATE_OFF(spr[SPR_CTR]));
SUBS(rB, rB, 1);
STR(R9, rB, PPCSTATE_OFF(spr[SPR_CTR]));
STR(rB, R9, PPCSTATE_OFF(spr[SPR_CTR]));
//SUB(32, M(&CTR), Imm8(1));
if (inst.BO & BO_BRANCH_IF_CTR_0)
@@ -341,7 +342,7 @@ void JitArm::bclrx(UGeckoInstruction inst)
if (inst.LK){
u32 Jumpto = js.compilerPC + 4;
MOVI2R(rB, Jumpto);
STR(R9, rB, PPCSTATE_OFF(spr[SPR_LR]));
STR(rB, R9, PPCSTATE_OFF(spr[SPR_LR]));
//ARMABI_MOVI2M((u32)&LR, js.compilerPC + 4);
}
gpr.Unlock(rB); // rA gets unlocked in WriteExitDestInR
@@ -40,7 +40,7 @@ void JitArm::GenerateRC(int cr) {
SetCC(CC_MI); MOV(rB, 0x8); // Result < 0
SetCC();
STRB(R9, rB, PPCSTATE_OFF(cr_fast) + cr);
STRB(rB, R9, PPCSTATE_OFF(cr_fast) + cr);
gpr.Unlock(rB);
}
void JitArm::ComputeRC(int cr) {
@@ -51,7 +51,7 @@ void JitArm::ComputeRC(int cr) {
SetCC(CC_GT); MOV(rB, 0x4); // Result > 0
SetCC();
STRB(R9, rB, PPCSTATE_OFF(cr_fast) + cr);
STRB(rB, R9, PPCSTATE_OFF(cr_fast) + cr);
gpr.Unlock(rB);
}
@@ -232,7 +232,7 @@ void JitArm::cmpli(UGeckoInstruction inst)
SetCC(CC_HI); MOV(rA, 0x4); // Result > 0
SetCC();
STRB(R9, rA, PPCSTATE_OFF(cr_fast) + crf);
STRB(rA, R9, PPCSTATE_OFF(cr_fast) + crf);
gpr.Unlock(rA);
}
@@ -269,7 +269,7 @@ void JitArm::rlwimix(UGeckoInstruction inst)
ARMReg rB = gpr.GetReg();
MOVI2R(rA, mask);
Operand2 Shift(32 - inst.SH, ST_ROR, RS); // This rotates left, while ARM has only rotate right, so swap it.
Operand2 Shift(RS, ST_ROR, 32 - inst.SH); // This rotates left, while ARM has only rotate right, so swap it.
if (inst.Rc)
{
BIC (rB, RA, rA); // RA & ~mask
@@ -296,7 +296,7 @@ void JitArm::rlwinmx(UGeckoInstruction inst)
ARMReg rA = gpr.GetReg();
MOVI2R(rA, mask);
Operand2 Shift(32 - inst.SH, ST_ROR, RS); // This rotates left, while ARM has only rotate right, so swap it.
Operand2 Shift(RS, ST_ROR, 32 - inst.SH); // This rotates left, while ARM has only rotate right, so swap it.
if (inst.Rc)
{
ANDS(RA, rA, Shift);
@@ -141,7 +141,7 @@ void JitArm::StoreFromReg(ARMReg dest, ARMReg value, int accessSize, s32 offset)
switch (accessSize)
{
case 32:
STR(dest, value); // 8
STR(value, dest); // 8
break;
case 16:
// Not implemented
@@ -70,7 +70,7 @@ void JitArm::mtspr(UGeckoInstruction inst)
}
// OK, this is easy.
STR(R9, RD, PPCSTATE_OFF(spr) + iIndex * 4);
STR(RD, R9, PPCSTATE_OFF(spr) + iIndex * 4);
}
void JitArm::mfspr(UGeckoInstruction inst)
@@ -99,6 +99,6 @@ void JitArm::mtmsr(UGeckoInstruction inst)
// Don't interpret this, if we do we get thrown out
//JITDISABLE(SystemRegisters)
STR(R9, gpr.R(inst.RS), PPCSTATE_OFF(msr));
STR(gpr.R(inst.RS), R9, PPCSTATE_OFF(msr));
WriteExit(js.compilerPC + 4, 0);
}
@@ -102,10 +102,10 @@ void JitArmAsmRoutineManager::Generate()
fpException = GetCodePtr();
LDR(R0, R9, PPCSTATE_OFF(Exceptions));
ORR(R0, R0, EXCEPTION_FPU_UNAVAILABLE);
STR(R9, R0, PPCSTATE_OFF(Exceptions));
STR(R0, R9, PPCSTATE_OFF(Exceptions));
QuickCallFunction(R14, (void*)&PowerPC::CheckExceptions);
LDR(R0, R9, PPCSTATE_OFF(npc));
STR(R9, R0, PPCSTATE_OFF(pc));
STR(R0, R9, PPCSTATE_OFF(pc));
B(dispatcher);
SetJumpTarget(bail);
@@ -117,10 +117,10 @@ void JitArmAsmRoutineManager::Generate()
// Does exception checking
testExceptions = GetCodePtr();
LDR(R0, R9, PPCSTATE_OFF(pc));
STR(R9, R0, PPCSTATE_OFF(npc));
STR(R0, R9, PPCSTATE_OFF(npc));
QuickCallFunction(R14, (void*)&PowerPC::CheckExceptions);
LDR(R0, R9, PPCSTATE_OFF(npc));
STR(R9, R0, PPCSTATE_OFF(pc));
STR(R0, R9, PPCSTATE_OFF(pc));
// Check the state pointer to see if we are exiting
// Gets checked on every exception check
MOVI2R(R0, (u32)PowerPC::GetStatePtr());
@@ -148,7 +148,7 @@ ARMReg ArmRegCache::R(u32 preg)
return ArmCRegs[a].Reg;
}
// Alright, we couldn't get a free space, dump that least used register
emit->STR(R9, ArmCRegs[Num].Reg, PPCSTATE_OFF(gpr) + ArmCRegs[Num].PPCReg * 4);
emit->STR(ArmCRegs[Num].Reg, R9, PPCSTATE_OFF(gpr) + ArmCRegs[Num].PPCReg * 4);
emit->LDR(ArmCRegs[Num].Reg, R9, PPCSTATE_OFF(gpr) + preg * 4);
ArmCRegs[Num].PPCReg = preg;
ArmCRegs[Num].LastLoad = 0;
@@ -160,7 +160,7 @@ void ArmRegCache::Flush()
for(u8 a = 0; a < NUMPPCREG; ++a)
if (ArmCRegs[a].PPCReg != 33)
{
emit->STR(R9, ArmCRegs[a].Reg, PPCSTATE_OFF(gpr) + ArmCRegs[a].PPCReg * 4);
emit->STR(ArmCRegs[a].Reg, R9, PPCSTATE_OFF(gpr) + ArmCRegs[a].PPCReg * 4);
ArmCRegs[a].PPCReg = 33;
ArmCRegs[a].LastLoad = 0;
}
@@ -32,6 +32,7 @@
#include "../../HW/GPFifo.h"
#include "../../Core.h"
#include "JitAsmCommon.h"
#include "JitBase.h"
using namespace Gen;
@@ -81,6 +81,7 @@ namespace JitInterface
default:
{
PanicAlert("Unrecognizable cpu_core: %d", core);
jit = NULL;
return NULL;
break;
}
@@ -51,6 +51,3 @@ namespace JitInterface
extern bool bFakeVMEM;
extern bool bMMU;
#ifdef _M_ARM
#include "JitArm32/Jit.h"
#endif
+8 -1
View File
@@ -161,13 +161,18 @@ void Init(int cpu_core)
switch (cpu_core)
{
case 0:
case 0:
{
cpu_core_base = interpreter;
break;
}
default:
cpu_core_base = JitInterface::InitJitCore(cpu_core);
if (!cpu_core_base) // Handle Situations where JIT core isn't available
{
WARN_LOG(POWERPC, "Jit core %d not available. Defaulting to interpreter.", cpu_core);
cpu_core_base = interpreter;
}
break;
}
@@ -213,6 +218,8 @@ void SetMode(CoreMode new_mode)
case MODE_JIT: // Switching from interpreter to JIT.
// Don't really need to do much. It'll work, the cache will refill itself.
cpu_core_base = JitInterface::GetCore();
if (!cpu_core_base) // Has a chance to not get a working JIT core if one isn't active on host
cpu_core_base = interpreter;
break;
}
}