diff --git a/CMakeLists.txt b/CMakeLists.txt index 8d78af8512..8e4bb97ccb 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -306,8 +306,7 @@ endmacro() set(CommonExtra) if(ARM) set(CommonExtra ${CommonExtra} - Common/ArmCPUDetect.cpp - Common/ArmThunk.cpp) + Common/ArmCPUDetect.cpp) if(ARMV7) set(CommonExtra ${CommonExtra} Common/ColorConvNEON.cpp) @@ -1389,7 +1388,6 @@ add_library(${CoreLibName} ${CoreLinkType} Core/FileLoaders/RetryingFileLoader.h Core/MIPS/JitCommon/JitCommon.cpp Core/MIPS/JitCommon/JitCommon.h - Core/MIPS/JitCommon/NativeJit.h Core/MIPS/JitCommon/JitBlockCache.cpp Core/MIPS/JitCommon/JitBlockCache.h Core/MIPS/JitCommon/JitState.cpp diff --git a/Common/Arm64Emitter.cpp b/Common/Arm64Emitter.cpp index 805da7a85d..9029117e45 100644 --- a/Common/Arm64Emitter.cpp +++ b/Common/Arm64Emitter.cpp @@ -265,14 +265,14 @@ static int EncodeSize(int size) { } } -void ARM64XEmitter::SetCodePtr(u8* ptr) +void ARM64XEmitter::SetCodePointer(u8* ptr) { m_code = ptr; m_startcode = m_code; m_lastCacheFlushEnd = ptr; } -const u8* ARM64XEmitter::GetCodePtr() const +const u8* ARM64XEmitter::GetCodePointer() const { return m_code; } @@ -1914,7 +1914,7 @@ void ARM64XEmitter::MOVI2R(ARM64Reg Rd, u64 imm, bool optimize) } } - u64 aligned_pc = (u64)GetCodePtr() & ~0xFFF; + u64 aligned_pc = (u64)GetCodePointer() & ~0xFFF; s64 aligned_offset = (s64)imm - (s64)aligned_pc; if (upload_part.Count() > 1 && abs64(aligned_offset) < 0xFFFFFFFFLL) { @@ -1929,7 +1929,7 @@ void ARM64XEmitter::MOVI2R(ARM64Reg Rd, u64 imm, bool optimize) else { // If the address is within 1MB of PC we can load it in a single instruction still - s64 offset = (s64)imm - (s64)GetCodePtr(); + s64 offset = (s64)imm - (s64)GetCodePointer(); if (offset >= -0xFFFFF && offset <= 0xFFFFF) { ADR(Rd, (s32)offset); @@ -2100,7 +2100,7 @@ void ARM64FloatEmitter::EmitLoadStoreImmediate(u8 size, u32 opc, IndexType type, if (type == INDEX_UNSIGNED) { - _assert_msg_(DYNA_REC, !(imm & ((size - 1) >> 3)), "%s(INDEX_UNSIGNED) immediate offset must be aligned to size! (%d) (%p)", __FUNCTION__, imm, m_emit->GetCodePtr()); + _assert_msg_(DYNA_REC, !(imm & ((size - 1) >> 3)), "%s(INDEX_UNSIGNED) immediate offset must be aligned to size! (%d) (%p)", __FUNCTION__, imm, m_emit->GetCodePointer()); _assert_msg_(DYNA_REC, imm >= 0, "%s(INDEX_UNSIGNED) immediate offset must be positive!", __FUNCTION__); if (size == 16) imm >>= 1; diff --git a/Common/Arm64Emitter.h b/Common/Arm64Emitter.h index bf7e30987f..fc1814bae0 100644 --- a/Common/Arm64Emitter.h +++ b/Common/Arm64Emitter.h @@ -394,11 +394,12 @@ public: { } - void SetCodePtr(u8* ptr); + void SetCodePointer(u8* ptr); + const u8* GetCodePointer() const; + void ReserveCodeSpace(u32 bytes); const u8* AlignCode16(); const u8* AlignCodePage(); - const u8* GetCodePtr() const; void FlushIcache(); void FlushIcacheSection(u8* start, u8* end); u8* GetWritableCodePtr(); diff --git a/Common/ArmEmitter.cpp b/Common/ArmEmitter.cpp index c547fd4329..1ce785f10b 100644 --- a/Common/ArmEmitter.cpp +++ b/Common/ArmEmitter.cpp @@ -589,14 +589,14 @@ void ARMXEmitter::QuickCallFunction(ARMReg reg, const void *func) { } } -void ARMXEmitter::SetCodePtr(u8 *ptr) +void ARMXEmitter::SetCodePointer(u8 *ptr) { code = ptr; startcode = code; lastCacheFlushEnd = ptr; } -const u8 *ARMXEmitter::GetCodePtr() const +const u8 *ARMXEmitter::GetCodePointer() const { return code; } diff --git a/Common/ArmEmitter.h b/Common/ArmEmitter.h index 6000b94bde..d0cc1de2ed 100644 --- a/Common/ArmEmitter.h +++ b/Common/ArmEmitter.h @@ -445,11 +445,12 @@ public: } virtual ~ARMXEmitter() {} - void SetCodePtr(u8 *ptr); + void SetCodePointer(u8 *ptr); + const u8 *GetCodePointer() const; + void ReserveCodeSpace(u32 bytes); const u8 *AlignCode16(); const u8 *AlignCodePage(); - const u8 *GetCodePtr() const; void FlushIcache(); void FlushIcacheSection(u8 *start, u8 *end); u8 *GetWritableCodePtr(); diff --git a/Common/ArmThunk.cpp b/Common/ArmThunk.cpp deleted file mode 100644 index 8be655b4d9..0000000000 --- a/Common/ArmThunk.cpp +++ /dev/null @@ -1,74 +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. - -// 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/ - -#include "MemoryUtil.h" -#include "Thunk.h" - -#define THUNK_ARENA_SIZE 1024*1024*1 - -namespace -{ - -static u8 GC_ALIGNED32(saved_fp_state[16 * 4 * 4]); -static u8 GC_ALIGNED32(saved_gpr_state[16 * 8]); -static u16 saved_mxcsr; - -} // namespace - -using namespace ArmGen; - -void ThunkManager::Init() -{ -} - -void ThunkManager::Reset() -{ - thunks.clear(); - ResetCodePtr(); -} - -void ThunkManager::Shutdown() -{ - Reset(); - FreeCodeSpace(); -} - -int ThunkManager::ThunkStackOffset() -{ - return 0; -} - -int ThunkManager::ThunkBytesNeeded() -{ - return 0; -} - -const void *ThunkManager::ProtectFunction(const void *function, int num_params) -{ - _dbg_assert_msg_(JIT, false, "Arm ThunkManager not implemented? Will crash."); - return NULL; -} - -void Enter(ThunkEmitter *emit) -{ - _dbg_assert_msg_(JIT, false, "Arm ThunkManager not implemented? Will crash."); -} - -void Leave(ThunkEmitter *emit) -{ - _dbg_assert_msg_(JIT, false, "Arm ThunkManager not implemented? Will crash."); -} diff --git a/Common/CodeBlock.h b/Common/CodeBlock.h index ea8937b046..337f08a9c9 100644 --- a/Common/CodeBlock.h +++ b/Common/CodeBlock.h @@ -11,20 +11,42 @@ // You get memory management for free, plus, you can use all emitter functions without // having to prefix them with gen-> or something similar. // Example implementation: -// class JIT : public CodeBlock {} -template class CodeBlock : public T, NonCopyable +// class JIT : public CodeBlock, public JitInterface {} + +class CodeBlockCommon { +public: + CodeBlockCommon() : region(nullptr), region_size(0) {} + virtual ~CodeBlockCommon() {} + + bool IsInSpace(const u8 *ptr) { + return (ptr >= region) && (ptr < (region + region_size)); + } + + virtual void SetCodePtr(u8 *ptr) = 0; + virtual const u8 *GetCodePtr() const = 0; + + u8 *GetBasePtr() { + return region; + } + + size_t GetOffset(const u8 *ptr) const { + return ptr - region; + } + +protected: + u8 *region; + size_t region_size; +}; + +template class CodeBlock : public CodeBlockCommon, public T, NonCopyable { private: // A privately used function to set the executable RAM space to something invalid. // For debugging usefulness it should be used to set the RAM to a host specific breakpoint instruction virtual void PoisonMemory() = 0; -protected: - u8 *region; - size_t region_size; - public: - CodeBlock() : region(nullptr), region_size(0) {} + CodeBlock() {} virtual ~CodeBlock() { if (region) FreeCodeSpace(); } // Call this before you generate any code. @@ -32,7 +54,7 @@ public: { region_size = size; region = (u8*)AllocateExecutableMemory(region_size); - T::SetCodePtr(region); + T::SetCodePointer(region); } // Always clear code space with breakpoints, so that if someone accidentally executes @@ -55,11 +77,6 @@ public: region_size = 0; } - bool IsInSpace(const u8 *ptr) - { - return (ptr >= region) && (ptr < (region + region_size)); - } - // Cannot currently be undone. Will write protect the entire code region. // Start over if you need to change the code (call FreeCodeSpace(), AllocCodeSpace()). void WriteProtect() @@ -67,22 +84,21 @@ public: WriteProtectMemory(region, region_size, true); } + void SetCodePtr(u8 *ptr) override { + T::SetCodePointer(ptr); + } + + const u8 *GetCodePtr() const override { + return T::GetCodePointer(); + } + void ResetCodePtr() { - T::SetCodePtr(region); + T::SetCodePointer(region); } - size_t GetSpaceLeft() const - { - return region_size - (T::GetCodePtr() - region); - } - - u8 *GetBasePtr() { - return region; - } - - size_t GetOffset(const u8 *ptr) const { - return ptr - region; + size_t GetSpaceLeft() const { + return region_size - (T::GetCodePointer() - region); } }; diff --git a/Common/Common.vcxproj b/Common/Common.vcxproj index 2fb7c33a0b..cfd26a5698 100644 --- a/Common/Common.vcxproj +++ b/Common/Common.vcxproj @@ -258,12 +258,6 @@ true - - true - true - true - true - true true @@ -332,4 +326,4 @@ - \ No newline at end of file + diff --git a/Common/Common.vcxproj.filters b/Common/Common.vcxproj.filters index 1dcbacabe5..1a8a744b2f 100644 --- a/Common/Common.vcxproj.filters +++ b/Common/Common.vcxproj.filters @@ -104,7 +104,6 @@ Crypto - @@ -151,4 +150,4 @@ {c14d66ef-5f7c-4565-975a-72774e7ccfb9} - \ No newline at end of file + diff --git a/Common/Thunk.h b/Common/Thunk.h index 101ea84a8d..4e5feffd87 100644 --- a/Common/Thunk.h +++ b/Common/Thunk.h @@ -20,11 +20,7 @@ #include #include "Common.h" -#if defined(ARM) -#include "ArmEmitter.h" -#else #include "x64Emitter.h" -#endif // This simple class creates a wrapper around a C/C++ function that saves all fp state // before entering it, and restores it upon exit. This is required to be able to selectively @@ -32,18 +28,14 @@ // of complexity that it means to protect the generated code from this problem. // This process is called thunking. +// Only used for X86 right now. // There will only ever be one level of thunking on the stack, plus, // we don't want to pollute the stack, so we store away regs somewhere global. // NOT THREAD SAFE. This may only be used from the CPU thread. // Any other thread using this stuff will be FATAL. -#if defined(ARM) -typedef ArmGen::ARMXEmitter ThunkEmitter; -typedef ArmGen::ARMXCodeBlock ThunkCodeBlock; -#else typedef Gen::XEmitter ThunkEmitter; typedef Gen::XCodeBlock ThunkCodeBlock; -#endif class ThunkManager : public ThunkCodeBlock { diff --git a/Common/x64Emitter.cpp b/Common/x64Emitter.cpp index 3839df53b0..489223895f 100644 --- a/Common/x64Emitter.cpp +++ b/Common/x64Emitter.cpp @@ -96,12 +96,12 @@ enum NormalSSEOps }; -void XEmitter::SetCodePtr(u8 *ptr) +void XEmitter::SetCodePointer(u8 *ptr) { code = ptr; } -const u8 *XEmitter::GetCodePtr() const +const u8 *XEmitter::GetCodePointer() const { return code; } @@ -235,7 +235,7 @@ void OpArg::WriteRest(XEmitter *emit, int extraBytes, X64Reg _operandReg, emit->WriteModRM(0, _operandReg, _offsetOrBaseReg); //TODO : add some checks #ifdef _M_X64 - u64 ripAddr = (u64)emit->GetCodePtr() + 4 + extraBytes; + u64 ripAddr = (u64)emit->GetCodePointer() + 4 + extraBytes; s64 distance = (s64)offset - (s64)ripAddr; _assert_msg_(DYNA_REC, (distance < 0x80000000LL && diff --git a/Common/x64Emitter.h b/Common/x64Emitter.h index e78166f9b3..cd7647813d 100644 --- a/Common/x64Emitter.h +++ b/Common/x64Emitter.h @@ -374,12 +374,13 @@ public: void WriteModRM(int mod, int rm, int reg); void WriteSIB(int scale, int index, int base); - void SetCodePtr(u8 *ptr); + void SetCodePointer(u8 *ptr); + const u8 *GetCodePointer() const; + void ReserveCodeSpace(int bytes); const u8 *AlignCode4(); const u8 *AlignCode16(); const u8 *AlignCodePage(); - const u8 *GetCodePtr() const; u8 *GetWritableCodePtr(); void LockFlags() { flags_locked = true; } diff --git a/Core/Core.vcxproj b/Core/Core.vcxproj index 514cf98e74..caa73aaa5e 100644 --- a/Core/Core.vcxproj +++ b/Core/Core.vcxproj @@ -666,7 +666,6 @@ - @@ -737,4 +736,4 @@ - + \ No newline at end of file diff --git a/Core/Core.vcxproj.filters b/Core/Core.vcxproj.filters index 76cce1b921..74b4939acc 100644 --- a/Core/Core.vcxproj.filters +++ b/Core/Core.vcxproj.filters @@ -678,9 +678,6 @@ MIPS\JitCommon - - MIPS\JitCommon - FileSystems diff --git a/Core/CwCheat.cpp b/Core/CwCheat.cpp index 9fef3c0915..ca0bc3b90a 100644 --- a/Core/CwCheat.cpp +++ b/Core/CwCheat.cpp @@ -11,7 +11,7 @@ #include "Core/ELF/ParamSFO.h" #include "Core/System.h" #include "Core/HLE/sceCtrl.h" -#include "Core/MIPS/JitCommon/NativeJit.h" +#include "Core/MIPS/JitCommon/JitCommon.h" #ifdef _WIN32 #include "util/text/utf8.h" diff --git a/Core/Debugger/Breakpoints.cpp b/Core/Debugger/Breakpoints.cpp index dc77e088ab..8eef12f831 100644 --- a/Core/Debugger/Breakpoints.cpp +++ b/Core/Debugger/Breakpoints.cpp @@ -15,14 +15,16 @@ // Official git repository and contact information can be found at // https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/. +#include + +#include "Common/Log.h" #include "Core/Core.h" #include "Core/Debugger/Breakpoints.h" #include "Core/Debugger/SymbolMap.h" #include "Core/Host.h" #include "Core/MIPS/MIPSAnalyst.h" -#include "Core/MIPS/JitCommon/NativeJit.h" +#include "Core/MIPS/JitCommon/JitCommon.h" #include "Core/CoreTiming.h" -#include std::vector CBreakPoints::breakPoints_; u32 CBreakPoints::breakSkipFirstAt_ = 0; diff --git a/Core/HLE/ReplaceTables.cpp b/Core/HLE/ReplaceTables.cpp index 5fc1da5d7d..06b5392d9d 100644 --- a/Core/HLE/ReplaceTables.cpp +++ b/Core/HLE/ReplaceTables.cpp @@ -1109,17 +1109,7 @@ static int Hook_omertachinmokunookitethelegacy_download_frame() { return 0; } -#ifdef ARM -#define JITFUNC(f) (&MIPSComp::ArmJit::f) -#elif defined(ARM64) -#define JITFUNC(f) (&MIPSComp::Arm64Jit::f) -#elif defined(_M_X64) || defined(_M_IX86) -#define JITFUNC(f) (&MIPSComp::Jit::f) -#elif defined(MIPS) -#define JITFUNC(f) (&MIPSComp::MipsJit::f) -#else -#define JITFUNC(f) (&MIPSComp::FakeJit::f) -#endif +#define JITFUNC(f) (&MIPSComp::JitInterface::f) // Can either replace with C functions or functions emitted in Asm/ArmAsm. static const ReplacementTableEntry entries[] = { diff --git a/Core/HLE/ReplaceTables.h b/Core/HLE/ReplaceTables.h index ba512bde4f..84f85b7eea 100644 --- a/Core/HLE/ReplaceTables.h +++ b/Core/HLE/ReplaceTables.h @@ -34,7 +34,7 @@ #pragma once #include "Common/CommonTypes.h" -#include "Core/MIPS/JitCommon/NativeJit.h" +#include "Core/MIPS/JitCommon/JitCommon.h" typedef int (* ReplaceFunc)(); diff --git a/Core/MIPS/ARM/ArmJit.cpp b/Core/MIPS/ARM/ArmJit.cpp index ac78d8aab4..c7512181cd 100644 --- a/Core/MIPS/ARM/ArmJit.cpp +++ b/Core/MIPS/ARM/ArmJit.cpp @@ -271,17 +271,17 @@ const u8 *ArmJit::DoJit(u32 em_address, JitBlock *b) JumpTarget backJump = GetCodePtr(); gpr.SetRegImm(R0, js.blockStart); B((const void *)outerLoopPCInR0); - b->checkedEntry = GetCodePtr(); + b->checkedEntry = (u8 *)GetCodePtr(); SetCC(CC_LT); B(backJump); SetCC(CC_AL); } else if (jo.useForwardJump) { - b->checkedEntry = GetCodePtr(); + b->checkedEntry = (u8 *)GetCodePtr(); SetCC(CC_LT); bail = B(); SetCC(CC_AL); } else { - b->checkedEntry = GetCodePtr(); + b->checkedEntry = (u8 *)GetCodePtr(); SetCC(CC_LT); gpr.SetRegImm(R0, js.blockStart); B((const void *)outerLoopPCInR0); @@ -397,6 +397,37 @@ void ArmJit::Comp_RunBlock(MIPSOpcode op) ERROR_LOG(JIT, "Comp_RunBlock should never be reached!"); } +void ArmJit::LinkBlock(u8 *exitPoint, const u8 *checkedEntry) { + ARMXEmitter emit(exitPoint); + u32 op = *((const u32 *)emit.GetCodePointer()); + bool prelinked = (op & 0xFF000000) == 0xEA000000; + // Jump directly to the block, yay. + emit.B(checkedEntry); + + if (!prelinked) { + do { + op = *((const u32 *)emit.GetCodePointer()); + // Overwrite whatever is here with a breakpoint. + emit.BKPT(1); + // Stop after overwriting the next unconditional branch or BKPT. + // It can be a BKPT if we unlinked, and are now linking a different one. + } while ((op & 0xFF000000) != 0xEA000000 && (op & 0xFFF000F0) != 0xE1200070); + } + emit.FlushIcache(); +} + +void ArmJit::UnlinkBlock(u8 *checkedEntry, u32 originalAddress) { + // Send anyone who tries to run this block back to the dispatcher. + // Not entirely ideal, but .. pretty good. + // I hope there's enough space... + // checkedEntry is the only "linked" entrance so it's enough to overwrite that. + ARMXEmitter emit(checkedEntry); + emit.MOVI2R(R0, originalAddress); + emit.STR(R0, CTXREG, offsetof(MIPSState, pc)); + emit.B(MIPSComp::jit->GetDispatcher()); + emit.FlushIcache(); +} + bool ArmJit::ReplaceJalTo(u32 dest) { #ifdef ARM const ReplacementTableEntry *entry = nullptr; diff --git a/Core/MIPS/ARM/ArmJit.h b/Core/MIPS/ARM/ArmJit.h index 3df0936f69..07b70af968 100644 --- a/Core/MIPS/ARM/ArmJit.h +++ b/Core/MIPS/ARM/ArmJit.h @@ -22,6 +22,7 @@ #include "Common/ArmEmitter.h" #include "Core/MIPS/JitCommon/JitState.h" #include "Core/MIPS/JitCommon/JitBlockCache.h" +#include "Core/MIPS/JitCommon/JitCommon.h" #include "Core/MIPS/ARM/ArmRegCache.h" #include "Core/MIPS/ARM/ArmRegCacheFPU.h" #include "Core/MIPS/MIPSVFPUUtils.h" @@ -32,98 +33,97 @@ namespace MIPSComp { -class ArmJit : public ArmGen::ARMXCodeBlock { +class ArmJit : public ArmGen::ARMXCodeBlock, public JitInterface { public: ArmJit(MIPSState *mips); virtual ~ArmJit(); - void DoState(PointerWrap &p); - static void DoDummyState(PointerWrap &p); + void DoState(PointerWrap &p) override; + void DoDummyState(PointerWrap &p) override; const JitOptions &GetJitOptions() { return jo; } // Compiled ops should ignore delay slots // the compiler will take care of them by itself // OR NOT - void Comp_Generic(MIPSOpcode op); + void Comp_Generic(MIPSOpcode op) override; - void RunLoopUntil(u64 globalticks); + void RunLoopUntil(u64 globalticks) override; - void Compile(u32 em_address); // Compiles a block at current MIPS PC - const u8 *DoJit(u32 em_address, JitBlock *b); + void Compile(u32 em_address) override; // Compiles a block at current MIPS PC - bool DescribeCodePtr(const u8 *ptr, std::string &name); + bool DescribeCodePtr(const u8 *ptr, std::string &name) override; - void Comp_RunBlock(MIPSOpcode op); - void Comp_ReplacementFunc(MIPSOpcode op); + void Comp_RunBlock(MIPSOpcode op) override; + void Comp_ReplacementFunc(MIPSOpcode op) override; // Ops - void Comp_ITypeMem(MIPSOpcode op); - void Comp_Cache(MIPSOpcode op); + void Comp_ITypeMem(MIPSOpcode op) override; + void Comp_Cache(MIPSOpcode op) override; - void Comp_RelBranch(MIPSOpcode op); - void Comp_RelBranchRI(MIPSOpcode op); - void Comp_FPUBranch(MIPSOpcode op); - void Comp_FPULS(MIPSOpcode op); - void Comp_FPUComp(MIPSOpcode op); - void Comp_Jump(MIPSOpcode op); - void Comp_JumpReg(MIPSOpcode op); - void Comp_Syscall(MIPSOpcode op); - void Comp_Break(MIPSOpcode op); + void Comp_RelBranch(MIPSOpcode op) override; + void Comp_RelBranchRI(MIPSOpcode op) override; + void Comp_FPUBranch(MIPSOpcode op) override; + void Comp_FPULS(MIPSOpcode op) override; + void Comp_FPUComp(MIPSOpcode op) override; + void Comp_Jump(MIPSOpcode op) override; + void Comp_JumpReg(MIPSOpcode op) override; + void Comp_Syscall(MIPSOpcode op) override; + void Comp_Break(MIPSOpcode op) override; - void Comp_IType(MIPSOpcode op); - void Comp_RType2(MIPSOpcode op); - void Comp_RType3(MIPSOpcode op); - void Comp_ShiftType(MIPSOpcode op); - void Comp_Allegrex(MIPSOpcode op); - void Comp_Allegrex2(MIPSOpcode op); - void Comp_VBranch(MIPSOpcode op); - void Comp_MulDivType(MIPSOpcode op); - void Comp_Special3(MIPSOpcode op); + void Comp_IType(MIPSOpcode op) override; + void Comp_RType2(MIPSOpcode op) override; + void Comp_RType3(MIPSOpcode op) override; + void Comp_ShiftType(MIPSOpcode op) override; + void Comp_Allegrex(MIPSOpcode op) override; + void Comp_Allegrex2(MIPSOpcode op) override; + void Comp_VBranch(MIPSOpcode op) override; + void Comp_MulDivType(MIPSOpcode op) override; + void Comp_Special3(MIPSOpcode op) override; - void Comp_FPU3op(MIPSOpcode op); - void Comp_FPU2op(MIPSOpcode op); - void Comp_mxc1(MIPSOpcode op); + void Comp_FPU3op(MIPSOpcode op) override; + void Comp_FPU2op(MIPSOpcode op) override; + void Comp_mxc1(MIPSOpcode op) override; - void Comp_DoNothing(MIPSOpcode op); + void Comp_DoNothing(MIPSOpcode op) override; - void Comp_SV(MIPSOpcode op); - void Comp_SVQ(MIPSOpcode op); - void Comp_VPFX(MIPSOpcode op); - void Comp_VVectorInit(MIPSOpcode op); - void Comp_VMatrixInit(MIPSOpcode op); - void Comp_VDot(MIPSOpcode op); - void Comp_VecDo3(MIPSOpcode op); - void Comp_VV2Op(MIPSOpcode op); - void Comp_Mftv(MIPSOpcode op); - void Comp_Vmfvc(MIPSOpcode op); - void Comp_Vmtvc(MIPSOpcode op); - void Comp_Vmmov(MIPSOpcode op); - void Comp_VScl(MIPSOpcode op); - void Comp_Vmmul(MIPSOpcode op); - void Comp_Vmscl(MIPSOpcode op); - void Comp_Vtfm(MIPSOpcode op); - void Comp_VHdp(MIPSOpcode op); - void Comp_VCrs(MIPSOpcode op); - void Comp_VDet(MIPSOpcode op); - void Comp_Vi2x(MIPSOpcode op); - void Comp_Vx2i(MIPSOpcode op); - void Comp_Vf2i(MIPSOpcode op); - void Comp_Vi2f(MIPSOpcode op); - void Comp_Vh2f(MIPSOpcode op); - void Comp_Vcst(MIPSOpcode op); - void Comp_Vhoriz(MIPSOpcode op); - void Comp_VRot(MIPSOpcode op); - void Comp_VIdt(MIPSOpcode op); - void Comp_Vcmp(MIPSOpcode op); - void Comp_Vcmov(MIPSOpcode op); - void Comp_Viim(MIPSOpcode op); - void Comp_Vfim(MIPSOpcode op); - void Comp_VCrossQuat(MIPSOpcode op); - void Comp_Vsgn(MIPSOpcode op); - void Comp_Vocp(MIPSOpcode op); - void Comp_ColorConv(MIPSOpcode op); - void Comp_Vbfy(MIPSOpcode op); + void Comp_SV(MIPSOpcode op) override; + void Comp_SVQ(MIPSOpcode op) override; + void Comp_VPFX(MIPSOpcode op) override; + void Comp_VVectorInit(MIPSOpcode op) override; + void Comp_VMatrixInit(MIPSOpcode op) override; + void Comp_VDot(MIPSOpcode op) override; + void Comp_VecDo3(MIPSOpcode op) override; + void Comp_VV2Op(MIPSOpcode op) override; + void Comp_Mftv(MIPSOpcode op) override; + void Comp_Vmfvc(MIPSOpcode op) override; + void Comp_Vmtvc(MIPSOpcode op) override; + void Comp_Vmmov(MIPSOpcode op) override; + void Comp_VScl(MIPSOpcode op) override; + void Comp_Vmmul(MIPSOpcode op) override; + void Comp_Vmscl(MIPSOpcode op) override; + void Comp_Vtfm(MIPSOpcode op) override; + void Comp_VHdp(MIPSOpcode op) override; + void Comp_VCrs(MIPSOpcode op) override; + void Comp_VDet(MIPSOpcode op) override; + void Comp_Vi2x(MIPSOpcode op) override; + void Comp_Vx2i(MIPSOpcode op) override; + void Comp_Vf2i(MIPSOpcode op) override; + void Comp_Vi2f(MIPSOpcode op) override; + void Comp_Vh2f(MIPSOpcode op) override; + void Comp_Vcst(MIPSOpcode op) override; + void Comp_Vhoriz(MIPSOpcode op) override; + void Comp_VRot(MIPSOpcode op) override; + void Comp_VIdt(MIPSOpcode op) override; + void Comp_Vcmp(MIPSOpcode op) override; + void Comp_Vcmov(MIPSOpcode op) override; + void Comp_Viim(MIPSOpcode op) override; + void Comp_Vfim(MIPSOpcode op) override; + void Comp_VCrossQuat(MIPSOpcode op) override; + void Comp_Vsgn(MIPSOpcode op) override; + void Comp_Vocp(MIPSOpcode op) override; + void Comp_ColorConv(MIPSOpcode op) override; + void Comp_Vbfy(MIPSOpcode op) override; // Non-NEON: VPFX @@ -167,15 +167,24 @@ public: int Replace_fabsf(); - JitBlockCache *GetBlockCache() { return &blocks; } + JitBlockCache *GetBlockCache() override { return &blocks; } - void ClearCache(); - void InvalidateCache(); - void InvalidateCacheAt(u32 em_address, int length = 4); + void ClearCache() override; + void InvalidateCache() override; + void InvalidateCacheAt(u32 em_address, int length = 4) override; - void EatPrefix() { js.EatPrefix(); } + void EatPrefix() override { js.EatPrefix(); } + + const u8 *GetDispatcher() const override { + return dispatcher; + } + + void LinkBlock(u8 *exitPoint, const u8 *checkedEntry) override; + void UnlinkBlock(u8 *checkedEntry, u32 originalAddress) override; private: + const u8 *DoJit(u32 em_address, JitBlock *b); + void GenerateFixedCode(); void FlushAll(); void FlushPrefixV(); diff --git a/Core/MIPS/ARM64/Arm64Jit.cpp b/Core/MIPS/ARM64/Arm64Jit.cpp index 898b0f5b3f..7eadb8d9ed 100644 --- a/Core/MIPS/ARM64/Arm64Jit.cpp +++ b/Core/MIPS/ARM64/Arm64Jit.cpp @@ -262,13 +262,13 @@ const u8 *Arm64Jit::DoJit(u32 em_address, JitBlock *b) { const u8 *backJump = GetCodePtr(); MOVI2R(SCRATCH1, js.blockStart); B((const void *)outerLoopPCInSCRATCH1); - b->checkedEntry = GetCodePtr(); + b->checkedEntry = (u8 *)GetCodePtr(); B(CC_LT, backJump); } else if (jo.useForwardJump) { - b->checkedEntry = GetCodePtr(); + b->checkedEntry = (u8 *)GetCodePtr(); bail = B(CC_LT); } else if (jo.enableBlocklink) { - b->checkedEntry = GetCodePtr(); + b->checkedEntry = (u8 *)GetCodePtr(); MOVI2R(SCRATCH1, js.blockStart); FixupBranch skip = B(CC_GE); B((const void *)outerLoopPCInSCRATCH1); @@ -395,6 +395,24 @@ void Arm64Jit::Comp_RunBlock(MIPSOpcode op) { ERROR_LOG(JIT, "Comp_RunBlock should never be reached!"); } +void Arm64Jit::LinkBlock(u8 *exitPoint, const u8 *checkedEntry) { + ARM64XEmitter emit(exitPoint); + emit.B(checkedEntry); + // TODO: Write stuff after. + emit.FlushIcache(); +} + +void Arm64Jit::UnlinkBlock(u8 *checkedEntry, u32 originalAddress) { + // Send anyone who tries to run this block back to the dispatcher. + // Not entirely ideal, but .. works. + // Spurious entrances from previously linked blocks can only come through checkedEntry + ARM64XEmitter emit(checkedEntry); + emit.MOVI2R(SCRATCH1, originalAddress); + emit.STR(INDEX_UNSIGNED, SCRATCH1, CTXREG, offsetof(MIPSState, pc)); + emit.B(MIPSComp::jit->GetDispatcher()); + emit.FlushIcache(); +} + bool Arm64Jit::ReplaceJalTo(u32 dest) { #ifdef ARM64 const ReplacementTableEntry *entry = nullptr; diff --git a/Core/MIPS/ARM64/Arm64Jit.h b/Core/MIPS/ARM64/Arm64Jit.h index 36caaabe25..e1c9cf5dec 100644 --- a/Core/MIPS/ARM64/Arm64Jit.h +++ b/Core/MIPS/ARM64/Arm64Jit.h @@ -22,6 +22,7 @@ #include "Common/Arm64Emitter.h" #include "Core/MIPS/JitCommon/JitState.h" #include "Core/MIPS/JitCommon/JitBlockCache.h" +#include "Core/MIPS/JitCommon/JitCommon.h" #include "Core/MIPS/ARM64/Arm64RegCache.h" #include "Core/MIPS/ARM64/Arm64RegCacheFPU.h" #include "Core/MIPS/MIPSVFPUUtils.h" @@ -32,98 +33,98 @@ namespace MIPSComp { -class Arm64Jit : public Arm64Gen::ARM64CodeBlock { +class Arm64Jit : public Arm64Gen::ARM64CodeBlock, public JitInterface { public: Arm64Jit(MIPSState *mips); virtual ~Arm64Jit(); - void DoState(PointerWrap &p); - static void DoDummyState(PointerWrap &p); + void DoState(PointerWrap &p) override; + void DoDummyState(PointerWrap &p) override; const JitOptions &GetJitOptions() { return jo; } // Compiled ops should ignore delay slots // the compiler will take care of them by itself // OR NOT - void Comp_Generic(MIPSOpcode op); + void Comp_Generic(MIPSOpcode op) override; - void RunLoopUntil(u64 globalticks); + void RunLoopUntil(u64 globalticks) override; - void Compile(u32 em_address); // Compiles a block at current MIPS PC + void Compile(u32 em_address) override; // Compiles a block at current MIPS PC const u8 *DoJit(u32 em_address, JitBlock *b); - bool DescribeCodePtr(const u8 *ptr, std::string &name); + bool DescribeCodePtr(const u8 *ptr, std::string &name) override; - void Comp_RunBlock(MIPSOpcode op); - void Comp_ReplacementFunc(MIPSOpcode op); + void Comp_RunBlock(MIPSOpcode op) override; + void Comp_ReplacementFunc(MIPSOpcode op) override; // Ops - void Comp_ITypeMem(MIPSOpcode op); - void Comp_Cache(MIPSOpcode op); + void Comp_ITypeMem(MIPSOpcode op) override; + void Comp_Cache(MIPSOpcode op) override; - void Comp_RelBranch(MIPSOpcode op); - void Comp_RelBranchRI(MIPSOpcode op); - void Comp_FPUBranch(MIPSOpcode op); - void Comp_FPULS(MIPSOpcode op); - void Comp_FPUComp(MIPSOpcode op); - void Comp_Jump(MIPSOpcode op); - void Comp_JumpReg(MIPSOpcode op); - void Comp_Syscall(MIPSOpcode op); - void Comp_Break(MIPSOpcode op); + void Comp_RelBranch(MIPSOpcode op) override; + void Comp_RelBranchRI(MIPSOpcode op) override; + void Comp_FPUBranch(MIPSOpcode op) override; + void Comp_FPULS(MIPSOpcode op) override; + void Comp_FPUComp(MIPSOpcode op) override; + void Comp_Jump(MIPSOpcode op) override; + void Comp_JumpReg(MIPSOpcode op) override; + void Comp_Syscall(MIPSOpcode op) override; + void Comp_Break(MIPSOpcode op) override; - void Comp_IType(MIPSOpcode op); - void Comp_RType2(MIPSOpcode op); - void Comp_RType3(MIPSOpcode op); - void Comp_ShiftType(MIPSOpcode op); - void Comp_Allegrex(MIPSOpcode op); - void Comp_Allegrex2(MIPSOpcode op); - void Comp_VBranch(MIPSOpcode op); - void Comp_MulDivType(MIPSOpcode op); - void Comp_Special3(MIPSOpcode op); + void Comp_IType(MIPSOpcode op) override; + void Comp_RType2(MIPSOpcode op) override; + void Comp_RType3(MIPSOpcode op) override; + void Comp_ShiftType(MIPSOpcode op) override; + void Comp_Allegrex(MIPSOpcode op) override; + void Comp_Allegrex2(MIPSOpcode op) override; + void Comp_VBranch(MIPSOpcode op) override; + void Comp_MulDivType(MIPSOpcode op) override; + void Comp_Special3(MIPSOpcode op) override; - void Comp_FPU3op(MIPSOpcode op); - void Comp_FPU2op(MIPSOpcode op); - void Comp_mxc1(MIPSOpcode op); + void Comp_FPU3op(MIPSOpcode op) override; + void Comp_FPU2op(MIPSOpcode op) override; + void Comp_mxc1(MIPSOpcode op) override; - void Comp_DoNothing(MIPSOpcode op); + void Comp_DoNothing(MIPSOpcode op) override; - void Comp_SV(MIPSOpcode op); - void Comp_SVQ(MIPSOpcode op); - void Comp_VPFX(MIPSOpcode op); - void Comp_VVectorInit(MIPSOpcode op); - void Comp_VMatrixInit(MIPSOpcode op); - void Comp_VDot(MIPSOpcode op); - void Comp_VecDo3(MIPSOpcode op); - void Comp_VV2Op(MIPSOpcode op); - void Comp_Mftv(MIPSOpcode op); - void Comp_Vmfvc(MIPSOpcode op); - void Comp_Vmtvc(MIPSOpcode op); - void Comp_Vmmov(MIPSOpcode op); - void Comp_VScl(MIPSOpcode op); - void Comp_Vmmul(MIPSOpcode op); - void Comp_Vmscl(MIPSOpcode op); - void Comp_Vtfm(MIPSOpcode op); - void Comp_VHdp(MIPSOpcode op); - void Comp_VCrs(MIPSOpcode op); - void Comp_VDet(MIPSOpcode op); - void Comp_Vi2x(MIPSOpcode op); - void Comp_Vx2i(MIPSOpcode op); - void Comp_Vf2i(MIPSOpcode op); - void Comp_Vi2f(MIPSOpcode op); - void Comp_Vh2f(MIPSOpcode op); - void Comp_Vcst(MIPSOpcode op); - void Comp_Vhoriz(MIPSOpcode op); - void Comp_VRot(MIPSOpcode op); - void Comp_VIdt(MIPSOpcode op); - void Comp_Vcmp(MIPSOpcode op); - void Comp_Vcmov(MIPSOpcode op); - void Comp_Viim(MIPSOpcode op); - void Comp_Vfim(MIPSOpcode op); - void Comp_VCrossQuat(MIPSOpcode op); - void Comp_Vsgn(MIPSOpcode op); - void Comp_Vocp(MIPSOpcode op); - void Comp_ColorConv(MIPSOpcode op); - void Comp_Vbfy(MIPSOpcode op); + void Comp_SV(MIPSOpcode op) override; + void Comp_SVQ(MIPSOpcode op) override; + void Comp_VPFX(MIPSOpcode op) override; + void Comp_VVectorInit(MIPSOpcode op) override; + void Comp_VMatrixInit(MIPSOpcode op) override; + void Comp_VDot(MIPSOpcode op) override; + void Comp_VecDo3(MIPSOpcode op) override; + void Comp_VV2Op(MIPSOpcode op) override; + void Comp_Mftv(MIPSOpcode op) override; + void Comp_Vmfvc(MIPSOpcode op) override; + void Comp_Vmtvc(MIPSOpcode op) override; + void Comp_Vmmov(MIPSOpcode op) override; + void Comp_VScl(MIPSOpcode op) override; + void Comp_Vmmul(MIPSOpcode op) override; + void Comp_Vmscl(MIPSOpcode op) override; + void Comp_Vtfm(MIPSOpcode op) override; + void Comp_VHdp(MIPSOpcode op) override; + void Comp_VCrs(MIPSOpcode op) override; + void Comp_VDet(MIPSOpcode op) override; + void Comp_Vi2x(MIPSOpcode op) override; + void Comp_Vx2i(MIPSOpcode op) override; + void Comp_Vf2i(MIPSOpcode op) override; + void Comp_Vi2f(MIPSOpcode op) override; + void Comp_Vh2f(MIPSOpcode op) override; + void Comp_Vcst(MIPSOpcode op) override; + void Comp_Vhoriz(MIPSOpcode op) override; + void Comp_VRot(MIPSOpcode op) override; + void Comp_VIdt(MIPSOpcode op) override; + void Comp_Vcmp(MIPSOpcode op) override; + void Comp_Vcmov(MIPSOpcode op) override; + void Comp_Viim(MIPSOpcode op) override; + void Comp_Vfim(MIPSOpcode op) override; + void Comp_VCrossQuat(MIPSOpcode op) override; + void Comp_Vsgn(MIPSOpcode op) override; + void Comp_Vocp(MIPSOpcode op) override; + void Comp_ColorConv(MIPSOpcode op) override; + void Comp_Vbfy(MIPSOpcode op) override; // Non-NEON: VPFX @@ -175,6 +176,13 @@ public: void EatPrefix() { js.EatPrefix(); } + const u8 *GetDispatcher() const override { + return dispatcher; + } + + void LinkBlock(u8 *exitPoint, const u8 *checkedEntry) override; + void UnlinkBlock(u8 *checkedEntry, u32 originalAddress) override; + private: void GenerateFixedCode(const JitOptions &jo); void FlushAll(); diff --git a/Core/MIPS/JitCommon/JitBlockCache.cpp b/Core/MIPS/JitCommon/JitBlockCache.cpp index af49b8ccb4..5b59e0bad7 100644 --- a/Core/MIPS/JitCommon/JitBlockCache.cpp +++ b/Core/MIPS/JitCommon/JitBlockCache.cpp @@ -42,11 +42,7 @@ #include "Core/MIPS/JitCommon/JitBlockCache.h" #include "Core/MIPS/JitCommon/JitCommon.h" -#include "Core/MIPS/JitCommon/NativeJit.h" -#if defined(_M_IX86) || defined(_M_X64) -#include "Common/x64Analyzer.h" -#endif // #include "JitBase.h" #if defined USE_OPROFILE && USE_OPROFILE @@ -61,19 +57,9 @@ op_agent_t agent; #pragma comment(lib, "jitprofiling.lib") #endif -#ifdef ARM -using namespace ArmGen; -using namespace ArmJitConstants; -#elif defined(_M_X64) || defined(_M_IX86) -using namespace Gen; -#elif defined(ARM64) -using namespace Arm64Gen; -using namespace Arm64JitConstants; -#endif - const u32 INVALID_EXIT = 0xFFFFFFFF; -JitBlockCache::JitBlockCache(MIPSState *mips, NativeCodeBlock *codeBlock) : +JitBlockCache::JitBlockCache(MIPSState *mips, CodeBlockCommon *codeBlock) : mips_(mips), codeBlock_(codeBlock), blocks_(0), num_blocks_(0) { } @@ -196,7 +182,7 @@ void JitBlockCache::ProxyBlock(u32 rootAddress, u32 startAddress, u32 size, cons // Make binary searches and stuff work ok b.normalEntry = codePtr; - b.checkedEntry = codePtr; + b.checkedEntry = (u8 *)codePtr; // Ugh, casting away const.. proxyBlockMap_.insert(std::make_pair(startAddress, num_blocks_)); AddBlockMap(num_blocks_); @@ -414,46 +400,8 @@ void JitBlockCache::LinkBlockExits(int i) { JitBlock &eb = blocks_[destinationBlock]; // Make sure the destination is not invalid. if (!eb.invalid) { -#if defined(ARM) - ARMXEmitter emit(b.exitPtrs[e]); - u32 op = *((const u32 *)emit.GetCodePtr()); - bool prelinked = (op & 0xFF000000) == 0xEA000000; - // Jump directly to the block, yay. - emit.B(eb.checkedEntry); - - if (!prelinked) { - do { - op = *((const u32 *)emit.GetCodePtr()); - // Overwrite whatever is here with a breakpoint. - emit.BKPT(1); - // Stop after overwriting the next unconditional branch or BKPT. - // It can be a BKPT if we unlinked, and are now linking a different one. - } while ((op & 0xFF000000) != 0xEA000000 && (op & 0xFFF000F0) != 0xE1200070); - } - emit.FlushIcache(); + MIPSComp::jit->LinkBlock(b.exitPtrs[e], eb.checkedEntry); b.linkStatus[e] = true; -#elif defined(_M_IX86) || defined(_M_X64) - XEmitter emit(b.exitPtrs[e]); - // Okay, this is a bit ugly, but we check here if it already has a JMP. - // That means it doesn't have a full exit to pad with INT 3. - bool prelinked = *emit.GetCodePtr() == 0xE9; - emit.JMP(eb.checkedEntry, true); - - if (!prelinked) { - ptrdiff_t actualSize = emit.GetWritableCodePtr() - b.exitPtrs[e]; - int pad = JitBlockCache::GetBlockExitSize() - (int)actualSize; - for (int i = 0; i < pad; ++i) { - emit.INT3(); - } - } - b.linkStatus[e] = true; -#elif defined(ARM64) - ARM64XEmitter emit(b.exitPtrs[e]); - emit.B(eb.checkedEntry); - // TODO: Write stuff after. - emit.FlushIcache(); - b.linkStatus[e] = true; -#endif } } } @@ -586,39 +534,7 @@ void JitBlockCache::DestroyBlock(int block_num, bool invalidate) { return; } -#if defined(ARM) - - // Send anyone who tries to run this block back to the dispatcher. - // Not entirely ideal, but .. pretty good. - // I hope there's enough space... - // checkedEntry is the only "linked" entrance so it's enough to overwrite that. - ARMXEmitter emit((u8 *)b->checkedEntry); - emit.MOVI2R(R0, b->originalAddress); - emit.STR(R0, CTXREG, offsetof(MIPSState, pc)); - emit.B(MIPSComp::jit->dispatcher); - emit.FlushIcache(); - -#elif defined(_M_IX86) || defined(_M_X64) - - // Send anyone who tries to run this block back to the dispatcher. - // Not entirely ideal, but .. pretty good. - // 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->GetDispatcher(), true); - -#elif defined(ARM64) - - // Send anyone who tries to run this block back to the dispatcher. - // Not entirely ideal, but .. works. - // Spurious entrances from previously linked blocks can only come through checkedEntry - ARM64XEmitter emit((u8 *)b->checkedEntry); - emit.MOVI2R(SCRATCH1, b->originalAddress); - emit.STR(INDEX_UNSIGNED, SCRATCH1, CTXREG, offsetof(MIPSState, pc)); - emit.B(MIPSComp::jit->dispatcher); - emit.FlushIcache(); - -#endif + MIPSComp::jit->UnlinkBlock(b->checkedEntry, b->originalAddress); } void JitBlockCache::InvalidateICache(u32 address, const u32 length) { diff --git a/Core/MIPS/JitCommon/JitBlockCache.h b/Core/MIPS/JitCommon/JitBlockCache.h index ccd448337b..7331961d9e 100644 --- a/Core/MIPS/JitCommon/JitBlockCache.h +++ b/Core/MIPS/JitCommon/JitBlockCache.h @@ -23,31 +23,10 @@ #include #include "Common/CommonTypes.h" +#include "Common/CodeBlock.h" #include "Core/MIPS/MIPSAnalyst.h" #include "Core/MIPS/MIPS.h" -#if defined(ARM) -#include "Common/ArmEmitter.h" -namespace ArmGen { class ARMXEmitter; } -typedef ArmGen::ARMXCodeBlock NativeCodeBlock; -#elif defined(ARM64) -#include "Common/Arm64Emitter.h" -namespace Arm64Gen { class ARM64XEmitter; } -typedef Arm64Gen::ARM64CodeBlock NativeCodeBlock; -#elif defined(_M_IX86) || defined(_M_X64) -#include "Common/x64Emitter.h" -namespace Gen { class XEmitter; } -typedef Gen::XCodeBlock NativeCodeBlock; -#elif defined(MIPS) -#include "Common/MipsEmitter.h" -namespace MIPSGen { class MIPSEmitter; } -typedef MIPSGen::MIPSCodeBlock NativeCodeBlock; -#else -#include "Common/FakeEmitter.h" -namespace FakeGen { class FakeXEmitter; } -typedef FakeGen::FakeXCodeBlock NativeCodeBlock; -#endif - #if defined(ARM) || defined(ARM64) const int MAX_JIT_BLOCK_EXITS = 2; #else @@ -73,7 +52,7 @@ struct BlockCacheStats { struct JitBlock { bool ContainsAddress(u32 em_address); - const u8 *checkedEntry; + u8 *checkedEntry; // not const, may need to write through this to unlink const u8 *normalEntry; u8 *exitPtrs[MAX_JIT_BLOCK_EXITS]; // to be able to rewrite the exit jump @@ -109,12 +88,11 @@ typedef void (*CompiledCode)(); class JitBlockCache { public: - JitBlockCache(MIPSState *mips_, NativeCodeBlock *codeBlock); + JitBlockCache(MIPSState *mips_, CodeBlockCommon *codeBlock); ~JitBlockCache(); int AllocateBlock(u32 em_address); - // When a proxy block is invalidated, the block located at the rootAddress - // is invalidated too. + // When a proxy block is invalidated, the block located at the rootAddress is invalidated too. void ProxyBlock(u32 rootAddress, u32 startAddress, u32 size, const u8 *codePtr); void FinalizeBlock(int block_num, bool block_link); @@ -174,7 +152,7 @@ private: MIPSOpcode GetEmuHackOpForBlock(int block_num) const; MIPSState *mips_; - NativeCodeBlock *codeBlock_; + CodeBlockCommon *codeBlock_; JitBlock *blocks_; std::unordered_multimap proxyBlockMap_; diff --git a/Core/MIPS/JitCommon/JitCommon.cpp b/Core/MIPS/JitCommon/JitCommon.cpp index 83903e9ab3..91ed4c10d6 100644 --- a/Core/MIPS/JitCommon/JitCommon.cpp +++ b/Core/MIPS/JitCommon/JitCommon.cpp @@ -15,36 +15,53 @@ // Official git repository and contact information can be found at // https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/. -#include - -#include "Core/MIPS/JitCommon/JitCommon.h" -#include "Core/MIPS/JitCommon/NativeJit.h" -#include "Common/StringUtils.h" +#include #include "ext/disarm.h" #include "ext/udis86/udis86.h" + +#include "Common/StringUtils.h" #include "Core/Util/DisArm64.h" -#if (defined(_M_IX86) || defined(_M_X64)) && defined(_WIN32) -#define DISASM_ALL 1 +#include "Core/MIPS/JitCommon/JitCommon.h" +#include "Core/MIPS/JitCommon/JitState.h" + +#if defined(ARM) +#include "../ARM/ArmJit.h" +#elif defined(ARM64) +#include "../ARM64/Arm64Jit.h" +#elif defined(_M_IX86) || defined(_M_X64) +#include "../x86/Jit.h" +#elif defined(MIPS) +#include "../MIPS/MipsJit.h" +#else +#include "../fake/FakeJit.h" #endif namespace MIPSComp { -#if defined(ARM) - ArmJit *jit; -#elif defined(ARM64) - Arm64Jit *jit; -#elif defined(_M_IX86) || defined(_M_X64) - Jit *jit; -#elif defined(MIPS) - MipsJit *jit; -#else - FakeJit *jit; -#endif + JitInterface *jit; void JitAt() { jit->Compile(currentMIPS->pc); } + + JitInterface *CreateNativeJit(MIPSState *mips) { +#if defined(ARM) + return new MIPSComp::ArmJit(mips); +#elif defined(ARM64) + return new MIPSComp::Arm64Jit(mips); +#elif defined(_M_IX86) || defined(_M_X64) + return new MIPSComp::Jit(mips); +#elif defined(MIPS) + return new MIPSComp::MipsJit(mips); +#else + return new MIPSComp::FakeJit(mips); +#endif + } + } +#if (defined(_M_IX86) || defined(_M_X64)) && defined(_WIN32) +#define DISASM_ALL 1 +#endif #if defined(ARM) || defined(DISASM_ALL) // We compile this for x86 as well because it may be useful when developing the ARM JIT on a PC. diff --git a/Core/MIPS/JitCommon/JitCommon.h b/Core/MIPS/JitCommon/JitCommon.h index a3a1c35828..9c440a6cdb 100644 --- a/Core/MIPS/JitCommon/JitCommon.h +++ b/Core/MIPS/JitCommon/JitCommon.h @@ -21,12 +21,120 @@ #include #include "Common/Common.h" +#include "Common/CommonTypes.h" +#include "Core/MIPS/MIPS.h" // TODO: Find a better place for these. std::vector DisassembleArm2(const u8 *data, int size); std::vector DisassembleArm64(const u8 *data, int size); std::vector DisassembleX86(const u8 *data, int size); +struct JitBlock; +class JitBlockCache; +class PointerWrap; + +#ifdef USING_QT_UI +#undef emit +#endif + +class MIPSState; + namespace MIPSComp { void JitAt(); -} \ No newline at end of file + + class JitInterface { + public: + virtual ~JitInterface() {} + + virtual bool DescribeCodePtr(const u8 *ptr, std::string &name) = 0; + virtual const u8 *GetDispatcher() const = 0; + virtual JitBlockCache *GetBlockCache() = 0; + virtual void InvalidateCache() = 0; + virtual void InvalidateCacheAt(u32 em_address, int length = 4) = 0; + virtual void DoState(PointerWrap &p) = 0; + virtual void DoDummyState(PointerWrap &p) = 0; + virtual void RunLoopUntil(u64 globalticks) = 0; + virtual void Compile(u32 em_address) = 0; + virtual void ClearCache() = 0; + virtual void EatPrefix() = 0; + + // Block linking. This may need to work differently for whole-function JITs and stuff + // like that. + virtual void LinkBlock(u8 *exitPoint, const u8 *entryPoint) = 0; + virtual void UnlinkBlock(u8 *checkedEntry, u32 originalAddress) = 0; + + virtual void Comp_Generic(MIPSOpcode op) = 0; + virtual void Comp_RunBlock(MIPSOpcode op) = 0; + virtual void Comp_ReplacementFunc(MIPSOpcode op) = 0; + virtual void Comp_ITypeMem(MIPSOpcode op) = 0; + virtual void Comp_Cache(MIPSOpcode op) = 0; + virtual void Comp_RelBranch(MIPSOpcode op) = 0; + virtual void Comp_RelBranchRI(MIPSOpcode op) = 0; + virtual void Comp_FPUBranch(MIPSOpcode op) = 0; + virtual void Comp_FPULS(MIPSOpcode op) = 0; + virtual void Comp_FPUComp(MIPSOpcode op) = 0; + virtual void Comp_Jump(MIPSOpcode op) = 0; + virtual void Comp_JumpReg(MIPSOpcode op) = 0; + virtual void Comp_Syscall(MIPSOpcode op) = 0; + virtual void Comp_Break(MIPSOpcode op) = 0; + virtual void Comp_IType(MIPSOpcode op) = 0; + virtual void Comp_RType2(MIPSOpcode op) = 0; + virtual void Comp_RType3(MIPSOpcode op) = 0; + virtual void Comp_ShiftType(MIPSOpcode op) = 0; + virtual void Comp_Allegrex(MIPSOpcode op) = 0; + virtual void Comp_Allegrex2(MIPSOpcode op) = 0; + virtual void Comp_VBranch(MIPSOpcode op) = 0; + virtual void Comp_MulDivType(MIPSOpcode op) = 0; + virtual void Comp_Special3(MIPSOpcode op) = 0; + virtual void Comp_FPU3op(MIPSOpcode op) = 0; + virtual void Comp_FPU2op(MIPSOpcode op) = 0; + virtual void Comp_mxc1(MIPSOpcode op) = 0; + virtual void Comp_SV(MIPSOpcode op) = 0; + virtual void Comp_SVQ(MIPSOpcode op) = 0; + virtual void Comp_VPFX(MIPSOpcode op) = 0; + virtual void Comp_VVectorInit(MIPSOpcode op) = 0; + virtual void Comp_VMatrixInit(MIPSOpcode op) = 0; + virtual void Comp_VDot(MIPSOpcode op) = 0; + virtual void Comp_VecDo3(MIPSOpcode op) = 0; + virtual void Comp_VV2Op(MIPSOpcode op) = 0; + virtual void Comp_Mftv(MIPSOpcode op) = 0; + virtual void Comp_Vmfvc(MIPSOpcode op) = 0; + virtual void Comp_Vmtvc(MIPSOpcode op) = 0; + virtual void Comp_Vmmov(MIPSOpcode op) = 0; + virtual void Comp_VScl(MIPSOpcode op) = 0; + virtual void Comp_Vmmul(MIPSOpcode op) = 0; + virtual void Comp_Vmscl(MIPSOpcode op) = 0; + virtual void Comp_Vtfm(MIPSOpcode op) = 0; + virtual void Comp_VHdp(MIPSOpcode op) = 0; + virtual void Comp_VCrs(MIPSOpcode op) = 0; + virtual void Comp_VDet(MIPSOpcode op) = 0; + virtual void Comp_Vi2x(MIPSOpcode op) = 0; + virtual void Comp_Vx2i(MIPSOpcode op) = 0; + virtual void Comp_Vf2i(MIPSOpcode op) = 0; + virtual void Comp_Vi2f(MIPSOpcode op) = 0; + virtual void Comp_Vh2f(MIPSOpcode op) = 0; + virtual void Comp_Vcst(MIPSOpcode op) = 0; + virtual void Comp_Vhoriz(MIPSOpcode op) = 0; + virtual void Comp_VRot(MIPSOpcode op) = 0; + virtual void Comp_VIdt(MIPSOpcode op) = 0; + virtual void Comp_Vcmp(MIPSOpcode op) = 0; + virtual void Comp_Vcmov(MIPSOpcode op) = 0; + virtual void Comp_Viim(MIPSOpcode op) = 0; + virtual void Comp_Vfim(MIPSOpcode op) = 0; + virtual void Comp_VCrossQuat(MIPSOpcode op) = 0; + virtual void Comp_Vsgn(MIPSOpcode op) = 0; + virtual void Comp_Vocp(MIPSOpcode op) = 0; + virtual void Comp_ColorConv(MIPSOpcode op) = 0; + virtual void Comp_Vbfy(MIPSOpcode op) = 0; + virtual void Comp_DoNothing(MIPSOpcode op) = 0; + + virtual int Replace_fabsf() = 0; + }; + + typedef void (JitInterface::*MIPSCompileFunc)(MIPSOpcode opcode); + typedef int (JitInterface::*MIPSReplaceFunc)(); + + extern JitInterface *jit; + + JitInterface *CreateNativeJit(MIPSState *mips); +} diff --git a/Core/MIPS/JitCommon/JitState.h b/Core/MIPS/JitCommon/JitState.h index b4e81b18fe..1bc75b083c 100644 --- a/Core/MIPS/JitCommon/JitState.h +++ b/Core/MIPS/JitCommon/JitState.h @@ -19,8 +19,10 @@ #pragma once #include "Common/Common.h" +#include "Core/MIPS/MIPS.h" struct JitBlock; +class JitBlockCache; namespace MIPSComp { @@ -203,4 +205,6 @@ namespace MIPSComp { bool continueJumps; int continueMaxInstructions; }; + } + diff --git a/Core/MIPS/JitCommon/NativeJit.h b/Core/MIPS/JitCommon/NativeJit.h deleted file mode 100644 index 96be0d0bfb..0000000000 --- a/Core/MIPS/JitCommon/NativeJit.h +++ /dev/null @@ -1,48 +0,0 @@ -// Copyright (c) 2012- PPSSPP 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 git repository and contact information can be found at -// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/. - -#pragma once - -struct JitBlock; - -#ifdef USING_QT_UI -#undef emit -#endif - -#if defined(ARM) -#include "../ARM/ArmJit.h" -typedef MIPSComp::ArmJit NativeJit; -#elif defined(ARM64) -#include "../ARM64/Arm64Jit.h" -typedef MIPSComp::Arm64Jit NativeJit; -#elif defined(_M_IX86) || defined(_M_X64) -#include "../x86/Jit.h" -typedef MIPSComp::Jit NativeJit; -#elif defined(MIPS) -#include "../MIPS/MipsJit.h" -typedef MIPSComp::MipsJit NativeJit; -#else -#include "../fake/FakeJit.h" -typedef MIPSComp::FakeJit NativeJit; -#endif - -namespace MIPSComp { - extern NativeJit *jit; - - typedef void (NativeJit::*MIPSCompileFunc)(MIPSOpcode opcode); - typedef int (NativeJit::*MIPSReplaceFunc)(); -} diff --git a/Core/MIPS/MIPS.cpp b/Core/MIPS/MIPS.cpp index e69ec9cbbf..1140b67914 100644 --- a/Core/MIPS/MIPS.cpp +++ b/Core/MIPS/MIPS.cpp @@ -27,12 +27,10 @@ #include "Core/MIPS/MIPSTables.h" #include "Core/MIPS/MIPSDebugInterface.h" #include "Core/MIPS/MIPSVFPUUtils.h" -#include "Core/MIPS/JitCommon/JitBlockCache.h" #include "Core/Reporting.h" #include "Core/System.h" #include "Core/HLE/sceDisplay.h" #include "Core/MIPS/JitCommon/JitCommon.h" -#include "Core/MIPS/JitCommon/NativeJit.h" #include "Core/CoreTiming.h" MIPSState mipsr4k; @@ -209,17 +207,7 @@ void MIPSState::Init() { rng.Init(0x1337); if (PSP_CoreParameter().cpuCore == CPU_JIT) { -#ifdef ARM - MIPSComp::jit = new MIPSComp::ArmJit(this); -#elif defined(ARM64) - MIPSComp::jit = new MIPSComp::Arm64Jit(this); -#elif defined(_M_IX86) || defined(_M_X64) - MIPSComp::jit = new MIPSComp::Jit(this); -#elif defined(MIPS) - MIPSComp::jit = new MIPSComp::MipsJit(this); -#else - MIPSComp::jit = new MIPSComp::FakeJit(this); -#endif + MIPSComp::jit = MIPSComp::CreateNativeJit(this); } else { MIPSComp::jit = nullptr; } @@ -239,17 +227,7 @@ void MIPSState::UpdateCore(CPUCore desired) { case CPU_JIT: INFO_LOG(CPU, "Switching to JIT"); if (!MIPSComp::jit) { -#ifdef ARM - MIPSComp::jit = new MIPSComp::ArmJit(this); -#elif defined(ARM64) - MIPSComp::jit = new MIPSComp::Arm64Jit(this); -#elif defined(_M_IX86) || defined(_M_X64) - MIPSComp::jit = new MIPSComp::Jit(this); -#elif defined(MIPS) - MIPSComp::jit = new MIPSComp::MipsJit(this); -#else - MIPSComp::jit = new MIPSComp::FakeJit(this); -#endif + MIPSComp::jit = MIPSComp::CreateNativeJit(this); } break; diff --git a/Core/MIPS/MIPS/MipsJit.h b/Core/MIPS/MIPS/MipsJit.h index dfbaa89e5c..1fcb6faea6 100644 --- a/Core/MIPS/MIPS/MipsJit.h +++ b/Core/MIPS/MIPS/MipsJit.h @@ -31,22 +31,22 @@ using namespace MIPSGen; namespace MIPSComp { -class MipsJit : public MIPSGen::MIPSCodeBlock +class MipsJit : public MIPSGen::MIPSCodeBlock, public JitInterface { public: MipsJit(MIPSState *mips); - void DoState(PointerWrap &p); - static void DoDummyState(PointerWrap &p); + void DoState(PointerWrap &p) override; + void DoDummyState(PointerWrap &p) override; // Compiled ops should ignore delay slots // the compiler will take care of them by itself // OR NOT - void Comp_Generic(MIPSOpcode op); + void Comp_Generic(MIPSOpcode op) override; - void RunLoopUntil(u64 globalticks); + void RunLoopUntil(u64 globalticks) override; - void Compile(u32 em_address); // Compiles a block at current MIPS PC + void Compile(u32 em_address) override; // Compiles a block at current MIPS PC const u8 *DoJit(u32 em_address, JitBlock *b); bool DescribeCodePtr(const u8 *ptr, std::string &name); @@ -55,75 +55,75 @@ public: void EatInstruction(MIPSOpcode op); void AddContinuedBlock(u32 dest); - void Comp_RunBlock(MIPSOpcode op); - void Comp_ReplacementFunc(MIPSOpcode op); + void Comp_RunBlock(MIPSOpcode op) override; + void Comp_ReplacementFunc(MIPSOpcode op) override; // Ops - void Comp_ITypeMem(MIPSOpcode op) {} - void Comp_Cache(MIPSOpcode op) {} + void Comp_ITypeMem(MIPSOpcode op) override {} + void Comp_Cache(MIPSOpcode op) override {} - void Comp_RelBranch(MIPSOpcode op) {} - void Comp_RelBranchRI(MIPSOpcode op) {} - void Comp_FPUBranch(MIPSOpcode op) {} - void Comp_FPULS(MIPSOpcode op) {} - void Comp_FPUComp(MIPSOpcode op) {} - void Comp_Jump(MIPSOpcode op) {} - void Comp_JumpReg(MIPSOpcode op) {} - void Comp_Syscall(MIPSOpcode op) {} - void Comp_Break(MIPSOpcode op) {} + void Comp_RelBranch(MIPSOpcode op) override {} + void Comp_RelBranchRI(MIPSOpcode op) override {} + void Comp_FPUBranch(MIPSOpcode op) override {} + void Comp_FPULS(MIPSOpcode op) override {} + void Comp_FPUComp(MIPSOpcode op) override {} + void Comp_Jump(MIPSOpcode op) override {} + void Comp_JumpReg(MIPSOpcode op) override {} + void Comp_Syscall(MIPSOpcode op) override {} + void Comp_Break(MIPSOpcode op) override {} - void Comp_IType(MIPSOpcode op) {} - void Comp_RType2(MIPSOpcode op) {} - void Comp_RType3(MIPSOpcode op) {} - void Comp_ShiftType(MIPSOpcode op) {} - void Comp_Allegrex(MIPSOpcode op) {} - void Comp_Allegrex2(MIPSOpcode op) {} - void Comp_VBranch(MIPSOpcode op) {} - void Comp_MulDivType(MIPSOpcode op) {} - void Comp_Special3(MIPSOpcode op) {} + void Comp_IType(MIPSOpcode op) override {} + void Comp_RType2(MIPSOpcode op) override {} + void Comp_RType3(MIPSOpcode op) override {} + void Comp_ShiftType(MIPSOpcode op) override {} + void Comp_Allegrex(MIPSOpcode op) override {} + void Comp_Allegrex2(MIPSOpcode op) override {} + void Comp_VBranch(MIPSOpcode op) override {} + void Comp_MulDivType(MIPSOpcode op) override {} + void Comp_Special3(MIPSOpcode op) override {} - void Comp_FPU3op(MIPSOpcode op) {} - void Comp_FPU2op(MIPSOpcode op) {} - void Comp_mxc1(MIPSOpcode op) {} + void Comp_FPU3op(MIPSOpcode op) override {} + void Comp_FPU2op(MIPSOpcode op) override {} + void Comp_mxc1(MIPSOpcode op) override {} - void Comp_DoNothing(MIPSOpcode op) {} + void Comp_DoNothing(MIPSOpcode op) override {} - void Comp_SV(MIPSOpcode op) {} - void Comp_SVQ(MIPSOpcode op) {} - void Comp_VPFX(MIPSOpcode op) {} - void Comp_VVectorInit(MIPSOpcode op) {} - void Comp_VMatrixInit(MIPSOpcode op) {} - void Comp_VDot(MIPSOpcode op) {} - void Comp_VecDo3(MIPSOpcode op) {} - void Comp_VV2Op(MIPSOpcode op) {} - void Comp_Mftv(MIPSOpcode op) {} - void Comp_Vmfvc(MIPSOpcode op) {} - void Comp_Vmtvc(MIPSOpcode op) {} - void Comp_Vmmov(MIPSOpcode op) {} - void Comp_VScl(MIPSOpcode op) {} - void Comp_Vmmul(MIPSOpcode op) {} - void Comp_Vmscl(MIPSOpcode op) {} - void Comp_Vtfm(MIPSOpcode op) {} - void Comp_VHdp(MIPSOpcode op) {} - void Comp_VCrs(MIPSOpcode op) {} - void Comp_VDet(MIPSOpcode op) {} - void Comp_Vi2x(MIPSOpcode op) {} - void Comp_Vx2i(MIPSOpcode op) {} - void Comp_Vf2i(MIPSOpcode op) {} - void Comp_Vi2f(MIPSOpcode op) {} - void Comp_Vh2f(MIPSOpcode op) {} - void Comp_Vcst(MIPSOpcode op) {} - void Comp_Vhoriz(MIPSOpcode op) {} - void Comp_VRot(MIPSOpcode op) {} - void Comp_VIdt(MIPSOpcode op) {} - void Comp_Vcmp(MIPSOpcode op) {} - void Comp_Vcmov(MIPSOpcode op) {} - void Comp_Viim(MIPSOpcode op) {} - void Comp_Vfim(MIPSOpcode op) {} - void Comp_VCrossQuat(MIPSOpcode op) {} - void Comp_Vsgn(MIPSOpcode op) {} - void Comp_Vocp(MIPSOpcode op) {} - void Comp_ColorConv(MIPSOpcode op) {} + void Comp_SV(MIPSOpcode op) override {} + void Comp_SVQ(MIPSOpcode op) override {} + void Comp_VPFX(MIPSOpcode op) override {} + void Comp_VVectorInit(MIPSOpcode op) override {} + void Comp_VMatrixInit(MIPSOpcode op) override {} + void Comp_VDot(MIPSOpcode op) override {} + void Comp_VecDo3(MIPSOpcode op) override {} + void Comp_VV2Op(MIPSOpcode op) override {} + void Comp_Mftv(MIPSOpcode op) override {} + void Comp_Vmfvc(MIPSOpcode op) override {} + void Comp_Vmtvc(MIPSOpcode op) override {} + void Comp_Vmmov(MIPSOpcode op) override {} + void Comp_VScl(MIPSOpcode op) override {} + void Comp_Vmmul(MIPSOpcode op) override {} + void Comp_Vmscl(MIPSOpcode op) override {} + void Comp_Vtfm(MIPSOpcode op) override {} + void Comp_VHdp(MIPSOpcode op) override {} + void Comp_VCrs(MIPSOpcode op) override {} + void Comp_VDet(MIPSOpcode op) override {} + void Comp_Vi2x(MIPSOpcode op) override {} + void Comp_Vx2i(MIPSOpcode op) override {} + void Comp_Vf2i(MIPSOpcode op) override {} + void Comp_Vi2f(MIPSOpcode op) override {} + void Comp_Vh2f(MIPSOpcode op) override {} + void Comp_Vcst(MIPSOpcode op) override {} + void Comp_Vhoriz(MIPSOpcode op) override {} + void Comp_VRot(MIPSOpcode op) override {} + void Comp_VIdt(MIPSOpcode op) override {} + void Comp_Vcmp(MIPSOpcode op) override {} + void Comp_Vcmov(MIPSOpcode op) override {} + void Comp_Viim(MIPSOpcode op) override {} + void Comp_Vfim(MIPSOpcode op) override {} + void Comp_VCrossQuat(MIPSOpcode op) override {} + void Comp_Vsgn(MIPSOpcode op) override {} + void Comp_Vocp(MIPSOpcode op) override {} + void Comp_ColorConv(MIPSOpcode op) override {} int Replace_fabsf() { return 0; } void Comp_Vbfy(MIPSOpcode op) {} diff --git a/Core/MIPS/MIPSAnalyst.cpp b/Core/MIPS/MIPSAnalyst.cpp index fbe4863962..cf248816f0 100644 --- a/Core/MIPS/MIPSAnalyst.cpp +++ b/Core/MIPS/MIPSAnalyst.cpp @@ -25,6 +25,7 @@ #include "Core/MemMap.h" #include "Core/System.h" #include "Core/MIPS/MIPS.h" +#include "Core/MIPS/MIPSVFPUUtils.h" #include "Core/MIPS/MIPSTables.h" #include "Core/MIPS/MIPSAnalyst.h" #include "Core/MIPS/MIPSCodeUtils.h" diff --git a/Core/MIPS/MIPSAsm.cpp b/Core/MIPS/MIPSAsm.cpp index ae7982ef8a..ecb9ea1859 100644 --- a/Core/MIPS/MIPSAsm.cpp +++ b/Core/MIPS/MIPSAsm.cpp @@ -15,7 +15,7 @@ #include "util/text/utf8.h" #include "Core/Debugger/SymbolMap.h" #include "Core/MemMapHelpers.h" -#include "Core/MIPS/JitCommon/NativeJit.h" +#include "Core/MIPS/JitCommon/JitCommon.h" #include "Core/MIPS/MIPSAsm.h" namespace MIPSAsm diff --git a/Core/MIPS/MIPSTables.cpp b/Core/MIPS/MIPSTables.cpp index 2b7169a00e..dec15e41b6 100644 --- a/Core/MIPS/MIPSTables.cpp +++ b/Core/MIPS/MIPSTables.cpp @@ -29,7 +29,7 @@ #include "Core/Reporting.h" #include "Core/Debugger/Breakpoints.h" -#include "JitCommon/NativeJit.h" +#include "JitCommon/JitCommon.h" enum MipsEncoding { Imme, @@ -81,17 +81,7 @@ struct MIPSInstruction { #define ENCODING(a) {a} #define INSTR(name, comp, dis, inter, flags) {Instruc, name, comp, dis, inter, MIPSInfo(flags)} -#ifdef ARM -#define JITFUNC(f) (&ArmJit::f) -#elif defined(ARM64) -#define JITFUNC(f) (&Arm64Jit::f) -#elif defined(_M_X64) || defined(_M_IX86) -#define JITFUNC(f) (&Jit::f) -#elif defined(MIPS) -#define JITFUNC(f) (&MipsJit::f) -#else -#define JITFUNC(f) (&FakeJit::f) -#endif +#define JITFUNC(f) (&JitInterface::f) using namespace MIPSDis; using namespace MIPSInt; diff --git a/Core/MIPS/MIPSTables.h b/Core/MIPS/MIPSTables.h index ac77e34f2b..75ac6c5003 100644 --- a/Core/MIPS/MIPSTables.h +++ b/Core/MIPS/MIPSTables.h @@ -111,7 +111,6 @@ struct MIPSInfo { typedef void (CDECL *MIPSDisFunc)(MIPSOpcode opcode, char *out); typedef void (CDECL *MIPSInterpretFunc)(MIPSOpcode opcode); - void MIPSCompileOp(MIPSOpcode op); void MIPSDisAsm(MIPSOpcode op, u32 pc, char *out, bool tabsToSpaces = false); MIPSInfo MIPSGetInfo(MIPSOpcode op); @@ -124,3 +123,4 @@ const char *MIPSGetName(MIPSOpcode op); const char *MIPSDisasmAt(u32 compilerPC); void FillMIPSTables(); + diff --git a/Core/MIPS/fake/FakeJit.h b/Core/MIPS/fake/FakeJit.h index 0546d0e038..cfb09a8a56 100644 --- a/Core/MIPS/fake/FakeJit.h +++ b/Core/MIPS/fake/FakeJit.h @@ -178,8 +178,5 @@ public: const u8 *breakpointBailout; }; -typedef void (FakeJit::*MIPSCompileFunc)(MIPSOpcode opcode); -typedef int (FakeJit::*MIPSReplaceFunc)(); - } // namespace MIPSComp diff --git a/Core/MIPS/x86/CompReplace.cpp b/Core/MIPS/x86/CompReplace.cpp index f0e907d03f..336a38264e 100644 --- a/Core/MIPS/x86/CompReplace.cpp +++ b/Core/MIPS/x86/CompReplace.cpp @@ -16,8 +16,9 @@ // https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/. #include "Core/MemMap.h" -#include "Core/MIPS/JitCommon/NativeJit.h" +#include "Core/MIPS/JitCommon/JitCommon.h" #include "Core/MIPS/x86/RegCache.h" +#include "Core/MIPS/x86/Jit.h" static const u64 MEMORY_ALIGNED16(ssNoSignMask[2]) = {0x7FFFFFFF7FFFFFFFULL, 0x7FFFFFFF7FFFFFFFULL}; diff --git a/Core/MIPS/x86/Jit.cpp b/Core/MIPS/x86/Jit.cpp index badd772e22..f3f83b58d3 100644 --- a/Core/MIPS/x86/Jit.cpp +++ b/Core/MIPS/x86/Jit.cpp @@ -359,7 +359,7 @@ const u8 *Jit::DoJit(u32 em_address, JitBlock *b) js.PrefixStart(); // We add a check before the block, used when entering from a linked block. - b->checkedEntry = GetCodePtr(); + b->checkedEntry = (u8 *)GetCodePtr(); // 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)); @@ -501,6 +501,30 @@ void Jit::Comp_RunBlock(MIPSOpcode op) ERROR_LOG(JIT, "Comp_RunBlock"); } +void Jit::LinkBlock(u8 *exitPoint, const u8 *checkedEntry) { + XEmitter emit(exitPoint); + // Okay, this is a bit ugly, but we check here if it already has a JMP. + // That means it doesn't have a full exit to pad with INT 3. + bool prelinked = *emit.GetCodePointer() == 0xE9; + emit.JMP(checkedEntry, true); + if (!prelinked) { + ptrdiff_t actualSize = emit.GetWritableCodePtr() - exitPoint; + int pad = JitBlockCache::GetBlockExitSize() - (int)actualSize; + for (int i = 0; i < pad; ++i) { + emit.INT3(); + } + } +} + +void Jit::UnlinkBlock(u8 *checkedEntry, u32 originalAddress) { + // Send anyone who tries to run this block back to the dispatcher. + // Not entirely ideal, but .. pretty good. + // Spurious entrances from previously linked blocks can only come through checkedEntry + XEmitter emit(checkedEntry); + emit.MOV(32, M(&mips_->pc), Imm32(originalAddress)); + emit.JMP(MIPSComp::jit->GetDispatcher(), true); +} + bool Jit::ReplaceJalTo(u32 dest) { const ReplacementTableEntry *entry = nullptr; u32 funcSize = 0; diff --git a/Core/MIPS/x86/Jit.h b/Core/MIPS/x86/Jit.h index cc927bb389..68d160a958 100644 --- a/Core/MIPS/x86/Jit.h +++ b/Core/MIPS/x86/Jit.h @@ -28,6 +28,7 @@ #include "Common/x64Emitter.h" #include "Core/MIPS/JitCommon/JitBlockCache.h" #include "Core/MIPS/JitCommon/JitState.h" +#include "Core/MIPS/JitCommon/JitCommon.h" #include "Core/MIPS/x86/JitSafeMem.h" #include "Core/MIPS/x86/RegCache.h" #include "Core/MIPS/x86/RegCacheFPU.h" @@ -45,7 +46,7 @@ struct RegCacheState { FPURegCacheState fpr; }; -class Jit : public Gen::XCodeBlock { +class Jit : public Gen::XCodeBlock, public JitInterface { public: Jit(MIPSState *mips); virtual ~Jit(); @@ -53,92 +54,92 @@ public: const JitOptions &GetJitOptions() { return jo; } void DoState(PointerWrap &p); - static void DoDummyState(PointerWrap &p); + void DoDummyState(PointerWrap &p); // Compiled ops should ignore delay slots // the compiler will take care of them by itself // OR NOT - void Comp_Generic(MIPSOpcode op); + void Comp_Generic(MIPSOpcode op) override; - void RunLoopUntil(u64 globalticks); + void RunLoopUntil(u64 globalticks) override; - void Compile(u32 em_address); // Compiles a block at current MIPS PC + void Compile(u32 em_address) override; // Compiles a block at current MIPS PC const u8 *DoJit(u32 em_address, JitBlock *b); - bool DescribeCodePtr(const u8 *ptr, std::string &name); + bool DescribeCodePtr(const u8 *ptr, std::string &name) override; - void Comp_RunBlock(MIPSOpcode op); - void Comp_ReplacementFunc(MIPSOpcode op); + void Comp_RunBlock(MIPSOpcode op) override; + void Comp_ReplacementFunc(MIPSOpcode op) override; // Ops - void Comp_ITypeMem(MIPSOpcode op); - void Comp_Cache(MIPSOpcode op); + void Comp_ITypeMem(MIPSOpcode op) override; + void Comp_Cache(MIPSOpcode op) override; - void Comp_RelBranch(MIPSOpcode op); - void Comp_RelBranchRI(MIPSOpcode op); - void Comp_FPUBranch(MIPSOpcode op); - void Comp_FPULS(MIPSOpcode op); - void Comp_FPUComp(MIPSOpcode op); - void Comp_Jump(MIPSOpcode op); - void Comp_JumpReg(MIPSOpcode op); - void Comp_Syscall(MIPSOpcode op); - void Comp_Break(MIPSOpcode op); + void Comp_RelBranch(MIPSOpcode op) override; + void Comp_RelBranchRI(MIPSOpcode op) override; + void Comp_FPUBranch(MIPSOpcode op) override; + void Comp_FPULS(MIPSOpcode op) override; + void Comp_FPUComp(MIPSOpcode op) override; + void Comp_Jump(MIPSOpcode op) override; + void Comp_JumpReg(MIPSOpcode op) override; + void Comp_Syscall(MIPSOpcode op) override; + void Comp_Break(MIPSOpcode op) override; - void Comp_IType(MIPSOpcode op); - void Comp_RType2(MIPSOpcode op); - void Comp_RType3(MIPSOpcode op); - void Comp_ShiftType(MIPSOpcode op); - void Comp_Allegrex(MIPSOpcode op); - void Comp_Allegrex2(MIPSOpcode op); - void Comp_VBranch(MIPSOpcode op); - void Comp_MulDivType(MIPSOpcode op); - void Comp_Special3(MIPSOpcode op); + void Comp_IType(MIPSOpcode op) override; + void Comp_RType2(MIPSOpcode op) override; + void Comp_RType3(MIPSOpcode op) override; + void Comp_ShiftType(MIPSOpcode op) override; + void Comp_Allegrex(MIPSOpcode op) override; + void Comp_Allegrex2(MIPSOpcode op) override; + void Comp_VBranch(MIPSOpcode op) override; + void Comp_MulDivType(MIPSOpcode op) override; + void Comp_Special3(MIPSOpcode op) override; - void Comp_FPU3op(MIPSOpcode op); - void Comp_FPU2op(MIPSOpcode op); - void Comp_mxc1(MIPSOpcode op); + void Comp_FPU3op(MIPSOpcode op) override; + void Comp_FPU2op(MIPSOpcode op) override; + void Comp_mxc1(MIPSOpcode op) override; - void Comp_SV(MIPSOpcode op); - void Comp_SVQ(MIPSOpcode op); - void Comp_VPFX(MIPSOpcode op); - void Comp_VVectorInit(MIPSOpcode op); - void Comp_VMatrixInit(MIPSOpcode op); - void Comp_VDot(MIPSOpcode op); - void Comp_VecDo3(MIPSOpcode op); - void Comp_VV2Op(MIPSOpcode op); - void Comp_Mftv(MIPSOpcode op); - void Comp_Vmfvc(MIPSOpcode op); - void Comp_Vmtvc(MIPSOpcode op); - void Comp_Vmmov(MIPSOpcode op); - void Comp_VScl(MIPSOpcode op); - void Comp_Vmmul(MIPSOpcode op); - void Comp_Vmscl(MIPSOpcode op); - void Comp_Vtfm(MIPSOpcode op); - void Comp_VHdp(MIPSOpcode op); - void Comp_VCrs(MIPSOpcode op); - void Comp_VDet(MIPSOpcode op); - void Comp_Vi2x(MIPSOpcode op); - void Comp_Vx2i(MIPSOpcode op); - void Comp_Vf2i(MIPSOpcode op); - void Comp_Vi2f(MIPSOpcode op); - void Comp_Vh2f(MIPSOpcode op); - void Comp_Vcst(MIPSOpcode op); - void Comp_Vhoriz(MIPSOpcode op); - void Comp_VRot(MIPSOpcode op); - void Comp_VIdt(MIPSOpcode op); - void Comp_Vcmp(MIPSOpcode op); - void Comp_Vcmov(MIPSOpcode op); - void Comp_Viim(MIPSOpcode op); - void Comp_Vfim(MIPSOpcode op); - void Comp_VCrossQuat(MIPSOpcode op); - void Comp_Vsgn(MIPSOpcode op); - void Comp_Vocp(MIPSOpcode op); - void Comp_ColorConv(MIPSOpcode op); - void Comp_Vbfy(MIPSOpcode op); + void Comp_SV(MIPSOpcode op) override; + void Comp_SVQ(MIPSOpcode op) override; + void Comp_VPFX(MIPSOpcode op) override; + void Comp_VVectorInit(MIPSOpcode op) override; + void Comp_VMatrixInit(MIPSOpcode op) override; + void Comp_VDot(MIPSOpcode op) override; + void Comp_VecDo3(MIPSOpcode op) override; + void Comp_VV2Op(MIPSOpcode op) override; + void Comp_Mftv(MIPSOpcode op) override; + void Comp_Vmfvc(MIPSOpcode op) override; + void Comp_Vmtvc(MIPSOpcode op) override; + void Comp_Vmmov(MIPSOpcode op) override; + void Comp_VScl(MIPSOpcode op) override; + void Comp_Vmmul(MIPSOpcode op) override; + void Comp_Vmscl(MIPSOpcode op) override; + void Comp_Vtfm(MIPSOpcode op) override; + void Comp_VHdp(MIPSOpcode op) override; + void Comp_VCrs(MIPSOpcode op) override; + void Comp_VDet(MIPSOpcode op) override; + void Comp_Vi2x(MIPSOpcode op) override; + void Comp_Vx2i(MIPSOpcode op) override; + void Comp_Vf2i(MIPSOpcode op) override; + void Comp_Vi2f(MIPSOpcode op) override; + void Comp_Vh2f(MIPSOpcode op) override; + void Comp_Vcst(MIPSOpcode op) override; + void Comp_Vhoriz(MIPSOpcode op) override; + void Comp_VRot(MIPSOpcode op) override; + void Comp_VIdt(MIPSOpcode op) override; + void Comp_Vcmp(MIPSOpcode op) override; + void Comp_Vcmov(MIPSOpcode op) override; + void Comp_Viim(MIPSOpcode op) override; + void Comp_Vfim(MIPSOpcode op) override; + void Comp_VCrossQuat(MIPSOpcode op) override; + void Comp_Vsgn(MIPSOpcode op) override; + void Comp_Vocp(MIPSOpcode op) override; + void Comp_ColorConv(MIPSOpcode op) override; + void Comp_Vbfy(MIPSOpcode op) override; - void Comp_DoNothing(MIPSOpcode op); + void Comp_DoNothing(MIPSOpcode op) override; - int Replace_fabsf(); + int Replace_fabsf() override; void ApplyPrefixST(u8 *vregs, u32 prefix, VectorSize sz); void ApplyPrefixD(const u8 *vregs, VectorSize sz); @@ -162,17 +163,20 @@ public: JitBlockCache *GetBlockCache() { return &blocks; } void ClearCache(); - void InvalidateCache(); - inline void InvalidateCacheAt(u32 em_address, int length = 4) { + void InvalidateCache() override; + void InvalidateCacheAt(u32 em_address, int length = 4) { if (blocks.RangeMayHaveEmuHacks(em_address, em_address + length)) { blocks.InvalidateICache(em_address, length); } } - const u8 *GetDispatcher() const { + const u8 *GetDispatcher() const override { return dispatcher; } + void LinkBlock(u8 *exitPoint, const u8 *checkedEntry) override; + void UnlinkBlock(u8 *checkedEntry, u32 originalAddress) override; + private: void GenerateFixedCode(JitOptions &jo); void GetStateAndFlushAll(RegCacheState &state); diff --git a/Core/MemMap.cpp b/Core/MemMap.cpp index e07fc65bb8..557bc461c4 100644 --- a/Core/MemMap.cpp +++ b/Core/MemMap.cpp @@ -35,6 +35,7 @@ #include "Core/Debugger/Breakpoints.h" #include "Core/Config.h" #include "Core/HLE/ReplaceTables.h" +#include "Core/MIPS/JitCommon/JitBlockCache.h" namespace Memory { diff --git a/Core/SaveState.cpp b/Core/SaveState.cpp index 1155de1c61..bf6f30eeed 100644 --- a/Core/SaveState.cpp +++ b/Core/SaveState.cpp @@ -41,6 +41,7 @@ #include "Core/HLE/sceKernel.h" #include "Core/MemMap.h" #include "Core/MIPS/MIPS.h" +#include "Core/MIPS/JitCommon/JitBlockCache.h" #include "HW/MemoryStick.h" #include "GPU/GPUState.h" #include "UI/OnScreenDisplay.h" diff --git a/Qt/Common.pro b/Qt/Common.pro index 6aa505554d..7d2b705f06 100644 --- a/Qt/Common.pro +++ b/Qt/Common.pro @@ -7,8 +7,7 @@ include(Settings.pri) # CPU arm { - SOURCES += $$P/Common/ArmCPUDetect.cpp \ - $$P/Common/ArmThunk.cpp + SOURCES += $$P/Common/ArmCPUDetect.cpp } else:i86 { SOURCES += $$P/Common/ABI.cpp \ diff --git a/UI/CwCheatScreen.cpp b/UI/CwCheatScreen.cpp index e16262f159..7f6481709c 100644 --- a/UI/CwCheatScreen.cpp +++ b/UI/CwCheatScreen.cpp @@ -25,7 +25,7 @@ #include "Core/Core.h" #include "Core/Config.h" #include "Core/CwCheat.h" -#include "Core/MIPS/JitCommon/NativeJit.h" +#include "Core/MIPS/JitCommon/JitCommon.h" #include "UI/OnScreenDisplay.h" #include "UI/ui_atlas.h" diff --git a/UI/DevScreens.cpp b/UI/DevScreens.cpp index e25c8ad982..1b41243b61 100644 --- a/UI/DevScreens.cpp +++ b/UI/DevScreens.cpp @@ -34,7 +34,7 @@ #include "Core/System.h" #include "Core/CoreParameter.h" #include "Core/MIPS/MIPSTables.h" -#include "Core/MIPS/JitCommon/NativeJit.h" +#include "Core/MIPS/JitCommon/JitBlockCache.h" #include "Core/MIPS/JitCommon/JitCommon.h" #include "GPU/GPUInterface.h" #include "GPU/GPUState.h" diff --git a/UI/MiscScreens.cpp b/UI/MiscScreens.cpp index 7925287eda..e6f0cc28e6 100644 --- a/UI/MiscScreens.cpp +++ b/UI/MiscScreens.cpp @@ -37,7 +37,7 @@ #include "Core/Config.h" #include "Core/Host.h" #include "Core/System.h" -#include "Core/MIPS/JitCommon/NativeJit.h" +#include "Core/MIPS/JitCommon/JitCommon.h" #include "Core/HLE/sceUtility.h" #include "Common/FileUtil.h" #include "GPU/GPUState.h" diff --git a/Windows/MainWindow.cpp b/Windows/MainWindow.cpp index 2dd40ce64e..317bf72fbc 100644 --- a/Windows/MainWindow.cpp +++ b/Windows/MainWindow.cpp @@ -47,7 +47,7 @@ #include "Windows/Debugger/Debugger_Disasm.h" #include "Windows/Debugger/Debugger_MemoryDlg.h" #include "Windows/GEDebugger/GEDebugger.h" -#include "Core/MIPS/JitCommon/NativeJit.h" +#include "Core/MIPS/JitCommon/JitCommon.h" #include "Core/MIPS/JitCommon/JitBlockCache.h" #include "main.h" diff --git a/android/jni/Android.mk b/android/jni/Android.mk index 6eb9e787c8..8a3c46c084 100644 --- a/android/jni/Android.mk +++ b/android/jni/Android.mk @@ -57,7 +57,6 @@ ARCH_FILES := \ $(SRC)/Core/Util/AudioFormatNEON.cpp.neon \ $(SRC)/Common/ArmEmitter.cpp \ $(SRC)/Common/ArmCPUDetect.cpp \ - $(SRC)/Common/ArmThunk.cpp \ $(SRC)/Common/ColorConvNEON.cpp.neon \ $(SRC)/Core/MIPS/ARM/ArmCompALU.cpp \ $(SRC)/Core/MIPS/ARM/ArmCompBranch.cpp \ @@ -102,7 +101,6 @@ ifeq ($(TARGET_ARCH_ABI),armeabi) ARCH_FILES := \ $(SRC)/Common/ArmEmitter.cpp \ $(SRC)/Common/ArmCPUDetect.cpp \ - $(SRC)/Common/ArmThunk.cpp \ $(SRC)/Core/MIPS/ARM/ArmCompALU.cpp \ $(SRC)/Core/MIPS/ARM/ArmCompBranch.cpp \ $(SRC)/Core/MIPS/ARM/ArmCompFPU.cpp \ diff --git a/unittest/JitHarness.cpp b/unittest/JitHarness.cpp index dc533ad362..b80fb04e6d 100644 --- a/unittest/JitHarness.cpp +++ b/unittest/JitHarness.cpp @@ -21,7 +21,7 @@ #include "base/NativeApp.h" #include "input/input_state.h" #include "Core/MIPS/JitCommon/JitCommon.h" -#include "Core/MIPS/JitCommon/NativeJit.h" +#include "Core/MIPS/JitCommon/JitBlockCache.h" #include "Core/MIPS/MIPSCodeUtils.h" #include "Core/MIPS/MIPSDebugInterface.h" #include "Core/MIPS/MIPSAsm.h" diff --git a/unittest/TestArm64Emitter.cpp b/unittest/TestArm64Emitter.cpp index e4781a9905..6aea74f0dc 100644 --- a/unittest/TestArm64Emitter.cpp +++ b/unittest/TestArm64Emitter.cpp @@ -10,7 +10,7 @@ static bool CheckLast(Arm64Gen::ARM64XEmitter &emit, const char *comp) { u32 instr; - memcpy(&instr, emit.GetCodePtr() - 4, 4); + memcpy(&instr, emit.GetCodePointer() - 4, 4); char disasm[512]; Arm64Dis(0, instr, disasm, sizeof(disasm), true); EXPECT_EQ_STR(std::string(disasm), std::string(comp)); diff --git a/unittest/TestArmEmitter.cpp b/unittest/TestArmEmitter.cpp index 84b6bee9e0..aa9db3f72a 100644 --- a/unittest/TestArmEmitter.cpp +++ b/unittest/TestArmEmitter.cpp @@ -11,7 +11,7 @@ static bool CheckLast(ArmGen::ARMXEmitter &emit, const char *comp) { u32 instr; - memcpy(&instr, emit.GetCodePtr() - 4, 4); + memcpy(&instr, emit.GetCodePointer() - 4, 4); char disasm[512]; ArmDis(0, instr, disasm, sizeof(disasm), true); EXPECT_EQ_STR(std::string(disasm), std::string(comp)); @@ -227,7 +227,7 @@ bool TestArmEmitter() { //RET(CheckLast(emitter, "eef70a00 VMOV.f32 s1, #112")); - const u8 *codeStart = emitter.GetCodePtr(); + const u8 *codeStart = emitter.GetCodePointer(); MIPSState mips; MIPSComp::JitState js; @@ -269,7 +269,7 @@ bool TestArmEmitter() { fpr.QMapReg(C000, V_Quad, MAP_DIRTY); fpr.FlushAll(); - const u8 *codeEnd = emitter.GetCodePtr(); + const u8 *codeEnd = emitter.GetCodePointer(); DisassembleARMBetween(codeStart, codeEnd); diff --git a/unittest/TestX64Emitter.cpp b/unittest/TestX64Emitter.cpp index 6ff8d0b2c4..6fe2882859 100644 --- a/unittest/TestX64Emitter.cpp +++ b/unittest/TestX64Emitter.cpp @@ -11,13 +11,13 @@ static const u8 *prevStart = NULL; bool CheckLast(Gen::XEmitter &emit, const char *comp) { - auto vec = DisassembleX86(prevStart, emit.GetCodePtr() - prevStart); + auto vec = DisassembleX86(prevStart, emit.GetCodePointer() - prevStart); EXPECT_EQ_STR(vec[0], std::string(comp)); return true; } void PrintLast(Gen::XEmitter &emit) { - for (const u8 *p = prevStart; p < emit.GetCodePtr(); p++) { + for (const u8 *p = prevStart; p < emit.GetCodePointer(); p++) { printf("%02x ", *p); } printf("\n"); @@ -29,11 +29,11 @@ bool TestX64Emitter() { u32 code[512]; XEmitter emitter((u8 *)code); - prevStart = emitter.GetCodePtr(); + prevStart = emitter.GetCodePointer(); emitter.VADDSD(XMM0, XMM1, R(XMM7)); RET(CheckLast(emitter, "vaddsd xmm0, xmm1, xmm7")); - prevStart = emitter.GetCodePtr(); + prevStart = emitter.GetCodePointer(); emitter.VMULSD(XMM0, XMM1, R(XMM7)); RET(CheckLast(emitter, "vmulsd xmm0, xmm1, xmm7"));