Introduce JitCommon folder to share things between the two jits.
git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@2396 8ced0084-cf51-0410-be5f-012b33b47a6e
This commit is contained in:
parent
7d84ac6a5a
commit
96827d9996
|
@ -492,7 +492,7 @@
|
|||
OmitFramePointers="true"
|
||||
EnableFiberSafeOptimizations="false"
|
||||
AdditionalIncludeDirectories=".\Core\Core\Src\Debugger;..\Common\Src;..\DiscIO\Src;..\..\Core\InputCommon\Src;..\..\PluginSpecs;..\..\..\Externals\LZO;..\..\..\Externals\Bochs_disasm;..\..\..\Externals\zlib"
|
||||
PreprocessorDefinitions="WIN32;NDEBUG;_LIB;_CRT_SECURE_NO_DEPRECATE;_SECURE_SCL=0;JITTEST"
|
||||
PreprocessorDefinitions="WIN32;NDEBUG;_LIB;_CRT_SECURE_NO_DEPRECATE;_SECURE_SCL=0;JITTEST=1"
|
||||
StringPooling="true"
|
||||
RuntimeLibrary="0"
|
||||
BufferSecurityCheck="false"
|
||||
|
@ -1258,26 +1258,6 @@
|
|||
/>
|
||||
</FileConfiguration>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Src\PowerPC\Jit64\Jit_Util.cpp"
|
||||
>
|
||||
<FileConfiguration
|
||||
Name="Release_JITIL|Win32"
|
||||
ExcludedFromBuild="true"
|
||||
>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
/>
|
||||
</FileConfiguration>
|
||||
<FileConfiguration
|
||||
Name="Release_JITIL|x64"
|
||||
ExcludedFromBuild="true"
|
||||
>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
/>
|
||||
</FileConfiguration>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Src\PowerPC\Jit64\JitAsm.cpp"
|
||||
>
|
||||
|
@ -1302,50 +1282,6 @@
|
|||
RelativePath=".\Src\PowerPC\Jit64\JitAsm.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Src\PowerPC\Jit64\JitBackpatch.cpp"
|
||||
>
|
||||
<FileConfiguration
|
||||
Name="Release_JITIL|Win32"
|
||||
ExcludedFromBuild="true"
|
||||
>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
/>
|
||||
</FileConfiguration>
|
||||
<FileConfiguration
|
||||
Name="Release_JITIL|x64"
|
||||
ExcludedFromBuild="true"
|
||||
>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
/>
|
||||
</FileConfiguration>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Src\PowerPC\Jit64\JitCache.cpp"
|
||||
>
|
||||
<FileConfiguration
|
||||
Name="Release_JITIL|Win32"
|
||||
ExcludedFromBuild="true"
|
||||
>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
/>
|
||||
</FileConfiguration>
|
||||
<FileConfiguration
|
||||
Name="Release_JITIL|x64"
|
||||
ExcludedFromBuild="true"
|
||||
>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
/>
|
||||
</FileConfiguration>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Src\PowerPC\Jit64\JitCache.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Src\PowerPC\Jit64\JitRegCache.cpp"
|
||||
>
|
||||
|
@ -1902,58 +1838,6 @@
|
|||
/>
|
||||
</FileConfiguration>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Src\PowerPC\Jit64IL\Jit_Util.cpp"
|
||||
>
|
||||
<FileConfiguration
|
||||
Name="Debug|Win32"
|
||||
ExcludedFromBuild="true"
|
||||
>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
/>
|
||||
</FileConfiguration>
|
||||
<FileConfiguration
|
||||
Name="Debug|x64"
|
||||
ExcludedFromBuild="true"
|
||||
>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
/>
|
||||
</FileConfiguration>
|
||||
<FileConfiguration
|
||||
Name="Release|Win32"
|
||||
ExcludedFromBuild="true"
|
||||
>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
/>
|
||||
</FileConfiguration>
|
||||
<FileConfiguration
|
||||
Name="Release|x64"
|
||||
ExcludedFromBuild="true"
|
||||
>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
/>
|
||||
</FileConfiguration>
|
||||
<FileConfiguration
|
||||
Name="DebugFast|Win32"
|
||||
ExcludedFromBuild="true"
|
||||
>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
/>
|
||||
</FileConfiguration>
|
||||
<FileConfiguration
|
||||
Name="DebugFast|x64"
|
||||
ExcludedFromBuild="true"
|
||||
>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
/>
|
||||
</FileConfiguration>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Src\PowerPC\Jit64IL\JitAsm.cpp"
|
||||
>
|
||||
|
@ -2010,114 +1894,6 @@
|
|||
RelativePath=".\Src\PowerPC\Jit64IL\JitAsm.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Src\PowerPC\Jit64IL\JitBackpatch.cpp"
|
||||
>
|
||||
<FileConfiguration
|
||||
Name="Debug|Win32"
|
||||
ExcludedFromBuild="true"
|
||||
>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
/>
|
||||
</FileConfiguration>
|
||||
<FileConfiguration
|
||||
Name="Debug|x64"
|
||||
ExcludedFromBuild="true"
|
||||
>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
/>
|
||||
</FileConfiguration>
|
||||
<FileConfiguration
|
||||
Name="Release|Win32"
|
||||
ExcludedFromBuild="true"
|
||||
>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
/>
|
||||
</FileConfiguration>
|
||||
<FileConfiguration
|
||||
Name="Release|x64"
|
||||
ExcludedFromBuild="true"
|
||||
>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
/>
|
||||
</FileConfiguration>
|
||||
<FileConfiguration
|
||||
Name="DebugFast|Win32"
|
||||
ExcludedFromBuild="true"
|
||||
>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
/>
|
||||
</FileConfiguration>
|
||||
<FileConfiguration
|
||||
Name="DebugFast|x64"
|
||||
ExcludedFromBuild="true"
|
||||
>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
/>
|
||||
</FileConfiguration>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Src\PowerPC\Jit64IL\JitCache.cpp"
|
||||
>
|
||||
<FileConfiguration
|
||||
Name="Debug|Win32"
|
||||
ExcludedFromBuild="true"
|
||||
>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
/>
|
||||
</FileConfiguration>
|
||||
<FileConfiguration
|
||||
Name="Debug|x64"
|
||||
ExcludedFromBuild="true"
|
||||
>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
/>
|
||||
</FileConfiguration>
|
||||
<FileConfiguration
|
||||
Name="Release|Win32"
|
||||
ExcludedFromBuild="true"
|
||||
>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
/>
|
||||
</FileConfiguration>
|
||||
<FileConfiguration
|
||||
Name="Release|x64"
|
||||
ExcludedFromBuild="true"
|
||||
>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
/>
|
||||
</FileConfiguration>
|
||||
<FileConfiguration
|
||||
Name="DebugFast|Win32"
|
||||
ExcludedFromBuild="true"
|
||||
>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
/>
|
||||
</FileConfiguration>
|
||||
<FileConfiguration
|
||||
Name="DebugFast|x64"
|
||||
ExcludedFromBuild="true"
|
||||
>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
/>
|
||||
</FileConfiguration>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Src\PowerPC\Jit64IL\JitCache.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Src\PowerPC\Jit64IL\JitRegCache.cpp"
|
||||
>
|
||||
|
@ -2175,6 +1951,26 @@
|
|||
>
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="JitCommon"
|
||||
>
|
||||
<File
|
||||
RelativePath=".\Src\PowerPC\JitCommon\Jit_Util.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Src\PowerPC\JitCommon\JitBackpatch.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Src\PowerPC\JitCommon\JitCache.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Src\PowerPC\JitCommon\JitCache.h"
|
||||
>
|
||||
</File>
|
||||
</Filter>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="Debugger"
|
||||
|
|
|
@ -30,7 +30,6 @@ may be redirected here (for example to Read_U32()).
|
|||
#include "../Core.h"
|
||||
#include "../PowerPC/PowerPC.h"
|
||||
#include "../PowerPC/Jit64/Jit.h"
|
||||
#include "../PowerPC/Jit64/JitCache.h"
|
||||
#include "../HLE/HLE.h"
|
||||
#include "CPU.h"
|
||||
#include "PeripheralInterface.h"
|
||||
|
|
|
@ -23,7 +23,7 @@
|
|||
#include "../../Core.h"
|
||||
|
||||
#include "../Jit64/Jit.h"
|
||||
#include "../Jit64/JitCache.h"
|
||||
#include "../JitCommon/JitCache.h"
|
||||
|
||||
namespace Interpreter
|
||||
{
|
||||
|
|
|
@ -34,7 +34,6 @@
|
|||
#include "../../HW/GPFifo.h"
|
||||
#include "Jit.h"
|
||||
#include "JitAsm.h"
|
||||
#include "JitCache.h"
|
||||
#include "JitRegCache.h"
|
||||
|
||||
#if defined JITTEST && JITTEST
|
||||
|
|
|
@ -46,7 +46,7 @@
|
|||
#define _JIT_H
|
||||
|
||||
#include "../PPCAnalyst.h"
|
||||
#include "JitCache.h"
|
||||
#include "../JitCommon/JitCache.h"
|
||||
#include "JitRegCache.h"
|
||||
#include "x64Emitter.h"
|
||||
#include "x64Analyzer.h"
|
||||
|
|
|
@ -26,7 +26,7 @@
|
|||
|
||||
#include "ABI.h"
|
||||
#include "Jit.h"
|
||||
#include "JitCache.h"
|
||||
#include "../JitCommon/JitCache.h"
|
||||
|
||||
#include "../../HW/GPFifo.h"
|
||||
#include "../../Core.h"
|
||||
|
@ -78,10 +78,8 @@ void AsmRoutineManager::Generate()
|
|||
FixupBranch skipToRealDispatch = J(); //skip the sync and compare first time
|
||||
|
||||
dispatcher = GetCodePtr();
|
||||
//This is the place for CPUCompare!
|
||||
|
||||
//The result of slice decrementation should be in flags if somebody jumped here
|
||||
//Jump on negative, not carry!!!
|
||||
// The result of slice decrementation should be in flags if somebody jumped here
|
||||
// IMPORTANT - We jump on negative, not carry!!!
|
||||
FixupBranch bail = J_CC(CC_BE);
|
||||
SetJumpTarget(skipToRealDispatch);
|
||||
|
||||
|
|
|
@ -19,7 +19,6 @@
|
|||
#include "../PPCTables.h"
|
||||
#include "../PPCAnalyst.h"
|
||||
#include "Jit.h"
|
||||
#include "JitCache.h"
|
||||
#include "JitAsm.h"
|
||||
#include "JitRegCache.h"
|
||||
|
||||
|
|
|
@ -25,7 +25,6 @@
|
|||
|
||||
#include "Jit.h"
|
||||
#include "JitRegCache.h"
|
||||
#include "JitCache.h"
|
||||
#include "JitAsm.h"
|
||||
|
||||
// The branches are known good, or at least reasonably good.
|
||||
|
|
|
@ -23,7 +23,6 @@
|
|||
#include "x64Emitter.h"
|
||||
|
||||
#include "Jit.h"
|
||||
#include "JitCache.h"
|
||||
#include "JitRegCache.h"
|
||||
|
||||
const u64 GC_ALIGNED16(psSignBits2[2]) = {0x8000000000000000ULL, 0x8000000000000000ULL};
|
||||
|
|
|
@ -21,7 +21,6 @@
|
|||
#include "x64Emitter.h"
|
||||
|
||||
#include "Jit.h"
|
||||
#include "JitCache.h"
|
||||
#include "JitRegCache.h"
|
||||
#include "JitAsm.h"
|
||||
|
||||
|
|
|
@ -32,7 +32,6 @@
|
|||
#include "ABI.h"
|
||||
|
||||
#include "Jit.h"
|
||||
#include "JitCache.h"
|
||||
#include "JitAsm.h"
|
||||
#include "JitRegCache.h"
|
||||
|
||||
|
|
|
@ -32,7 +32,6 @@
|
|||
#include "ABI.h"
|
||||
|
||||
#include "Jit.h"
|
||||
#include "JitCache.h"
|
||||
#include "JitAsm.h"
|
||||
#include "JitRegCache.h"
|
||||
|
||||
|
@ -160,6 +159,10 @@ void Jit64::stfd(UGeckoInstruction inst)
|
|||
{
|
||||
if (Core::g_CoreStartupParameter.bJITOff || Core::g_CoreStartupParameter.bJITLoadStoreFloatingOff)
|
||||
{Default(inst); return;} // turn off from debugger
|
||||
|
||||
Default(inst);
|
||||
return;
|
||||
|
||||
INSTRUCTION_START;
|
||||
|
||||
int s = inst.RS;
|
||||
|
|
|
@ -33,7 +33,6 @@
|
|||
#include "ABI.h"
|
||||
|
||||
#include "Jit.h"
|
||||
#include "JitCache.h"
|
||||
#include "JitAsm.h"
|
||||
#include "JitRegCache.h"
|
||||
|
||||
|
|
|
@ -24,7 +24,6 @@
|
|||
#include "../../HW/GPFifo.h"
|
||||
|
||||
#include "Jit.h"
|
||||
#include "JitCache.h"
|
||||
#include "JitRegCache.h"
|
||||
|
||||
// TODO
|
||||
|
|
|
@ -27,7 +27,6 @@
|
|||
#include "Thunk.h"
|
||||
|
||||
#include "Jit.h"
|
||||
#include "JitCache.h"
|
||||
#include "JitRegCache.h"
|
||||
|
||||
void Jit64::mtspr(UGeckoInstruction inst)
|
||||
|
|
|
@ -1,161 +0,0 @@
|
|||
// Copyright (C) 2003-2008 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 "Common.h"
|
||||
#include "Thunk.h"
|
||||
|
||||
#include "../PowerPC.h"
|
||||
#include "../../Core.h"
|
||||
#include "../../HW/GPFifo.h"
|
||||
#include "../../HW/CommandProcessor.h"
|
||||
#include "../../HW/PixelEngine.h"
|
||||
#include "../../HW/Memmap.h"
|
||||
#include "../PPCTables.h"
|
||||
#include "x64Emitter.h"
|
||||
#include "ABI.h"
|
||||
|
||||
#include "Jit.h"
|
||||
#include "JitCache.h"
|
||||
#include "JitAsm.h"
|
||||
#include "JitRegCache.h"
|
||||
|
||||
void Jit64::JitClearCA()
|
||||
{
|
||||
AND(32, M(&PowerPC::ppcState.spr[SPR_XER]), Imm32(~XER_CA_MASK)); //XER.CA = 0
|
||||
}
|
||||
|
||||
void Jit64::JitSetCA()
|
||||
{
|
||||
OR(32, M(&PowerPC::ppcState.spr[SPR_XER]), Imm32(XER_CA_MASK)); //XER.CA = 1
|
||||
}
|
||||
|
||||
void Jit64::UnsafeLoadRegToReg(X64Reg reg_addr, X64Reg reg_value, int accessSize, s32 offset, bool signExtend)
|
||||
{
|
||||
#ifdef _M_IX86
|
||||
AND(32, R(reg_addr), Imm32(Memory::MEMVIEW32_MASK));
|
||||
MOVZX(32, accessSize, reg_value, MDisp(reg_addr, (u32)Memory::base + offset));
|
||||
#else
|
||||
MOVZX(32, accessSize, reg_value, MComplex(RBX, reg_addr, SCALE_1, offset));
|
||||
#endif
|
||||
if (accessSize == 32)
|
||||
{
|
||||
BSWAP(32, reg_value);
|
||||
}
|
||||
else if (accessSize == 16)
|
||||
{
|
||||
BSWAP(32, reg_value);
|
||||
if (signExtend)
|
||||
SAR(32, R(reg_value), Imm8(16));
|
||||
else
|
||||
SHR(32, R(reg_value), Imm8(16));
|
||||
} else if (signExtend) {
|
||||
// TODO: bake 8-bit into the original load.
|
||||
MOVSX(32, accessSize, reg_value, R(reg_value));
|
||||
}
|
||||
}
|
||||
|
||||
void Jit64::SafeLoadRegToEAX(X64Reg reg, int accessSize, s32 offset, bool signExtend)
|
||||
{
|
||||
if (offset)
|
||||
ADD(32, R(reg), Imm32((u32)offset));
|
||||
TEST(32, R(reg), Imm32(0x0C000000));
|
||||
FixupBranch argh = J_CC(CC_Z);
|
||||
switch (accessSize)
|
||||
{
|
||||
case 32: ABI_CallFunctionR(thunks.ProtectFunction((void *)&Memory::Read_U32, 1), reg); break;
|
||||
case 16: ABI_CallFunctionR(thunks.ProtectFunction((void *)&Memory::Read_U16, 1), reg); break;
|
||||
case 8: ABI_CallFunctionR(thunks.ProtectFunction((void *)&Memory::Read_U8, 1), reg); break;
|
||||
}
|
||||
if (signExtend && accessSize < 32) {
|
||||
// Need to sign extend values coming from the Read_U* functions.
|
||||
MOVSX(32, accessSize, EAX, R(EAX));
|
||||
}
|
||||
FixupBranch arg2 = J();
|
||||
SetJumpTarget(argh);
|
||||
UnsafeLoadRegToReg(reg, EAX, accessSize, 0, signExtend);
|
||||
SetJumpTarget(arg2);
|
||||
}
|
||||
|
||||
void Jit64::UnsafeWriteRegToReg(X64Reg reg_value, X64Reg reg_addr, int accessSize, s32 offset)
|
||||
{
|
||||
if (accessSize == 8 && reg_value >= 4) {
|
||||
PanicAlert("WARNING: likely incorrect use of UnsafeWriteRegToReg!");
|
||||
}
|
||||
BSWAP(accessSize, reg_value);
|
||||
#ifdef _M_IX86
|
||||
AND(32, R(reg_addr), Imm32(Memory::MEMVIEW32_MASK));
|
||||
MOV(accessSize, MDisp(reg_addr, (u32)Memory::base + offset), R(reg_value));
|
||||
#else
|
||||
MOV(accessSize, MComplex(RBX, reg_addr, SCALE_1, offset), R(reg_value));
|
||||
#endif
|
||||
}
|
||||
|
||||
// Destroys both arg registers
|
||||
void Jit64::SafeWriteRegToReg(X64Reg reg_value, X64Reg reg_addr, int accessSize, s32 offset)
|
||||
{
|
||||
if (offset)
|
||||
ADD(32, R(reg_addr), Imm32(offset));
|
||||
TEST(32, R(reg_addr), Imm32(0x0C000000));
|
||||
FixupBranch argh = J_CC(CC_Z);
|
||||
switch (accessSize)
|
||||
{
|
||||
case 32: ABI_CallFunctionRR(thunks.ProtectFunction((void *)&Memory::Write_U32, 2), reg_value, reg_addr); break;
|
||||
case 16: ABI_CallFunctionRR(thunks.ProtectFunction((void *)&Memory::Write_U16, 2), reg_value, reg_addr); break;
|
||||
case 8: ABI_CallFunctionRR(thunks.ProtectFunction((void *)&Memory::Write_U8, 2), reg_value, reg_addr); break;
|
||||
}
|
||||
FixupBranch arg2 = J();
|
||||
SetJumpTarget(argh);
|
||||
UnsafeWriteRegToReg(reg_value, reg_addr, accessSize, 0);
|
||||
SetJumpTarget(arg2);
|
||||
}
|
||||
|
||||
void Jit64::WriteToConstRamAddress(int accessSize, const Gen::OpArg& arg, u32 address)
|
||||
{
|
||||
#ifdef _M_X64
|
||||
MOV(accessSize, MDisp(RBX, address & 0x3FFFFFFF), arg);
|
||||
#else
|
||||
MOV(accessSize, M((void*)(Memory::base + (address & Memory::MEMVIEW32_MASK))), arg);
|
||||
#endif
|
||||
}
|
||||
|
||||
void Jit64::WriteFloatToConstRamAddress(const Gen::X64Reg& xmm_reg, u32 address)
|
||||
{
|
||||
#ifdef _M_X64
|
||||
MOV(32, R(RAX), Imm32(address));
|
||||
MOVSS(MComplex(RBX, RAX, 1, 0), xmm_reg);
|
||||
#else
|
||||
MOVSS(M((void*)((u32)Memory::base + (address & Memory::MEMVIEW32_MASK))), xmm_reg);
|
||||
#endif
|
||||
}
|
||||
|
||||
void Jit64::ForceSinglePrecisionS(X64Reg xmm) {
|
||||
// Most games don't need these. Zelda requires it though - some platforms get stuck without them.
|
||||
if (jo.accurateSinglePrecision)
|
||||
{
|
||||
CVTSD2SS(xmm, R(xmm));
|
||||
CVTSS2SD(xmm, R(xmm));
|
||||
}
|
||||
}
|
||||
|
||||
void Jit64::ForceSinglePrecisionP(X64Reg xmm) {
|
||||
// Most games don't need these. Zelda requires it though - some platforms get stuck without them.
|
||||
if (jo.accurateSinglePrecision)
|
||||
{
|
||||
CVTPD2PS(xmm, R(xmm));
|
||||
CVTPS2PD(xmm, R(xmm));
|
||||
}
|
||||
}
|
|
@ -34,7 +34,7 @@
|
|||
#include "../../HW/GPFifo.h"
|
||||
#include "Jit.h"
|
||||
#include "JitAsm.h"
|
||||
#include "JitCache.h"
|
||||
#include "../JitCommon/JitCache.h"
|
||||
#include "JitRegCache.h"
|
||||
|
||||
#if !defined JITTEST || ! JITTEST
|
||||
|
|
|
@ -31,8 +31,12 @@
|
|||
#define _JIT_H
|
||||
|
||||
#include "../PPCAnalyst.h"
|
||||
#include "JitCache.h"
|
||||
#include "JitRegCache.h"
|
||||
#include "../JitCommon/JitCache.h"
|
||||
#if JITTEST
|
||||
#include "../Jit64IL/JitRegCache.h"
|
||||
#else
|
||||
#include "../Jit64/JitRegCache.h"
|
||||
#endif
|
||||
#include "x64Emitter.h"
|
||||
#include "x64Analyzer.h"
|
||||
#include "IR.h"
|
||||
|
|
|
@ -27,7 +27,6 @@
|
|||
|
||||
#include "ABI.h"
|
||||
#include "Jit.h"
|
||||
#include "JitCache.h"
|
||||
#include "Thunk.h"
|
||||
|
||||
#include "../../HW/GPFifo.h"
|
||||
|
|
|
@ -1,215 +0,0 @@
|
|||
// Copyright (C) 2003-2008 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 <string>
|
||||
|
||||
#include "Common.h"
|
||||
#include "disasm.h"
|
||||
#include "JitAsm.h"
|
||||
#include "../../HW/Memmap.h"
|
||||
|
||||
#include "x64Emitter.h"
|
||||
#include "ABI.h"
|
||||
#include "Thunk.h"
|
||||
#include "x64Analyzer.h"
|
||||
|
||||
#include "StringUtil.h"
|
||||
#include "Jit.h"
|
||||
|
||||
using namespace Gen;
|
||||
|
||||
extern u8 *trampolineCodePtr;
|
||||
|
||||
void BackPatchError(const std::string &text, u8 *codePtr, u32 emAddress) {
|
||||
u64 code_addr = (u64)codePtr;
|
||||
disassembler disasm;
|
||||
char disbuf[256];
|
||||
memset(disbuf, 0, 256);
|
||||
#ifdef _M_IX86
|
||||
disasm.disasm32(0, code_addr, codePtr, disbuf);
|
||||
#else
|
||||
disasm.disasm64(0, code_addr, codePtr, disbuf);
|
||||
#endif
|
||||
PanicAlert("%s\n\n"
|
||||
"Error encountered accessing emulated address %08x.\n"
|
||||
"Culprit instruction: \n%s\nat %08x%08x",
|
||||
text.c_str(), emAddress, disbuf, code_addr>>32, code_addr);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void TrampolineCache::Init()
|
||||
{
|
||||
AllocCodeSpace(1024 * 1024);
|
||||
}
|
||||
|
||||
void TrampolineCache::Shutdown()
|
||||
{
|
||||
AllocCodeSpace(1024 * 1024);
|
||||
}
|
||||
|
||||
// Extremely simplistic - just generate the requested trampoline. May reuse them in the future.
|
||||
const u8 *TrampolineCache::GetReadTrampoline(const InstructionInfo &info)
|
||||
{
|
||||
if (GetSpaceLeft() < 1024)
|
||||
PanicAlert("Trampoline cache full");
|
||||
|
||||
X64Reg addrReg = (X64Reg)info.scaledReg;
|
||||
X64Reg dataReg = (X64Reg)info.regOperandReg;
|
||||
const u8 *trampoline = GetCodePtr();
|
||||
#ifdef _M_X64
|
||||
// It's a read. Easy.
|
||||
ABI_PushAllCallerSavedRegsAndAdjustStack();
|
||||
if (addrReg != ABI_PARAM1)
|
||||
MOV(32, R(ABI_PARAM1), R((X64Reg)addrReg));
|
||||
if (info.displacement) {
|
||||
ADD(32, R(ABI_PARAM1), Imm32(info.displacement));
|
||||
}
|
||||
switch (info.operandSize) {
|
||||
case 4:
|
||||
CALL(thunks.ProtectFunction((void *)&Memory::Read_U32, 1));
|
||||
break;
|
||||
}
|
||||
ABI_PopAllCallerSavedRegsAndAdjustStack();
|
||||
MOV(32, R(dataReg), R(EAX));
|
||||
RET();
|
||||
#endif
|
||||
return trampoline;
|
||||
}
|
||||
|
||||
// Extremely simplistic - just generate the requested trampoline. May reuse them in the future.
|
||||
const u8 *TrampolineCache::GetWriteTrampoline(const InstructionInfo &info)
|
||||
{
|
||||
if (GetSpaceLeft() < 1024)
|
||||
PanicAlert("Trampoline cache full");
|
||||
|
||||
X64Reg addrReg = (X64Reg)info.scaledReg;
|
||||
X64Reg dataReg = (X64Reg)info.regOperandReg;
|
||||
if (dataReg != EAX)
|
||||
PanicAlert("Backpatch write - not through EAX");
|
||||
|
||||
const u8 *trampoline = GetCodePtr();
|
||||
|
||||
#ifdef _M_X64
|
||||
|
||||
// It's a write. Yay. Remember that we don't have to be super efficient since it's "just" a
|
||||
// hardware access - we can take shortcuts.
|
||||
//if (emAddress == 0xCC008000)
|
||||
// PanicAlert("caught a fifo write");
|
||||
CMP(32, R(addrReg), Imm32(0xCC008000));
|
||||
FixupBranch skip_fast = J_CC(CC_NE, false);
|
||||
MOV(32, R(ABI_PARAM1), R((X64Reg)dataReg));
|
||||
CALL((void*)asm_routines.fifoDirectWrite32);
|
||||
RET();
|
||||
SetJumpTarget(skip_fast);
|
||||
ABI_PushAllCallerSavedRegsAndAdjustStack();
|
||||
if (addrReg != ABI_PARAM1) {
|
||||
MOV(32, R(ABI_PARAM1), R((X64Reg)dataReg));
|
||||
MOV(32, R(ABI_PARAM2), R((X64Reg)addrReg));
|
||||
} else {
|
||||
MOV(32, R(ABI_PARAM2), R((X64Reg)addrReg));
|
||||
MOV(32, R(ABI_PARAM1), R((X64Reg)dataReg));
|
||||
}
|
||||
if (info.displacement) {
|
||||
ADD(32, R(ABI_PARAM2), Imm32(info.displacement));
|
||||
}
|
||||
switch (info.operandSize) {
|
||||
case 4:
|
||||
CALL(thunks.ProtectFunction((void *)&Memory::Write_U32, 2));
|
||||
break;
|
||||
}
|
||||
ABI_PopAllCallerSavedRegsAndAdjustStack();
|
||||
RET();
|
||||
#endif
|
||||
|
||||
return trampoline;
|
||||
}
|
||||
|
||||
|
||||
// This generates some fairly heavy trampolines, but:
|
||||
// 1) It's really necessary. We don't know anything about the context.
|
||||
// 2) It doesn't really hurt. Only instructions that access I/O will get these, and there won't be
|
||||
// that many of them in a typical program/game.
|
||||
const u8 *Jit64::BackPatch(u8 *codePtr, int accessType, u32 emAddress, CONTEXT *ctx)
|
||||
{
|
||||
#ifdef _M_X64
|
||||
if (!jit.IsInCodeSpace(codePtr))
|
||||
return 0; // this will become a regular crash real soon after this
|
||||
|
||||
InstructionInfo info;
|
||||
if (!DisassembleMov(codePtr, info, accessType)) {
|
||||
BackPatchError("BackPatch - failed to disassemble MOV instruction", codePtr, emAddress);
|
||||
}
|
||||
|
||||
/*
|
||||
if (info.isMemoryWrite) {
|
||||
if (!Memory::IsRAMAddress(emAddress, true)) {
|
||||
PanicAlert("Exception: Caught write to invalid address %08x", emAddress);
|
||||
return;
|
||||
}
|
||||
BackPatchError("BackPatch - determined that MOV is write, not yet supported and should have been caught before",
|
||||
codePtr, emAddress);
|
||||
}*/
|
||||
|
||||
if (info.operandSize != 4) {
|
||||
BackPatchError(StringFromFormat("BackPatch - no support for operand size %i", info.operandSize), codePtr, emAddress);
|
||||
}
|
||||
|
||||
if (info.otherReg != RBX)
|
||||
PanicAlert("BackPatch : Base reg not RBX."
|
||||
"\n\nAttempted to access %08x.", emAddress);
|
||||
|
||||
if (accessType == OP_ACCESS_WRITE)
|
||||
PanicAlert("BackPatch : Currently only supporting reads."
|
||||
"\n\nAttempted to write to %08x.", emAddress);
|
||||
|
||||
// In the first iteration, we assume that all accesses are 32-bit. We also only deal with reads.
|
||||
if (accessType == 0)
|
||||
{
|
||||
XEmitter emitter(codePtr);
|
||||
int bswapNopCount;
|
||||
// Check the following BSWAP for REX byte
|
||||
if ((codePtr[info.instructionSize] & 0xF0) == 0x40)
|
||||
bswapNopCount = 3;
|
||||
else
|
||||
bswapNopCount = 2;
|
||||
const u8 *trampoline = trampolines.GetReadTrampoline(info);
|
||||
emitter.CALL((void *)trampoline);
|
||||
emitter.NOP((int)info.instructionSize + bswapNopCount - 5);
|
||||
return codePtr;
|
||||
}
|
||||
else if (accessType == 1)
|
||||
{
|
||||
// TODO: special case FIFO writes. Also, support 32-bit mode.
|
||||
// Also, debug this so that it actually works correctly :P
|
||||
XEmitter emitter(codePtr - 2);
|
||||
// We know it's EAX so the BSWAP before will be two byte. Overwrite it.
|
||||
const u8 *trampoline = trampolines.GetWriteTrampoline(info);
|
||||
emitter.CALL((void *)trampoline);
|
||||
emitter.NOP((int)info.instructionSize - 3);
|
||||
if (info.instructionSize < 3)
|
||||
PanicAlert("instruction too small");
|
||||
// We entered here with a BSWAP-ed EAX. We'll have to swap it back.
|
||||
ctx->Rax = Common::swap32((u32)ctx->Rax);
|
||||
return codePtr - 2;
|
||||
}
|
||||
return 0;
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
|
@ -1,344 +0,0 @@
|
|||
// Copyright (C) 2003-2008 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/
|
||||
|
||||
// Enable define below to enable oprofile integration. For this to work,
|
||||
// it requires at least oprofile version 0.9.4, and changing the build
|
||||
// system to link the Dolphin executable against libopagent. Since the
|
||||
// dependency is a little inconvenient and this is possibly a slight
|
||||
// performance hit, it's not enabled by default, but it's useful for
|
||||
// locating performance issues.
|
||||
|
||||
#include "Common.h"
|
||||
#include "../../Core.h"
|
||||
#include "MemoryUtil.h"
|
||||
|
||||
#include "../../HW/Memmap.h"
|
||||
#include "../../CoreTiming.h"
|
||||
|
||||
#include "../PowerPC.h"
|
||||
#include "../PPCTables.h"
|
||||
#include "../PPCAnalyst.h"
|
||||
|
||||
#include "x64Emitter.h"
|
||||
#include "x64Analyzer.h"
|
||||
|
||||
#include "Jit.h"
|
||||
#include "JitCache.h"
|
||||
#include "JitAsm.h"
|
||||
|
||||
#include "disasm.h"
|
||||
|
||||
#if defined USE_OPROFILE && USE_OPROFILE
|
||||
#include <opagent.h>
|
||||
#endif
|
||||
|
||||
#if defined USE_OPROFILE && USE_OPROFILE
|
||||
op_agent_t agent;
|
||||
#endif
|
||||
|
||||
using namespace Gen;
|
||||
|
||||
#define INVALID_EXIT 0xFFFFFFFF
|
||||
|
||||
|
||||
bool JitBlock::ContainsAddress(u32 em_address)
|
||||
{
|
||||
// WARNING - THIS DOES NOT WORK WITH INLINING ENABLED.
|
||||
return (em_address >= originalAddress && em_address < originalAddress + originalSize);
|
||||
}
|
||||
|
||||
bool JitBlockCache::IsFull() const
|
||||
{
|
||||
return GetNumBlocks() >= MAX_NUM_BLOCKS - 1;
|
||||
}
|
||||
|
||||
void JitBlockCache::Init()
|
||||
{
|
||||
MAX_NUM_BLOCKS = 65536*2;
|
||||
if (Core::g_CoreStartupParameter.bJITUnlimitedCache)
|
||||
{
|
||||
MAX_NUM_BLOCKS = 65536*8;
|
||||
}
|
||||
|
||||
#if defined USE_OPROFILE && USE_OPROFILE
|
||||
agent = op_open_agent();
|
||||
#endif
|
||||
blocks = new JitBlock[MAX_NUM_BLOCKS];
|
||||
blockCodePointers = new const u8*[MAX_NUM_BLOCKS];
|
||||
|
||||
Clear();
|
||||
}
|
||||
|
||||
void JitBlockCache::Shutdown()
|
||||
{
|
||||
delete [] blocks;
|
||||
delete [] blockCodePointers;
|
||||
blocks = 0;
|
||||
blockCodePointers = 0;
|
||||
num_blocks = 0;
|
||||
#if defined USE_OPROFILE && USE_OPROFILE
|
||||
op_close_agent(agent);
|
||||
#endif
|
||||
}
|
||||
|
||||
// This clears the JIT cache. It's called from JitCache.cpp when the JIT cache
|
||||
// is full and when saving and loading states.
|
||||
void JitBlockCache::Clear()
|
||||
{
|
||||
Core::DisplayMessage("Cleared code cache.", 3000);
|
||||
// Is destroying the blocks really necessary?
|
||||
for (int i = 0; i < num_blocks; i++)
|
||||
{
|
||||
DestroyBlock(i, false);
|
||||
}
|
||||
links_to.clear();
|
||||
num_blocks = 0;
|
||||
memset(blockCodePointers, 0, sizeof(u8*)*MAX_NUM_BLOCKS);
|
||||
}
|
||||
|
||||
void JitBlockCache::DestroyBlocksWithFlag(BlockFlag death_flag)
|
||||
{
|
||||
for (int i = 0; i < num_blocks; i++)
|
||||
{
|
||||
if (blocks[i].flags & death_flag)
|
||||
{
|
||||
DestroyBlock(i, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void JitBlockCache::Reset()
|
||||
{
|
||||
Shutdown();
|
||||
Init();
|
||||
}
|
||||
|
||||
JitBlock *JitBlockCache::GetBlock(int no)
|
||||
{
|
||||
return &blocks[no];
|
||||
}
|
||||
|
||||
int JitBlockCache::GetNumBlocks() const
|
||||
{
|
||||
return num_blocks;
|
||||
}
|
||||
|
||||
bool JitBlockCache::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 JitBlockCache::AllocateBlock(u32 em_address)
|
||||
{
|
||||
JitBlock &b = blocks[num_blocks];
|
||||
b.invalid = false;
|
||||
b.originalAddress = em_address;
|
||||
b.originalFirstOpcode = Memory::ReadFast32(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;
|
||||
num_blocks++; //commit the current block
|
||||
return num_blocks - 1;
|
||||
}
|
||||
|
||||
void JitBlockCache::FinalizeBlock(int block_num, bool block_link, const u8 *code_ptr)
|
||||
{
|
||||
blockCodePointers[block_num] = code_ptr;
|
||||
JitBlock &b = blocks[block_num];
|
||||
Memory::WriteUnchecked_U32((JIT_OPCODE << 26) | block_num, blocks[block_num].originalAddress);
|
||||
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 = blockCodePointers[block_num];
|
||||
op_write_native_code(agent, buf, (uint64_t)blockStart,
|
||||
blockStart, b.codeSize);
|
||||
#endif
|
||||
}
|
||||
|
||||
const u8 **JitBlockCache::GetCodePointers()
|
||||
{
|
||||
return blockCodePointers;
|
||||
}
|
||||
|
||||
int JitBlockCache::GetBlockNumberFromStartAddress(u32 addr)
|
||||
{
|
||||
if (!blocks)
|
||||
return -1;
|
||||
u32 code = Memory::ReadFast32(addr);
|
||||
if ((code >> 26) == JIT_OPCODE)
|
||||
{
|
||||
// Jitted code.
|
||||
unsigned int block = code & 0x03FFFFFF;
|
||||
if (block >= (unsigned int)num_blocks) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (blocks[block].originalAddress != addr)
|
||||
{
|
||||
//_assert_msg_(DYNA_REC, 0, "GetBlockFromAddress %08x - No match - This is BAD", addr);
|
||||
return -1;
|
||||
}
|
||||
return block;
|
||||
}
|
||||
else
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
void JitBlockCache::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 JitBlockCache::GetOriginalCode(u32 address)
|
||||
{
|
||||
int num = GetBlockNumberFromStartAddress(address);
|
||||
if (num == -1)
|
||||
return Memory::ReadUnchecked_U32(address);
|
||||
else
|
||||
return blocks[num].originalFirstOpcode;
|
||||
}
|
||||
|
||||
CompiledCode JitBlockCache::GetCompiledCodeFromBlock(int blockNumber)
|
||||
{
|
||||
return (CompiledCode)blockCodePointers[blockNumber];
|
||||
}
|
||||
|
||||
//Block linker
|
||||
//Make sure to have as many blocks as possible compiled before calling this
|
||||
//It's O(N), so it's fast :)
|
||||
//Can be faster by doing a queue for blocks to link up, and only process those
|
||||
//Should probably be done
|
||||
|
||||
void JitBlockCache::LinkBlockExits(int i)
|
||||
{
|
||||
JitBlock &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)
|
||||
{
|
||||
XEmitter emit(b.exitPtrs[e]);
|
||||
emit.JMP(blocks[destinationBlock].checkedEntry, true);
|
||||
b.linkStatus[e] = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
using namespace std;
|
||||
|
||||
void JitBlockCache::LinkBlock(int i)
|
||||
{
|
||||
LinkBlockExits(i);
|
||||
JitBlock &b = blocks[i];
|
||||
std::map<u32, int>::iterator iter;
|
||||
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 iter2 = ppp.first; iter2 != ppp.second; ++iter2) {
|
||||
// PanicAlert("Linking block %i to block %i", iter2->second, i);
|
||||
LinkBlockExits(iter2->second);
|
||||
}
|
||||
}
|
||||
|
||||
void JitBlockCache::DestroyBlock(int blocknum, bool invalidate)
|
||||
{
|
||||
u32 codebytes = (JIT_OPCODE << 26) | blocknum; //generate from i
|
||||
JitBlock &b = blocks[blocknum];
|
||||
b.invalid = 1;
|
||||
if (codebytes == Memory::ReadFast32(b.originalAddress))
|
||||
{
|
||||
//nobody has changed it, good
|
||||
Memory::WriteUnchecked_U32(b.originalFirstOpcode, b.originalAddress);
|
||||
}
|
||||
else if (!invalidate)
|
||||
{
|
||||
//PanicAlert("Detected code overwrite");
|
||||
//else, we may be in trouble, since we apparently know of this block but it's been
|
||||
//overwritten. We should have thrown it out before, on instruction cache invalidate or something.
|
||||
//Not ne cessarily bad though , if a game has simply thrown away a lot of code and is now using the space
|
||||
//for something else, then it's fine.
|
||||
LOG(MASTER_LOG, "WARNING - ClearCache detected code overwrite @ %08x", blocks[blocknum].originalAddress);
|
||||
}
|
||||
|
||||
// We don't unlink blocks, we just send anyone who tries to run them back to the dispatcher.
|
||||
// Not entirely ideal, but .. pretty good.
|
||||
|
||||
// TODO - make sure that the below stuff really is safe.
|
||||
|
||||
// Spurious entrances from previously linked blocks can only come through checkedEntry
|
||||
XEmitter emit((u8 *)b.checkedEntry);
|
||||
emit.MOV(32, M(&PC), Imm32(b.originalAddress));
|
||||
emit.JMP(asm_routines.dispatcher, true);
|
||||
|
||||
emit.SetCodePtr((u8 *)blockCodePointers[blocknum]);
|
||||
emit.MOV(32, M(&PC), Imm32(b.originalAddress));
|
||||
emit.JMP(asm_routines.dispatcher, true);
|
||||
}
|
||||
|
||||
|
||||
void JitBlockCache::InvalidateCodeRange(u32 address, u32 length)
|
||||
{
|
||||
if (!jit.jo.enableBlocklink)
|
||||
return;
|
||||
return;
|
||||
//This is slow but should be safe (zelda needs it for block linking)
|
||||
for (int i = 0; i < num_blocks; i++)
|
||||
{
|
||||
if (RangeIntersect(blocks[i].originalAddress, blocks[i].originalAddress + blocks[i].originalSize,
|
||||
address, address + length))
|
||||
{
|
||||
DestroyBlock(i, true);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,116 +0,0 @@
|
|||
// Copyright (C) 2003-2008 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/
|
||||
|
||||
#ifndef _JITCACHE_H
|
||||
#define _JITCACHE_H
|
||||
|
||||
#include <map>
|
||||
#include <vector>
|
||||
|
||||
#include "../Gekko.h"
|
||||
#include "../PPCAnalyst.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <windows.h>
|
||||
#endif
|
||||
|
||||
enum BlockFlag
|
||||
{
|
||||
BLOCK_USE_GQR0 = 0x1, BLOCK_USE_GQR1 = 0x2, BLOCK_USE_GQR2 = 0x4, BLOCK_USE_GQR3 = 0x8,
|
||||
BLOCK_USE_GQR4 = 0x10, BLOCK_USE_GQR5 = 0x20, BLOCK_USE_GQR6 = 0x40, BLOCK_USE_GQR7 = 0x80,
|
||||
};
|
||||
|
||||
// TODO(ector) - optimize this struct for size
|
||||
struct JitBlock
|
||||
{
|
||||
u32 exitAddress[2]; // 0xFFFFFFFF == unknown
|
||||
u8 *exitPtrs[2]; // to be able to rewrite the exit jump
|
||||
bool linkStatus[2];
|
||||
|
||||
u32 originalAddress;
|
||||
u32 originalFirstOpcode; //to be able to restore
|
||||
u32 codeSize;
|
||||
u32 originalSize;
|
||||
int runCount; // for profiling.
|
||||
|
||||
#ifdef _WIN32
|
||||
// we don't really need to save start and stop
|
||||
// TODO (mb2): ticStart and ticStop -> "local var" mean "in block" ... low priority ;)
|
||||
LARGE_INTEGER ticStart; // for profiling - time.
|
||||
LARGE_INTEGER ticStop; // for profiling - time.
|
||||
LARGE_INTEGER ticCounter; // for profiling - time.
|
||||
#endif
|
||||
const u8 *checkedEntry;
|
||||
bool invalid;
|
||||
int flags;
|
||||
|
||||
bool ContainsAddress(u32 em_address);
|
||||
};
|
||||
|
||||
typedef void (*CompiledCode)();
|
||||
|
||||
class JitBlockCache
|
||||
{
|
||||
const u8 **blockCodePointers;
|
||||
JitBlock *blocks;
|
||||
int num_blocks;
|
||||
std::multimap<u32, int> links_to;
|
||||
int MAX_NUM_BLOCKS;
|
||||
|
||||
bool RangeIntersect(int s1, int e1, int s2, int e2) const;
|
||||
void LinkBlockExits(int i);
|
||||
void LinkBlock(int i);
|
||||
|
||||
public:
|
||||
JitBlockCache() {}
|
||||
|
||||
int AllocateBlock(u32 em_address);
|
||||
void FinalizeBlock(int block_num, bool block_link, const u8 *code_ptr);
|
||||
|
||||
void Clear();
|
||||
void Init();
|
||||
void Shutdown();
|
||||
void Reset();
|
||||
|
||||
bool IsFull() const;
|
||||
|
||||
// Code Cache
|
||||
JitBlock *GetBlock(int block_num);
|
||||
int GetNumBlocks() const;
|
||||
const u8 **GetCodePointers();
|
||||
|
||||
// Fast way to get a block. Only works on the first ppc 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 GetOriginalCode(u32 address);
|
||||
CompiledCode GetCompiledCodeFromBlock(int blockNumber);
|
||||
|
||||
// DOES NOT WORK CORRECTLY WITH INLINING
|
||||
void InvalidateCodeRange(u32 em_address, u32 length);
|
||||
void DestroyBlock(int blocknum, bool invalidate);
|
||||
|
||||
// Not currently used
|
||||
void DestroyBlocksWithFlag(BlockFlag death_flag);
|
||||
};
|
||||
|
||||
#endif
|
|
@ -19,7 +19,6 @@
|
|||
#include "../PPCTables.h"
|
||||
#include "../PPCAnalyst.h"
|
||||
#include "Jit.h"
|
||||
#include "JitCache.h"
|
||||
#include "JitAsm.h"
|
||||
#include "JitRegCache.h"
|
||||
|
||||
|
|
|
@ -25,7 +25,6 @@
|
|||
|
||||
#include "Jit.h"
|
||||
#include "JitRegCache.h"
|
||||
#include "JitCache.h"
|
||||
#include "JitAsm.h"
|
||||
|
||||
// The branches are known good, or at least reasonably good.
|
||||
|
|
|
@ -23,7 +23,6 @@
|
|||
#include "x64Emitter.h"
|
||||
|
||||
#include "Jit.h"
|
||||
#include "JitCache.h"
|
||||
#include "JitRegCache.h"
|
||||
|
||||
//#define INSTRUCTION_START Default(inst); return;
|
||||
|
|
|
@ -25,7 +25,6 @@
|
|||
#include "x64Emitter.h"
|
||||
|
||||
#include "Jit.h"
|
||||
#include "JitCache.h"
|
||||
#include "JitRegCache.h"
|
||||
#include "JitAsm.h"
|
||||
|
||||
|
|
|
@ -32,7 +32,6 @@
|
|||
#include "ABI.h"
|
||||
|
||||
#include "Jit.h"
|
||||
#include "JitCache.h"
|
||||
#include "JitAsm.h"
|
||||
#include "JitRegCache.h"
|
||||
|
||||
|
|
|
@ -32,7 +32,6 @@
|
|||
#include "ABI.h"
|
||||
|
||||
#include "Jit.h"
|
||||
#include "JitCache.h"
|
||||
#include "JitAsm.h"
|
||||
#include "JitRegCache.h"
|
||||
|
||||
|
|
|
@ -33,7 +33,6 @@
|
|||
#include "ABI.h"
|
||||
|
||||
#include "Jit.h"
|
||||
#include "JitCache.h"
|
||||
#include "JitAsm.h"
|
||||
#include "JitRegCache.h"
|
||||
|
||||
|
|
|
@ -24,7 +24,6 @@
|
|||
#include "../../HW/GPFifo.h"
|
||||
|
||||
#include "Jit.h"
|
||||
#include "JitCache.h"
|
||||
#include "JitRegCache.h"
|
||||
|
||||
void Jit64::ps_mr(UGeckoInstruction inst)
|
||||
|
|
|
@ -27,7 +27,6 @@
|
|||
#include "Thunk.h"
|
||||
|
||||
#include "Jit.h"
|
||||
#include "JitCache.h"
|
||||
#include "JitRegCache.h"
|
||||
|
||||
//#define INSTRUCTION_START Default(inst); return;
|
||||
|
|
|
@ -19,7 +19,13 @@
|
|||
|
||||
#include "Common.h"
|
||||
#include "disasm.h"
|
||||
#include "JitAsm.h"
|
||||
#ifdef JITTEST
|
||||
#include "../Jit64IL/Jit.h"
|
||||
#include "../Jit64IL/JitAsm.h"
|
||||
#else
|
||||
#include "../Jit64/Jit.h"
|
||||
#include "../Jit64/JitAsm.h"
|
||||
#endif
|
||||
#include "../../HW/Memmap.h"
|
||||
|
||||
#include "x64Emitter.h"
|
||||
|
@ -28,7 +34,6 @@
|
|||
#include "x64Analyzer.h"
|
||||
|
||||
#include "StringUtil.h"
|
||||
#include "Jit.h"
|
||||
|
||||
using namespace Gen;
|
||||
|
|
@ -36,9 +36,15 @@
|
|||
#include "x64Emitter.h"
|
||||
#include "x64Analyzer.h"
|
||||
|
||||
#include "Jit.h"
|
||||
#ifdef JITTEST
|
||||
#include "../Jit64IL/Jit.h"
|
||||
#include "../Jit64IL/JitAsm.h"
|
||||
#else
|
||||
#include "../Jit64/Jit.h"
|
||||
#include "../Jit64/JitAsm.h"
|
||||
#endif
|
||||
|
||||
#include "JitCache.h"
|
||||
#include "JitAsm.h"
|
||||
|
||||
#include "disasm.h"
|
||||
|
|
@ -28,10 +28,17 @@
|
|||
#include "x64Emitter.h"
|
||||
#include "ABI.h"
|
||||
|
||||
#include "Jit.h"
|
||||
#ifdef JITTEST
|
||||
#include "../Jit64IL/Jit.h"
|
||||
#include "JitCache.h"
|
||||
#include "JitAsm.h"
|
||||
#include "JitRegCache.h"
|
||||
#include "../Jit64IL/JitAsm.h"
|
||||
#include "../Jit64IL/JitRegCache.h"
|
||||
#else
|
||||
#include "../Jit64/Jit.h"
|
||||
#include "JitCache.h"
|
||||
#include "../Jit64/JitAsm.h"
|
||||
#include "../Jit64/JitRegCache.h"
|
||||
#endif
|
||||
|
||||
void Jit64::JitClearCA()
|
||||
{
|
|
@ -25,7 +25,6 @@
|
|||
|
||||
#if defined(_M_IX86) || defined(_M_X64)
|
||||
#include "Jit64/Jit.h"
|
||||
#include "Jit64/JitCache.h"
|
||||
#else
|
||||
#error Unknown architecture!
|
||||
#endif
|
||||
|
|
|
@ -27,7 +27,6 @@
|
|||
|
||||
#include "Interpreter/Interpreter.h"
|
||||
#include "Jit64/Jit.h"
|
||||
#include "Jit64/JitCache.h"
|
||||
#include "PowerPC.h"
|
||||
#include "PPCTables.h"
|
||||
|
||||
|
|
|
@ -81,6 +81,9 @@ files = ["Console.cpp",
|
|||
"PowerPC/Interpreter/Interpreter_LoadStore.cpp",
|
||||
"PowerPC/Interpreter/Interpreter_LoadStorePaired.cpp",
|
||||
"PowerPC/Interpreter/Interpreter_SystemRegisters.cpp",
|
||||
"PowerPC/JitCommon/JitCache.cpp",
|
||||
"PowerPC/JitCommon/JitBackpatch.cpp",
|
||||
"PowerPC/JitCommon/Jit_Util.cpp",
|
||||
"HLE/HLE.cpp",
|
||||
"HLE/HLE_Misc.cpp",
|
||||
"HLE/HLE_OS.cpp",
|
||||
|
@ -88,8 +91,6 @@ files = ["Console.cpp",
|
|||
|
||||
if env['JITTEST']:
|
||||
files += ["PowerPC/Jit64IL/Jit.cpp",
|
||||
"PowerPC/Jit64IL/JitBackpatch.cpp",
|
||||
"PowerPC/Jit64IL/JitCache.cpp",
|
||||
"PowerPC/Jit64IL/JitRegCache.cpp",
|
||||
"PowerPC/Jit64IL/JitAsm.cpp",
|
||||
"PowerPC/Jit64IL/Jit_Branch.cpp",
|
||||
|
@ -100,13 +101,10 @@ if env['JITTEST']:
|
|||
"PowerPC/Jit64IL/Jit_LoadStore.cpp",
|
||||
"PowerPC/Jit64IL/Jit_LoadStoreFloating.cpp",
|
||||
"PowerPC/Jit64IL/Jit_SystemRegisters.cpp",
|
||||
"PowerPC/Jit64IL/Jit_Util.cpp",
|
||||
"PowerPC/Jit64IL/IR.cpp",
|
||||
]
|
||||
else:
|
||||
files += ["PowerPC/Jit64/Jit.cpp",
|
||||
"PowerPC/Jit64/JitBackpatch.cpp",
|
||||
"PowerPC/Jit64/JitCache.cpp",
|
||||
"PowerPC/Jit64/JitRegCache.cpp",
|
||||
"PowerPC/Jit64/JitAsm.cpp",
|
||||
"PowerPC/Jit64/Jit_Branch.cpp",
|
||||
|
@ -117,7 +115,6 @@ else:
|
|||
"PowerPC/Jit64/Jit_LoadStore.cpp",
|
||||
"PowerPC/Jit64/Jit_LoadStoreFloating.cpp",
|
||||
"PowerPC/Jit64/Jit_SystemRegisters.cpp",
|
||||
"PowerPC/Jit64/Jit_Util.cpp",
|
||||
]
|
||||
|
||||
libs = [
|
||||
|
|
|
@ -60,7 +60,7 @@
|
|||
#include "PowerPC/SignatureDB.h"
|
||||
#include "PowerPC/PPCTables.h"
|
||||
#include "PowerPC/Jit64/Jit.h"
|
||||
#include "PowerPC/Jit64/JitCache.h" // for ClearCache()
|
||||
#include "PowerPC/JitCommon/JitCache.h" // for ClearCache()
|
||||
|
||||
#include "PluginManager.h"
|
||||
#include "ConfigManager.h"
|
||||
|
|
|
@ -61,7 +61,7 @@
|
|||
#include "PowerPC/SignatureDB.h"
|
||||
#include "PowerPC/PPCTables.h"
|
||||
#include "PowerPC/Jit64/Jit.h"
|
||||
#include "PowerPC/Jit64/JitCache.h" // for ClearCache()
|
||||
#include "PowerPC/JitCommon/JitCache.h" // for ClearCache()
|
||||
|
||||
#include "PluginManager.h"
|
||||
#include "ConfigManager.h"
|
||||
|
|
|
@ -23,11 +23,16 @@
|
|||
#include <wx/listctrl.h>
|
||||
#include <wx/thread.h>
|
||||
#include <wx/listctrl.h>
|
||||
|
||||
#include "JitWindow.h"
|
||||
#include "HW/CPU.h"
|
||||
#include "PowerPC/PowerPC.h"
|
||||
#if JITTEST
|
||||
#include "PowerPC/Jit64/Jit.h"
|
||||
#include "PowerPC/Jit64/JitCache.h"
|
||||
#else
|
||||
#include "PowerPC/Jit64IL/Jit.h"
|
||||
#endif
|
||||
#include "PowerPC/JitCommon/JitCache.h"
|
||||
#include "PowerPC/PPCAnalyst.h"
|
||||
#include "PowerPCDisasm.h"
|
||||
#include "Host.h"
|
||||
|
|
|
@ -103,7 +103,7 @@
|
|||
SubSystem="2"
|
||||
BaseAddress="0x00400000"
|
||||
RandomizedBaseAddress="1"
|
||||
DataExecutionPrevention="0"
|
||||
DataExecutionPrevention="2"
|
||||
TargetMachine="1"
|
||||
/>
|
||||
<Tool
|
||||
|
@ -215,7 +215,7 @@
|
|||
BaseAddress="0x00400000"
|
||||
RandomizedBaseAddress="1"
|
||||
FixedBaseAddress="1"
|
||||
DataExecutionPrevention="0"
|
||||
DataExecutionPrevention="2"
|
||||
TargetMachine="17"
|
||||
/>
|
||||
<Tool
|
||||
|
@ -325,7 +325,7 @@
|
|||
SubSystem="2"
|
||||
BaseAddress="0x00400000"
|
||||
RandomizedBaseAddress="1"
|
||||
DataExecutionPrevention="0"
|
||||
DataExecutionPrevention="2"
|
||||
TargetMachine="1"
|
||||
/>
|
||||
<Tool
|
||||
|
@ -435,7 +435,7 @@
|
|||
SubSystem="2"
|
||||
BaseAddress="0x00400000"
|
||||
RandomizedBaseAddress="1"
|
||||
DataExecutionPrevention="0"
|
||||
DataExecutionPrevention="2"
|
||||
TargetMachine="17"
|
||||
/>
|
||||
<Tool
|
||||
|
@ -548,7 +548,7 @@
|
|||
LargeAddressAware="1"
|
||||
BaseAddress="0x00400000"
|
||||
RandomizedBaseAddress="1"
|
||||
DataExecutionPrevention="0"
|
||||
DataExecutionPrevention="2"
|
||||
TargetMachine="1"
|
||||
/>
|
||||
<Tool
|
||||
|
@ -659,7 +659,7 @@
|
|||
SubSystem="2"
|
||||
BaseAddress="0x00400000"
|
||||
RandomizedBaseAddress="1"
|
||||
DataExecutionPrevention="0"
|
||||
DataExecutionPrevention="2"
|
||||
TargetMachine="17"
|
||||
/>
|
||||
<Tool
|
||||
|
@ -774,7 +774,7 @@
|
|||
SubSystem="2"
|
||||
BaseAddress="0x00400000"
|
||||
RandomizedBaseAddress="1"
|
||||
DataExecutionPrevention="0"
|
||||
DataExecutionPrevention="2"
|
||||
TargetMachine="1"
|
||||
/>
|
||||
<Tool
|
||||
|
@ -886,7 +886,7 @@
|
|||
BaseAddress="0x00400000"
|
||||
RandomizedBaseAddress="1"
|
||||
FixedBaseAddress="1"
|
||||
DataExecutionPrevention="0"
|
||||
DataExecutionPrevention="2"
|
||||
TargetMachine="17"
|
||||
/>
|
||||
<Tool
|
||||
|
|
|
@ -211,7 +211,7 @@
|
|||
ProgramDatabaseFile="$(TargetDir)$(TargetName).pdb"
|
||||
RandomizedBaseAddress="1"
|
||||
FixedBaseAddress="1"
|
||||
DataExecutionPrevention="0"
|
||||
DataExecutionPrevention="2"
|
||||
ImportLibrary="$(TargetDir)$(TargetName).lib"
|
||||
TargetMachine="17"
|
||||
/>
|
||||
|
|
Loading…
Reference in New Issue