From 7fee5abf9fae3d070a729e06ca2874c258e14b3c Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Thu, 8 Oct 2015 22:15:28 +0200 Subject: [PATCH] x86/x64: Don't use a separate code block for pregenerated functions, just like on ARM --- CMakeLists.txt | 1 - Core/Core.vcxproj | 1 - Core/Core.vcxproj.filters | 3 -- Core/MIPS/JitCommon/JitBlockCache.cpp | 3 +- Core/MIPS/JitCommon/JitCommon.cpp | 5 +- Core/MIPS/x86/Asm.cpp | 67 ++++++++++++++------------- Core/MIPS/x86/Asm.h | 54 --------------------- Core/MIPS/x86/Jit.cpp | 55 ++++++++++------------ Core/MIPS/x86/Jit.h | 30 +++++++++--- Core/MIPS/x86/RegCache.cpp | 1 - 10 files changed, 84 insertions(+), 136 deletions(-) delete mode 100644 Core/MIPS/x86/Asm.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 2b7c3a2d73..cb370df423 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1091,7 +1091,6 @@ elseif(ARM64) elseif(X86) set(CoreExtra ${CoreExtra} Core/MIPS/x86/Asm.cpp - Core/MIPS/x86/Asm.h Core/MIPS/x86/CompALU.cpp Core/MIPS/x86/CompBranch.cpp Core/MIPS/x86/CompFPU.cpp diff --git a/Core/Core.vcxproj b/Core/Core.vcxproj index d84ff688e7..6358eb313a 100644 --- a/Core/Core.vcxproj +++ b/Core/Core.vcxproj @@ -679,7 +679,6 @@ true true - diff --git a/Core/Core.vcxproj.filters b/Core/Core.vcxproj.filters index c004922624..0752ffdb08 100644 --- a/Core/Core.vcxproj.filters +++ b/Core/Core.vcxproj.filters @@ -666,9 +666,6 @@ MIPS\x86 - - MIPS\x86 - MIPS\x86 diff --git a/Core/MIPS/JitCommon/JitBlockCache.cpp b/Core/MIPS/JitCommon/JitBlockCache.cpp index 2e49d4834b..9fa6ceb040 100644 --- a/Core/MIPS/JitCommon/JitBlockCache.cpp +++ b/Core/MIPS/JitCommon/JitBlockCache.cpp @@ -46,7 +46,6 @@ #if defined(_M_IX86) || defined(_M_X64) #include "Common/x64Analyzer.h" -#include "Core/MIPS/x86/Asm.h" #endif // #include "JitBase.h" @@ -593,7 +592,7 @@ void JitBlockCache::DestroyBlock(int block_num, bool invalidate) { // Spurious entrances from previously linked blocks can only come through checkedEntry XEmitter emit((u8 *)b->checkedEntry); emit.MOV(32, M(&mips_->pc), Imm32(b->originalAddress)); - emit.JMP(MIPSComp::jit->Asm().dispatcher, true); + emit.JMP(MIPSComp::jit->GetDispatcher(), true); #elif defined(ARM64) diff --git a/Core/MIPS/JitCommon/JitCommon.cpp b/Core/MIPS/JitCommon/JitCommon.cpp index d96a69ce65..0591f5b286 100644 --- a/Core/MIPS/JitCommon/JitCommon.cpp +++ b/Core/MIPS/JitCommon/JitCommon.cpp @@ -154,15 +154,12 @@ const char *ppsspp_resolver(struct ud*, *offset = addr - (uint64_t)(¤tMIPS->v[0]); return "mips.v"; } + // But these do. if (MIPSComp::jit->IsInSpace((u8 *)(intptr_t)addr)) { *offset = addr - (uint64_t)MIPSComp::jit->GetBasePtr(); return "jitcode"; } - if (MIPSComp::jit->Asm().IsInSpace((u8 *)(intptr_t)addr)) { - *offset = addr - (uint64_t)MIPSComp::jit->Asm().GetBasePtr(); - return "dispatcher"; - } return NULL; } diff --git a/Core/MIPS/x86/Asm.cpp b/Core/MIPS/x86/Asm.cpp index 2fb8301397..253a3c2a3d 100644 --- a/Core/MIPS/x86/Asm.cpp +++ b/Core/MIPS/x86/Asm.cpp @@ -28,12 +28,16 @@ #include "Common/MemoryUtil.h" #include "Core/MIPS/JitCommon/JitCommon.h" -#include "Core/MIPS/x86/Asm.h" #include "Core/MIPS/x86/Jit.h" using namespace Gen; using namespace X64JitConstants; +extern volatile CoreState coreState; + +namespace MIPSComp +{ + //TODO - make an option //#if _DEBUG static bool enableDebug = false; @@ -54,25 +58,23 @@ static bool enableDebug = false; //R14 - Pointer to fpr/gpr regs //R15 - Pointer to array of block pointers -extern volatile CoreState coreState; - void ImHere() { DEBUG_LOG(CPU, "JIT Here: %08x", currentMIPS->pc); } -void AsmRoutineManager::Generate(MIPSState *mips, MIPSComp::Jit *jit, MIPSComp::JitOptions *jo) { +void Jit::GenerateFixedCode(JitOptions &jo) { const u8 *start = AlignCode16(); restoreRoundingMode = AlignCode16(); { - STMXCSR(M(&mips->temp)); + STMXCSR(M(&mips_->temp)); // Clear the rounding mode and flush-to-zero bits back to 0. - AND(32, M(&mips->temp), Imm32(~(7 << 13))); - LDMXCSR(M(&mips->temp)); + AND(32, M(&mips_->temp), Imm32(~(7 << 13))); + LDMXCSR(M(&mips_->temp)); RET(); } applyRoundingMode = AlignCode16(); { - MOV(32, R(EAX), M(&mips->fcr31)); + MOV(32, R(EAX), M(&mips_->fcr31)); AND(32, R(EAX), Imm32(0x1000003)); // If it's 0, we don't actually bother setting. This is the most common. @@ -80,7 +82,7 @@ void AsmRoutineManager::Generate(MIPSState *mips, MIPSComp::Jit *jit, MIPSComp:: // flush-to-zero disabled. FixupBranch skip = J_CC(CC_Z); - STMXCSR(M(&mips->temp)); + STMXCSR(M(&mips_->temp)); // The MIPS bits don't correspond exactly, so we have to adjust. // 0 -> 0 (skip2), 1 -> 3, 2 -> 2 (skip2), 3 -> 1 @@ -90,14 +92,14 @@ void AsmRoutineManager::Generate(MIPSState *mips, MIPSComp::Jit *jit, MIPSComp:: SetJumpTarget(skip2); SHL(32, R(EAX), Imm8(13)); - OR(32, M(&mips->temp), R(EAX)); + OR(32, M(&mips_->temp), R(EAX)); - TEST(32, M(&mips->fcr31), Imm32(1 << 24)); + TEST(32, M(&mips_->fcr31), Imm32(1 << 24)); FixupBranch skip3 = J_CC(CC_Z); - OR(32, M(&mips->temp), Imm32(1 << 15)); + OR(32, M(&mips_->temp), Imm32(1 << 15)); SetJumpTarget(skip3); - LDMXCSR(M(&mips->temp)); + LDMXCSR(M(&mips_->temp)); SetJumpTarget(skip); RET(); } @@ -105,14 +107,14 @@ void AsmRoutineManager::Generate(MIPSState *mips, MIPSComp::Jit *jit, MIPSComp:: updateRoundingMode = AlignCode16(); { // If it's only ever 0, we don't actually bother applying or restoring it. // This is the most common situation. - TEST(32, M(&mips->fcr31), Imm32(0x01000003)); + TEST(32, M(&mips_->fcr31), Imm32(0x01000003)); FixupBranch skip = J_CC(CC_Z); #ifdef _M_X64 // TODO: Move the hasSetRounding flag somewhere we can reach it through the context pointer, or something. - MOV(64, R(RAX), Imm64((uintptr_t)&jit->js.hasSetRounding)); + MOV(64, R(RAX), Imm64((uintptr_t)&js.hasSetRounding)); MOV(8, MatR(RAX), Imm8(1)); #else - MOV(8, M(&jit->js.hasSetRounding), Imm8(1)); + MOV(8, M(&js.hasSetRounding), Imm8(1)); #endif SetJumpTarget(skip); @@ -124,20 +126,19 @@ void AsmRoutineManager::Generate(MIPSState *mips, MIPSComp::Jit *jit, MIPSComp:: #ifdef _M_X64 // Two statically allocated registers. MOV(64, R(MEMBASEREG), ImmPtr(Memory::base)); - uintptr_t jitbase = (uintptr_t)jit->GetBasePtr(); - if (jitbase > 0x7FFFFFFFULL) - { - MOV(64, R(JITBASEREG), ImmPtr(jit->GetBasePtr())); - jo->reserveR15ForAsm = true; + uintptr_t jitbase = (uintptr_t)GetBasePtr(); + if (jitbase > 0x7FFFFFFFULL) { + MOV(64, R(JITBASEREG), ImmPtr(GetBasePtr())); + jo.reserveR15ForAsm = true; } #endif // From the start of the FP reg, a single byte offset can reach all GPR + all FPR (but no VFPUR) - MOV(PTRBITS, R(CTXREG), ImmPtr(&mips->f[0])); + MOV(PTRBITS, R(CTXREG), ImmPtr(&mips_->f[0])); outerLoop = GetCodePtr(); - jit->RestoreRoundingMode(true, this); + RestoreRoundingMode(true); ABI_CallFunction(reinterpret_cast(&CoreTiming::Advance)); - jit->ApplyRoundingMode(true, this); + ApplyRoundingMode(true); FixupBranch skipToRealDispatch = J(); //skip the sync and compare first time dispatcherCheckCoreState = GetCodePtr(); @@ -161,7 +162,7 @@ void AsmRoutineManager::Generate(MIPSState *mips, MIPSComp::Jit *jit, MIPSComp:: dispatcherNoCheck = GetCodePtr(); - MOV(32, R(EAX), M(&mips->pc)); + MOV(32, R(EAX), M(&mips_->pc)); dispatcherInEAXNoCheck = GetCodePtr(); #ifdef _M_IX86 @@ -178,14 +179,14 @@ void AsmRoutineManager::Generate(MIPSState *mips, MIPSComp::Jit *jit, MIPSComp:: FixupBranch notfound = J_CC(CC_NE); if (enableDebug) { - ADD(32, M(&mips->debugCount), Imm8(1)); + ADD(32, M(&mips_->debugCount), Imm8(1)); } //grab from list and jump to it AND(32, R(EAX), Imm32(MIPS_EMUHACK_VALUE_MASK)); #ifdef _M_IX86 - ADD(32, R(EAX), ImmPtr(jit->GetBasePtr())); + ADD(32, R(EAX), ImmPtr(GetBasePtr())); #elif _M_X64 - if (jo->reserveR15ForAsm) + if (jo.reserveR15ForAsm) ADD(64, R(RAX), R(JITBASEREG)); else ADD(64, R(EAX), Imm32(jitbase)); @@ -194,9 +195,9 @@ void AsmRoutineManager::Generate(MIPSState *mips, MIPSComp::Jit *jit, MIPSComp:: SetJumpTarget(notfound); //Ok, no block, let's jit - jit->RestoreRoundingMode(true, this); + RestoreRoundingMode(true); ABI_CallFunction(&MIPSComp::JitAt); - jit->ApplyRoundingMode(true, this); + ApplyRoundingMode(true); JMP(dispatcherNoCheck, true); // Let's just dispatch again, we'll enter the block since we know it's there. SetJumpTarget(bail); @@ -206,12 +207,14 @@ void AsmRoutineManager::Generate(MIPSState *mips, MIPSComp::Jit *jit, MIPSComp:: J_CC(CC_Z, outerLoop, true); SetJumpTarget(badCoreState); - jit->RestoreRoundingMode(true, this); + RestoreRoundingMode(true); ABI_PopAllCalleeSavedRegsAndAdjustStack(); RET(); breakpointBailout = GetCodePtr(); - jit->RestoreRoundingMode(true, this); + RestoreRoundingMode(true); ABI_PopAllCalleeSavedRegsAndAdjustStack(); RET(); } + +} // namespace \ No newline at end of file diff --git a/Core/MIPS/x86/Asm.h b/Core/MIPS/x86/Asm.h deleted file mode 100644 index af841b8256..0000000000 --- a/Core/MIPS/x86/Asm.h +++ /dev/null @@ -1,54 +0,0 @@ -// Copyright (C) 2003 Dolphin Project. - -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, version 2.0 or later versions. - -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License 2.0 for more details. - -// A copy of the GPL 2.0 should have been included with the program. -// If not, see http://www.gnu.org/licenses/ - -// Official SVN repository and contact information can be found at -// http://code.google.com/p/dolphin-emu/ - -#pragma once - -#include "Common/x64Emitter.h" -#include "Core/MIPS/MIPS.h" - -// Runtime generated assembly routines, like the Dispatcher. - -namespace MIPSComp { - class Jit; - struct JitOptions; -} - -class AsmRoutineManager : public Gen::XCodeBlock { -private: - void Generate(MIPSState *mips, MIPSComp::Jit *jit, MIPSComp::JitOptions *jo); - -public: - void Init(MIPSState *mips, MIPSComp::Jit *jit, MIPSComp::JitOptions *jo) { - AllocCodeSpace(8192); - Generate(mips, jit, jo); - WriteProtect(); - } - - const u8 *enterDispatcher; - - const u8 *outerLoop; - const u8 *dispatcher; - const u8 *dispatcherCheckCoreState; - const u8 *dispatcherNoCheck; - const u8 *dispatcherInEAXNoCheck; - - const u8 *breakpointBailout; - - const u8 *restoreRoundingMode; - const u8 *applyRoundingMode; - const u8 *updateRoundingMode; -}; diff --git a/Core/MIPS/x86/Jit.cpp b/Core/MIPS/x86/Jit.cpp index abb7c2a883..7f14c537af 100644 --- a/Core/MIPS/x86/Jit.cpp +++ b/Core/MIPS/x86/Jit.cpp @@ -119,13 +119,13 @@ static void JitLogMiss(MIPSOpcode op) // JitBlockCache doesn't use this, just stores it. #pragma warning(disable:4355) #endif -Jit::Jit(MIPSState *mips) : blocks(mips, this), mips_(mips) -{ +Jit::Jit(MIPSState *mips) + : blocks(mips, this), mips_(mips) { blocks.Init(); gpr.SetEmitter(this); fpr.SetEmitter(this); AllocCodeSpace(1024 * 1024 * 16); - asm_.Init(mips, this, &jo); + GenerateFixedCode(jo); safeMemFuncs.Init(&thunks); js.startDefaultPrefix = mips_->HasDefaultPrefix(); @@ -220,34 +220,29 @@ void Jit::WriteDowncount(int offset) SUB(32, M(&mips_->downcount), downcount > 127 ? Imm32(downcount) : Imm8(downcount)); } -void Jit::RestoreRoundingMode(bool force, XEmitter *emitter) { +void Jit::RestoreRoundingMode(bool force) { // If the game has never set an interesting rounding mode, we can safely skip this. if (force || js.hasSetRounding) { - if (emitter == NULL) - emitter = this; - emitter->CALL(asm_.restoreRoundingMode); + CALL(restoreRoundingMode); } } -void Jit::ApplyRoundingMode(bool force, XEmitter *emitter) { +void Jit::ApplyRoundingMode(bool force) { // If the game has never set an interesting rounding mode, we can safely skip this. if (force || js.hasSetRounding) { - if (emitter == NULL) - emitter = this; - emitter->CALL(asm_.applyRoundingMode); + CALL(applyRoundingMode); } } -void Jit::UpdateRoundingMode(XEmitter *emitter) { - if (emitter == NULL) - emitter = this; - emitter->CALL(asm_.updateRoundingMode); +void Jit::UpdateRoundingMode() { + CALL(updateRoundingMode); } void Jit::ClearCache() { blocks.Clear(); ClearCodeSpace(); + GenerateFixedCode(jo); } void Jit::InvalidateCache() @@ -337,7 +332,7 @@ void Jit::Compile(u32 em_address) void Jit::RunLoopUntil(u64 globalticks) { PROFILE_THIS_SCOPE("jit"); - ((void (*)())asm_.enterDispatcher)(); + ((void (*)())enterDispatcher)(); } u32 Jit::GetCompilerPC() { @@ -367,7 +362,7 @@ const u8 *Jit::DoJit(u32 em_address, JitBlock *b) // Downcount flag check. The last block decremented downcounter, and the flag should still be available. FixupBranch skip = J_CC(CC_NS); MOV(32, M(&mips_->pc), Imm32(js.blockStart)); - JMP(asm_.outerLoop, true); // downcount hit zero - go advance. + JMP(outerLoop, true); // downcount hit zero - go advance. SetJumpTarget(skip); b->normalEntry = GetCodePtr(); @@ -445,15 +440,13 @@ void Jit::AddContinuedBlock(u32 dest) js.lastContinuedPC = dest; } -bool Jit::DescribeCodePtr(const u8 *ptr, std::string &name) -{ +bool Jit::DescribeCodePtr(const u8 *ptr, std::string &name) { u32 jitAddr = blocks.GetAddressFromBlockPtr(ptr); // Returns 0 when it's valid, but unknown. if (jitAddr == 0) name = "UnknownOrDeletedBlock"; - else if (jitAddr != (u32)-1) - { + else if (jitAddr != (u32)-1) { char temp[1024]; const std::string label = symbolMap.GetDescription(jitAddr); if (!label.empty()) @@ -462,7 +455,7 @@ bool Jit::DescribeCodePtr(const u8 *ptr, std::string &name) snprintf(temp, sizeof(temp), "%08x", jitAddr); name = temp; } - else if (asm_.IsInSpace(ptr)) + else if (IsInSpace(ptr)) name = "RunLoopUntil"; else if (thunks.IsInSpace(ptr)) name = "Thunk"; @@ -660,7 +653,7 @@ void Jit::WriteExit(u32 destination, int exit_num) } else { // No blocklinking. MOV(32, M(&mips_->pc), Imm32(destination)); - JMP(asm_.dispatcher, true); + JMP(dispatcher, true); // Normally, exits are 15 bytes (MOV + &pc + dest + JMP + dest) on 64 or 32 bit. // But just in case we somehow optimized, pad. @@ -699,8 +692,8 @@ void Jit::WriteExitDestInReg(X64Reg reg) // Need to set neg flag again. SUB(32, M(&mips_->downcount), Imm8(0)); if (reg == EAX) - J_CC(CC_NS, asm_.dispatcherInEAXNoCheck, true); - JMP(asm_.dispatcher, true); + J_CC(CC_NS, dispatcherInEAXNoCheck, true); + JMP(dispatcher, true); SetJumpTarget(tooLow); SetJumpTarget(tooHigh); @@ -717,15 +710,15 @@ void Jit::WriteExitDestInReg(X64Reg reg) } SUB(32, M(&mips_->downcount), Imm8(0)); - JMP(asm_.dispatcherCheckCoreState, true); + JMP(dispatcherCheckCoreState, true); } else if (reg == EAX) { - J_CC(CC_NS, asm_.dispatcherInEAXNoCheck, true); - JMP(asm_.dispatcher, true); + J_CC(CC_NS, dispatcherInEAXNoCheck, true); + JMP(dispatcher, true); } else - JMP(asm_.dispatcher, true); + JMP(dispatcher, true); } void Jit::WriteSyscallExit() @@ -736,7 +729,7 @@ void Jit::WriteSyscallExit() ABI_CallFunction(&JitMemCheckCleanup); ApplyRoundingMode(); } - JMP(asm_.dispatcherCheckCoreState, true); + JMP(dispatcherCheckCoreState, true); } bool Jit::CheckJitBreakpoint(u32 addr, int downcountOffset) @@ -756,7 +749,7 @@ bool Jit::CheckJitBreakpoint(u32 addr, int downcountOffset) ApplyRoundingMode(); // Just to fix the stack. LOAD_FLAGS; - JMP(asm_.dispatcherCheckCoreState, true); + JMP(dispatcherCheckCoreState, true); SetJumpTarget(skip); ApplyRoundingMode(); diff --git a/Core/MIPS/x86/Jit.h b/Core/MIPS/x86/Jit.h index 703be6e341..d5650d19b9 100644 --- a/Core/MIPS/x86/Jit.h +++ b/Core/MIPS/x86/Jit.h @@ -20,7 +20,6 @@ #include "Common/CommonTypes.h" #include "Common/Thunk.h" #include "Common/x64Emitter.h" -#include "Core/MIPS/x86/Asm.h" #if defined(ARM) #error DO NOT BUILD X86 JIT ON ARM @@ -156,12 +155,11 @@ public: void GetVectorRegsPrefixD(u8 *regs, VectorSize sz, int vectorReg); void EatPrefix() { js.EatPrefix(); } - void RestoreRoundingMode(bool force = false, XEmitter *emitter = NULL); - void ApplyRoundingMode(bool force = false, XEmitter *emitter = NULL); - void UpdateRoundingMode(XEmitter *emitter = NULL); + void RestoreRoundingMode(bool force = false); + void ApplyRoundingMode(bool force = false); + void UpdateRoundingMode(); JitBlockCache *GetBlockCache() { return &blocks; } - AsmRoutineManager &Asm() { return asm_; } void ClearCache(); void InvalidateCache(); @@ -171,7 +169,12 @@ public: } } + const u8 *GetDispatcher() const { + return dispatcher; + } + private: + void GenerateFixedCode(JitOptions &jo); void GetStateAndFlushAll(RegCacheState &state); void RestoreState(const RegCacheState& state); void FlushAll(); @@ -295,15 +298,28 @@ private: GPRRegCache gpr; FPURegCache fpr; - AsmRoutineManager asm_; ThunkManager thunks; JitSafeMemFuncs safeMemFuncs; MIPSState *mips_; + + const u8 *enterDispatcher; + + const u8 *outerLoop; + const u8 *dispatcher; + const u8 *dispatcherCheckCoreState; + const u8 *dispatcherNoCheck; + const u8 *dispatcherInEAXNoCheck; + + const u8 *breakpointBailout; + + const u8 *restoreRoundingMode; + const u8 *applyRoundingMode; + const u8 *updateRoundingMode; + friend class JitSafeMem; friend class JitSafeMemFuncs; - friend class AsmRoutineManager; }; } // namespace MIPSComp diff --git a/Core/MIPS/x86/RegCache.cpp b/Core/MIPS/x86/RegCache.cpp index d93df0b8fd..5a48b290f2 100644 --- a/Core/MIPS/x86/RegCache.cpp +++ b/Core/MIPS/x86/RegCache.cpp @@ -23,7 +23,6 @@ #include "Core/MIPS/MIPSTables.h" #include "Core/MIPS/MIPSAnalyst.h" #include "Core/MIPS/x86/Jit.h" -#include "Core/MIPS/x86/Asm.h" #include "Core/MIPS/x86/RegCache.h" using namespace Gen;