mirror of
https://github.com/izzy2lost/dolphin.git
synced 2026-06-19 01:16:48 -07:00
add ppc disassembly to jit results viewer windowTurn the JIT into a class. Indentation cleanup will be in a separate CL, and the block cache will later be split out into its own class. Cannot detect any speed difference whatsoever - the games spend 99.9% of their time in already jitted code anyway. I have a good reason for doing this - see upcoming changes.
git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@1585 8ced0084-cf51-0410-be5f-012b33b47a6e
This commit is contained in:
@@ -990,10 +990,6 @@
|
||||
RelativePath=".\Src\PowerPC\Jit64\Jit_Util.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Src\PowerPC\Jit64\Jit_Util.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Src\PowerPC\Jit64\JitAsm.cpp"
|
||||
>
|
||||
@@ -1006,10 +1002,6 @@
|
||||
RelativePath=".\Src\PowerPC\Jit64\JitBackpatch.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Src\PowerPC\Jit64\JitBackpatch.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Src\PowerPC\Jit64\JitCache.cpp"
|
||||
>
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
#include "PowerPC/PPCTables.h"
|
||||
#include "CoreTiming.h"
|
||||
#include "Core.h"
|
||||
#include "PowerPC/Jit64/JitCache.h"
|
||||
#include "PowerPC/Jit64/Jit.h"
|
||||
#include "PowerPC/SymbolDB.h"
|
||||
#include "PowerPCDisasm.h"
|
||||
#include "Console.h"
|
||||
@@ -38,7 +38,7 @@ void Console_Submit(const char *cmd)
|
||||
CASE1("jits")
|
||||
{
|
||||
#ifdef _M_X64
|
||||
Jit64::PrintStats();
|
||||
jit.PrintStats();
|
||||
#endif
|
||||
}
|
||||
CASE1("r")
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
#include "Memmap.h"
|
||||
#include "../Core.h"
|
||||
#include "../PowerPC/PowerPC.h"
|
||||
#include "../PowerPC/Jit64/Jit.h"
|
||||
#include "../PowerPC/Jit64/JitCache.h"
|
||||
#include "CPU.h"
|
||||
#include "PeripheralInterface.h"
|
||||
@@ -758,7 +759,7 @@ bool AreMemoryBreakpointsActivated()
|
||||
|
||||
u32 Read_Instruction(const u32 _Address)
|
||||
{
|
||||
return Jit64::GetOriginalCode(_Address);
|
||||
return jit.GetOriginalCode(_Address);
|
||||
}
|
||||
|
||||
u32 Read_Opcode(const u32 _Address)
|
||||
|
||||
@@ -47,7 +47,6 @@
|
||||
#include "HW/Memmap.h"
|
||||
#include "PowerPC/PowerPC.h"
|
||||
#include "PowerPC/Jit64/Jit.h"
|
||||
#include "PowerPC/Jit64/JitBackpatch.h"
|
||||
#include "x64Analyzer.h"
|
||||
|
||||
namespace EMM
|
||||
@@ -76,7 +75,7 @@ LONG NTAPI Handler(PEXCEPTION_POINTERS pPtrs)
|
||||
PVOID codeAddr = pPtrs->ExceptionRecord->ExceptionAddress;
|
||||
unsigned char *codePtr = (unsigned char*)codeAddr;
|
||||
|
||||
if (!Jit64::IsInJitCode(codePtr)) {
|
||||
if (!jit.IsInJitCode(codePtr)) {
|
||||
// Let's not prevent debugging.
|
||||
return (DWORD)EXCEPTION_CONTINUE_SEARCH;
|
||||
}
|
||||
@@ -105,7 +104,7 @@ LONG NTAPI Handler(PEXCEPTION_POINTERS pPtrs)
|
||||
|
||||
//We could emulate the memory accesses here, but then they would still be around to take up
|
||||
//execution resources. Instead, we backpatch into a generic memory call and retry.
|
||||
u8 *new_rip = Jit64::BackPatch(codePtr, accessType, emAddress, ctx);
|
||||
u8 *new_rip = jit.BackPatch(codePtr, accessType, emAddress, ctx);
|
||||
|
||||
// Rip/Eip needs to be updated.
|
||||
if (new_rip)
|
||||
|
||||
@@ -340,7 +340,7 @@ void icbi(UGeckoInstruction _inst)
|
||||
// VERY IMPORTANT when we start linking blocks
|
||||
// There are a TON of these so hopefully we can make this mechanism
|
||||
// fast in the JIT
|
||||
Jit64::InvalidateCodeRange(address, 0x20);
|
||||
jit.InvalidateCodeRange(address, 0x20);
|
||||
}
|
||||
|
||||
void lbzux(UGeckoInstruction _inst)
|
||||
|
||||
@@ -161,20 +161,15 @@ ps_adds1
|
||||
|
||||
*/
|
||||
|
||||
Jit64 jit;
|
||||
PPCAnalyst::CodeBuffer code_buffer(32000);
|
||||
|
||||
namespace CPUCompare
|
||||
{
|
||||
extern u32 m_BlockStart;
|
||||
}
|
||||
|
||||
|
||||
namespace Jit64
|
||||
{
|
||||
JitState js;
|
||||
JitOptions jo;
|
||||
PPCAnalyst::CodeBuffer code_buffer(32000);
|
||||
|
||||
void Init()
|
||||
void Jit64::Init()
|
||||
{
|
||||
jo.optimizeStack = true;
|
||||
jo.enableBlocklink = true; // Speed boost, but not 100% safe
|
||||
@@ -189,7 +184,7 @@ namespace Jit64
|
||||
jo.fastInterrupts = false;
|
||||
}
|
||||
|
||||
void WriteCallInterpreter(UGeckoInstruction _inst)
|
||||
void Jit64::WriteCallInterpreter(UGeckoInstruction _inst)
|
||||
{
|
||||
gpr.Flush(FLUSH_ALL);
|
||||
fpr.Flush(FLUSH_ALL);
|
||||
@@ -202,12 +197,12 @@ namespace Jit64
|
||||
ABI_CallFunctionC((void*)instr, _inst.hex);
|
||||
}
|
||||
|
||||
void Default(UGeckoInstruction _inst)
|
||||
void Jit64::Default(UGeckoInstruction _inst)
|
||||
{
|
||||
WriteCallInterpreter(_inst.hex);
|
||||
}
|
||||
|
||||
void HLEFunction(UGeckoInstruction _inst)
|
||||
void Jit64::HLEFunction(UGeckoInstruction _inst)
|
||||
{
|
||||
gpr.Flush(FLUSH_ALL);
|
||||
fpr.Flush(FLUSH_ALL);
|
||||
@@ -216,7 +211,7 @@ namespace Jit64
|
||||
WriteExitDestInEAX(0);
|
||||
}
|
||||
|
||||
void DoNothing(UGeckoInstruction _inst)
|
||||
void Jit64::DoNothing(UGeckoInstruction _inst)
|
||||
{
|
||||
// Yup, just don't do anything.
|
||||
}
|
||||
@@ -249,13 +244,13 @@ namespace Jit64
|
||||
been_here[PC] = 1;
|
||||
}
|
||||
|
||||
void Cleanup()
|
||||
void Jit64::Cleanup()
|
||||
{
|
||||
if (jo.optimizeGatherPipe && js.fifoBytesThisBlock > 0)
|
||||
CALL((void *)&GPFifo::CheckGatherPipe);
|
||||
}
|
||||
|
||||
void WriteExit(u32 destination, int exit_num)
|
||||
void Jit64::WriteExit(u32 destination, int exit_num)
|
||||
{
|
||||
Cleanup();
|
||||
SUB(32, M(&CoreTiming::downcount), js.downcountAmount > 127 ? Imm32(js.downcountAmount) : Imm8(js.downcountAmount));
|
||||
@@ -280,7 +275,7 @@ namespace Jit64
|
||||
}
|
||||
}
|
||||
|
||||
void WriteExitDestInEAX(int exit_num)
|
||||
void Jit64::WriteExitDestInEAX(int exit_num)
|
||||
{
|
||||
MOV(32, M(&PC), R(EAX));
|
||||
Cleanup();
|
||||
@@ -288,7 +283,7 @@ namespace Jit64
|
||||
JMP(Asm::dispatcher, true);
|
||||
}
|
||||
|
||||
void WriteRfiExitDestInEAX()
|
||||
void Jit64::WriteRfiExitDestInEAX()
|
||||
{
|
||||
MOV(32, M(&PC), R(EAX));
|
||||
Cleanup();
|
||||
@@ -296,7 +291,7 @@ namespace Jit64
|
||||
JMP(Asm::testExceptions, true);
|
||||
}
|
||||
|
||||
void WriteExceptionExit(u32 exception)
|
||||
void Jit64::WriteExceptionExit(u32 exception)
|
||||
{
|
||||
Cleanup();
|
||||
OR(32, M(&PowerPC::ppcState.Exceptions), Imm32(exception));
|
||||
@@ -304,7 +299,7 @@ namespace Jit64
|
||||
JMP(Asm::testExceptions, true);
|
||||
}
|
||||
|
||||
const u8* DoJit(u32 emaddress, JitBlock &b)
|
||||
const u8* Jit64::DoJit(u32 emaddress, JitBlock &b)
|
||||
{
|
||||
if (emaddress == 0)
|
||||
PanicAlert("ERROR : Trying to compile at 0. LR=%08x", LR);
|
||||
@@ -424,4 +419,3 @@ namespace Jit64
|
||||
b.originalSize = size;
|
||||
return normalEntry;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,20 +26,71 @@
|
||||
#include "JitCache.h"
|
||||
#include "x64Emitter.h"
|
||||
|
||||
namespace Jit64
|
||||
#ifdef _WIN32
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
#else
|
||||
|
||||
// A bit of a hack to get things building under linux. We manually fill in this structure as needed
|
||||
// from the real context.
|
||||
struct CONTEXT
|
||||
{
|
||||
struct JitStats
|
||||
#ifdef _M_X64
|
||||
u64 Rip;
|
||||
u64 Rax;
|
||||
#else
|
||||
u32 Eip;
|
||||
u32 Eax;
|
||||
#endif
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
class Jit64
|
||||
{
|
||||
public:
|
||||
typedef void (*CompiledCode)();
|
||||
|
||||
void unknown_instruction(UGeckoInstruction _inst);
|
||||
|
||||
//Code pointers are stored separately, they will be accessed much more frequently
|
||||
|
||||
enum BlockFlag
|
||||
{
|
||||
u32 compiledBlocks;
|
||||
float averageCodeExpansion;
|
||||
float ratioOpsCompiled; //how many really were compiled, how many became "call interpreter"?
|
||||
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,
|
||||
};
|
||||
|
||||
#define JIT_OPCODE 0
|
||||
// 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];
|
||||
|
||||
struct JitBlock;
|
||||
const u8* DoJit(u32 emaddress, JitBlock &b);
|
||||
bool IsInJitCode(const u8 *codePtr);
|
||||
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;
|
||||
};
|
||||
|
||||
struct JitState
|
||||
{
|
||||
@@ -77,21 +128,84 @@ namespace Jit64
|
||||
bool fastInterrupts;
|
||||
};
|
||||
|
||||
extern JitState js;
|
||||
extern JitOptions jo;
|
||||
JitState js;
|
||||
JitOptions jo;
|
||||
|
||||
void PrintStats();
|
||||
void EnterFastRun();
|
||||
|
||||
// Code Cache
|
||||
|
||||
u32 GetOriginalCode(u32 address);
|
||||
JitBlock *GetBlock(int no);
|
||||
void InvalidateCodeRange(u32 address, u32 length);
|
||||
int GetBlockNumberFromAddress(u32 address);
|
||||
CompiledCode GetCompiledCode(u32 address);
|
||||
CompiledCode GetCompiledCodeFromBlock(int blockNumber);
|
||||
int GetCodeSize();
|
||||
int GetNumBlocks();
|
||||
u8 **GetCodePointers();
|
||||
void DestroyBlocksWithFlag(BlockFlag death_flag);
|
||||
void LinkBlocks();
|
||||
void LinkBlockExits(int i);
|
||||
void LinkBlock(int i);
|
||||
void ClearCache();
|
||||
void InitCache();
|
||||
void ShutdownCache();
|
||||
void ResetCache();
|
||||
void DestroyBlock(int blocknum, bool invalidate);
|
||||
bool RangeIntersect(int s1, int e1, int s2, int e2) const;
|
||||
bool IsInJitCode(const u8 *codePtr);
|
||||
|
||||
u8 *BackPatch(u8 *codePtr, int accessType, u32 emAddress, CONTEXT *ctx);
|
||||
|
||||
#define JIT_OPCODE 0
|
||||
|
||||
const u8* Jit(u32 emaddress);
|
||||
const u8* DoJit(u32 emaddress, JitBlock &b);
|
||||
|
||||
void Init();
|
||||
|
||||
void Default(UGeckoInstruction _inst);
|
||||
void DoNothing(UGeckoInstruction _inst);
|
||||
|
||||
// Utilities for use by opcodes
|
||||
|
||||
void WriteExit(u32 destination, int exit_num);
|
||||
void WriteExitDestInEAX(int exit_num);
|
||||
void WriteExceptionExit(u32 exception);
|
||||
void WriteRfiExitDestInEAX();
|
||||
void WriteCallInterpreter(UGeckoInstruction _inst);
|
||||
void Cleanup();
|
||||
|
||||
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);
|
||||
void GenerateCarry(Gen::X64Reg temp_reg);
|
||||
|
||||
void ForceSinglePrecisionS(Gen::X64Reg xmm);
|
||||
void ForceSinglePrecisionP(Gen::X64Reg xmm);
|
||||
void JitClearCA();
|
||||
void JitSetCA();
|
||||
void tri_op(int d, int a, int b, bool reversible, void (*op)(Gen::X64Reg, Gen::OpArg));
|
||||
typedef u32 (*Operation)(u32 a, u32 b);
|
||||
void regimmop(int d, int a, bool binary, u32 value, Operation doop, void(*op)(int, const Gen::OpArg&, const Gen::OpArg&), bool Rc = false, bool carry = false);
|
||||
void fp_tri_op(int d, int a, int b, bool reversible, bool dupe, void (*op)(Gen::X64Reg, Gen::OpArg));
|
||||
|
||||
|
||||
// OPCODES
|
||||
|
||||
void Default(UGeckoInstruction _inst);
|
||||
void DoNothing(UGeckoInstruction _inst);
|
||||
void HLEFunction(UGeckoInstruction _inst);
|
||||
|
||||
void DynaRunTable4(UGeckoInstruction _inst);
|
||||
void DynaRunTable19(UGeckoInstruction _inst);
|
||||
void DynaRunTable31(UGeckoInstruction _inst);
|
||||
void DynaRunTable59(UGeckoInstruction _inst);
|
||||
void DynaRunTable63(UGeckoInstruction _inst);
|
||||
|
||||
void addx(UGeckoInstruction inst);
|
||||
void orx(UGeckoInstruction inst);
|
||||
void xorx(UGeckoInstruction inst);
|
||||
@@ -176,7 +290,11 @@ namespace Jit64
|
||||
|
||||
void lmw(UGeckoInstruction inst);
|
||||
void stmw(UGeckoInstruction inst);
|
||||
}
|
||||
};
|
||||
|
||||
extern Jit64 jit;
|
||||
|
||||
const u8 *Jit(u32 emaddress);
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@@ -35,9 +35,6 @@
|
||||
using namespace Gen;
|
||||
int blocksExecuted;
|
||||
|
||||
namespace Jit64
|
||||
{
|
||||
|
||||
namespace Asm
|
||||
{
|
||||
const u8 *enterCode;
|
||||
@@ -133,7 +130,7 @@ void Generate()
|
||||
}
|
||||
//grab from list and jump to it
|
||||
//INT3();
|
||||
MOV(32, R(EDX), ImmPtr(GetCodePointers()));
|
||||
MOV(32, R(EDX), ImmPtr(jit.GetCodePointers()));
|
||||
JMPptr(MComplex(EDX, EAX, 4, 0));
|
||||
SetJumpTarget(notfound);
|
||||
|
||||
@@ -190,7 +187,7 @@ void Generate()
|
||||
ABI_PushAllCalleeSavedRegsAndAdjustStack();
|
||||
|
||||
MOV(64, R(RBX), Imm64((u64)Memory::base));
|
||||
MOV(64, R(R15), Imm64((u64)GetCodePointers())); //It's below 2GB so 32 bits are good enough
|
||||
MOV(64, R(R15), Imm64((u64)jit.GetCodePointers())); //It's below 2GB so 32 bits are good enough
|
||||
const u8 *outerLoop = GetCodePtr();
|
||||
|
||||
CALL((void *)&CoreTiming::Advance);
|
||||
@@ -369,6 +366,3 @@ void GenerateCommon()
|
||||
}
|
||||
|
||||
} // namespace Asm
|
||||
|
||||
} // namespace Jit64
|
||||
|
||||
|
||||
@@ -17,33 +17,29 @@
|
||||
#ifndef _JITASM_H
|
||||
#define _JITASM_H
|
||||
|
||||
|
||||
namespace Jit64
|
||||
namespace Asm
|
||||
{
|
||||
namespace Asm
|
||||
{
|
||||
extern const u8 *enterCode;
|
||||
extern const u8 *enterCode;
|
||||
|
||||
extern const u8 *dispatcher;
|
||||
extern const u8 *dispatcherNoCheck;
|
||||
extern const u8 *dispatcherPcInEAX;
|
||||
extern const u8 *dispatcher;
|
||||
extern const u8 *dispatcherNoCheck;
|
||||
extern const u8 *dispatcherPcInEAX;
|
||||
|
||||
extern const u8 *fpException;
|
||||
extern const u8 *computeRc;
|
||||
extern const u8 *computeRcFp;
|
||||
extern const u8 *testExceptions;
|
||||
extern const u8 *dispatchPcInEAX;
|
||||
extern const u8 *doTiming;
|
||||
extern const u8 *fpException;
|
||||
extern const u8 *computeRc;
|
||||
extern const u8 *computeRcFp;
|
||||
extern const u8 *testExceptions;
|
||||
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 const u8 *fifoDirectWriteXmm64;
|
||||
extern const u8 *fifoDirectWrite8;
|
||||
extern const u8 *fifoDirectWrite16;
|
||||
extern const u8 *fifoDirectWrite32;
|
||||
extern const u8 *fifoDirectWriteFloat;
|
||||
extern const u8 *fifoDirectWriteXmm64;
|
||||
|
||||
extern bool compareEnabled;
|
||||
void Generate();
|
||||
}
|
||||
extern bool compareEnabled;
|
||||
void Generate();
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -20,7 +20,6 @@
|
||||
#include "Common.h"
|
||||
#include "disasm.h"
|
||||
#include "JitAsm.h"
|
||||
#include "JitBackpatch.h"
|
||||
#include "../../HW/Memmap.h"
|
||||
|
||||
#include "x64Emitter.h"
|
||||
@@ -33,8 +32,6 @@
|
||||
|
||||
using namespace Gen;
|
||||
|
||||
namespace Jit64 {
|
||||
|
||||
extern u8 *trampolineCodePtr;
|
||||
|
||||
void BackPatchError(const std::string &text, u8 *codePtr, u32 emAddress) {
|
||||
@@ -58,7 +55,7 @@ void BackPatchError(const std::string &text, u8 *codePtr, u32 emAddress) {
|
||||
// 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.
|
||||
u8 *BackPatch(u8 *codePtr, int accessType, u32 emAddress, CONTEXT *ctx)
|
||||
u8 *Jit64::BackPatch(u8 *codePtr, int accessType, u32 emAddress, CONTEXT *ctx)
|
||||
{
|
||||
#ifdef _M_X64
|
||||
if (!IsInJitCode(codePtr))
|
||||
@@ -194,4 +191,3 @@ u8 *BackPatch(u8 *codePtr, int accessType, u32 emAddress, CONTEXT *ctx)
|
||||
#endif
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
@@ -1,50 +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 _JITBACKPATCH_H
|
||||
#define _JITBACKPATCH_H
|
||||
|
||||
#include "Common.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
#else
|
||||
|
||||
// A bit of a hack to get things building under linux. We manually fill in this structure as needed
|
||||
// from the real context.
|
||||
struct CONTEXT
|
||||
{
|
||||
#ifdef _M_X64
|
||||
u64 Rip;
|
||||
u64 Rax;
|
||||
#else
|
||||
u32 Eip;
|
||||
u32 Eax;
|
||||
#endif
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
namespace Jit64 {
|
||||
// Returns the new RIP value
|
||||
u8 *BackPatch(u8 *codePtr, int accessType, u32 emAddress, CONTEXT *ctx);
|
||||
|
||||
} // namespace
|
||||
|
||||
#endif
|
||||
@@ -52,8 +52,6 @@
|
||||
|
||||
using namespace Gen;
|
||||
|
||||
namespace Jit64
|
||||
{
|
||||
#ifdef OPROFILE_REPORT
|
||||
op_agent_t agent;
|
||||
#endif
|
||||
@@ -62,8 +60,6 @@ namespace Jit64
|
||||
static u8 *trampolineCache;
|
||||
u8 *trampolineCodePtr;
|
||||
#define INVALID_EXIT 0xFFFFFFFF
|
||||
void LinkBlockExits(int i);
|
||||
void LinkBlock(int i);
|
||||
|
||||
enum
|
||||
{
|
||||
@@ -79,12 +75,11 @@ namespace Jit64
|
||||
|
||||
static std::multimap<u32, int> links_to;
|
||||
|
||||
static JitBlock *blocks;
|
||||
static Jit64::JitBlock *blocks;
|
||||
static int numBlocks;
|
||||
|
||||
void DestroyBlock(int blocknum, bool invalidate);
|
||||
|
||||
void PrintStats()
|
||||
void Jit64::PrintStats()
|
||||
{
|
||||
LOG(DYNA_REC, "JIT Statistics =======================");
|
||||
LOG(DYNA_REC, "Number of blocks currently: %i", numBlocks);
|
||||
@@ -92,7 +87,7 @@ namespace Jit64
|
||||
LOG(DYNA_REC, "======================================");
|
||||
}
|
||||
|
||||
void InitCache()
|
||||
void Jit64::InitCache()
|
||||
{
|
||||
if(Core::g_CoreStartupParameter.bJITUnlimitedCache)
|
||||
{
|
||||
@@ -118,7 +113,7 @@ namespace Jit64
|
||||
SetCodePtr(codeCache);
|
||||
}
|
||||
|
||||
void ShutdownCache()
|
||||
void Jit64::ShutdownCache()
|
||||
{
|
||||
UnWriteProtectMemory(genFunctions, GEN_SIZE, true);
|
||||
FreeMemoryPages(codeCache, CODE_SIZE);
|
||||
@@ -136,7 +131,7 @@ namespace Jit64
|
||||
|
||||
// This clears the JIT cache. It's called from JitCache.cpp when the JIT cache
|
||||
// is full and when saving and loading states.
|
||||
void ClearCache()
|
||||
void Jit64::ClearCache()
|
||||
{
|
||||
Core::DisplayMessage("Cleared code cache.", 3000);
|
||||
// Is destroying the blocks really necessary?
|
||||
@@ -151,7 +146,7 @@ namespace Jit64
|
||||
SetCodePtr(codeCache);
|
||||
}
|
||||
|
||||
void DestroyBlocksWithFlag(BlockFlag death_flag)
|
||||
void Jit64::DestroyBlocksWithFlag(BlockFlag death_flag)
|
||||
{
|
||||
for (int i = 0; i < numBlocks; i++) {
|
||||
if (blocks[i].flags & death_flag) {
|
||||
@@ -160,28 +155,23 @@ namespace Jit64
|
||||
}
|
||||
}
|
||||
|
||||
void ResetCache()
|
||||
void Jit64::ResetCache()
|
||||
{
|
||||
ShutdownCache();
|
||||
InitCache();
|
||||
}
|
||||
|
||||
JitBlock *CurBlock()
|
||||
{
|
||||
return &blocks[numBlocks];
|
||||
}
|
||||
|
||||
JitBlock *GetBlock(int no)
|
||||
Jit64::JitBlock *Jit64::GetBlock(int no)
|
||||
{
|
||||
return &blocks[no];
|
||||
}
|
||||
|
||||
int GetNumBlocks()
|
||||
int Jit64::GetNumBlocks()
|
||||
{
|
||||
return numBlocks;
|
||||
}
|
||||
|
||||
bool RangeIntersect(int s1, int e1, int s2, int e2)
|
||||
bool Jit64::RangeIntersect(int s1, int e1, int s2, int e2) const
|
||||
{
|
||||
// check if any endpoint is inside the other range
|
||||
if ( (s1 >= s2 && s1 <= e2) ||
|
||||
@@ -193,7 +183,12 @@ namespace Jit64
|
||||
return false;
|
||||
}
|
||||
|
||||
u8 *Jit(u32 emAddress)
|
||||
const u8 *Jit(u32 emAddress)
|
||||
{
|
||||
return jit.Jit(emAddress);
|
||||
}
|
||||
|
||||
const u8 *Jit64::Jit(u32 emAddress)
|
||||
{
|
||||
if (GetCodePtr() >= codeCache + CODE_SIZE - 0x10000 || numBlocks >= MAX_NUM_BLOCKS - 1)
|
||||
{
|
||||
@@ -244,30 +239,30 @@ namespace Jit64
|
||||
return 0;
|
||||
}
|
||||
|
||||
void unknown_instruction(UGeckoInstruction _inst)
|
||||
void Jit64::unknown_instruction(UGeckoInstruction _inst)
|
||||
{
|
||||
// CCPU::Break();
|
||||
PanicAlert("unknown_instruction Jit64 - Fix me ;)");
|
||||
_dbg_assert_(DYNA_REC, 0);
|
||||
}
|
||||
|
||||
u8 **GetCodePointers()
|
||||
u8 **Jit64::GetCodePointers()
|
||||
{
|
||||
return blockCodePointers;
|
||||
}
|
||||
|
||||
bool IsInJitCode(const u8 *codePtr) {
|
||||
bool Jit64::IsInJitCode(const u8 *codePtr) {
|
||||
return codePtr >= codeCache && codePtr <= GetCodePtr();
|
||||
}
|
||||
|
||||
void EnterFastRun()
|
||||
void Jit64::EnterFastRun()
|
||||
{
|
||||
CompiledCode pExecAddr = (CompiledCode)Asm::enterCode;
|
||||
pExecAddr();
|
||||
//Will return when PowerPC::state changes
|
||||
}
|
||||
|
||||
int GetBlockNumberFromAddress(u32 addr)
|
||||
int Jit64::GetBlockNumberFromAddress(u32 addr)
|
||||
{
|
||||
if (!blocks)
|
||||
return -1;
|
||||
@@ -293,7 +288,7 @@ namespace Jit64
|
||||
}
|
||||
}
|
||||
|
||||
u32 GetOriginalCode(u32 address)
|
||||
u32 Jit64::GetOriginalCode(u32 address)
|
||||
{
|
||||
int num = GetBlockNumberFromAddress(address);
|
||||
if (num == -1)
|
||||
@@ -302,7 +297,7 @@ namespace Jit64
|
||||
return blocks[num].originalFirstOpcode;
|
||||
}
|
||||
|
||||
CompiledCode GetCompiledCode(u32 address)
|
||||
Jit64::CompiledCode Jit64::GetCompiledCode(u32 address)
|
||||
{
|
||||
int num = GetBlockNumberFromAddress(address);
|
||||
if (num == -1)
|
||||
@@ -311,12 +306,12 @@ namespace Jit64
|
||||
return (CompiledCode)blockCodePointers[num];
|
||||
}
|
||||
|
||||
CompiledCode GetCompiledCodeFromBlock(int blockNumber)
|
||||
Jit64::CompiledCode Jit64::GetCompiledCodeFromBlock(int blockNumber)
|
||||
{
|
||||
return (CompiledCode)blockCodePointers[blockNumber];
|
||||
}
|
||||
|
||||
int GetCodeSize() {
|
||||
int Jit64::GetCodeSize() {
|
||||
return (int)(GetCodePtr() - codeCache);
|
||||
}
|
||||
|
||||
@@ -326,7 +321,7 @@ namespace Jit64
|
||||
//Can be faster by doing a queue for blocks to link up, and only process those
|
||||
//Should probably be done
|
||||
|
||||
void LinkBlockExits(int i)
|
||||
void Jit64::LinkBlockExits(int i)
|
||||
{
|
||||
JitBlock &b = blocks[i];
|
||||
if (b.invalid)
|
||||
@@ -350,10 +345,10 @@ namespace Jit64
|
||||
}
|
||||
|
||||
using namespace std;
|
||||
void LinkBlock(int i)
|
||||
void Jit64::LinkBlock(int i)
|
||||
{
|
||||
LinkBlockExits(i);
|
||||
JitBlock &b = blocks[i];
|
||||
Jit64::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
|
||||
@@ -367,10 +362,10 @@ namespace Jit64
|
||||
}
|
||||
}
|
||||
|
||||
void DestroyBlock(int blocknum, bool invalidate)
|
||||
void Jit64::DestroyBlock(int blocknum, bool invalidate)
|
||||
{
|
||||
u32 codebytes = (JIT_OPCODE << 26) | blocknum; //generate from i
|
||||
JitBlock &b = blocks[blocknum];
|
||||
Jit64::JitBlock &b = blocks[blocknum];
|
||||
b.invalid = 1;
|
||||
if (codebytes == Memory::ReadFast32(b.originalAddress))
|
||||
{
|
||||
@@ -403,7 +398,7 @@ namespace Jit64
|
||||
}
|
||||
|
||||
|
||||
void InvalidateCodeRange(u32 address, u32 length)
|
||||
void Jit64::InvalidateCodeRange(u32 address, u32 length)
|
||||
{
|
||||
if (!jo.enableBlocklink)
|
||||
return;
|
||||
@@ -418,5 +413,3 @@ namespace Jit64
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
@@ -18,85 +18,7 @@
|
||||
#define _JITCACHE_H
|
||||
|
||||
#include "../Gekko.h"
|
||||
#ifdef _WIN32
|
||||
#include <windows.h> // -> LARGE_INTEGER
|
||||
#endif
|
||||
|
||||
namespace Jit64
|
||||
{
|
||||
|
||||
typedef void (*CompiledCode)();
|
||||
|
||||
void unknown_instruction(UGeckoInstruction _inst);
|
||||
|
||||
//Code pointers are stored separately, they will be accessed much more frequently
|
||||
|
||||
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;
|
||||
};
|
||||
|
||||
void PrintStats();
|
||||
|
||||
JitBlock *CurBlock();
|
||||
JitBlock *GetBlock(int no);
|
||||
|
||||
u32 GetOriginalCode(u32 address);
|
||||
|
||||
void InvalidateCodeRange(u32 address, u32 length);
|
||||
int GetBlockNumberFromAddress(u32 address);
|
||||
CompiledCode GetCompiledCode(u32 address);
|
||||
CompiledCode GetCompiledCodeFromBlock(int blockNumber);
|
||||
|
||||
int GetCodeSize();
|
||||
int GetNumBlocks();
|
||||
|
||||
u8 **GetCodePointers();
|
||||
|
||||
u8 *Jit(u32 emaddress);
|
||||
|
||||
void DestroyBlocksWithFlag(BlockFlag death_flag);
|
||||
|
||||
void LinkBlocks();
|
||||
void ClearCache();
|
||||
|
||||
void EnterFastRun();
|
||||
|
||||
void InitCache();
|
||||
void ShutdownCache();
|
||||
void ResetCache();
|
||||
}
|
||||
// Will soon introduced the JitBlockCache class here.
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@@ -28,21 +28,19 @@
|
||||
#include "../../HW/SerialInterface.h"
|
||||
#include "../../Core.h"
|
||||
|
||||
namespace Jit64
|
||||
{
|
||||
namespace Core
|
||||
namespace JitCore
|
||||
{
|
||||
|
||||
void Init()
|
||||
{
|
||||
::Jit64::Init();
|
||||
InitCache();
|
||||
jit.Init();
|
||||
jit.InitCache();
|
||||
Asm::compareEnabled = ::Core::g_CoreStartupParameter.bRunCompareClient;
|
||||
}
|
||||
|
||||
void Shutdown()
|
||||
{
|
||||
ShutdownCache();
|
||||
jit.ShutdownCache();
|
||||
}
|
||||
|
||||
void SingleStep()
|
||||
@@ -52,8 +50,7 @@ void SingleStep()
|
||||
|
||||
void Run()
|
||||
{
|
||||
EnterFastRun();
|
||||
jit.EnterFastRun();
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace
|
||||
|
||||
@@ -17,16 +17,13 @@
|
||||
#ifndef _JITCORE_H
|
||||
#define _JITCORE_H
|
||||
|
||||
namespace Jit64
|
||||
namespace JitCore
|
||||
{
|
||||
namespace Core
|
||||
{
|
||||
void Init();
|
||||
void Shutdown();
|
||||
void Reset();
|
||||
void SingleStep();
|
||||
void Run();
|
||||
};
|
||||
void Init();
|
||||
void Shutdown();
|
||||
void Reset();
|
||||
void SingleStep();
|
||||
void Run();
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -26,8 +26,7 @@
|
||||
using namespace Gen;
|
||||
using namespace PowerPC;
|
||||
|
||||
namespace Jit64
|
||||
{
|
||||
|
||||
GPRRegCache gpr;
|
||||
FPURegCache fpr;
|
||||
|
||||
@@ -165,7 +164,7 @@ namespace Jit64
|
||||
if (regs[i].location.IsSimpleReg()) {
|
||||
Gen::X64Reg simple = regs[i].location.GetSimpleReg();
|
||||
if (xlocks[simple]) {
|
||||
PanicAlert("%08x : PPC Reg %i is in locked x64 register %i", js.compilerPC, i, regs[i].location.GetSimpleReg());
|
||||
PanicAlert("%08x : PPC Reg %i is in locked x64 register %i", /*js.compilerPC*/ 0, i, regs[i].location.GetSimpleReg());
|
||||
}
|
||||
if (xregs[simple].ppcReg != i) {
|
||||
PanicAlert("%08x : Xreg/ppcreg mismatch");
|
||||
@@ -394,4 +393,3 @@ namespace Jit64
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,12 +20,9 @@
|
||||
|
||||
#include "x64Emitter.h"
|
||||
|
||||
namespace Jit64
|
||||
{
|
||||
using namespace Gen;
|
||||
enum FlushMode
|
||||
{
|
||||
// FLUSH_ALLNONSTATIC,
|
||||
FLUSH_ALL
|
||||
};
|
||||
|
||||
@@ -36,11 +33,10 @@ namespace Jit64
|
||||
M_READWRITE = 3,
|
||||
};
|
||||
|
||||
//Regcache sketch
|
||||
struct PPCCachedReg
|
||||
{
|
||||
OpArg location;
|
||||
bool away; //not in source register
|
||||
bool away; // value not in source register
|
||||
};
|
||||
|
||||
struct X64CachedReg
|
||||
@@ -65,6 +61,7 @@ namespace Jit64
|
||||
bool locks[32];
|
||||
bool saved_locks[32];
|
||||
bool saved_xlocks[NUMXREGS];
|
||||
|
||||
protected:
|
||||
bool xlocks[NUMXREGS];
|
||||
PPCCachedReg regs[32];
|
||||
@@ -72,6 +69,10 @@ namespace Jit64
|
||||
|
||||
PPCCachedReg saved_regs[32];
|
||||
X64CachedReg saved_xregs[NUMXREGS];
|
||||
|
||||
void DiscardRegContentsIfCached(int preg);
|
||||
virtual const int *GetAllocationOrder(int &count) = 0;
|
||||
|
||||
public:
|
||||
virtual ~RegCache() {}
|
||||
virtual void Start(PPCAnalyst::BlockRegStats &stats) = 0;
|
||||
@@ -90,8 +91,6 @@ namespace Jit64
|
||||
void SanityCheck() const;
|
||||
void KillImmediate(int preg);
|
||||
|
||||
virtual const int *GetAllocationOrder(int &count) = 0;
|
||||
|
||||
//TODO - instead of doload, use "read", "write"
|
||||
//read only will not set dirty flag
|
||||
virtual void LoadToX64(int preg, bool doLoad = true, bool makeDirty = true) = 0;
|
||||
@@ -107,11 +106,12 @@ namespace Jit64
|
||||
}
|
||||
virtual OpArg GetDefaultLocation(int reg) const = 0;
|
||||
|
||||
void DiscardRegContentsIfCached(int preg);
|
||||
// Register locking.
|
||||
void Lock(int p1, int p2=0xff, int p3=0xff, int p4=0xff);
|
||||
void LockX(int x1, int x2=0xff, int x3=0xff, int x4=0xff);
|
||||
void UnlockAll();
|
||||
void UnlockAllX();
|
||||
|
||||
bool IsFreeX(int xreg) const;
|
||||
|
||||
X64Reg GetFreeXReg();
|
||||
@@ -144,7 +144,6 @@ namespace Jit64
|
||||
|
||||
extern GPRRegCache gpr;
|
||||
extern FPURegCache fpr;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@@ -40,16 +40,14 @@
|
||||
|
||||
using namespace Gen;
|
||||
|
||||
namespace Jit64
|
||||
{
|
||||
void sc(UGeckoInstruction _inst)
|
||||
void Jit64::sc(UGeckoInstruction _inst)
|
||||
{
|
||||
gpr.Flush(FLUSH_ALL);
|
||||
fpr.Flush(FLUSH_ALL);
|
||||
WriteExceptionExit(EXCEPTION_SYSCALL);
|
||||
}
|
||||
|
||||
void rfi(UGeckoInstruction _inst)
|
||||
void Jit64::rfi(UGeckoInstruction _inst)
|
||||
{
|
||||
gpr.Flush(FLUSH_ALL);
|
||||
fpr.Flush(FLUSH_ALL);
|
||||
@@ -70,7 +68,7 @@ namespace Jit64
|
||||
WriteRfiExitDestInEAX();
|
||||
}
|
||||
|
||||
void bx(UGeckoInstruction inst)
|
||||
void Jit64::bx(UGeckoInstruction inst)
|
||||
{
|
||||
if (inst.LK)
|
||||
MOV(32, M(&LR), Imm32(js.compilerPC + 4));
|
||||
@@ -107,7 +105,7 @@ namespace Jit64
|
||||
// TODO - optimize to hell and beyond
|
||||
// TODO - make nice easy to optimize special cases for the most common
|
||||
// variants of this instruction.
|
||||
void bcx(UGeckoInstruction inst)
|
||||
void Jit64::bcx(UGeckoInstruction inst)
|
||||
{
|
||||
// USES_CR
|
||||
_assert_msg_(DYNA_REC, js.isLastInstruction, "bcx not last instruction of block");
|
||||
@@ -198,7 +196,7 @@ namespace Jit64
|
||||
}
|
||||
}
|
||||
|
||||
void bcctrx(UGeckoInstruction inst)
|
||||
void Jit64::bcctrx(UGeckoInstruction inst)
|
||||
{
|
||||
gpr.Flush(FLUSH_ALL);
|
||||
fpr.Flush(FLUSH_ALL);
|
||||
@@ -237,7 +235,7 @@ namespace Jit64
|
||||
}
|
||||
|
||||
|
||||
void bclrx(UGeckoInstruction inst)
|
||||
void Jit64::bclrx(UGeckoInstruction inst)
|
||||
{
|
||||
gpr.Flush(FLUSH_ALL);
|
||||
fpr.Flush(FLUSH_ALL);
|
||||
@@ -260,5 +258,3 @@ namespace Jit64
|
||||
MOV(32, R(EAX), M(&NPC));
|
||||
WriteExitDestInEAX(0);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
@@ -25,18 +25,15 @@
|
||||
#include "Jit.h"
|
||||
#include "JitCache.h"
|
||||
#include "JitRegCache.h"
|
||||
#include "Jit_Util.h"
|
||||
|
||||
#define INSTRUCTION_START
|
||||
// #define INSTRUCTION_START Default(inst); return;
|
||||
|
||||
namespace Jit64
|
||||
{
|
||||
const u64 GC_ALIGNED16(psSignBits2[2]) = {0x8000000000000000ULL, 0x8000000000000000ULL};
|
||||
const u64 GC_ALIGNED16(psAbsMask2[2]) = {0x7FFFFFFFFFFFFFFFULL, 0x7FFFFFFFFFFFFFFFULL};
|
||||
const double GC_ALIGNED16(psOneOne2[2]) = {1.0, 1.0};
|
||||
|
||||
void fp_tri_op(int d, int a, int b, bool reversible, bool dupe, void (*op)(X64Reg, OpArg))
|
||||
void Jit64::fp_tri_op(int d, int a, int b, bool reversible, bool dupe, void (*op)(Gen::X64Reg, Gen::OpArg))
|
||||
{
|
||||
fpr.Lock(d, a, b);
|
||||
if (d == a)
|
||||
@@ -78,7 +75,7 @@ namespace Jit64
|
||||
fpr.UnlockAll();
|
||||
}
|
||||
|
||||
void fp_arith_s(UGeckoInstruction inst)
|
||||
void Jit64::fp_arith_s(UGeckoInstruction inst)
|
||||
{
|
||||
if(Core::g_CoreStartupParameter.bJITOff || Core::g_CoreStartupParameter.bJITFloatingPointOff)
|
||||
{Default(inst); return;} // turn off from debugger
|
||||
@@ -104,7 +101,7 @@ namespace Jit64
|
||||
}
|
||||
}
|
||||
|
||||
void fmaddXX(UGeckoInstruction inst)
|
||||
void Jit64::fmaddXX(UGeckoInstruction inst)
|
||||
{
|
||||
if(Core::g_CoreStartupParameter.bJITOff || Core::g_CoreStartupParameter.bJITFloatingPointOff)
|
||||
{Default(inst); return;} // turn off from debugger
|
||||
@@ -155,7 +152,7 @@ namespace Jit64
|
||||
fpr.UnlockAll();
|
||||
}
|
||||
|
||||
void fmrx(UGeckoInstruction inst)
|
||||
void Jit64::fmrx(UGeckoInstruction inst)
|
||||
{
|
||||
if(Core::g_CoreStartupParameter.bJITOff || Core::g_CoreStartupParameter.bJITFloatingPointOff)
|
||||
{Default(inst); return;} // turn off from debugger
|
||||
@@ -169,7 +166,7 @@ namespace Jit64
|
||||
MOVSD(fpr.RX(d), fpr.R(b));
|
||||
}
|
||||
|
||||
void fcmpx(UGeckoInstruction inst)
|
||||
void Jit64::fcmpx(UGeckoInstruction inst)
|
||||
{
|
||||
if(Core::g_CoreStartupParameter.bJITOff || Core::g_CoreStartupParameter.bJITFloatingPointOff)
|
||||
{Default(inst); return;} // turn off from debugger
|
||||
@@ -225,6 +222,3 @@ namespace Jit64
|
||||
SetJumpTarget(continue2);
|
||||
fpr.UnlockAll();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -24,15 +24,12 @@
|
||||
#include "JitCache.h"
|
||||
#include "JitRegCache.h"
|
||||
#include "JitAsm.h"
|
||||
#include "Jit_Util.h"
|
||||
|
||||
// #define INSTRUCTION_START Default(inst); return;
|
||||
#define INSTRUCTION_START
|
||||
|
||||
namespace Jit64
|
||||
{
|
||||
// Assumes that the flags were just set through an addition.
|
||||
void GenerateCarry(X64Reg temp_reg) {
|
||||
void Jit64::GenerateCarry(Gen::X64Reg temp_reg) {
|
||||
// USES_XER
|
||||
SETcc(CC_C, R(temp_reg));
|
||||
AND(32, M(&PowerPC::ppcState.spr[SPR_XER]), Imm32(~(1 << 29)));
|
||||
@@ -40,13 +37,12 @@ namespace Jit64
|
||||
OR(32, M(&PowerPC::ppcState.spr[SPR_XER]), R(temp_reg));
|
||||
}
|
||||
|
||||
typedef u32 (*Operation)(u32 a, u32 b);
|
||||
u32 Add(u32 a, u32 b) {return a + b;}
|
||||
u32 Or (u32 a, u32 b) {return a | b;}
|
||||
u32 And(u32 a, u32 b) {return a & b;}
|
||||
u32 Xor(u32 a, u32 b) {return a ^ b;}
|
||||
|
||||
void regimmop(int d, int a, bool binary, u32 value, Operation doop, void(*op)(int, const OpArg&, const OpArg&), bool Rc = false, bool carry = false)
|
||||
void Jit64::regimmop(int d, int a, bool binary, u32 value, Operation doop, void(*op)(int, const Gen::OpArg&, const Gen::OpArg&), bool Rc, bool carry)
|
||||
{
|
||||
gpr.Lock(d, a);
|
||||
if (a || binary || carry) // yeh nasty special case addic
|
||||
@@ -93,7 +89,7 @@ namespace Jit64
|
||||
gpr.UnlockAll();
|
||||
}
|
||||
|
||||
void reg_imm(UGeckoInstruction inst)
|
||||
void Jit64::reg_imm(UGeckoInstruction inst)
|
||||
{
|
||||
#ifdef JIT_OFF_OPTIONS
|
||||
if(Core::g_CoreStartupParameter.bJITOff || Core::g_CoreStartupParameter.bJITIntegerOff)
|
||||
@@ -147,7 +143,7 @@ namespace Jit64
|
||||
*/
|
||||
|
||||
// unsigned
|
||||
void cmpXX(UGeckoInstruction inst)
|
||||
void Jit64::cmpXX(UGeckoInstruction inst)
|
||||
{
|
||||
// USES_CR
|
||||
#ifdef JIT_OFF_OPTIONS
|
||||
@@ -263,7 +259,7 @@ namespace Jit64
|
||||
gpr.UnlockAll();
|
||||
}
|
||||
|
||||
void orx(UGeckoInstruction inst)
|
||||
void Jit64::orx(UGeckoInstruction inst)
|
||||
{
|
||||
#ifdef JIT_OFF_OPTIONS
|
||||
if(Core::g_CoreStartupParameter.bJITOff || Core::g_CoreStartupParameter.bJITIntegerOff)
|
||||
@@ -305,7 +301,7 @@ namespace Jit64
|
||||
|
||||
|
||||
// m_GPR[_inst.RA] = m_GPR[_inst.RS] ^ m_GPR[_inst.RB];
|
||||
void xorx(UGeckoInstruction inst)
|
||||
void Jit64::xorx(UGeckoInstruction inst)
|
||||
{
|
||||
#ifdef JIT_OFF_OPTIONS
|
||||
if(Core::g_CoreStartupParameter.bJITOff || Core::g_CoreStartupParameter.bJITIntegerOff)
|
||||
@@ -336,7 +332,7 @@ namespace Jit64
|
||||
}
|
||||
}
|
||||
|
||||
void andx(UGeckoInstruction inst)
|
||||
void Jit64::andx(UGeckoInstruction inst)
|
||||
{
|
||||
#ifdef JIT_OFF_OPTIONS
|
||||
if(Core::g_CoreStartupParameter.bJITOff || Core::g_CoreStartupParameter.bJITIntegerOff)
|
||||
@@ -361,7 +357,7 @@ namespace Jit64
|
||||
}
|
||||
}
|
||||
|
||||
void extsbx(UGeckoInstruction inst)
|
||||
void Jit64::extsbx(UGeckoInstruction inst)
|
||||
{
|
||||
#ifdef JIT_OFF_OPTIONS
|
||||
if(Core::g_CoreStartupParameter.bJITOff || Core::g_CoreStartupParameter.bJITIntegerOff)
|
||||
@@ -382,7 +378,7 @@ namespace Jit64
|
||||
}
|
||||
}
|
||||
|
||||
void extshx(UGeckoInstruction inst)
|
||||
void Jit64::extshx(UGeckoInstruction inst)
|
||||
{
|
||||
#ifdef JIT_OFF_OPTIONS
|
||||
if(Core::g_CoreStartupParameter.bJITOff || Core::g_CoreStartupParameter.bJITIntegerOff)
|
||||
@@ -402,7 +398,7 @@ namespace Jit64
|
||||
}
|
||||
}
|
||||
|
||||
void subfic(UGeckoInstruction inst)
|
||||
void Jit64::subfic(UGeckoInstruction inst)
|
||||
{
|
||||
#ifdef JIT_OFF_OPTIONS
|
||||
if(Core::g_CoreStartupParameter.bJITOff || Core::g_CoreStartupParameter.bJITIntegerOff)
|
||||
@@ -424,7 +420,7 @@ namespace Jit64
|
||||
// This instruction has no RC flag
|
||||
}
|
||||
|
||||
void subfcx(UGeckoInstruction inst)
|
||||
void Jit64::subfcx(UGeckoInstruction inst)
|
||||
{
|
||||
INSTRUCTION_START;
|
||||
Default(inst);
|
||||
@@ -440,7 +436,7 @@ namespace Jit64
|
||||
*/
|
||||
}
|
||||
|
||||
void subfex(UGeckoInstruction inst)
|
||||
void Jit64::subfex(UGeckoInstruction inst)
|
||||
{
|
||||
INSTRUCTION_START;
|
||||
Default(inst);
|
||||
@@ -457,7 +453,7 @@ namespace Jit64
|
||||
*/
|
||||
}
|
||||
|
||||
void subfx(UGeckoInstruction inst)
|
||||
void Jit64::subfx(UGeckoInstruction inst)
|
||||
{
|
||||
#ifdef JIT_OFF_OPTIONS
|
||||
if(Core::g_CoreStartupParameter.bJITOff || Core::g_CoreStartupParameter.bJITIntegerOff)
|
||||
@@ -482,7 +478,7 @@ namespace Jit64
|
||||
}
|
||||
}
|
||||
|
||||
void mulli(UGeckoInstruction inst)
|
||||
void Jit64::mulli(UGeckoInstruction inst)
|
||||
{
|
||||
#ifdef JIT_OFF_OPTIONS
|
||||
if(Core::g_CoreStartupParameter.bJITOff || Core::g_CoreStartupParameter.bJITIntegerOff)
|
||||
@@ -497,7 +493,7 @@ namespace Jit64
|
||||
gpr.UnlockAll();
|
||||
}
|
||||
|
||||
void mullwx(UGeckoInstruction inst)
|
||||
void Jit64::mullwx(UGeckoInstruction inst)
|
||||
{
|
||||
#ifdef JIT_OFF_OPTIONS
|
||||
if(Core::g_CoreStartupParameter.bJITOff || Core::g_CoreStartupParameter.bJITIntegerOff)
|
||||
@@ -522,7 +518,7 @@ namespace Jit64
|
||||
}
|
||||
}
|
||||
|
||||
void mulhwux(UGeckoInstruction inst)
|
||||
void Jit64::mulhwux(UGeckoInstruction inst)
|
||||
{
|
||||
#ifdef JIT_OFF_OPTIONS
|
||||
if(Core::g_CoreStartupParameter.bJITOff || Core::g_CoreStartupParameter.bJITIntegerOff)
|
||||
@@ -555,7 +551,7 @@ namespace Jit64
|
||||
}
|
||||
|
||||
// skipped some of the special handling in here - if we get crashes, let the interpreter handle this op
|
||||
void divwux(UGeckoInstruction inst) {
|
||||
void Jit64::divwux(UGeckoInstruction inst) {
|
||||
Default(inst); return;
|
||||
|
||||
int a = inst.RA, b = inst.RB, d = inst.RD;
|
||||
@@ -587,7 +583,7 @@ namespace Jit64
|
||||
);
|
||||
}
|
||||
|
||||
void addx(UGeckoInstruction inst)
|
||||
void Jit64::addx(UGeckoInstruction inst)
|
||||
{
|
||||
#ifdef JIT_OFF_OPTIONS
|
||||
if(Core::g_CoreStartupParameter.bJITOff || Core::g_CoreStartupParameter.bJITIntegerOff)
|
||||
@@ -645,7 +641,7 @@ namespace Jit64
|
||||
}
|
||||
|
||||
// This can be optimized
|
||||
void addex(UGeckoInstruction inst)
|
||||
void Jit64::addex(UGeckoInstruction inst)
|
||||
{
|
||||
// USES_XER
|
||||
#ifdef JIT_OFF_OPTIONS
|
||||
@@ -674,7 +670,7 @@ namespace Jit64
|
||||
}
|
||||
}
|
||||
|
||||
void rlwinmx(UGeckoInstruction inst)
|
||||
void Jit64::rlwinmx(UGeckoInstruction inst)
|
||||
{
|
||||
#ifdef JIT_OFF_OPTIONS
|
||||
if(Core::g_CoreStartupParameter.bJITOff || Core::g_CoreStartupParameter.bJITIntegerOff)
|
||||
@@ -739,7 +735,7 @@ namespace Jit64
|
||||
}
|
||||
|
||||
|
||||
void rlwimix(UGeckoInstruction inst)
|
||||
void Jit64::rlwimix(UGeckoInstruction inst)
|
||||
{
|
||||
#ifdef JIT_OFF_OPTIONS
|
||||
if(Core::g_CoreStartupParameter.bJITOff || Core::g_CoreStartupParameter.bJITIntegerOff)
|
||||
@@ -775,7 +771,7 @@ namespace Jit64
|
||||
}
|
||||
}
|
||||
|
||||
void rlwnmx(UGeckoInstruction inst)
|
||||
void Jit64::rlwnmx(UGeckoInstruction inst)
|
||||
{
|
||||
#ifdef JIT_OFF_OPTIONS
|
||||
if(Core::g_CoreStartupParameter.bJITOff || Core::g_CoreStartupParameter.bJITIntegerOff)
|
||||
@@ -807,7 +803,7 @@ namespace Jit64
|
||||
}
|
||||
}
|
||||
|
||||
void negx(UGeckoInstruction inst)
|
||||
void Jit64::negx(UGeckoInstruction inst)
|
||||
{
|
||||
#ifdef JIT_OFF_OPTIONS
|
||||
if(Core::g_CoreStartupParameter.bJITOff || Core::g_CoreStartupParameter.bJITIntegerOff)
|
||||
@@ -829,7 +825,7 @@ namespace Jit64
|
||||
}
|
||||
}
|
||||
|
||||
void srwx(UGeckoInstruction inst)
|
||||
void Jit64::srwx(UGeckoInstruction inst)
|
||||
{
|
||||
#ifdef JIT_OFF_OPTIONS
|
||||
if(Core::g_CoreStartupParameter.bJITOff || Core::g_CoreStartupParameter.bJITIntegerOff)
|
||||
@@ -859,7 +855,7 @@ namespace Jit64
|
||||
}
|
||||
}
|
||||
|
||||
void slwx(UGeckoInstruction inst)
|
||||
void Jit64::slwx(UGeckoInstruction inst)
|
||||
{
|
||||
#ifdef JIT_OFF_OPTIONS
|
||||
if(Core::g_CoreStartupParameter.bJITOff || Core::g_CoreStartupParameter.bJITIntegerOff)
|
||||
@@ -889,7 +885,7 @@ namespace Jit64
|
||||
}
|
||||
}
|
||||
|
||||
void srawx(UGeckoInstruction inst)
|
||||
void Jit64::srawx(UGeckoInstruction inst)
|
||||
{
|
||||
// USES_XER
|
||||
#ifdef JIT_OFF_OPTIONS
|
||||
@@ -937,7 +933,7 @@ namespace Jit64
|
||||
}
|
||||
}
|
||||
|
||||
void srawix(UGeckoInstruction inst)
|
||||
void Jit64::srawix(UGeckoInstruction inst)
|
||||
{
|
||||
#ifdef JIT_OFF_OPTIONS
|
||||
if(Core::g_CoreStartupParameter.bJITOff || Core::g_CoreStartupParameter.bJITIntegerOff)
|
||||
@@ -984,7 +980,7 @@ namespace Jit64
|
||||
}
|
||||
|
||||
// count leading zeroes
|
||||
void cntlzwx(UGeckoInstruction inst)
|
||||
void Jit64::cntlzwx(UGeckoInstruction inst)
|
||||
{
|
||||
#ifdef JIT_OFF_OPTIONS
|
||||
if(Core::g_CoreStartupParameter.bJITOff || Core::g_CoreStartupParameter.bJITIntegerOff)
|
||||
@@ -1014,5 +1010,3 @@ namespace Jit64
|
||||
// TODO: Check PPC manual too
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user