#include "ppsspp_config.h"
#if PPSSPP_ARCH(X86) || PPSSPP_ARCH(AMD64)
#include "Common/Math/math_util.h"
#include "ABI.h"
#include "x64Emitter.h"
#include "Core/Core.h"
#include "Core/MemMap.h"
#include "Core/System.h"
#include "Core/MIPS/MIPS.h"
#include "Core/CoreTiming.h"
#include "Common/MemoryUtil.h"
#include "Core/MIPS/JitCommon/JitCommon.h"
#include "Core/MIPS/x86/Jit.h"
using namespace Gen;
using namespace X64JitConstants;
extern volatile CoreState coreState;
namespace MIPSComp
{
static bool enableDebug = false;
void ImHere() {
DEBUG_LOG(Log::CPU, "JIT Here: %08x", currentMIPS->pc);
}
void Jit::GenerateFixedCode(JitOptions &jo) {
BeginWrite(GetMemoryProtectPageSize());
AlignCodePage();
restoreRoundingMode = AlignCode16(); {
STMXCSR(MIPSSTATE_VAR(temp));
AND(32, MIPSSTATE_VAR(temp), Imm32(~(7 << 13)));
LDMXCSR(MIPSSTATE_VAR(temp));
RET();
}
applyRoundingMode = AlignCode16(); {
MOV(32, R(EAX), MIPSSTATE_VAR(fcr31));
AND(32, R(EAX), Imm32(0x01000003));
FixupBranch skip = J_CC(CC_Z);
STMXCSR(MIPSSTATE_VAR(temp));
TEST(8, R(AL), Imm8(1));
FixupBranch skip2 = J_CC(CC_Z);
XOR(32, R(EAX), Imm8(2));
SetJumpTarget(skip2);
SHL(32, R(EAX), Imm8(13));
AND(32, MIPSSTATE_VAR(temp), Imm32(~(7 << 13)));
OR(32, MIPSSTATE_VAR(temp), R(EAX));
TEST(32, MIPSSTATE_VAR(fcr31), Imm32(1 << 24));
FixupBranch skip3 = J_CC(CC_Z);
OR(32, MIPSSTATE_VAR(temp), Imm32(1 << 15));
SetJumpTarget(skip3);
LDMXCSR(MIPSSTATE_VAR(temp));
SetJumpTarget(skip);
RET();
}
enterDispatcher = AlignCode16();
ABI_PushAllCalleeSavedRegsAndAdjustStack();
#if PPSSPP_ARCH(AMD64)
MOV(64, R(MEMBASEREG), ImmPtr(Memory::base));
uintptr_t jitbase = (uintptr_t)GetBasePtr();
if (jitbase > 0x7FFFFFFFULL) {
MOV(64, R(JITBASEREG), ImmPtr(GetBasePtr()));
jo.reserveR15ForAsm = true;
}
#endif
MOV(PTRBITS, R(CTXREG), ImmPtr(&mips_->f[0]));
outerLoop = GetCodePtr();
RestoreRoundingMode(true);
ABI_CallFunction(reinterpret_cast<void *>(&CoreTiming::Advance));
ApplyRoundingMode(true);
FixupBranch skipToCoreStateCheck = J();
dispatcherCheckCoreState = GetCodePtr();
FixupBranch bailCoreState = J_CC(CC_S, true);
SetJumpTarget(skipToCoreStateCheck);
if (RipAccessible((const void *)&coreState)) {
CMP(32, M(&coreState), Imm32(0));
} else {
MOV(PTRBITS, R(RAX), ImmPtr((const void *)&coreState));
CMP(32, MatR(RAX), Imm32(0));
}
FixupBranch badCoreState = J_CC(CC_NZ, true);
FixupBranch skipToRealDispatch2 = J();
dispatcher = GetCodePtr();
FixupBranch bail = J_CC(CC_S, true);
SetJumpTarget(skipToRealDispatch2);
dispatcherNoCheck = GetCodePtr();
MOV(32, R(EAX), MIPSSTATE_VAR(pc));
dispatcherInEAXNoCheck = GetCodePtr();
#ifdef MASKED_PSP_MEMORY
AND(32, R(EAX), Imm32(Memory::MEMVIEW32_MASK));
#endif
dispatcherFetch = GetCodePtr();
#if PPSSPP_ARCH(X86)
_assert_msg_( Memory::base != 0, "Memory base bogus");
MOV(32, R(EAX), MDisp(EAX, (u32)Memory::base));
#elif PPSSPP_ARCH(AMD64)
MOV(32, R(EAX), MComplex(MEMBASEREG, RAX, SCALE_1, 0));
#endif
MOV(32, R(EDX), R(EAX));
_assert_msg_(MIPS_JITBLOCK_MASK == 0xFF000000, "Hardcoded assumption of emuhack mask");
SHR(32, R(EDX), Imm8(24));
CMP(32, R(EDX), Imm8(MIPS_EMUHACK_OPCODE >> 24));
FixupBranch notfound = J_CC(CC_NE);
if (enableDebug) {
ADD(32, MIPSSTATE_VAR(debugCount), Imm8(1));
}
AND(32, R(EAX), Imm32(MIPS_EMUHACK_VALUE_MASK));
#if PPSSPP_ARCH(X86)
ADD(32, R(EAX), ImmPtr(GetBasePtr()));
#elif PPSSPP_ARCH(AMD64)
if (jo.reserveR15ForAsm) {
ADD(64, R(RAX), R(JITBASEREG));
} else {
ADD(64, R(EAX), Imm32((u32)jitbase));
}
#endif
JMPptr(R(EAX));
SetJumpTarget(notfound);
RestoreRoundingMode(true);
ABI_CallFunction(&MIPSComp::JitAt);
ApplyRoundingMode(true);
JMP(dispatcherNoCheck, true);
SetJumpTarget(bail);
SetJumpTarget(bailCoreState);
if (RipAccessible((const void *)&coreState)) {
CMP(32, M(&coreState), Imm32(0));
} else {
MOV(PTRBITS, R(RAX), ImmPtr((const void *)&coreState));
CMP(32, MatR(RAX), Imm32(0));
}
J_CC(CC_Z, outerLoop, true);
const uint8_t *quitLoop = GetCodePtr();
SetJumpTarget(badCoreState);
RestoreRoundingMode(true);
ABI_PopAllCalleeSavedRegsAndAdjustStack();
RET();
crashHandler = GetCodePtr();
if (RipAccessible((const void *)&coreState)) {
MOV(32, M(&coreState), Imm32(CORE_RUNTIME_ERROR));
} else {
MOV(PTRBITS, R(RAX), ImmPtr((const void *)&coreState));
MOV(32, MatR(RAX), Imm32(CORE_RUNTIME_ERROR));
}
JMP(quitLoop, true);
endOfPregeneratedCode = AlignCodePage();
EndWrite();
}
}
#endif