From 3001d9492c6e7e83e82843a4b9c6186b0b58f5e5 Mon Sep 17 00:00:00 2001 From: RSDuck Date: Sat, 17 Aug 2019 16:50:48 +0200 Subject: [PATCH] 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. --- src/ARM.cpp | 46 +++++++++++++++++++++- src/ARM.h | 6 +++ src/ARMJIT.cpp | 1 + src/ARMJIT_x64/ARMJIT_Branch.cpp | 39 ++++++++---------- src/ARMJIT_x64/ARMJIT_Compiler.cpp | 5 --- src/ARMJIT_x64/ARMJIT_LoadStore.cpp | 5 --- src/libui_sdl/DlgEmuSettings.cpp | 28 ++++++++++--- src/libui_sdl/libui/ui.h | 1 + src/libui_sdl/libui/windows/stddialogs.cpp | 17 +++++++- src/libui_sdl/main.cpp | 16 ++++---- 10 files changed, 116 insertions(+), 48 deletions(-) diff --git a/src/ARM.cpp b/src/ARM.cpp index 868c2879..e4049431 100644 --- a/src/ARM.cpp +++ b/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 \ No newline at end of file +#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]); + } +} \ No newline at end of file diff --git a/src/ARM.h b/src/ARM.h index ecdf5b4e..4d387bce 100644 --- a/src/ARM.h +++ b/src/ARM.h @@ -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(); diff --git a/src/ARMJIT.cpp b/src/ARMJIT.cpp index 74554d76..949bc1c4 100644 --- a/src/ARMJIT.cpp +++ b/src/ARMJIT.cpp @@ -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 { diff --git a/src/ARMJIT_x64/ARMJIT_Branch.cpp b/src/ARMJIT_x64/ARMJIT_Branch.cpp index 9d4c1e25..30b18d77 100644 --- a/src/ARMJIT_x64/ARMJIT_Branch.cpp +++ b/src/ARMJIT_x64/ARMJIT_Branch.cpp @@ -4,6 +4,14 @@ using namespace Gen; namespace ARMJIT { + +template +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) diff --git a/src/ARMJIT_x64/ARMJIT_Compiler.cpp b/src/ARMJIT_x64/ARMJIT_Compiler.cpp index 0fbcfda9..ab13cb69 100644 --- a/src/ARMJIT_x64/ARMJIT_Compiler.cpp +++ b/src/ARMJIT_x64/ARMJIT_Compiler.cpp @@ -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(); diff --git a/src/ARMJIT_x64/ARMJIT_LoadStore.cpp b/src/ARMJIT_x64/ARMJIT_LoadStore.cpp index 6386f8ba..3b4cb7d3 100644 --- a/src/ARMJIT_x64/ARMJIT_LoadStore.cpp +++ b/src/ARMJIT_x64/ARMJIT_LoadStore.cpp @@ -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(); diff --git a/src/libui_sdl/DlgEmuSettings.cpp b/src/libui_sdl/DlgEmuSettings.cpp index 46f5f9fa..2f5ee2d7 100644 --- a/src/libui_sdl/DlgEmuSettings.cpp +++ b/src/libui_sdl/DlgEmuSettings.cpp @@ -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 diff --git a/src/libui_sdl/libui/ui.h b/src/libui_sdl/libui/ui.h index 03aef5de..e45fe913 100644 --- a/src/libui_sdl/libui/ui.h +++ b/src/libui_sdl/libui/ui.h @@ -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; diff --git a/src/libui_sdl/libui/windows/stddialogs.cpp b/src/libui_sdl/libui/windows/stddialogs.cpp index d0fd506a..75370152 100644 --- a/src/libui_sdl/libui/windows/stddialogs.cpp +++ b/src/libui_sdl/libui/windows/stddialogs.cpp @@ -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; +} \ No newline at end of file diff --git a/src/libui_sdl/main.cpp b/src/libui_sdl/main.cpp index af05d7a8..00666689 100644 --- a/src/libui_sdl/main.cpp +++ b/src/libui_sdl/main.cpp @@ -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; }