abandon pipelining on jit
fixes Golden Sun Dawn this makes the cpu state incompatible between interpreter and JIT. That's why switching cpu mode requires a restart(not requiring is stupid anyway) and the pipeline is manually filled when making a save state.
This commit is contained in:
parent
ec21172cd9
commit
3001d9492c
46
src/ARM.cpp
46
src/ARM.cpp
|
@ -22,6 +22,7 @@
|
|||
#include "ARMInterpreter.h"
|
||||
#include "AREngine.h"
|
||||
#include "ARMJIT.h"
|
||||
#include "Config.h"
|
||||
|
||||
|
||||
// instruction timing notes
|
||||
|
@ -122,6 +123,13 @@ void ARM::DoSavestate(Savestate* file)
|
|||
file->VarArray(R_IRQ, 3*sizeof(u32));
|
||||
file->VarArray(R_UND, 3*sizeof(u32));
|
||||
file->Var32(&CurInstr);
|
||||
if (!file->Saving && Config::JIT_Enable)
|
||||
{
|
||||
// hack, the JIT doesn't really pipeline
|
||||
// but we still want JIT save states to be
|
||||
// loaded while running the interpreter
|
||||
FillPipeline();
|
||||
}
|
||||
file->VarArray(NextInstr, 2*sizeof(u32));
|
||||
|
||||
file->Var32(&ExceptionBase);
|
||||
|
@ -724,4 +732,40 @@ void ARMv4::ExecuteJIT()
|
|||
if (Halted == 2)
|
||||
Halted = 0;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
void ARMv5::FillPipeline()
|
||||
{
|
||||
if (CPSR & 0x20)
|
||||
{
|
||||
if ((R[15] - 2) & 0x2)
|
||||
{
|
||||
NextInstr[0] = CodeRead32(R[15] - 4, false) >> 16;
|
||||
NextInstr[1] = CodeRead32(R[15], false);
|
||||
}
|
||||
else
|
||||
{
|
||||
NextInstr[0] = CodeRead32(R[15] - 2, false);
|
||||
NextInstr[1] = NextInstr[0] >> 16;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
NextInstr[0] = CodeRead32(R[15] - 4, false);
|
||||
NextInstr[1] = CodeRead32(R[15], false);
|
||||
}
|
||||
}
|
||||
|
||||
void ARMv4::FillPipeline()
|
||||
{
|
||||
if (CPSR & 0x20)
|
||||
{
|
||||
NextInstr[0] = CodeRead16(R[15] - 2);
|
||||
NextInstr[1] = CodeRead16(R[15]);
|
||||
}
|
||||
else
|
||||
{
|
||||
NextInstr[0] = CodeRead32(R[15] - 4);
|
||||
NextInstr[1] = CodeRead32(R[15]);
|
||||
}
|
||||
}
|
|
@ -42,6 +42,8 @@ public:
|
|||
|
||||
virtual void DoSavestate(Savestate* file);
|
||||
|
||||
virtual void FillPipeline() = 0;
|
||||
|
||||
virtual void JumpTo(u32 addr, bool restorecpsr = false) = 0;
|
||||
void RestoreCPSR();
|
||||
|
||||
|
@ -148,6 +150,8 @@ public:
|
|||
|
||||
void UpdateRegionTimings(u32 addrstart, u32 addrend);
|
||||
|
||||
void FillPipeline();
|
||||
|
||||
void JumpTo(u32 addr, bool restorecpsr = false);
|
||||
|
||||
void PrefetchAbort();
|
||||
|
@ -272,6 +276,8 @@ class ARMv4 : public ARM
|
|||
public:
|
||||
ARMv4();
|
||||
|
||||
void FillPipeline();
|
||||
|
||||
void JumpTo(u32 addr, bool restorecpsr = false);
|
||||
|
||||
void Execute();
|
||||
|
|
|
@ -139,6 +139,7 @@ CompiledBlock CompileBlock(ARM* cpu)
|
|||
int i = 0;
|
||||
u32 blockAddr = cpu->R[15] - (thumb ? 2 : 4);
|
||||
u32 r15 = cpu->R[15];
|
||||
cpu->FillPipeline();
|
||||
u32 nextInstr[2] = {cpu->NextInstr[0], cpu->NextInstr[1]};
|
||||
do
|
||||
{
|
||||
|
|
|
@ -4,6 +4,14 @@ using namespace Gen;
|
|||
|
||||
namespace ARMJIT
|
||||
{
|
||||
|
||||
template <typename T>
|
||||
int squeezePointer(T* ptr)
|
||||
{
|
||||
int truncated = (int)((u64)ptr);
|
||||
assert((T*)((u64)truncated) == ptr);
|
||||
return truncated;
|
||||
}
|
||||
|
||||
void Compiler::Comp_JumpTo(u32 addr, bool forceNonConstantCycles)
|
||||
{
|
||||
|
@ -12,9 +20,7 @@ void Compiler::Comp_JumpTo(u32 addr, bool forceNonConstantCycles)
|
|||
// we'll see how it works out
|
||||
|
||||
u32 newPC;
|
||||
u32 nextInstr[2];
|
||||
u32 cycles = 0;
|
||||
bool setupRegion = false;
|
||||
|
||||
if (addr & 0x1 && !Thumb)
|
||||
{
|
||||
|
@ -40,7 +46,7 @@ void Compiler::Comp_JumpTo(u32 addr, bool forceNonConstantCycles)
|
|||
|
||||
MOV(32, MDisp(RCPU, offsetof(ARMv5, RegionCodeCycles)), Imm32(regionCodeCycles));
|
||||
|
||||
setupRegion = newregion != oldregion;
|
||||
bool setupRegion = newregion != oldregion;
|
||||
if (setupRegion)
|
||||
cpu9->SetupCodeMem(addr);
|
||||
|
||||
|
@ -53,15 +59,14 @@ void Compiler::Comp_JumpTo(u32 addr, bool forceNonConstantCycles)
|
|||
// doesn't matter if we put garbage in the MSbs there
|
||||
if (addr & 0x2)
|
||||
{
|
||||
nextInstr[0] = cpu9->CodeRead32(addr-2, true) >> 16;
|
||||
cpu9->CodeRead32(addr-2, true);
|
||||
cycles += cpu9->CodeCycles;
|
||||
nextInstr[1] = cpu9->CodeRead32(addr+2, false);
|
||||
cpu9->CodeRead32(addr+2, false);
|
||||
cycles += CurCPU->CodeCycles;
|
||||
}
|
||||
else
|
||||
{
|
||||
nextInstr[0] = cpu9->CodeRead32(addr, true);
|
||||
nextInstr[1] = nextInstr[0] >> 16;
|
||||
cpu9->CodeRead32(addr, true);
|
||||
cycles += cpu9->CodeCycles;
|
||||
}
|
||||
}
|
||||
|
@ -70,12 +75,15 @@ void Compiler::Comp_JumpTo(u32 addr, bool forceNonConstantCycles)
|
|||
addr &= ~0x3;
|
||||
newPC = addr+4;
|
||||
|
||||
nextInstr[0] = cpu9->CodeRead32(addr, true);
|
||||
cpu9->CodeRead32(addr, true);
|
||||
cycles += cpu9->CodeCycles;
|
||||
nextInstr[1] = cpu9->CodeRead32(addr+4, false);
|
||||
cpu9->CodeRead32(addr+4, false);
|
||||
cycles += cpu9->CodeCycles;
|
||||
}
|
||||
|
||||
MOV(64, MDisp(RCPU, offsetof(ARM, CodeMem.Mem)), Imm32(squeezePointer(cpu9->CodeMem.Mem)));
|
||||
MOV(32, MDisp(RCPU, offsetof(ARM, CodeMem.Mask)), Imm32(cpu9->CodeMem.Mask));
|
||||
|
||||
cpu9->RegionCodeCycles = compileTimeCodeCycles;
|
||||
if (setupRegion)
|
||||
cpu9->SetupCodeMem(R15);
|
||||
|
@ -102,8 +110,6 @@ void Compiler::Comp_JumpTo(u32 addr, bool forceNonConstantCycles)
|
|||
u32 compileTimePC = CurCPU->R[15];
|
||||
CurCPU->R[15] = newPC;
|
||||
|
||||
nextInstr[0] = ((ARMv4*)CurCPU)->CodeRead16(addr);
|
||||
nextInstr[1] = ((ARMv4*)CurCPU)->CodeRead16(addr+2);
|
||||
cycles += NDS::ARM7MemTimings[codeCycles][0] + NDS::ARM7MemTimings[codeCycles][1];
|
||||
|
||||
CurCPU->R[15] = compileTimePC;
|
||||
|
@ -116,8 +122,6 @@ void Compiler::Comp_JumpTo(u32 addr, bool forceNonConstantCycles)
|
|||
u32 compileTimePC = CurCPU->R[15];
|
||||
CurCPU->R[15] = newPC;
|
||||
|
||||
nextInstr[0] = cpu7->CodeRead32(addr);
|
||||
nextInstr[1] = cpu7->CodeRead32(addr+4);
|
||||
cycles += NDS::ARM7MemTimings[codeCycles][2] + NDS::ARM7MemTimings[codeCycles][3];
|
||||
|
||||
CurCPU->R[15] = compileTimePC;
|
||||
|
@ -128,19 +132,10 @@ void Compiler::Comp_JumpTo(u32 addr, bool forceNonConstantCycles)
|
|||
}
|
||||
|
||||
MOV(32, MDisp(RCPU, offsetof(ARM, R[15])), Imm32(newPC));
|
||||
MOV(32, MDisp(RCPU, offsetof(ARM, NextInstr[0])), Imm32(nextInstr[0]));
|
||||
MOV(32, MDisp(RCPU, offsetof(ARM, NextInstr[1])), Imm32(nextInstr[1]));
|
||||
if ((Thumb || CurInstr.Cond() >= 0xE) && !forceNonConstantCycles)
|
||||
ConstantCycles += cycles;
|
||||
else
|
||||
ADD(32, MDisp(RCPU, offsetof(ARM, Cycles)), Imm8(cycles));
|
||||
|
||||
if (setupRegion)
|
||||
{
|
||||
MOV(64, R(ABI_PARAM1), R(RCPU));
|
||||
MOV(32, R(ABI_PARAM2), Imm32(newPC));
|
||||
CALL((void*)&ARMv5::SetupCodeMem);
|
||||
}
|
||||
}
|
||||
|
||||
void Compiler::Comp_JumpTo(Gen::X64Reg addr, bool restoreCPSR)
|
||||
|
|
|
@ -395,11 +395,6 @@ CompiledBlock Compiler::CompileBlock(ARM* cpu, FetchedInstr instrs[], int instrs
|
|||
MOV(32, MDisp(RCPU, offsetof(ARM, R[15])), Imm32(R15));
|
||||
MOV(32, MDisp(RCPU, offsetof(ARM, CodeCycles)), Imm32(CurInstr.CodeCycles));
|
||||
MOV(32, MDisp(RCPU, offsetof(ARM, CurInstr)), Imm32(CurInstr.Instr));
|
||||
if (i == instrsCount - 1)
|
||||
{
|
||||
MOV(32, MDisp(RCPU, offsetof(ARM, NextInstr[0])), Imm32(CurInstr.NextInstr[0]));
|
||||
MOV(32, MDisp(RCPU, offsetof(ARM, NextInstr[1])), Imm32(CurInstr.NextInstr[1]));
|
||||
}
|
||||
|
||||
if (comp == NULL)
|
||||
SaveCPSR();
|
||||
|
|
|
@ -457,11 +457,6 @@ void Compiler::Comp_MemAccess(OpArg rd, bool signExtend, bool store, int size)
|
|||
}
|
||||
}
|
||||
|
||||
void printStuff2(u32 a, u32 b)
|
||||
{
|
||||
printf("b %x %x\n", a, b);
|
||||
}
|
||||
|
||||
s32 Compiler::Comp_MemAccessBlock(int rn, BitSet16 regs, bool store, bool preinc, bool decrement, bool usermode)
|
||||
{
|
||||
int regsCount = regs.Count();
|
||||
|
|
|
@ -29,6 +29,7 @@
|
|||
|
||||
void ApplyNewSettings(int type);
|
||||
|
||||
extern bool RunningSomething;
|
||||
|
||||
namespace DlgEmuSettings
|
||||
{
|
||||
|
@ -57,10 +58,10 @@ void OnCancel(uiButton* btn, void* blarg)
|
|||
|
||||
void OnOk(uiButton* btn, void* blarg)
|
||||
{
|
||||
Config::DirectBoot = uiCheckboxChecked(cbDirectBoot);
|
||||
|
||||
#ifdef JIT_ENABLED
|
||||
Config::JIT_Enable = uiCheckboxChecked(cbJITEnabled);
|
||||
bool restart = false;
|
||||
|
||||
bool enableJit = uiCheckboxChecked(cbJITEnabled);
|
||||
char* maxBlockSizeStr = uiEntryText(enJITMaxBlockSize);
|
||||
long blockSize = strtol(maxBlockSizeStr, NULL, 10);
|
||||
uiFreeText(maxBlockSizeStr);
|
||||
|
@ -68,15 +69,32 @@ void OnOk(uiButton* btn, void* blarg)
|
|||
blockSize = 1;
|
||||
if (blockSize > 32)
|
||||
blockSize = 32;
|
||||
Config::JIT_MaxBlockSize = blockSize;
|
||||
|
||||
if (enableJit != Config::JIT_Enable || blockSize != Config::JIT_MaxBlockSize)
|
||||
{
|
||||
if (RunningSomething &&
|
||||
!uiMsgBoxConfirm(win, "Reset emulator",
|
||||
"Changing JIT settings requires a reset.\n\nDo you want to continue?"))
|
||||
return;
|
||||
|
||||
Config::JIT_Enable = enableJit;
|
||||
Config::JIT_MaxBlockSize = Config::JIT_MaxBlockSize;
|
||||
|
||||
restart = true;
|
||||
}
|
||||
#endif
|
||||
|
||||
Config::DirectBoot = uiCheckboxChecked(cbDirectBoot);
|
||||
|
||||
Config::Save();
|
||||
|
||||
uiControlDestroy(uiControl(win));
|
||||
opened = false;
|
||||
|
||||
ApplyNewSettings(4);
|
||||
#ifdef JIT_ENABLED
|
||||
if (restart)
|
||||
ApplyNewSettings(4);
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef JIT_ENABLED
|
||||
|
|
|
@ -289,6 +289,7 @@ _UI_EXTERN char *uiOpenFile(uiWindow *parent, const char* filter, const char* in
|
|||
_UI_EXTERN char *uiSaveFile(uiWindow *parent, const char* filter, const char* initpath);
|
||||
_UI_EXTERN void uiMsgBox(uiWindow *parent, const char *title, const char *description);
|
||||
_UI_EXTERN void uiMsgBoxError(uiWindow *parent, const char *title, const char *description);
|
||||
_UI_EXTERN int uiMsgBoxConfirm(uiWindow * parent, const char *title, const char *description);
|
||||
|
||||
typedef struct uiArea uiArea;
|
||||
typedef struct uiAreaHandler uiAreaHandler;
|
||||
|
|
|
@ -136,7 +136,7 @@ char *uiSaveFile(uiWindow *parent, const char* filter, const char* initpath)
|
|||
|
||||
// TODO switch to TaskDialogIndirect()?
|
||||
|
||||
static void msgbox(HWND parent, const char *title, const char *description, TASKDIALOG_COMMON_BUTTON_FLAGS buttons, PCWSTR icon)
|
||||
static int msgbox(HWND parent, const char *title, const char *description, TASKDIALOG_COMMON_BUTTON_FLAGS buttons, PCWSTR icon)
|
||||
{
|
||||
WCHAR *wtitle, *wdescription;
|
||||
HRESULT hr;
|
||||
|
@ -144,12 +144,15 @@ static void msgbox(HWND parent, const char *title, const char *description, TASK
|
|||
wtitle = toUTF16(title);
|
||||
wdescription = toUTF16(description);
|
||||
|
||||
hr = TaskDialog(parent, NULL, NULL, wtitle, wdescription, buttons, icon, NULL);
|
||||
int result;
|
||||
hr = TaskDialog(parent, NULL, NULL, wtitle, wdescription, buttons, icon, &result);
|
||||
if (hr != S_OK)
|
||||
logHRESULT(L"error showing task dialog", hr);
|
||||
|
||||
uiFree(wdescription);
|
||||
uiFree(wtitle);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void uiMsgBox(uiWindow *parent, const char *title, const char *description)
|
||||
|
@ -165,3 +168,13 @@ void uiMsgBoxError(uiWindow *parent, const char *title, const char *description)
|
|||
msgbox(windowHWND(parent), title, description, TDCBF_OK_BUTTON, TD_ERROR_ICON);
|
||||
enableAllWindowsExcept(parent);
|
||||
}
|
||||
|
||||
int uiMsgBoxConfirm(uiWindow * parent, const char *title, const char *description)
|
||||
{
|
||||
disableAllWindowsExcept(parent);
|
||||
int result =
|
||||
msgbox(windowHWND(parent), title, description, TDCBF_OK_BUTTON | TDCBF_CANCEL_BUTTON, TD_WARNING_ICON);
|
||||
enableAllWindowsExcept(parent);
|
||||
|
||||
return result == IDOK;
|
||||
}
|
|
@ -2355,6 +2355,14 @@ void OnSetShowOSD(uiMenuItem* item, uiWindow* window, void* blarg)
|
|||
|
||||
void ApplyNewSettings(int type)
|
||||
{
|
||||
#ifdef JIT_ENABLED
|
||||
if (type == 4)
|
||||
{
|
||||
Reset(NULL);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!RunningSomething)
|
||||
{
|
||||
if (type == 1) return;
|
||||
|
@ -2409,14 +2417,6 @@ void ApplyNewSettings(int type)
|
|||
GPU3D::InitRenderer(Screen_UseGL);
|
||||
if (Screen_UseGL) uiGLMakeContextCurrent(NULL);
|
||||
}
|
||||
else if (type == 4)
|
||||
{
|
||||
#ifdef JIT_ENABLED
|
||||
if (Config::JIT_Enable)
|
||||
ARMJIT::InvalidateBlockCache();
|
||||
#endif
|
||||
}
|
||||
|
||||
EmuRunning = prevstatus;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue