Minor code formatting in x86 Jit

This commit is contained in:
Henrik Rydgard 2017-02-04 14:34:39 +01:00
parent 3ceb0a8540
commit c1f9f96621
2 changed files with 59 additions and 82 deletions

View File

@ -48,20 +48,8 @@ namespace MIPSComp
{
using namespace Gen;
#ifdef _M_IX86
#define SAVE_FLAGS PUSHF();
#define LOAD_FLAGS POPF();
#elif defined(_M_X64)
static u64 saved_flags;
#define SAVE_FLAGS {PUSHF(); POP(64, R(EAX)); MOV(64, M(&saved_flags), R(EAX));}
#define LOAD_FLAGS {MOV(64, R(EAX), M(&saved_flags)); PUSH(64, R(EAX)); POPF();}
#endif
const bool USE_JIT_MISSMAP = false;
static std::map<std::string, u32> notJitOps;
@ -138,8 +126,7 @@ Jit::Jit(MIPSState *mips)
Jit::~Jit() {
}
void Jit::DoState(PointerWrap &p)
{
void Jit::DoState(PointerWrap &p) {
auto s = p.Section("Jit", 1, 2);
if (!s)
return;
@ -158,8 +145,7 @@ void Jit::DoState(PointerWrap &p)
}
// This is here so the savestate matches between jit and non-jit.
void Jit::DoDummyState(PointerWrap &p)
{
void Jit::DoDummyState(PointerWrap &p) {
auto s = p.Section("Jit", 1, 2);
if (!s)
return;
@ -173,49 +159,41 @@ void Jit::DoDummyState(PointerWrap &p)
}
void Jit::GetStateAndFlushAll(RegCacheState &state)
{
void Jit::GetStateAndFlushAll(RegCacheState &state) {
gpr.GetState(state.gpr);
fpr.GetState(state.fpr);
FlushAll();
}
void Jit::RestoreState(const RegCacheState& state)
{
void Jit::RestoreState(const RegCacheState& state) {
gpr.RestoreState(state.gpr);
fpr.RestoreState(state.fpr);
}
void Jit::FlushAll()
{
void Jit::FlushAll() {
gpr.Flush();
fpr.Flush();
FlushPrefixV();
}
void Jit::FlushPrefixV()
{
if ((js.prefixSFlag & JitState::PREFIX_DIRTY) != 0)
{
void Jit::FlushPrefixV() {
if ((js.prefixSFlag & JitState::PREFIX_DIRTY) != 0) {
MOV(32, M(&mips_->vfpuCtrl[VFPU_CTRL_SPREFIX]), Imm32(js.prefixS));
js.prefixSFlag = (JitState::PrefixState) (js.prefixSFlag & ~JitState::PREFIX_DIRTY);
}
if ((js.prefixTFlag & JitState::PREFIX_DIRTY) != 0)
{
if ((js.prefixTFlag & JitState::PREFIX_DIRTY) != 0) {
MOV(32, M(&mips_->vfpuCtrl[VFPU_CTRL_TPREFIX]), Imm32(js.prefixT));
js.prefixTFlag = (JitState::PrefixState) (js.prefixTFlag & ~JitState::PREFIX_DIRTY);
}
if ((js.prefixDFlag & JitState::PREFIX_DIRTY) != 0)
{
if ((js.prefixDFlag & JitState::PREFIX_DIRTY) != 0) {
MOV(32, M(&mips_->vfpuCtrl[VFPU_CTRL_DPREFIX]), Imm32(js.prefixD));
js.prefixDFlag = (JitState::PrefixState) (js.prefixDFlag & ~JitState::PREFIX_DIRTY);
}
}
void Jit::WriteDowncount(int offset)
{
void Jit::WriteDowncount(int offset) {
const int downcount = js.downcountAmount + offset;
SUB(32, M(&mips_->downcount), downcount > 127 ? Imm32(downcount) : Imm8(downcount));
}
@ -245,32 +223,46 @@ void Jit::ClearCache()
GenerateFixedCode(jo);
}
void Jit::CompileDelaySlot(int flags, RegCacheState *state)
{
void Jit::SaveFlags() {
PUSHF();
#if defined(_M_X64)
// On X64, the above misaligns the stack. However there might be a cheaper solution than this.
POP(64, R(EAX));
MOV(64, M(&saved_flags), R(EAX));
#endif
}
void Jit::LoadFlags() {
#if defined(_M_X64)
MOV(64, R(EAX), M(&saved_flags));
PUSH(64, R(EAX));
#endif
POPF();
}
void Jit::CompileDelaySlot(int flags, RegCacheState *state) {
// Need to offset the downcount which was already incremented for the branch + delay slot.
CheckJitBreakpoint(GetCompilerPC() + 4, -2);
if (flags & DELAYSLOT_SAFE)
SAVE_FLAGS; // preserve flag around the delay slot!
SaveFlags(); // preserve flag around the delay slot!
js.inDelaySlot = true;
MIPSOpcode op = GetOffsetInstruction(1);
MIPSCompileOp(op, this);
js.inDelaySlot = false;
if (flags & DELAYSLOT_FLUSH)
{
if (flags & DELAYSLOT_FLUSH) {
if (state != NULL)
GetStateAndFlushAll(*state);
else
FlushAll();
}
if (flags & DELAYSLOT_SAFE)
LOAD_FLAGS; // restore flag!
LoadFlags(); // restore flag!
}
void Jit::EatInstruction(MIPSOpcode op)
{
void Jit::EatInstruction(MIPSOpcode op) {
MIPSInfo info = MIPSGetInfo(op);
if (info & DELAYSLOT) {
ERROR_LOG_REPORT_ONCE(ateDelaySlot, JIT, "Ate a branch op.");
@ -285,8 +277,7 @@ void Jit::EatInstruction(MIPSOpcode op)
js.downcountAmount += MIPSGetInstructionCycleEstimate(op);
}
void Jit::Compile(u32 em_address)
{
void Jit::Compile(u32 em_address) {
PROFILE_THIS_SCOPE("jitc");
if (GetSpaceLeft() < 0x10000 || blocks.IsFull()) {
ClearCache();
@ -327,8 +318,7 @@ void Jit::Compile(u32 em_address)
}
}
void Jit::RunLoopUntil(u64 globalticks)
{
void Jit::RunLoopUntil(u64 globalticks) {
PROFILE_THIS_SCOPE("jit");
((void (*)())enterDispatcher)();
}
@ -569,8 +559,7 @@ bool Jit::ReplaceJalTo(u32 dest) {
return true;
}
void Jit::Comp_ReplacementFunc(MIPSOpcode op)
{
void Jit::Comp_ReplacementFunc(MIPSOpcode op) {
// We get here if we execute the first instruction of a replaced function. This means
// that we do need to return to RA.
@ -646,8 +635,7 @@ void Jit::Comp_ReplacementFunc(MIPSOpcode op)
}
}
void Jit::Comp_Generic(MIPSOpcode op)
{
void Jit::Comp_Generic(MIPSOpcode op) {
FlushAll();
MIPSInterpretFunc func = MIPSGetInterpretFunc(op);
_dbg_assert_msg_(JIT, (MIPSGetInfo(op) & DELAYSLOT) == 0, "Cannot use interpreter for branch ops.");
@ -675,16 +663,14 @@ void Jit::Comp_Generic(MIPSOpcode op)
}
}
void Jit::WriteExit(u32 destination, int exit_num)
{
void Jit::WriteExit(u32 destination, int exit_num) {
_dbg_assert_msg_(JIT, exit_num < MAX_JIT_BLOCK_EXITS, "Expected a valid exit_num");
if (!Memory::IsValidAddress(destination)) {
ERROR_LOG_REPORT(JIT, "Trying to write block exit to illegal destination %08x: pc = %08x", destination, currentMIPS->pc);
}
// If we need to verify coreState and rewind, we may not jump yet.
if (js.afterOp & (JitState::AFTER_CORE_STATE | JitState::AFTER_REWIND_PC_BAD_STATE))
{
if (js.afterOp & (JitState::AFTER_CORE_STATE | JitState::AFTER_REWIND_PC_BAD_STATE)) {
// CORE_RUNNING is <= CORE_NEXTFRAME.
CMP(32, M(&coreState), Imm32(CORE_NEXTFRAME));
FixupBranch skipCheck = J_CC(CC_LE);
@ -721,8 +707,7 @@ void Jit::WriteExit(u32 destination, int exit_num)
}
}
void Jit::WriteExitDestInReg(X64Reg reg)
{
void Jit::WriteExitDestInReg(X64Reg reg) {
// If we need to verify coreState and rewind, we may not jump yet.
if (js.afterOp & (JitState::AFTER_CORE_STATE | JitState::AFTER_REWIND_PC_BAD_STATE))
{
@ -738,8 +723,7 @@ void Jit::WriteExitDestInReg(X64Reg reg)
WriteDowncount();
// Validate the jump to avoid a crash?
if (!g_Config.bFastMemory)
{
if (!g_Config.bFastMemory) {
CMP(32, R(reg), Imm32(PSP_GetKernelMemoryBase()));
FixupBranch tooLow = J_CC(CC_B);
CMP(32, R(reg), Imm32(PSP_GetUserMemoryEnd()));
@ -757,8 +741,7 @@ void Jit::WriteExitDestInReg(X64Reg reg)
ABI_CallFunctionA((const void *)&Memory::GetPointer, R(reg));
// If we're ignoring, coreState didn't trip - so trip it now.
if (g_Config.bIgnoreBadMemAccess)
{
if (g_Config.bIgnoreBadMemAccess) {
CMP(32, R(EAX), Imm32(0));
FixupBranch skip = J_CC(CC_NE);
ABI_CallFunctionA((const void *)&Core_UpdateState, Imm32(CORE_ERROR));
@ -767,18 +750,15 @@ void Jit::WriteExitDestInReg(X64Reg reg)
SUB(32, M(&mips_->downcount), Imm8(0));
JMP(dispatcherCheckCoreState, true);
}
else if (reg == EAX)
{
} else if (reg == EAX) {
J_CC(CC_NS, dispatcherInEAXNoCheck, true);
JMP(dispatcher, true);
}
else
} else {
JMP(dispatcher, true);
}
}
void Jit::WriteSyscallExit()
{
void Jit::WriteSyscallExit() {
WriteDowncount();
if (js.afterOp & JitState::AFTER_MEMCHECK_CLEANUP) {
RestoreRoundingMode();
@ -788,11 +768,9 @@ void Jit::WriteSyscallExit()
JMP(dispatcherCheckCoreState, true);
}
bool Jit::CheckJitBreakpoint(u32 addr, int downcountOffset)
{
if (CBreakPoints::IsAddressBreakPoint(addr))
{
SAVE_FLAGS;
bool Jit::CheckJitBreakpoint(u32 addr, int downcountOffset) {
if (CBreakPoints::IsAddressBreakPoint(addr)) {
SaveFlags();
FlushAll();
MOV(32, M(&mips_->pc), Imm32(GetCompilerPC()));
RestoreRoundingMode();
@ -804,41 +782,36 @@ bool Jit::CheckJitBreakpoint(u32 addr, int downcountOffset)
WriteDowncount(downcountOffset);
ApplyRoundingMode();
// Just to fix the stack.
LOAD_FLAGS;
LoadFlags();
JMP(dispatcherCheckCoreState, true);
SetJumpTarget(skip);
ApplyRoundingMode();
LOAD_FLAGS;
LoadFlags();
return true;
}
return false;
}
void Jit::CallProtectedFunction(const void *func, const OpArg &arg1)
{
void Jit::CallProtectedFunction(const void *func, const OpArg &arg1) {
// We don't regcache RCX, so the below is safe (and also faster, maybe branch prediction?)
ABI_CallFunctionA(thunks.ProtectFunction(func, 1), arg1);
}
void Jit::CallProtectedFunction(const void *func, const OpArg &arg1, const OpArg &arg2)
{
void Jit::CallProtectedFunction(const void *func, const OpArg &arg1, const OpArg &arg2) {
// We don't regcache RCX/RDX, so the below is safe (and also faster, maybe branch prediction?)
ABI_CallFunctionAA(thunks.ProtectFunction(func, 2), arg1, arg2);
}
void Jit::CallProtectedFunction(const void *func, const u32 arg1, const u32 arg2, const u32 arg3)
{
void Jit::CallProtectedFunction(const void *func, const u32 arg1, const u32 arg2, const u32 arg3) {
// On x64, we need to save R8, which is caller saved.
thunks.Enter(this);
ABI_CallFunctionCCC(func, arg1, arg2, arg3);
thunks.Leave(this);
}
void Jit::CallProtectedFunction(const void *func, const OpArg &arg1, const u32 arg2, const u32 arg3)
{
void Jit::CallProtectedFunction(const void *func, const OpArg &arg1, const u32 arg2, const u32 arg3) {
// On x64, we need to save R8, which is caller saved.
thunks.Enter(this);
ABI_CallFunctionACC(func, arg1, arg2, arg3);

View File

@ -15,6 +15,9 @@
// Official git repository and contact information can be found at
// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/.
// TODO: Implement https://github.com/dolphin-emu/dolphin/pull/1025/commits/b597ec3e081a289d9ac782586617a876535183d6 .
#pragma once
#include "Common/CommonTypes.h"
@ -36,7 +39,6 @@ namespace MIPSComp {
// This is called when Jit hits a breakpoint. Returns 1 when hit.
u32 JitBreakpoint();
// TODO: Hmm, humongous.
struct RegCacheState {
GPRRegCacheState gpr;
FPURegCacheState fpr;
@ -292,6 +294,8 @@ private:
}
return true;
}
void SaveFlags();
void LoadFlags();
JitBlockCache blocks;
JitOptions jo;