mirror of
https://github.com/libretro/ppsspp.git
synced 2024-11-23 16:19:44 +00:00
Combine the two JitCache implementations (x86, ARM) into one.
This commit is contained in:
parent
8a904fe478
commit
9eace8a80e
@ -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
|
||||
|
@ -266,18 +266,13 @@
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClCompile Include="MIPS\ARM\ArmJitCache.cpp">
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClCompile Include="MIPS\ARM\ArmRegCache.cpp">
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClCompile Include="MIPS\JitCommon\JitBlockCache.cpp" />
|
||||
<ClCompile Include="MIPS\JitCommon\JitCommon.cpp" />
|
||||
<ClCompile Include="Mips\MIPS.cpp" />
|
||||
<ClCompile Include="Mips\MIPSAnalyst.cpp" />
|
||||
@ -297,7 +292,6 @@
|
||||
<ClCompile Include="MIPS\x86\CompVFPU.cpp" />
|
||||
<ClCompile Include="MIPS\x86\RegCacheFPU.cpp" />
|
||||
<ClCompile Include="MIPS\x86\Jit.cpp" />
|
||||
<ClCompile Include="MIPS\x86\JitCache.cpp" />
|
||||
<ClCompile Include="MIPS\x86\RegCache.cpp" />
|
||||
<ClCompile Include="PSPLoaders.cpp" />
|
||||
<ClCompile Include="PSPMixer.cpp" />
|
||||
@ -405,12 +399,6 @@
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
|
||||
</ClInclude>
|
||||
<ClInclude Include="MIPS\ARM\ArmJitCache.h">
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
|
||||
</ClInclude>
|
||||
<ClInclude Include="MIPS\ARM\ArmRegCache.h">
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
|
||||
@ -423,6 +411,7 @@
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
|
||||
</ClInclude>
|
||||
<ClInclude Include="MIPS\JitCommon\JitBlockCache.h" />
|
||||
<ClInclude Include="MIPS\JitCommon\JitCommon.h" />
|
||||
<ClInclude Include="Mips\MIPS.h" />
|
||||
<ClInclude Include="Mips\MIPSAnalyst.h" />
|
||||
@ -437,7 +426,6 @@
|
||||
<ClInclude Include="MIPS\x86\Asm.h" />
|
||||
<ClInclude Include="MIPS\x86\RegCacheFPU.h" />
|
||||
<ClInclude Include="MIPS\x86\Jit.h" />
|
||||
<ClInclude Include="MIPS\x86\JitCache.h" />
|
||||
<ClInclude Include="MIPS\x86\RegCache.h" />
|
||||
<ClInclude Include="PSPLoaders.h" />
|
||||
<ClInclude Include="PSPMixer.h" />
|
||||
@ -471,4 +459,4 @@
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
</ImportGroup>
|
||||
</Project>
|
||||
</Project>
|
@ -105,9 +105,6 @@
|
||||
<ClCompile Include="MIPS\x86\Asm.cpp">
|
||||
<Filter>MIPS\x86</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="MIPS\x86\JitCache.cpp">
|
||||
<Filter>MIPS\x86</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="MIPS\x86\RegCache.cpp">
|
||||
<Filter>MIPS\x86</Filter>
|
||||
</ClCompile>
|
||||
@ -366,9 +363,6 @@
|
||||
<ClCompile Include="MIPS\ARM\ArmJit.cpp">
|
||||
<Filter>MIPS\ARM</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="MIPS\ARM\ArmJitCache.cpp">
|
||||
<Filter>MIPS\ARM</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="MIPS\ARM\ArmRegCache.cpp">
|
||||
<Filter>MIPS\ARM</Filter>
|
||||
</ClCompile>
|
||||
@ -403,6 +397,7 @@
|
||||
<ClCompile Include="ELF\PBPReader.cpp">
|
||||
<Filter>ELF</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="MIPS\JitCommon\JitBlockCache.cpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="ELF\ElfReader.h">
|
||||
@ -447,9 +442,6 @@
|
||||
<ClInclude Include="MIPS\x86\Asm.h">
|
||||
<Filter>MIPS\x86</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="MIPS\x86\JitCache.h">
|
||||
<Filter>MIPS\x86</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="MIPS\x86\RegCache.h">
|
||||
<Filter>MIPS\x86</Filter>
|
||||
</ClInclude>
|
||||
@ -711,9 +703,6 @@
|
||||
<ClInclude Include="MIPS\ARM\ArmJit.h">
|
||||
<Filter>MIPS\ARM</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="MIPS\ARM\ArmJitCache.h">
|
||||
<Filter>MIPS\ARM</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="MIPS\ARM\ArmRegCache.h">
|
||||
<Filter>MIPS\ARM</Filter>
|
||||
</ClInclude>
|
||||
@ -744,6 +733,7 @@
|
||||
<ClInclude Include="ELF\PBPReader.h">
|
||||
<Filter>ELF</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="MIPS\JitCommon\JitBlockCache.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="CMakeLists.txt" />
|
||||
|
@ -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 <ArmEmitter.h>
|
||||
#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)
|
||||
|
@ -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();
|
||||
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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 <windows.h>
|
||||
#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 <opagent.h>
|
||||
|
||||
op_agent_t agent;
|
||||
#endif
|
||||
|
||||
#if defined USE_VTUNE
|
||||
#include <jitprofiling.h>
|
||||
#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<u32, int>(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<int> *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<multimap<u32, int>::iterator, multimap<u32, int>::iterator> ppp;
|
||||
// equal_range(b) returns pair<iterator,iterator> representing the range
|
||||
// of element with key b
|
||||
ppp = links_to.equal_range(b.originalAddress);
|
||||
if (ppp.first == ppp.second)
|
||||
return;
|
||||
for (multimap<u32, int>::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<multimap<u32, int>::iterator, multimap<u32, int>::iterator> ppp;
|
||||
ppp = links_to.equal_range(b.originalAddress);
|
||||
if (ppp.first == ppp.second)
|
||||
return;
|
||||
for (multimap<u32, int>::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<pair<u32,u32>, 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);
|
||||
}
|
||||
}
|
@ -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 <map>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
|
||||
#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<int> *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<u32, int> links_to;
|
||||
std::map<std::pair<u32,u32>, u32> block_map; // (end_addr, start_addr) -> number
|
||||
|
||||
int MAX_NUM_BLOCKS;
|
||||
};
|
@ -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)
|
@ -21,27 +21,14 @@
|
||||
#include <vector>
|
||||
#include <string>
|
||||
|
||||
#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;
|
@ -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;
|
||||
|
@ -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)
|
||||
|
@ -26,7 +26,7 @@
|
||||
#endif
|
||||
|
||||
#include "Common/x64Emitter.h"
|
||||
#include "JitCache.h"
|
||||
#include "Core/MIPS/JitCommon/JitBlockCache.h"
|
||||
#include "RegCache.h"
|
||||
#include "RegCacheFPU.h"
|
||||
|
||||
|
@ -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 \
|
||||
|
Loading…
Reference in New Issue
Block a user