Skip to content

Commit

Permalink
Minor code formatting in x86 Jit
Browse files Browse the repository at this point in the history
  • Loading branch information
hrydgard committed Feb 4, 2017
1 parent 3ceb0a8 commit c1f9f96
Show file tree
Hide file tree
Showing 2 changed files with 59 additions and 82 deletions.
135 changes: 54 additions & 81 deletions Core/MIPS/x86/Jit.cpp
Expand Up @@ -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;

Expand Down Expand Up @@ -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;
Expand All @@ -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;
Expand All @@ -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));
}
Expand Down Expand Up @@ -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));

This comment has been minimized.

Copy link
@unknownbrackets

unknownbrackets Mar 14, 2017

Collaborator

I've always wondered, why do this when we could just SUB RSP by another 8?

-[Unknown]

#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.");
Expand All @@ -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();
Expand Down Expand Up @@ -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)();
}
Expand Down Expand Up @@ -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.

Expand Down Expand Up @@ -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.");
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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))
{
Expand All @@ -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()));
Expand All @@ -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));
Expand All @@ -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();
Expand All @@ -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();
Expand All @@ -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);
Expand Down
6 changes: 5 additions & 1 deletion Core/MIPS/x86/Jit.h
Expand Up @@ -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"
Expand All @@ -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;
Expand Down Expand Up @@ -292,6 +294,8 @@ class Jit : public Gen::XCodeBlock, public JitInterface, public MIPSFrontendInte
}
return true;
}
void SaveFlags();
void LoadFlags();

JitBlockCache blocks;
JitOptions jo;
Expand Down

0 comments on commit c1f9f96

Please sign in to comment.