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:
hrydgard 2009-02-23 20:29:55 +00:00
parent 7d84ac6a5a
commit 96827d9996
43 changed files with 82 additions and 1119 deletions

View File

@ -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"

View File

@ -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"

View File

@ -23,7 +23,7 @@
#include "../../Core.h"
#include "../Jit64/Jit.h"
#include "../Jit64/JitCache.h"
#include "../JitCommon/JitCache.h"
namespace Interpreter
{

View File

@ -34,7 +34,6 @@
#include "../../HW/GPFifo.h"
#include "Jit.h"
#include "JitAsm.h"
#include "JitCache.h"
#include "JitRegCache.h"
#if defined JITTEST && JITTEST

View File

@ -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"

View File

@ -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);

View File

@ -19,7 +19,6 @@
#include "../PPCTables.h"
#include "../PPCAnalyst.h"
#include "Jit.h"
#include "JitCache.h"
#include "JitAsm.h"
#include "JitRegCache.h"

View File

@ -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.

View File

@ -23,7 +23,6 @@
#include "x64Emitter.h"
#include "Jit.h"
#include "JitCache.h"
#include "JitRegCache.h"
const u64 GC_ALIGNED16(psSignBits2[2]) = {0x8000000000000000ULL, 0x8000000000000000ULL};

View File

@ -21,7 +21,6 @@
#include "x64Emitter.h"
#include "Jit.h"
#include "JitCache.h"
#include "JitRegCache.h"
#include "JitAsm.h"

View File

@ -32,7 +32,6 @@
#include "ABI.h"
#include "Jit.h"
#include "JitCache.h"
#include "JitAsm.h"
#include "JitRegCache.h"

View File

@ -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;

View File

@ -33,7 +33,6 @@
#include "ABI.h"
#include "Jit.h"
#include "JitCache.h"
#include "JitAsm.h"
#include "JitRegCache.h"

View File

@ -24,7 +24,6 @@
#include "../../HW/GPFifo.h"
#include "Jit.h"
#include "JitCache.h"
#include "JitRegCache.h"
// TODO

View File

@ -27,7 +27,6 @@
#include "Thunk.h"
#include "Jit.h"
#include "JitCache.h"
#include "JitRegCache.h"
void Jit64::mtspr(UGeckoInstruction inst)

View File

@ -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));
}
}

View File

@ -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

View File

@ -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"

View File

@ -27,7 +27,6 @@
#include "ABI.h"
#include "Jit.h"
#include "JitCache.h"
#include "Thunk.h"
#include "../../HW/GPFifo.h"

View File

@ -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
}

View File

@ -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);
}
}
}

View File

@ -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

View File

@ -19,7 +19,6 @@
#include "../PPCTables.h"
#include "../PPCAnalyst.h"
#include "Jit.h"
#include "JitCache.h"
#include "JitAsm.h"
#include "JitRegCache.h"

View File

@ -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.

View File

@ -23,7 +23,6 @@
#include "x64Emitter.h"
#include "Jit.h"
#include "JitCache.h"
#include "JitRegCache.h"
//#define INSTRUCTION_START Default(inst); return;

View File

@ -25,7 +25,6 @@
#include "x64Emitter.h"
#include "Jit.h"
#include "JitCache.h"
#include "JitRegCache.h"
#include "JitAsm.h"

View File

@ -32,7 +32,6 @@
#include "ABI.h"
#include "Jit.h"
#include "JitCache.h"
#include "JitAsm.h"
#include "JitRegCache.h"

View File

@ -32,7 +32,6 @@
#include "ABI.h"
#include "Jit.h"
#include "JitCache.h"
#include "JitAsm.h"
#include "JitRegCache.h"

View File

@ -33,7 +33,6 @@
#include "ABI.h"
#include "Jit.h"
#include "JitCache.h"
#include "JitAsm.h"
#include "JitRegCache.h"

View File

@ -24,7 +24,6 @@
#include "../../HW/GPFifo.h"
#include "Jit.h"
#include "JitCache.h"
#include "JitRegCache.h"
void Jit64::ps_mr(UGeckoInstruction inst)

View File

@ -27,7 +27,6 @@
#include "Thunk.h"
#include "Jit.h"
#include "JitCache.h"
#include "JitRegCache.h"
//#define INSTRUCTION_START Default(inst); return;

View File

@ -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;

View File

@ -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"

View File

@ -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()
{

View File

@ -25,7 +25,6 @@
#if defined(_M_IX86) || defined(_M_X64)
#include "Jit64/Jit.h"
#include "Jit64/JitCache.h"
#else
#error Unknown architecture!
#endif

View File

@ -27,7 +27,6 @@
#include "Interpreter/Interpreter.h"
#include "Jit64/Jit.h"
#include "Jit64/JitCache.h"
#include "PowerPC.h"
#include "PPCTables.h"

View File

@ -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 = [

View File

@ -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"

View File

@ -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"

View File

@ -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"

View File

@ -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

View File

@ -211,7 +211,7 @@
ProgramDatabaseFile="$(TargetDir)$(TargetName).pdb"
RandomizedBaseAddress="1"
FixedBaseAddress="1"
DataExecutionPrevention="0"
DataExecutionPrevention="2"
ImportLibrary="$(TargetDir)$(TargetName).lib"
TargetMachine="17"
/>