From 9eace8a80e1efdca23d728644b99b4f024f5e037 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Fri, 26 Apr 2013 23:58:20 +0200 Subject: [PATCH] Combine the two JitCache implementations (x86, ARM) into one. --- CMakeLists.txt | 6 +- Core/Core.vcxproj | 18 +- Core/Core.vcxproj.filters | 14 +- Core/MIPS/ARM/ArmCompBranch.cpp | 20 +- Core/MIPS/ARM/ArmJit.cpp | 8 +- Core/MIPS/ARM/ArmJit.h | 16 +- Core/MIPS/ARM/ArmJitCache.cpp | 362 ------------------ Core/MIPS/ARM/ArmJitCache.h | 122 ------ .../JitBlockCache.cpp} | 43 ++- .../JitCache.h => JitCommon/JitBlockCache.h} | 19 +- Core/MIPS/MIPS.cpp | 19 +- Core/MIPS/x86/CompBranch.cpp | 2 +- Core/MIPS/x86/Jit.h | 2 +- android/jni/Android.mk | 4 +- 14 files changed, 82 insertions(+), 573 deletions(-) delete mode 100644 Core/MIPS/ARM/ArmJitCache.cpp delete mode 100644 Core/MIPS/ARM/ArmJitCache.h rename Core/MIPS/{x86/JitCache.cpp => JitCommon/JitBlockCache.cpp} (90%) rename Core/MIPS/{x86/JitCache.h => JitCommon/JitBlockCache.h} (86%) diff --git a/CMakeLists.txt b/CMakeLists.txt index f17affce66..11847a7f0a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -641,8 +641,6 @@ if(ARM) Core/MIPS/ARM/ArmCompVFPU.cpp Core/MIPS/ARM/ArmJit.cpp Core/MIPS/ARM/ArmJit.h - Core/MIPS/ARM/ArmJitCache.cpp - Core/MIPS/ARM/ArmJitCache.h Core/MIPS/ARM/ArmRegCache.cpp Core/MIPS/ARM/ArmRegCache.h Core/MIPS/ARM/ArmRegCacheFPU.cpp @@ -659,8 +657,6 @@ elseif(X86) Core/MIPS/x86/CompVFPU.cpp Core/MIPS/x86/Jit.cpp Core/MIPS/x86/Jit.h - Core/MIPS/x86/JitCache.cpp - Core/MIPS/x86/JitCache.h Core/MIPS/x86/RegCache.cpp Core/MIPS/x86/RegCache.h Core/MIPS/x86/RegCacheFPU.cpp @@ -822,6 +818,8 @@ add_library(${CoreLibName} ${CoreLinkType} Core/Loaders.h Core/MIPS/JitCommon/JitCommon.cpp Core/MIPS/JitCommon/JitCommon.h + Core/MIPS/JitCommon/JitBlockCache.cpp + Core/MIPS/JitCommon/JitBlockCache.h Core/MIPS/MIPS.cpp Core/MIPS/MIPS.h Core/MIPS/MIPSAnalyst.cpp diff --git a/Core/Core.vcxproj b/Core/Core.vcxproj index f59c45a6ff..f997bdba7d 100644 --- a/Core/Core.vcxproj +++ b/Core/Core.vcxproj @@ -266,18 +266,13 @@ true true - - true - true - true - true - true true true true + @@ -297,7 +292,6 @@ - @@ -405,12 +399,6 @@ true true - - true - true - true - true - true true @@ -423,6 +411,7 @@ true true + @@ -437,7 +426,6 @@ - @@ -471,4 +459,4 @@ - + \ No newline at end of file diff --git a/Core/Core.vcxproj.filters b/Core/Core.vcxproj.filters index 77296a5538..8baa3dc173 100644 --- a/Core/Core.vcxproj.filters +++ b/Core/Core.vcxproj.filters @@ -105,9 +105,6 @@ MIPS\x86 - - MIPS\x86 - MIPS\x86 @@ -366,9 +363,6 @@ MIPS\ARM - - MIPS\ARM - MIPS\ARM @@ -403,6 +397,7 @@ ELF + @@ -447,9 +442,6 @@ MIPS\x86 - - MIPS\x86 - MIPS\x86 @@ -711,9 +703,6 @@ MIPS\ARM - - MIPS\ARM - MIPS\ARM @@ -744,6 +733,7 @@ ELF + diff --git a/Core/MIPS/ARM/ArmCompBranch.cpp b/Core/MIPS/ARM/ArmCompBranch.cpp index 42b130593c..9bf983a380 100644 --- a/Core/MIPS/ARM/ArmCompBranch.cpp +++ b/Core/MIPS/ARM/ArmCompBranch.cpp @@ -14,17 +14,19 @@ // Official git repository and contact information can be found at // https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/. -#include "../../HLE/HLE.h" -#include "../MIPS.h" -#include "../MIPSCodeUtils.h" -#include "../MIPSAnalyst.h" -#include "../MIPSTables.h" +#include "Core/HLE/HLE.h" -#include "ArmJit.h" -#include "ArmRegCache.h" -#include "ArmJitCache.h" -#include +#include "Core/MIPS/MIPS.h" +#include "Core/MIPS/MIPSCodeUtils.h" +#include "Core/MIPS/MIPSAnalyst.h" +#include "Core/MIPS/MIPSTables.h" + +#include "Core/MIPS/ARM/ArmJit.h" +#include "Core/MIPS/ARM/ArmRegCache.h" +#include "Core/MIPS/JitCommon/JitBlockCache.h" + +#include "Common/ArmEmitter.h" #define _RS ((op>>21) & 0x1F) #define _RT ((op>>16) & 0x1F) diff --git a/Core/MIPS/ARM/ArmJit.cpp b/Core/MIPS/ARM/ArmJit.cpp index 6d3c1a551a..39057dea9e 100644 --- a/Core/MIPS/ARM/ArmJit.cpp +++ b/Core/MIPS/ARM/ArmJit.cpp @@ -168,7 +168,7 @@ void Jit::Compile(u32 em_address) } int block_num = blocks.AllocateBlock(em_address); - ArmJitBlock *b = blocks.GetBlock(block_num); + JitBlock *b = blocks.GetBlock(block_num); DoJit(em_address, b); blocks.FinalizeBlock(block_num, jo.enableBlocklink); @@ -190,9 +190,9 @@ void Jit::RunLoopUntil(u64 globalticks) ((void (*)())enterCode)(); } static int dontLogBlocks = 20; -int logBlocks = 40; +static int logBlocks = 40; -const u8 *Jit::DoJit(u32 em_address, ArmJitBlock *b) +const u8 *Jit::DoJit(u32 em_address, JitBlock *b) { js.cancel = false; js.blockStart = js.compilerPC = mips_->pc; @@ -331,7 +331,7 @@ void Jit::WriteExit(u32 destination, int exit_num) { WriteDownCount(); //If nobody has taken care of this yet (this can be removed when all branches are done) - ArmJitBlock *b = js.curBlock; + JitBlock *b = js.curBlock; b->exitAddress[exit_num] = destination; b->exitPtrs[exit_num] = GetWritableCodePtr(); diff --git a/Core/MIPS/ARM/ArmJit.h b/Core/MIPS/ARM/ArmJit.h index 8c9c78ffaa..10d776c2d1 100644 --- a/Core/MIPS/ARM/ArmJit.h +++ b/Core/MIPS/ARM/ArmJit.h @@ -19,10 +19,10 @@ #include "../../../Globals.h" -#include "ArmJitCache.h" -#include "ArmRegCache.h" -#include "ArmRegCacheFPU.h" -#include "ArmAsm.h" +#include "Core/MIPS/JitCommon/JitBlockCache.h" +#include "Core/MIPS/ARM/ArmRegCache.h" +#include "Core/MIPS/ARM/ArmRegCacheFPU.h" +#include "Core/MIPS/ARM/ArmAsm.h" #if defined(MAEMO) #include "stddef.h" @@ -57,7 +57,7 @@ struct ArmJitState bool inDelaySlot; int downcountAmount; bool compiling; // TODO: get rid of this in favor of using analysis results to determine end of block - ArmJitBlock *curBlock; + JitBlock *curBlock; // VFPU prefix magic bool startDefaultPrefix; @@ -148,7 +148,7 @@ public: void RunLoopUntil(u64 globalticks); void Compile(u32 em_address); // Compiles a block at current MIPS PC - const u8 *DoJit(u32 em_address, ArmJitBlock *b); + const u8 *DoJit(u32 em_address, JitBlock *b); void CompileDelaySlot(int flags); void CompileAt(u32 addr); @@ -198,7 +198,7 @@ public: void Comp_Vmscl(u32 op); void Comp_Vtfm(u32 op); - ArmJitBlockCache *GetBlockCache() { return &blocks; } + JitBlockCache *GetBlockCache() { return &blocks; } void ClearCache(); void ClearCacheAt(u32 em_address); @@ -259,7 +259,7 @@ private: void SetR0ToEffectiveAddress(int rs, s16 offset); void SetCCAndR0ForSafeAddress(int rs, s16 offset, ARMReg tempReg); - ArmJitBlockCache blocks; + JitBlockCache blocks; ArmJitOptions jo; ArmJitState js; diff --git a/Core/MIPS/ARM/ArmJitCache.cpp b/Core/MIPS/ARM/ArmJitCache.cpp deleted file mode 100644 index 2743ce7e37..0000000000 --- a/Core/MIPS/ARM/ArmJitCache.cpp +++ /dev/null @@ -1,362 +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/. - -#include "Common.h" - -#ifdef _WIN32 -#include -#endif - -#include "../../Core.h" -#include "../../MemMap.h" -#include "../../CoreTiming.h" - -#include "../MIPS.h" -#include "../MIPSTables.h" -#include "../MIPSAnalyst.h" - -#include "ArmEmitter.h" - -#include "ArmJitCache.h" -#include "../JitCommon/JitCommon.h" -#include "ArmAsm.h" - -#if defined USE_OPROFILE && USE_OPROFILE -#include - -op_agent_t agent; -#endif - -#if defined USE_VTUNE -#include -#pragma comment(lib, "libittnotify.lib") -#pragma comment(lib, "jitprofiling.lib") -#endif - -using namespace ArmGen; - -#define INVALID_EXIT 0xFFFFFFFF - -bool ArmJitBlock::ContainsAddress(u32 em_address) -{ - // WARNING - THIS DOES NOT WORK WITH INLINING ENABLED. - return (em_address >= originalAddress && em_address < originalAddress + 4 * originalSize); -} - -bool ArmJitBlockCache::IsFull() const -{ - return GetNumBlocks() >= MAX_NUM_BLOCKS - 1; -} - -void ArmJitBlockCache::Init() -{ - MAX_NUM_BLOCKS = 65536*2; - -#if defined USE_OPROFILE && USE_OPROFILE - agent = op_open_agent(); -#endif - blocks = new ArmJitBlock[MAX_NUM_BLOCKS]; - blockCodePointers = new const u8*[MAX_NUM_BLOCKS]; - Clear(); -} - -void ArmJitBlockCache::Shutdown() -{ - delete[] blocks; - delete[] blockCodePointers; - blocks = 0; - blockCodePointers = 0; - num_blocks = 0; -#if defined USE_OPROFILE && USE_OPROFILE - op_close_agent(agent); -#endif - -#ifdef USE_VTUNE - iJIT_NotifyEvent(iJVM_EVENT_TYPE_SHUTDOWN, NULL); -#endif -} - -ArmJitBlockCache::~ArmJitBlockCache() -{ - Shutdown(); -} - -// This clears the JIT block cache. It's called from JitCache.cpp when the JIT cache -// is full and when saving and loading states. -void ArmJitBlockCache::Clear() -{ - for (int i = 0; i < num_blocks; i++) - { - DestroyBlock(i, false); - } - links_to.clear(); - block_map.clear(); - num_blocks = 0; - memset(blockCodePointers, 0xCC, sizeof(u8*)*MAX_NUM_BLOCKS); -} - -void ArmJitBlockCache::ClearSafe() -{ -#ifdef JIT_UNLIMITED_ICACHE - memset(iCache, JIT_ICACHE_INVALID_BYTE, JIT_ICACHE_SIZE); -#endif -} - -void ArmJitBlockCache::Reset() -{ - Shutdown(); - Init(); -} - -ArmJitBlock *ArmJitBlockCache::GetBlock(int no) -{ - return &blocks[no]; -} - -int ArmJitBlockCache::GetNumBlocks() const -{ - return num_blocks; -} - -bool ArmJitBlockCache::RangeIntersect(int s1, int e1, int s2, int e2) const -{ - // check if any endpoint is inside the other range - if ((s1 >= s2 && s1 <= e2) || - (e1 >= s2 && e1 <= e2) || - (s2 >= s1 && s2 <= e1) || - (e2 >= s1 && e2 <= e1)) - return true; - else - return false; -} - -int ArmJitBlockCache::AllocateBlock(u32 em_address) -{ - ArmJitBlock &b = blocks[num_blocks]; - b.invalid = false; - b.originalAddress = em_address; - b.exitAddress[0] = INVALID_EXIT; - b.exitAddress[1] = INVALID_EXIT; - b.exitPtrs[0] = 0; - b.exitPtrs[1] = 0; - b.linkStatus[0] = false; - b.linkStatus[1] = false; - b.blockNum = num_blocks; - num_blocks++; //commit the current block - return num_blocks - 1; -} - -void ArmJitBlockCache::FinalizeBlock(int block_num, bool block_link) -{ - ArmJitBlock &b = blocks[block_num]; - blockCodePointers[block_num] = b.normalEntry; - - b.originalFirstOpcode = Memory::Read_Opcode_JIT(b.originalAddress); - u32 opcode = MIPS_MAKE_EMUHACK(0, block_num); - Memory::Write_Opcode_JIT(b.originalAddress, opcode); - - // Convert the logical address to a physical address for the block map - // Yeah, this'll work fine for PSP too I think. - u32 pAddr = b.originalAddress & 0x1FFFFFFF; - - block_map[std::make_pair(pAddr + 4 * b.originalSize - 1, pAddr)] = block_num; - if (block_link) - { - for (int i = 0; i < 2; i++) - { - if (b.exitAddress[i] != INVALID_EXIT) - links_to.insert(std::pair(b.exitAddress[i], block_num)); - } - - LinkBlock(block_num); - LinkBlockExits(block_num); - } - -#if defined USE_OPROFILE && USE_OPROFILE - char buf[100]; - sprintf(buf, "EmuCode%x", b.originalAddress); - const u8* blockStart = blocks[block_num].checkedEntry; - op_write_native_code(agent, buf, (uint64_t)blockStart, - blockStart, b.codeSize); -#endif - -#ifdef USE_VTUNE - sprintf(b.blockName, "EmuCode_0x%08x", b.originalAddress); - - iJIT_Method_Load jmethod = {0}; - jmethod.method_id = iJIT_GetNewMethodID(); - jmethod.class_file_name = ""; - jmethod.source_file_name = __FILE__; - jmethod.method_load_address = (void*)blocks[block_num].checkedEntry; - jmethod.method_size = b.codeSize; - jmethod.line_number_size = 0; - jmethod.method_name = b.blockName; - iJIT_NotifyEvent(iJVM_EVENT_TYPE_METHOD_LOAD_FINISHED, (void*)&jmethod); -#endif -} - -const u8 **ArmJitBlockCache::GetCodePointers() -{ - return blockCodePointers; -} - -int ArmJitBlockCache::GetBlockNumberFromStartAddress(u32 addr) -{ - if (!blocks) - return -1; - u32 inst = Memory::Read_U32(addr); - if (!MIPS_IS_EMUHACK(inst)) // definitely not a JIT block - return -1; - int bl = (inst & MIPS_EMUHACK_VALUE_MASK); - if (bl >= num_blocks) - return -1; - if (blocks[bl].originalAddress != addr) - return -1; - return bl; -} - -void ArmJitBlockCache::GetBlockNumbersFromAddress(u32 em_address, std::vector *block_numbers) -{ - for (int i = 0; i < num_blocks; i++) - if (blocks[i].ContainsAddress(em_address)) - block_numbers->push_back(i); -} - -u32 ArmJitBlockCache::GetOriginalFirstOp(int block_num) -{ - if (block_num >= num_blocks) - { - //PanicAlert("JitBlockCache::GetOriginalFirstOp - block_num = %u is out of range", block_num); - return block_num; - } - return blocks[block_num].originalFirstOpcode; -} - -void ArmJitBlockCache::LinkBlockExits(int i) -{ - ArmJitBlock &b = blocks[i]; - if (b.invalid) - { - // This block is dead. Don't relink it. - return; - } - for (int e = 0; e < 2; e++) - { - if (b.exitAddress[e] != INVALID_EXIT && !b.linkStatus[e]) - { - int destinationBlock = GetBlockNumberFromStartAddress(b.exitAddress[e]); - if (destinationBlock != -1) - { - ARMXEmitter emit(b.exitPtrs[e]); - emit.B(blocks[destinationBlock].checkedEntry); - emit.FlushIcache(); - b.linkStatus[e] = true; - } - } - } -} - -using namespace std; - -void ArmJitBlockCache::LinkBlock(int i) -{ - LinkBlockExits(i); - ArmJitBlock &b = blocks[i]; - pair::iterator, multimap::iterator> ppp; - // equal_range(b) returns pair representing the range - // of element with key b - ppp = links_to.equal_range(b.originalAddress); - if (ppp.first == ppp.second) - return; - for (multimap::iterator iter = ppp.first; iter != ppp.second; ++iter) { - // PanicAlert("Linking block %i to block %i", iter2->second, i); - LinkBlockExits(iter->second); - } -} - -void ArmJitBlockCache::UnlinkBlock(int i) -{ - ArmJitBlock &b = blocks[i]; - pair::iterator, multimap::iterator> ppp; - ppp = links_to.equal_range(b.originalAddress); - if (ppp.first == ppp.second) - return; - for (multimap::iterator iter = ppp.first; iter != ppp.second; ++iter) { - ArmJitBlock &sourceBlock = blocks[iter->second]; - for (int e = 0; e < 2; e++) - { - if (sourceBlock.exitAddress[e] == b.originalAddress) - sourceBlock.linkStatus[e] = false; - } - } -} - -u32 ArmJitBlockCache::GetEmuHackOpForBlock(int blockNum) const { - return (MIPS_EMUHACK_OPCODE | blockNum); -} - -void ArmJitBlockCache::DestroyBlock(int block_num, bool invalidate) -{ - if (block_num < 0 || block_num >= num_blocks) - { - ERROR_LOG(JIT, "DestroyBlock: Invalid block number %d", block_num); - return; - } - ArmJitBlock &b = blocks[block_num]; - if (b.invalid) - { - if (invalidate) - ERROR_LOG(JIT, "Invalidating invalid block %d", block_num); - return; - } - b.invalid = true; - if ((int)Memory::ReadUnchecked_U32(b.originalAddress) == GetEmuHackOpForBlock(block_num)) - Memory::WriteUnchecked_U32(b.originalFirstOpcode, b.originalAddress); - - UnlinkBlock(block_num); - b.normalEntry = 0; - // TODO: remove - blockCodePointers[block_num] = 0; - - // 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(); -} - -void ArmJitBlockCache::InvalidateICache(u32 address, const u32 length) -{ - u32 pAddr = address & 0x3FFFFFFF; - - // destroy JIT blocks - // !! this works correctly under assumption that any two overlapping blocks end at the same address - std::map, u32>::iterator it1 = block_map.lower_bound(std::make_pair(pAddr, 0)), it2 = it1; - while (it2 != block_map.end() && it2->first.second < pAddr + length) - { - DestroyBlock(it2->second, true); - it2++; - } - if (it1 != it2) - { - block_map.erase(it1, it2); - } -} diff --git a/Core/MIPS/ARM/ArmJitCache.h b/Core/MIPS/ARM/ArmJitCache.h deleted file mode 100644 index 46725ec423..0000000000 --- a/Core/MIPS/ARM/ArmJitCache.h +++ /dev/null @@ -1,122 +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 - -#include -#include -#include - -#include "../MIPSAnalyst.h" -#include "../MIPS.h" -// Define this in order to get VTune profile support for the Jit generated code. -// Add the VTune include/lib directories to the project directories to get this to build. -// #define USE_VTUNE - -// emulate CPU with unlimited instruction cache -// the only way to invalidate a region is the "icbi" instruction - - -struct ArmJitBlock -{ - const u8 *checkedEntry; - const u8 *normalEntry; - - u8 *exitPtrs[2]; // to be able to rewrite the exit jum - u32 exitAddress[2]; // 0xFFFFFFFF == unknown - - u32 originalAddress; - u32 originalFirstOpcode; //to be able to restore - u32 codeSize; - u32 originalSize; - int runCount; // for profiling. - int blockNum; - int flags; - - bool invalid; - bool linkStatus[2]; - bool ContainsAddress(u32 em_address); - -#ifdef _WIN32 - // we don't really need to save start and stop - // TODO (mb2): ticStart and ticStop -> "local var" mean "in block" ... low priority ;) - u64 ticStart; // for profiling - time. - u64 ticStop; // for profiling - time. - u64 ticCounter; // for profiling - time. -#endif - -#ifdef USE_VTUNE - char blockName[32]; -#endif -}; - -typedef void (*CompiledCode)(); - -class ArmJitBlockCache -{ -public: - ArmJitBlockCache(MIPSState *mips_) : - mips(mips_), blockCodePointers(0), blocks(0), num_blocks(0), - MAX_NUM_BLOCKS(0) { } - ~ArmJitBlockCache(); - int AllocateBlock(u32 em_address); - void FinalizeBlock(int block_num, bool block_link); - - void Clear(); - void ClearSafe(); - void Init(); - void Shutdown(); - void Reset(); - - bool IsFull() const; - - // Code Cache - ArmJitBlock *GetBlock(int block_num); - int GetNumBlocks() const; - const u8 **GetCodePointers(); - - // Fast way to get a block. Only works on the first source-cpu instruction of a block. - int GetBlockNumberFromStartAddress(u32 em_address); - - // slower, but can get numbers from within blocks, not just the first instruction. - // WARNING! WILL NOT WORK WITH INLINING ENABLED (not yet a feature but will be soon) - // Returns a list of block numbers - only one block can start at a particular address, but they CAN overlap. - // This one is slow so should only be used for one-shots from the debugger UI, not for anything during runtime. - void GetBlockNumbersFromAddress(u32 em_address, std::vector *block_numbers); - - u32 GetOriginalFirstOp(int block_num); - - // DOES NOT WORK CORRECTLY WITH INLINING - void InvalidateICache(u32 address, const u32 length); - void DestroyBlock(int block_num, bool invalidate); - -private: - bool RangeIntersect(int s1, int e1, int s2, int e2) const; - void LinkBlockExits(int i); - void LinkBlock(int i); - void UnlinkBlock(int i); - u32 GetEmuHackOpForBlock(int blockNum) const; - - MIPSState *mips; - const u8 **blockCodePointers; - ArmJitBlock *blocks; - int num_blocks; - std::multimap links_to; - std::map, u32> block_map; // (end_addr, start_addr) -> number - - int MAX_NUM_BLOCKS; -}; diff --git a/Core/MIPS/x86/JitCache.cpp b/Core/MIPS/JitCommon/JitBlockCache.cpp similarity index 90% rename from Core/MIPS/x86/JitCache.cpp rename to Core/MIPS/JitCommon/JitBlockCache.cpp index 34580e5bf8..16454ffd57 100644 --- a/Core/MIPS/x86/JitCache.cpp +++ b/Core/MIPS/JitCommon/JitBlockCache.cpp @@ -36,12 +36,21 @@ #include "../MIPSTables.h" #include "../MIPSAnalyst.h" -#include "x64Emitter.h" -#include "x64Analyzer.h" -#include "JitCache.h" -#include "../JitCommon/JitCommon.h" -#include "Asm.h" + +#include "JitBlockCache.h" +#include "JitCommon.h" + +#if defined(ARM) +#include "Common/ArmEmitter.h" +#include "Core/MIPS/ARM/ArmAsm.h" +using namespace ArmGen; +#elif defined(_M_IX86) || defined(_M_X64) +#include "Common/x64Emitter.h" +#include "Common/x64Analyzer.h" +#include "Core/MIPS/x86/Asm.h" +using namespace Gen; +#endif // #include "JitBase.h" #if defined USE_OPROFILE && USE_OPROFILE @@ -56,7 +65,6 @@ op_agent_t agent; #pragma comment(lib, "jitprofiling.lib") #endif -using namespace Gen; #define INVALID_EXIT 0xFFFFFFFF @@ -273,8 +281,15 @@ void JitBlockCache::LinkBlockExits(int i) int destinationBlock = GetBlockNumberFromStartAddress(b.exitAddress[e]); if (destinationBlock != -1) { +#if defined(ARM) + ARMXEmitter emit(b.exitPtrs[e]); + emit.B(blocks[destinationBlock].checkedEntry); + emit.FlushIcache(); + +#elif defined(_M_IX86) || defined(_M_X64) XEmitter emit(b.exitPtrs[e]); emit.JMP(blocks[destinationBlock].checkedEntry, true); +#endif b.linkStatus[e] = true; } } @@ -340,12 +355,28 @@ void JitBlockCache::DestroyBlock(int block_num, bool invalidate) UnlinkBlock(block_num); + +#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->Asm().dispatcher, true); +#endif } void JitBlockCache::InvalidateICache(u32 address, const u32 length) diff --git a/Core/MIPS/x86/JitCache.h b/Core/MIPS/JitCommon/JitBlockCache.h similarity index 86% rename from Core/MIPS/x86/JitCache.h rename to Core/MIPS/JitCommon/JitBlockCache.h index c12baab03e..a9fa193518 100644 --- a/Core/MIPS/x86/JitCache.h +++ b/Core/MIPS/JitCommon/JitBlockCache.h @@ -21,27 +21,14 @@ #include #include -#include "../MIPSAnalyst.h" +#include "Common/CommonTypes.h" +#include "Core/MIPS/MIPSAnalyst.h" +#include "Core/MIPS/MIPS.h" // Define this in order to get VTune profile support for the Jit generated code. // Add the VTune include/lib directories to the project directories to get this to build. // #define USE_VTUNE -// emulate CPU with unlimited instruction cache -// the only way to invalidate a region is the "icbi" instruction - -#define JIT_ICACHE_SIZE 0x2000000 -#define JIT_ICACHE_MASK 0x1ffffff -#define JIT_ICACHEEX_SIZE 0x4000000 -#define JIT_ICACHEEX_MASK 0x3ffffff -#define JIT_ICACHE_EXRAM_BIT 0x10000000 -#define JIT_ICACHE_VMEM_BIT 0x20000000 -// this corresponds to opcode 5 which is invalid in PowerPC -#define JIT_ICACHE_INVALID_BYTE 0x14 -#define JIT_ICACHE_INVALID_WORD 0x14141414 - -#define JIT_OPCODE 0xFFCCCCCC // yeah this ain't gonna work - struct JitBlock { const u8 *checkedEntry; diff --git a/Core/MIPS/MIPS.cpp b/Core/MIPS/MIPS.cpp index 706b95f1e9..d21b408f7c 100644 --- a/Core/MIPS/MIPS.cpp +++ b/Core/MIPS/MIPS.cpp @@ -16,22 +16,21 @@ // https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/. #include "Common.h" -#include "MIPS.h" -#include "MIPSTables.h" -#include "MIPSDebugInterface.h" -#include "MIPSVFPUUtils.h" -#include "../System.h" -#include "../HLE/sceDisplay.h" +#include "Core/MIPS/MIPS.h" +#include "Core/MIPS/MIPSTables.h" +#include "Core/MIPS/MIPSDebugInterface.h" +#include "Core/MIPS/MIPSVFPUUtils.h" +#include "Core/MIPS/JitCommon/JitBlockCache.h" +#include "Core/System.h" +#include "Core/HLE/sceDisplay.h" #if defined(ARM) -#include "ARM/ArmJitCache.h" #include "ARM/ArmJit.h" #else -#include "x86/JitCache.h" #include "x86/Jit.h" #endif -#include "JitCommon/JitCommon.h" -#include "../../Core/CoreTiming.h" +#include "Core/MIPS/JitCommon/JitCommon.h" +#include "Core/CoreTiming.h" MIPSState mipsr4k; MIPSState *currentMIPS = &mipsr4k; diff --git a/Core/MIPS/x86/CompBranch.cpp b/Core/MIPS/x86/CompBranch.cpp index 6697bafd69..1cb207e573 100644 --- a/Core/MIPS/x86/CompBranch.cpp +++ b/Core/MIPS/x86/CompBranch.cpp @@ -25,7 +25,7 @@ #include "Jit.h" #include "RegCache.h" -#include "JitCache.h" +#include "Core/MIPS/JitCommon/JitBlockCache.h" #define _RS ((op>>21) & 0x1F) #define _RT ((op>>16) & 0x1F) diff --git a/Core/MIPS/x86/Jit.h b/Core/MIPS/x86/Jit.h index 2590ac20c3..9921ad50c9 100644 --- a/Core/MIPS/x86/Jit.h +++ b/Core/MIPS/x86/Jit.h @@ -26,7 +26,7 @@ #endif #include "Common/x64Emitter.h" -#include "JitCache.h" +#include "Core/MIPS/JitCommon/JitBlockCache.h" #include "RegCache.h" #include "RegCacheFPU.h" diff --git a/android/jni/Android.mk b/android/jni/Android.mk index 7cb21f7e51..ca31abd40c 100644 --- a/android/jni/Android.mk +++ b/android/jni/Android.mk @@ -55,7 +55,6 @@ ARCH_FILES := \ $(SRC)/Common/x64Emitter.cpp \ $(SRC)/Common/CPUDetect.cpp \ $(SRC)/Common/Thunk.cpp \ - $(SRC)/Core/MIPS/x86/JitCache.cpp \ $(SRC)/Core/MIPS/x86/CompALU.cpp \ $(SRC)/Core/MIPS/x86/CompBranch.cpp \ $(SRC)/Core/MIPS/x86/CompFPU.cpp \ @@ -75,7 +74,6 @@ ARCH_FILES := \ $(SRC)/Common/ArmEmitter.cpp \ $(SRC)/Common/ArmCPUDetect.cpp \ $(SRC)/Common/ArmThunk.cpp \ - $(SRC)/Core/MIPS/ARM/ArmJitCache.cpp \ $(SRC)/Core/MIPS/ARM/ArmCompALU.cpp \ $(SRC)/Core/MIPS/ARM/ArmCompBranch.cpp \ $(SRC)/Core/MIPS/ARM/ArmCompFPU.cpp \ @@ -97,7 +95,6 @@ ARCH_FILES := \ $(SRC)/Common/ArmEmitter.cpp \ $(SRC)/Common/ArmCPUDetect.cpp \ $(SRC)/Common/ArmThunk.cpp \ - $(SRC)/Core/MIPS/ARM/ArmJitCache.cpp \ $(SRC)/Core/MIPS/ARM/ArmCompALU.cpp \ $(SRC)/Core/MIPS/ARM/ArmCompBranch.cpp \ $(SRC)/Core/MIPS/ARM/ArmCompFPU.cpp \ @@ -246,6 +243,7 @@ LOCAL_SRC_FILES := \ $(SRC)/Core/MIPS/MIPSCodeUtils.cpp.arm \ $(SRC)/Core/MIPS/MIPSDebugInterface.cpp \ $(SRC)/Core/MIPS/JitCommon/JitCommon.cpp \ + $(SRC)/Core/MIPS/JitCommon/JitBlockCache.cpp \ $(SRC)/Core/Util/BlockAllocator.cpp \ $(SRC)/Core/Util/ppge_atlas.cpp \ $(SRC)/Core/Util/PPGeDraw.cpp \