mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2024-11-14 13:27:45 -07:00
Yet another bunch of optimizations and cleanup.
git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@191 8ced0084-cf51-0410-be5f-012b33b47a6e
This commit is contained in:
parent
8900114c2b
commit
2b8a85ac5a
@ -896,6 +896,14 @@
|
||||
RelativePath=".\Src\PowerPC\Jit64\Jit_SystemRegisters.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Src\PowerPC\Jit64\Jit_Util.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Src\PowerPC\Jit64\Jit_Util.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Src\PowerPC\Jit64\JitAsm.cpp"
|
||||
>
|
||||
@ -1162,6 +1170,10 @@
|
||||
RelativePath=".\Src\PatchEngine.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Src\SConscript"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Src\stdafx.cpp"
|
||||
>
|
||||
|
@ -329,7 +329,7 @@ void Write32(const u32 _Data, const u32 _Address)
|
||||
|
||||
void GatherPipeBursted()
|
||||
{
|
||||
// we arn't linked, so we don't care about gather pipe data
|
||||
// if we aren't linked, we don't care about gather pipe data
|
||||
if (!fifo.bFF_GPLinkEnable)
|
||||
return;
|
||||
|
||||
|
@ -73,7 +73,7 @@ void CheckGatherPipe()
|
||||
// increase the CPUWritePointer
|
||||
CPeripheralInterface::Fifo_CPUWritePointer += GATHER_PIPE_SIZE;
|
||||
if (CPeripheralInterface::Fifo_CPUWritePointer > CPeripheralInterface::Fifo_CPUEnd)
|
||||
_assert_msg_(DYNA_REC, 0, "ARGH");
|
||||
_assert_msg_(DYNA_REC, 0, "Fifo_CPUWritePointer out of bounds");
|
||||
|
||||
if (CPeripheralInterface::Fifo_CPUWritePointer >= CPeripheralInterface::Fifo_CPUEnd)
|
||||
CPeripheralInterface::Fifo_CPUWritePointer = CPeripheralInterface::Fifo_CPUBase;
|
||||
|
@ -878,7 +878,7 @@ u8 *GetPointer(const u32 _Address)
|
||||
}
|
||||
|
||||
|
||||
bool IsRAMAddress(const u32 addr)
|
||||
bool IsRAMAddress(const u32 addr, bool allow_locked_cache)
|
||||
{
|
||||
switch ((addr >> 24) & 0xFC) {
|
||||
case 0x00:
|
||||
@ -896,7 +896,7 @@ bool IsRAMAddress(const u32 addr)
|
||||
else
|
||||
return false;
|
||||
case 0xE0:
|
||||
if (addr - 0xE0000000 < L1_CACHE_SIZE)
|
||||
if (allow_locked_cache && addr - 0xE0000000 < L1_CACHE_SIZE)
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
|
@ -77,7 +77,7 @@ namespace Memory
|
||||
void InitHWMemFuncsWii();
|
||||
|
||||
u32 Read_Instruction(const u32 _Address);
|
||||
bool IsRAMAddress(const u32 addr);
|
||||
bool IsRAMAddress(const u32 addr, bool allow_locked_cache = false);
|
||||
writeFn32 GetHWWriteFun32(const u32 _Address);
|
||||
|
||||
inline u8* GetCachePtr() {return m_pL1Cache;}
|
||||
|
@ -20,12 +20,14 @@
|
||||
#include "Common.h"
|
||||
#include "x64Emitter.h"
|
||||
#include "ABI.h"
|
||||
#include "Thunk.h"
|
||||
#include "../../HLE/HLE.h"
|
||||
#include "../../CoreTiming.h"
|
||||
#include "../PowerPC.h"
|
||||
#include "../PPCTables.h"
|
||||
#include "../PPCAnalyst.h"
|
||||
#include "../../HW/Memmap.h"
|
||||
#include "../../HW/GPFifo.h"
|
||||
#include "Jit.h"
|
||||
#include "JitAsm.h"
|
||||
#include "JitCache.h"
|
||||
@ -294,8 +296,15 @@ namespace Jit64
|
||||
been_here[PC] = 1;
|
||||
}
|
||||
|
||||
void Cleanup()
|
||||
{
|
||||
if (jo.optimizeGatherPipe && js.fifoBytesThisBlock > 0)
|
||||
CALL((void *)&GPFifo::CheckGatherPipe);
|
||||
}
|
||||
|
||||
void WriteExit(u32 destination, int exit_num)
|
||||
{
|
||||
Cleanup();
|
||||
SUB(32, M(&CoreTiming::downcount), js.downcountAmount > 127 ? Imm32(js.downcountAmount) : Imm8(js.downcountAmount));
|
||||
|
||||
//If nobody has taken care of this yet (this can be removed when all branches are done)
|
||||
@ -321,6 +330,7 @@ namespace Jit64
|
||||
void WriteExitDestInEAX(int exit_num)
|
||||
{
|
||||
MOV(32, M(&PC), R(EAX));
|
||||
Cleanup();
|
||||
SUB(32, M(&CoreTiming::downcount), js.downcountAmount > 127 ? Imm32(js.downcountAmount) : Imm8(js.downcountAmount));
|
||||
JMP(Asm::dispatcher, true);
|
||||
}
|
||||
@ -328,12 +338,14 @@ namespace Jit64
|
||||
void WriteRfiExitDestInEAX()
|
||||
{
|
||||
MOV(32, M(&PC), R(EAX));
|
||||
Cleanup();
|
||||
SUB(32, M(&CoreTiming::downcount), js.downcountAmount > 127 ? Imm32(js.downcountAmount) : Imm8(js.downcountAmount));
|
||||
JMP(Asm::testExceptions, true);
|
||||
}
|
||||
|
||||
void WriteExceptionExit(u32 exception)
|
||||
{
|
||||
Cleanup();
|
||||
OR(32, M(&PowerPC::ppcState.Exceptions), Imm32(exception));
|
||||
MOV(32, M(&PC), Imm32(js.compilerPC + 4));
|
||||
JMP(Asm::testExceptions, true);
|
||||
@ -396,6 +408,11 @@ namespace Jit64
|
||||
// Default(ops[i].inst);
|
||||
gpr.SanityCheck();
|
||||
fpr.SanityCheck();
|
||||
if (jo.optimizeGatherPipe && js.fifoBytesThisBlock >= 32)
|
||||
{
|
||||
js.fifoBytesThisBlock -= 32;
|
||||
CALL(ProtectFunction((void *)&GPFifo::CheckGatherPipe, 0));
|
||||
}
|
||||
}
|
||||
js.compilerPC += 4;
|
||||
|
||||
|
@ -69,6 +69,7 @@ namespace Jit64
|
||||
bool enableBlocklink;
|
||||
bool fpAccurateFlags;
|
||||
bool enableFastMem;
|
||||
bool optimizeGatherPipe;
|
||||
};
|
||||
|
||||
extern JitState js;
|
||||
@ -84,11 +85,6 @@ namespace Jit64
|
||||
|
||||
void HLEFunction(UGeckoInstruction _inst);
|
||||
|
||||
void UnsafeLoadRegToReg(Gen::X64Reg reg_addr, Gen::X64Reg reg_value, int accessSize, s32 offset = 0, bool signExtend = false);
|
||||
void UnsafeWriteRegToReg(Gen::X64Reg reg_value, Gen::X64Reg reg_addr, int accessSize, s32 offset = 0);
|
||||
void SafeLoadRegToEAX(Gen::X64Reg reg, int accessSize, s32 offset, bool signExtend = false);
|
||||
void SafeWriteRegToReg(Gen::X64Reg reg_value, Gen::X64Reg reg_addr, int accessSize, s32 offset);
|
||||
|
||||
void addx(UGeckoInstruction inst);
|
||||
void orx(UGeckoInstruction inst);
|
||||
void andx(UGeckoInstruction inst);
|
||||
|
@ -29,6 +29,7 @@
|
||||
#include "JitCache.h"
|
||||
|
||||
#include "../../HW/CPUCompare.h"
|
||||
#include "../../HW/GPFifo.h"
|
||||
#include "../../Core.h"
|
||||
|
||||
using namespace Gen;
|
||||
@ -36,6 +37,7 @@ int blocksExecuted;
|
||||
|
||||
namespace Jit64
|
||||
{
|
||||
|
||||
namespace Asm
|
||||
{
|
||||
const u8 *enterCode;
|
||||
@ -47,6 +49,11 @@ const u8 *dispatcherNoCheck;
|
||||
const u8 *dispatcherPcInEAX;
|
||||
const u8 *computeRc;
|
||||
|
||||
const u8 *fifoDirectWrite8;
|
||||
const u8 *fifoDirectWrite16;
|
||||
const u8 *fifoDirectWrite32;
|
||||
const u8 *fifoDirectWriteFloat;
|
||||
|
||||
static bool blockMode = false; //doesn't work as true!
|
||||
bool compareEnabled = false;
|
||||
|
||||
@ -73,6 +80,8 @@ static bool enableStatistics = false;
|
||||
// At this offset - 4, there is an int specifying the block number.
|
||||
|
||||
|
||||
void GenerateCommon();
|
||||
|
||||
#ifdef _M_IX86
|
||||
void Generate()
|
||||
{
|
||||
@ -167,36 +176,7 @@ void Generate()
|
||||
POP(EBP);
|
||||
RET();
|
||||
|
||||
computeRc = AlignCode16();
|
||||
AND(32, M(&CR), Imm32(0x0FFFFFFF));
|
||||
CMP(32, R(EAX), Imm8(0));
|
||||
FixupBranch pLesser = J_CC(CC_L);
|
||||
FixupBranch pGreater = J_CC(CC_G);
|
||||
|
||||
OR(32, M(&CR), Imm32(0x20000000)); // _x86Reg == 0
|
||||
RET();
|
||||
|
||||
SetJumpTarget(pGreater);
|
||||
OR(32, M(&CR), Imm32(0x40000000)); // _x86Reg > 0
|
||||
RET();
|
||||
|
||||
SetJumpTarget(pLesser);
|
||||
OR(32, M(&CR), Imm32(0x80000000)); // _x86Reg < 0
|
||||
RET();
|
||||
|
||||
// Fast write routines - special case the most common hardware write
|
||||
// TODO: use this.
|
||||
// Even in x86, the param values will be in the right registers.
|
||||
/*
|
||||
const u8 *fastMemWrite8 = AlignCode16();
|
||||
CMP(32, R(ABI_PARAM2), Imm32(0xCC008000));
|
||||
FixupBranch skip_fast_write = J_CC(CC_NE, false);
|
||||
MOV(32, EAX, M(&m_gatherPipeCount));
|
||||
MOV(8, MDisp(EAX, (u32)&m_gatherPipe), ABI_PARAM1);
|
||||
ADD(32, 1, M(&m_gatherPipeCount));
|
||||
RET();
|
||||
SetJumpTarget(skip_fast_write);
|
||||
CALL((void *)&Memory::Write_U8);*/
|
||||
GenerateCommon();
|
||||
}
|
||||
|
||||
#elif defined(_M_X64)
|
||||
@ -287,12 +267,59 @@ void Generate()
|
||||
ABI_PopAllCalleeSavedRegsAndAdjustStack();
|
||||
RET();
|
||||
|
||||
GenerateCommon();
|
||||
}
|
||||
#endif
|
||||
|
||||
void GenFifoWrite(int size)
|
||||
{
|
||||
// Assume value in ABI_PARAM1
|
||||
PUSH(ESI);
|
||||
if (size != 32)
|
||||
PUSH(EDX);
|
||||
BSWAP(size, ABI_PARAM1);
|
||||
MOV(32, R(EAX), Imm32((u32)GPFifo::m_gatherPipe));
|
||||
MOV(32, R(ESI), M(&GPFifo::m_gatherPipeCount));
|
||||
if (size != 32) {
|
||||
MOV(32, R(EDX), R(ABI_PARAM1));
|
||||
MOV(size, MComplex(RAX, RSI, 1, 0), R(EDX));
|
||||
} else {
|
||||
MOV(size, MComplex(RAX, RSI, 1, 0), R(ABI_PARAM1));
|
||||
}
|
||||
ADD(32, R(ESI), Imm8(size >> 3));
|
||||
MOV(32, M(&GPFifo::m_gatherPipeCount), R(ESI));
|
||||
if (size != 32)
|
||||
POP(EDX);
|
||||
POP(ESI);
|
||||
RET();
|
||||
}
|
||||
|
||||
static int temp32;
|
||||
void GenFifoFloatWrite()
|
||||
{
|
||||
// Assume value in XMM0
|
||||
PUSH(ESI);
|
||||
PUSH(EDX);
|
||||
MOVSS(M(&temp32), XMM0);
|
||||
MOV(32, R(EDX), M(&temp32));
|
||||
BSWAP(32, EDX);
|
||||
MOV(32, R(EAX), Imm32((u32)GPFifo::m_gatherPipe));
|
||||
MOV(32, R(ESI), M(&GPFifo::m_gatherPipeCount));
|
||||
MOV(32, MComplex(RAX, RSI, 1, 0), R(EDX));
|
||||
ADD(32, R(ESI), Imm8(4));
|
||||
MOV(32, M(&GPFifo::m_gatherPipeCount), R(ESI));
|
||||
POP(EDX);
|
||||
POP(ESI);
|
||||
RET();
|
||||
}
|
||||
|
||||
void GenerateCommon()
|
||||
{
|
||||
computeRc = AlignCode16();
|
||||
AND(32, M(&CR), Imm32(0x0FFFFFFF));
|
||||
CMP(32, R(EAX), Imm8(0));
|
||||
FixupBranch pLesser = J_CC(CC_L);
|
||||
FixupBranch pGreater = J_CC(CC_G);
|
||||
|
||||
OR(32, M(&CR), Imm32(0x20000000)); // _x86Reg == 0
|
||||
RET();
|
||||
SetJumpTarget(pGreater);
|
||||
@ -302,68 +329,30 @@ void Generate()
|
||||
OR(32, M(&CR), Imm32(0x80000000)); // _x86Reg < 0
|
||||
RET();
|
||||
|
||||
fifoDirectWrite8 = AlignCode4();
|
||||
GenFifoWrite(8);
|
||||
fifoDirectWrite16 = AlignCode4();
|
||||
GenFifoWrite(16);
|
||||
fifoDirectWrite32 = AlignCode4();
|
||||
GenFifoWrite(32);
|
||||
fifoDirectWriteFloat = AlignCode4();
|
||||
GenFifoFloatWrite();
|
||||
// Fast write routines - special case the most common hardware write
|
||||
// TODO: use this.
|
||||
// Even in x86, the param values will be in the right registers.
|
||||
/*
|
||||
const u8 *end = GetCodePtr();
|
||||
|
||||
|
||||
u8 *xDis = new u8[65536];
|
||||
memset(xDis,0,65536);
|
||||
|
||||
disassembler x64disasm;
|
||||
|
||||
x64disasm.set_syntax_intel();
|
||||
u64 disasmPtr = (u64)enterCode;
|
||||
int size = end-enterCode;
|
||||
char *sptr = (char*)xDis;
|
||||
|
||||
while ((u8*)disasmPtr < end)
|
||||
{
|
||||
disasmPtr += x64disasm.disasm64(disasmPtr, disasmPtr, (u8*)disasmPtr, sptr);
|
||||
sptr += strlen(sptr);
|
||||
*sptr++ = 13;
|
||||
*sptr++ = 10;
|
||||
}
|
||||
MessageBox(0,(char*)xDis,"yo",0);
|
||||
delete [] xDis; */
|
||||
|
||||
/*
|
||||
RUNTIME_FUNCTION func;
|
||||
func.BeginAddress = 0;
|
||||
func.EndAddress = (u32)(GetCodePtr() - enterCode);
|
||||
func.UnwindData = 0;
|
||||
|
||||
RtlAddFunctionTable(&func, 1, (ULONGLONG)enterCode);*/
|
||||
/*
|
||||
//we only want to do this once
|
||||
PUSH(RBX);
|
||||
PUSH(RSI);
|
||||
PUSH(RDI);
|
||||
PUSH(R12);
|
||||
PUSH(R13);
|
||||
PUSH(R14);
|
||||
PUSH(R15);
|
||||
//TODO: Also preserve XMM0-3?
|
||||
SUB(64, R(RSP), Imm8(0x20));
|
||||
|
||||
MOV(32, R(R15), M(&Memory::base));
|
||||
|
||||
|
||||
|
||||
|
||||
MOV(32, M(&PowerPC::ppcState.pc), R(R14));
|
||||
|
||||
//Landing pad for drec space
|
||||
ADD(64, R(RSP), Imm8(0x20));
|
||||
POP(R15);
|
||||
POP(R14);
|
||||
POP(R13);
|
||||
POP(R12);
|
||||
POP(RDI);
|
||||
POP(RSI);
|
||||
POP(RBX);
|
||||
RET();*/
|
||||
}
|
||||
#endif
|
||||
}
|
||||
const u8 *fastMemWrite8 = AlignCode16();
|
||||
CMP(32, R(ABI_PARAM2), Imm32(0xCC008000));
|
||||
FixupBranch skip_fast_write = J_CC(CC_NE, false);
|
||||
MOV(32, EAX, M(&m_gatherPipeCount));
|
||||
MOV(8, MDisp(EAX, (u32)&m_gatherPipe), ABI_PARAM1);
|
||||
ADD(32, 1, M(&m_gatherPipeCount));
|
||||
RET();
|
||||
SetJumpTarget(skip_fast_write);
|
||||
CALL((void *)&Memory::Write_U8);*/
|
||||
}
|
||||
|
||||
} // namespace Asm
|
||||
|
||||
} // namespace Jit64
|
||||
|
||||
|
@ -34,6 +34,11 @@ namespace Jit64
|
||||
extern const u8 *dispatchPcInEAX;
|
||||
extern const u8 *doTiming;
|
||||
|
||||
extern const u8 *fifoDirectWrite8;
|
||||
extern const u8 *fifoDirectWrite16;
|
||||
extern const u8 *fifoDirectWrite32;
|
||||
extern const u8 *fifoDirectWriteFloat;
|
||||
|
||||
extern bool compareEnabled;
|
||||
void Generate();
|
||||
}
|
||||
|
@ -85,6 +85,7 @@ namespace Jit64
|
||||
#endif
|
||||
jo.assumeFPLoadFromMem = true;
|
||||
jo.fpAccurateFlags = true;
|
||||
jo.optimizeGatherPipe = true;
|
||||
|
||||
codeCache = (u8*)AllocateExecutableMemory(CODE_SIZE);
|
||||
genFunctions = (u8*)AllocateExecutableMemory(GEN_SIZE);
|
||||
@ -260,7 +261,7 @@ namespace Jit64
|
||||
}
|
||||
|
||||
int GetCodeSize() {
|
||||
return GetCodePtr() - codeCache;
|
||||
return (int)(GetCodePtr() - codeCache);
|
||||
}
|
||||
|
||||
//Block linker
|
||||
@ -369,6 +370,7 @@ namespace Jit64
|
||||
|
||||
void ClearCache()
|
||||
{
|
||||
Core::DisplayMessage("Cleared code cache.", 3000);
|
||||
// Is destroying the blocks really necessary?
|
||||
for (int i = 0; i < numBlocks; i++) {
|
||||
DestroyBlock(i, false);
|
||||
|
@ -556,6 +556,16 @@ namespace Jit64
|
||||
int s = inst.RS;
|
||||
if (gpr.R(a).IsImm() || gpr.R(s).IsImm())
|
||||
{
|
||||
if (gpr.R(s).IsImm())
|
||||
{
|
||||
if (gpr.R(s).offset == 0 && !inst.Rc) {
|
||||
// This is pretty common for some reason
|
||||
gpr.LoadToX64(a, false);
|
||||
XOR(32, gpr.R(a), gpr.R(a));
|
||||
return;
|
||||
}
|
||||
// This might also be worth doing.
|
||||
}
|
||||
Default(inst);
|
||||
return;
|
||||
}
|
||||
|
@ -35,6 +35,7 @@
|
||||
#include "JitCache.h"
|
||||
#include "JitAsm.h"
|
||||
#include "JitRegCache.h"
|
||||
#include "Jit_Util.h"
|
||||
|
||||
// #define INSTRUCTION_START Default(inst); return;
|
||||
#define INSTRUCTION_START
|
||||
@ -47,77 +48,10 @@
|
||||
|
||||
namespace Jit64
|
||||
{
|
||||
static u64 GC_ALIGNED16(temp64);
|
||||
static u32 GC_ALIGNED16(temp32);
|
||||
|
||||
void 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, EAX);
|
||||
namespace {
|
||||
u64 GC_ALIGNED16(temp64);
|
||||
u32 GC_ALIGNED16(temp32);
|
||||
}
|
||||
else if (accessSize == 16)
|
||||
{
|
||||
BSWAP(32, EAX);
|
||||
SHR(32, R(EAX), Imm8(16));
|
||||
}
|
||||
if (signExtend && accessSize < 32) {
|
||||
MOVSX(32, accessSize, EAX, R(EAX));
|
||||
}
|
||||
}
|
||||
|
||||
void 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_NZ);
|
||||
UnsafeLoadRegToReg(reg, EAX, accessSize, 0, signExtend);
|
||||
FixupBranch arg2 = J();
|
||||
SetJumpTarget(argh);
|
||||
switch (accessSize)
|
||||
{
|
||||
case 32: ABI_CallFunctionR(ProtectFunction((void *)&Memory::Read_U32, 1), reg); break;
|
||||
case 16: ABI_CallFunctionR(ProtectFunction((void *)&Memory::Read_U16, 1), reg); break;
|
||||
case 8: ABI_CallFunctionR(ProtectFunction((void *)&Memory::Read_U8, 1), reg); break;
|
||||
}
|
||||
SetJumpTarget(arg2);
|
||||
}
|
||||
|
||||
void UnsafeWriteRegToReg(X64Reg reg_value, X64Reg reg_addr, int accessSize, s32 offset)
|
||||
{
|
||||
if (accessSize != 32) {
|
||||
PanicAlert("UnsafeWriteRegToReg can't handle %i byte accesses", accessSize);
|
||||
}
|
||||
BSWAP(32, 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 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 unsafe_addr = J_CC(CC_NZ);
|
||||
UnsafeWriteRegToReg(reg_value, reg_addr, accessSize, 0);
|
||||
FixupBranch skip_call = J();
|
||||
SetJumpTarget(unsafe_addr);
|
||||
ABI_CallFunctionRR(ProtectFunction((void *)&Memory::Write_U32, 2), ABI_PARAM1, ABI_PARAM2);
|
||||
SetJumpTarget(skip_call);
|
||||
}
|
||||
|
||||
void lbzx(UGeckoInstruction inst)
|
||||
{
|
||||
INSTRUCTION_START;
|
||||
@ -272,73 +206,58 @@ namespace Jit64
|
||||
case 38: accessSize = 8; break; //stb
|
||||
default: _assert_msg_(DYNA_REC, 0, "AWETKLJASDLKF"); return;
|
||||
}
|
||||
/*
|
||||
|
||||
if (gpr.R(a).IsImm() && !update)
|
||||
{
|
||||
u32 addr = (u32)gpr.R(a).offset;
|
||||
addr += offset;
|
||||
//YAY!
|
||||
//Now do something smart
|
||||
if ((addr & 0xFFFFF000) == 0xCC008000)
|
||||
if ((addr & 0xFFFFF000) == 0xCC008000 && jo.optimizeGatherPipe)
|
||||
{
|
||||
//MessageBox(0,"FIFO",0,0);
|
||||
//Do a direct I/O write
|
||||
#ifdef _M_X64
|
||||
MOV(32, R(EDX), Imm32((u32)gpr.R(a).offset));
|
||||
MOV(32, R(ECX), gpr.R(s));
|
||||
#elif _M_IX86
|
||||
PUSH(32, Imm32((u32)gpr.R(a).offset));
|
||||
PUSH(32, gpr.R(s));
|
||||
#endif
|
||||
gpr.FlushLockX(ABI_PARAM1);
|
||||
MOV(32, R(ABI_PARAM1), gpr.R(s));
|
||||
// INT3();
|
||||
switch (accessSize)
|
||||
{
|
||||
case 8: CALL((void *)&GPFifo::FastWrite8); break;
|
||||
case 16: CALL((void *)&GPFifo::FastWrite16); break;
|
||||
case 32: CALL((void *)&GPFifo::FastWrite32); break;
|
||||
// No need to protect these, they don't touch any state
|
||||
case 8: CALL((void *)Asm::fifoDirectWrite8); break;
|
||||
case 16: CALL((void *)Asm::fifoDirectWrite16); break;
|
||||
case 32: CALL((void *)Asm::fifoDirectWrite32); break;
|
||||
}
|
||||
js.fifoBytesThisBlock += accessSize >> 3;
|
||||
if (js.fifoBytesThisBlock > 32)
|
||||
{
|
||||
js.fifoBytesThisBlock -= 32;
|
||||
CALL((void *)&GPFifo::CheckGatherPipe);
|
||||
}
|
||||
#ifdef _M_IX86
|
||||
ADD(32, R(ESP), Imm8(8));
|
||||
#endif
|
||||
gpr.UnlockAllX();
|
||||
return;
|
||||
}
|
||||
else if ((addr>>24) == 0xCC && accessSize == 32) //Other I/O
|
||||
else if (Memory::IsRAMAddress(addr) && accessSize == 32)
|
||||
{
|
||||
#ifdef _M_X64
|
||||
MOV(32, R(EDX), Imm32((u32)gpr.R(a).offset));
|
||||
MOV(32, R(ECX), gpr.R(s));
|
||||
#elif _M_IX86
|
||||
PUSH(32, Imm32((u32)gpr.R(a).offset));
|
||||
PUSH(32, gpr.R(s));
|
||||
#endif
|
||||
CALL((void *)Memory::GetHWWriteFun32(addr));
|
||||
#ifdef _M_IX86
|
||||
ADD(32, R(ESP), Imm8(8));
|
||||
#endif
|
||||
MOV(accessSize, R(EAX), gpr.R(s));
|
||||
BSWAP(accessSize, EAX);
|
||||
WriteToConstRamAddress(accessSize, R(EAX), addr);
|
||||
return;
|
||||
// PanicAlert("yum yum");
|
||||
// This may be quite beneficial.
|
||||
}
|
||||
// Other IO not worth the trouble.
|
||||
}
|
||||
|
||||
// Optimized stack access?
|
||||
if (accessSize == 32 && !gpr.R(a).IsImm() && a == 1 && js.st.isFirstBlockOfFunction && jo.optimizeStack) //Zelda does not like this
|
||||
{
|
||||
//Stack access
|
||||
MOV(32, R(ECX), gpr.R(a));
|
||||
gpr.FlushLockX(ABI_PARAM1);
|
||||
MOV(32, R(ABI_PARAM1), gpr.R(a));
|
||||
MOV(32, R(EAX), gpr.R(s));
|
||||
BSWAP(32, EAX);
|
||||
#ifdef _M_X64
|
||||
MOV(accessSize, MComplex(RBX, ECX, SCALE_1, (u32)offset), R(EAX));
|
||||
MOV(accessSize, MComplex(RBX, ABI_PARAM1, SCALE_1, (u32)offset), R(EAX));
|
||||
#elif _M_IX86
|
||||
AND(32, R(ECX), Imm32(Memory::MEMVIEW32_MASK));
|
||||
MOV(accessSize, MDisp(ECX, (u32)Memory::base + (u32)offset), R(EAX));
|
||||
MOV(accessSize, MDisp(ABI_PARAM1, (u32)Memory::base + (u32)offset), R(EAX));
|
||||
#endif
|
||||
if (update)
|
||||
ADD(32, gpr.R(a), Imm32(offset));
|
||||
gpr.UnlockAllX();
|
||||
return;
|
||||
}
|
||||
*/
|
||||
|
||||
//Still here? Do regular path.
|
||||
gpr.Lock(s, a);
|
||||
gpr.FlushLockX(ABI_PARAM1, ABI_PARAM2);
|
||||
@ -394,8 +313,8 @@ namespace Jit64
|
||||
/*
|
||||
/// BUGGY
|
||||
//return _inst.RA ? (m_GPR[_inst.RA] + _inst.SIMM_16) : _inst.SIMM_16;
|
||||
gpr.Flush(FLUSH_ALL);
|
||||
gpr.LockX(ECX, EDX, ESI);
|
||||
gpr.FlushLockX(ECX, EDX);
|
||||
gpr.FlushLockX(ESI);
|
||||
//INT3();
|
||||
MOV(32, R(EAX), Imm32((u32)(s32)inst.SIMM_16));
|
||||
if (inst.RA)
|
||||
|
@ -35,6 +35,7 @@
|
||||
#include "JitCache.h"
|
||||
#include "JitAsm.h"
|
||||
#include "JitRegCache.h"
|
||||
#include "Jit_Util.h"
|
||||
|
||||
// #define INSTRUCTION_START Default(inst); return;
|
||||
#define INSTRUCTION_START
|
||||
@ -55,9 +56,10 @@ const u8 GC_ALIGNED16(bswapShuffle1x8[16]) = {7, 6, 5, 4, 3, 2, 1, 0, 8, 9, 10,
|
||||
const u8 GC_ALIGNED16(bswapShuffle1x8Dupe[16]) = {7, 6, 5, 4, 3, 2, 1, 0, 7, 6, 5, 4, 3, 2, 1, 0};
|
||||
const u8 GC_ALIGNED16(bswapShuffle2x8[16]) = {7, 6, 5, 4, 3, 2, 1, 0, 15, 14, 13, 12, 11, 10, 9, 8};
|
||||
|
||||
static u64 GC_ALIGNED16(temp64);
|
||||
static u32 GC_ALIGNED16(temp32);
|
||||
|
||||
namespace {
|
||||
u64 GC_ALIGNED16(temp64);
|
||||
u32 GC_ALIGNED16(temp32);
|
||||
}
|
||||
// TODO: Add peephole optimizations for multiple consecutive lfd/lfs/stfd/stfs since they are so common,
|
||||
// and pshufb could help a lot.
|
||||
// Also add hacks for things like lfs/stfs the same reg consecutively, that is, simple memory moves.
|
||||
@ -178,8 +180,34 @@ void stfs(UGeckoInstruction inst)
|
||||
int s = inst.RS;
|
||||
int a = inst.RA;
|
||||
s32 offset = (s32)(s16)inst.SIMM_16;
|
||||
if (a && !update)
|
||||
if (!a || update) {
|
||||
Default(inst);
|
||||
return;
|
||||
}
|
||||
|
||||
if (gpr.R(a).IsImm())
|
||||
{
|
||||
u32 addr = gpr.R(a).offset + offset;
|
||||
if (Memory::IsRAMAddress(addr))
|
||||
{
|
||||
if (cpu_info.bSSSE3) {
|
||||
CVTSD2SS(XMM0, fpr.R(s));
|
||||
PSHUFB(XMM0, M((void *)bswapShuffle1x4));
|
||||
WriteFloatToConstRamAddress(XMM0, addr);
|
||||
return;
|
||||
}
|
||||
}
|
||||
else if (addr == 0xCC008000)
|
||||
{
|
||||
// Float directly to write gather pipe! Fun!
|
||||
CVTSD2SS(XMM0, fpr.R(s));
|
||||
CALL((void*)Asm::fifoDirectWriteFloat);
|
||||
// TODO
|
||||
js.fifoBytesThisBlock += 4;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
gpr.FlushLockX(ABI_PARAM1, ABI_PARAM2);
|
||||
gpr.Lock(a);
|
||||
fpr.Lock(s);
|
||||
@ -197,11 +225,6 @@ void stfs(UGeckoInstruction inst)
|
||||
gpr.UnlockAllX();
|
||||
fpr.UnlockAll();
|
||||
}
|
||||
else
|
||||
{
|
||||
Default(inst);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void lfsx(UGeckoInstruction inst)
|
||||
|
@ -108,21 +108,67 @@ void psq_st(UGeckoInstruction inst)
|
||||
Default(inst);
|
||||
return;
|
||||
}
|
||||
if (!inst.RA)
|
||||
{
|
||||
// This really should never happen. Unless we change this to also support stwux
|
||||
Default(inst);
|
||||
return;
|
||||
}
|
||||
const UGQR gqr(rSPR(SPR_GQR0 + inst.I));
|
||||
const EQuantizeType stType = static_cast<EQuantizeType>(gqr.ST_TYPE);
|
||||
int stScale = gqr.ST_SCALE;
|
||||
bool update = inst.OPCD == 61;
|
||||
if (!inst.RA || inst.W)
|
||||
{
|
||||
// PanicAlert(inst.RA ? "W" : "inst");
|
||||
Default(inst);
|
||||
return;
|
||||
}
|
||||
|
||||
int offset = inst.SIMM_12;
|
||||
int a = inst.RA;
|
||||
int s = inst.RS; // Fp numbers
|
||||
|
||||
if (inst.W) {
|
||||
// PanicAlert("W=1: stType %i stScale %i update %i", (int)stType, (int)stScale, (int)update);
|
||||
// It's fairly common that games write stuff to the pipe using this. Then, it's pretty much only
|
||||
// floats so that's what we'll work on.
|
||||
switch (stType)
|
||||
{
|
||||
case QUANTIZE_FLOAT:
|
||||
{
|
||||
if (gpr.R(a).IsImm())
|
||||
{
|
||||
PanicAlert("Imm: %08x", gpr.R(a).offset);
|
||||
}
|
||||
DISABLE_32BIT;
|
||||
gpr.FlushLockX(ABI_PARAM1, ABI_PARAM2);
|
||||
gpr.Lock(a);
|
||||
fpr.Lock(s);
|
||||
if (update)
|
||||
gpr.LoadToX64(a, true, true);
|
||||
MOV(32, R(ABI_PARAM2), gpr.R(a));
|
||||
if (offset)
|
||||
ADD(32, R(ABI_PARAM2), Imm32((u32)offset));
|
||||
TEST(32, R(ABI_PARAM2), Imm32(0x0C000000));
|
||||
if (update && offset)
|
||||
MOV(32, gpr.R(a), R(ABI_PARAM2));
|
||||
CVTSD2SS(XMM0, fpr.R(s));
|
||||
MOVD_xmm(M(&temp64), XMM0);
|
||||
MOV(32, R(ABI_PARAM1), M(&temp64));
|
||||
FixupBranch argh = J_CC(CC_NZ);
|
||||
BSWAP(32, ABI_PARAM1);
|
||||
MOV(32, MComplex(RBX, ABI_PARAM2, SCALE_1, 0), R(ABI_PARAM1));
|
||||
FixupBranch skip_call = J();
|
||||
SetJumpTarget(argh);
|
||||
CALL(ProtectFunction((void *)&Memory::Write_U32, 2));
|
||||
SetJumpTarget(skip_call);
|
||||
gpr.UnlockAll();
|
||||
gpr.UnlockAllX();
|
||||
fpr.UnlockAll();
|
||||
return;
|
||||
}
|
||||
default:
|
||||
Default(inst);
|
||||
return;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (stType == QUANTIZE_FLOAT)
|
||||
{
|
||||
DISABLE_32BIT;
|
||||
|
@ -43,9 +43,9 @@
|
||||
|
||||
namespace Jit64
|
||||
{
|
||||
static const u64 GC_ALIGNED16(psSignBits[2]) = {0x8000000000000000ULL, 0x8000000000000000ULL};
|
||||
static const u64 GC_ALIGNED16(psAbsMask[2]) = {0x7FFFFFFFFFFFFFFFULL, 0x7FFFFFFFFFFFFFFFULL};
|
||||
static const double GC_ALIGNED16(psOneOne[2]) = {1.0, 1.0};
|
||||
const u64 GC_ALIGNED16(psSignBits[2]) = {0x8000000000000000ULL, 0x8000000000000000ULL};
|
||||
const u64 GC_ALIGNED16(psAbsMask[2]) = {0x7FFFFFFFFFFFFFFFULL, 0x7FFFFFFFFFFFFFFFULL};
|
||||
const double GC_ALIGNED16(psOneOne[2]) = {1.0, 1.0};
|
||||
|
||||
void ps_sign(UGeckoInstruction inst)
|
||||
{
|
||||
|
127
Source/Core/Core/Src/PowerPC/Jit64/Jit_Util.cpp
Normal file
127
Source/Core/Core/Src/PowerPC/Jit64/Jit_Util.cpp
Normal file
@ -0,0 +1,127 @@
|
||||
// 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"
|
||||
|
||||
|
||||
namespace Jit64
|
||||
{
|
||||
|
||||
void 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, EAX);
|
||||
}
|
||||
else if (accessSize == 16)
|
||||
{
|
||||
BSWAP(32, EAX);
|
||||
SHR(32, R(EAX), Imm8(16));
|
||||
}
|
||||
if (signExtend && accessSize < 32) {
|
||||
MOVSX(32, accessSize, EAX, R(EAX));
|
||||
}
|
||||
}
|
||||
|
||||
void 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_NZ);
|
||||
UnsafeLoadRegToReg(reg, EAX, accessSize, 0, signExtend);
|
||||
FixupBranch arg2 = J();
|
||||
SetJumpTarget(argh);
|
||||
switch (accessSize)
|
||||
{
|
||||
case 32: ABI_CallFunctionR(ProtectFunction((void *)&Memory::Read_U32, 1), reg); break;
|
||||
case 16: ABI_CallFunctionR(ProtectFunction((void *)&Memory::Read_U16, 1), reg); break;
|
||||
case 8: ABI_CallFunctionR(ProtectFunction((void *)&Memory::Read_U8, 1), reg); break;
|
||||
}
|
||||
SetJumpTarget(arg2);
|
||||
}
|
||||
|
||||
void UnsafeWriteRegToReg(X64Reg reg_value, X64Reg reg_addr, int accessSize, s32 offset)
|
||||
{
|
||||
if (accessSize != 32) {
|
||||
PanicAlert("UnsafeWriteRegToReg can't handle %i byte accesses", accessSize);
|
||||
}
|
||||
BSWAP(32, 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 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 unsafe_addr = J_CC(CC_NZ);
|
||||
UnsafeWriteRegToReg(reg_value, reg_addr, accessSize, 0);
|
||||
FixupBranch skip_call = J();
|
||||
SetJumpTarget(unsafe_addr);
|
||||
ABI_CallFunctionRR(ProtectFunction((void *)&Memory::Write_U32, 2), ABI_PARAM1, ABI_PARAM2);
|
||||
SetJumpTarget(skip_call);
|
||||
}
|
||||
|
||||
void 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 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
|
||||
}
|
||||
|
||||
} // namespace
|
33
Source/Core/Core/Src/PowerPC/Jit64/Jit_Util.h
Normal file
33
Source/Core/Core/Src/PowerPC/Jit64/Jit_Util.h
Normal file
@ -0,0 +1,33 @@
|
||||
// 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 "x64Emitter.h"
|
||||
|
||||
namespace Jit64
|
||||
{
|
||||
|
||||
// Memory Load/Store
|
||||
void UnsafeLoadRegToReg(Gen::X64Reg reg_addr, Gen::X64Reg reg_value, int accessSize, s32 offset = 0, bool signExtend = false);
|
||||
void UnsafeWriteRegToReg(Gen::X64Reg reg_value, Gen::X64Reg reg_addr, int accessSize, s32 offset = 0);
|
||||
void SafeLoadRegToEAX(Gen::X64Reg reg, int accessSize, s32 offset, bool signExtend = false);
|
||||
void SafeWriteRegToReg(Gen::X64Reg reg_value, Gen::X64Reg reg_addr, int accessSize, s32 offset);
|
||||
|
||||
void WriteToConstRamAddress(int accessSize, const Gen::OpArg& arg, u32 address);
|
||||
void WriteFloatToConstRamAddress(const Gen::X64Reg& xmm_reg, u32 address);
|
||||
|
||||
} // namespace
|
@ -76,6 +76,7 @@ files = ["Console.cpp",
|
||||
"PowerPC/Jit64/Jit_LoadStore.cpp",
|
||||
"PowerPC/Jit64/Jit_LoadStoreFloating.cpp",
|
||||
"PowerPC/Jit64/Jit_SystemRegisters.cpp",
|
||||
"PowerPC/Jit64/Jit_Util.cpp",
|
||||
"HLE/HLE.cpp",
|
||||
"HLE/HLE_Misc.cpp",
|
||||
"HLE/HLE_OS.cpp",
|
||||
|
@ -40,6 +40,8 @@
|
||||
#include "Debugger/PPCDebugInterface.h"
|
||||
#include "Debugger/Debugger_SymbolMap.h"
|
||||
#include "PowerPC/PPCAnalyst.h"
|
||||
#include "PowerPC/Jit64/Jit.h"
|
||||
#include "PowerPC/Jit64/JitCache.h"
|
||||
|
||||
#include "Core.h"
|
||||
#include "LogManager.h"
|
||||
@ -235,6 +237,13 @@ void CCodeWindow::CreateMenu(const SCoreStartupParameter& _LocalCoreStartupParam
|
||||
pSymbolsMenu->Append(IDM_SCANFUNCTIONS, _T("&Scan for functions"));
|
||||
pMenuBar->Append(pSymbolsMenu, _T("&Symbols"));
|
||||
}
|
||||
|
||||
{
|
||||
wxMenu *pJitMenu = new wxMenu;
|
||||
pJitMenu->Append(IDM_CLEARCODECACHE, _T("&Clear code cache"));
|
||||
pMenuBar->Append(pJitMenu, _T("&JIT"));
|
||||
}
|
||||
|
||||
SetMenuBar(pMenuBar);
|
||||
}
|
||||
|
||||
@ -256,6 +265,16 @@ void CCodeWindow::JumpToAddress(u32 _Address)
|
||||
codeview->Center(_Address);
|
||||
}
|
||||
|
||||
void CCodeWindow::OnJitMenu(wxCommandEvent& event)
|
||||
{
|
||||
switch (event.GetId())
|
||||
{
|
||||
case IDM_CLEARCODECACHE:
|
||||
Jit64::ClearCache();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void CCodeWindow::OnSymbolsMenu(wxCommandEvent& event)
|
||||
{
|
||||
if (Core::GetState() == Core::CORE_UNINITIALIZED)
|
||||
|
@ -81,6 +81,7 @@ class CCodeWindow
|
||||
IDM_SCANFUNCTIONS,
|
||||
IDM_LOADMAPFILE,
|
||||
IDM_SAVEMAPFILE,
|
||||
IDM_CLEARCODECACHE,
|
||||
};
|
||||
|
||||
enum
|
||||
@ -125,6 +126,7 @@ class CCodeWindow
|
||||
void OnToggleMemoryWindow(wxCommandEvent& event);
|
||||
void OnHostMessage(wxCommandEvent& event);
|
||||
void OnSymbolsMenu(wxCommandEvent& event);
|
||||
void OnJitMenu(wxCommandEvent& event);
|
||||
|
||||
void CreateMenu(const SCoreStartupParameter& _LocalCoreStartupParameter);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user