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