mirror of
https://github.com/hrydgard/ppsspp.git
synced 2024-11-24 05:49:58 +00:00
X86/X64: We have the context register loaded, let's use it more.
This commit is contained in:
parent
385204bec6
commit
730e9ced6c
@ -145,6 +145,14 @@ extern u8 fromvoffset[128];
|
||||
|
||||
enum class CPUCore;
|
||||
|
||||
#if defined(PPSSPP_ARCH_X86) || defined(PPSSPP_ARCH_AMD64)
|
||||
|
||||
// Note that CTXREG is offset to point at the first floating point register, intentionally. This is so that a byte offset
|
||||
// can reach both GPR and FPR regs.
|
||||
#define MIPSSTATE_VAR(x) MDisp(X64JitConstants::CTXREG, (int)(offsetof(MIPSState, x) - offsetof(MIPSState, f[0])))
|
||||
|
||||
#endif
|
||||
|
||||
class MIPSState
|
||||
{
|
||||
public:
|
||||
|
@ -70,21 +70,21 @@ void Jit::GenerateFixedCode(JitOptions &jo) {
|
||||
BeginWrite();
|
||||
|
||||
restoreRoundingMode = AlignCode16(); {
|
||||
STMXCSR(M(&mips_->temp));
|
||||
STMXCSR(MIPSSTATE_VAR(temp));
|
||||
// Clear the rounding mode and flush-to-zero bits back to 0.
|
||||
AND(32, M(&mips_->temp), Imm32(~(7 << 13)));
|
||||
LDMXCSR(M(&mips_->temp));
|
||||
AND(32, MIPSSTATE_VAR(temp), Imm32(~(7 << 13)));
|
||||
LDMXCSR(MIPSSTATE_VAR(temp));
|
||||
RET();
|
||||
}
|
||||
|
||||
applyRoundingMode = AlignCode16(); {
|
||||
MOV(32, R(EAX), M(&mips_->fcr31));
|
||||
MOV(32, R(EAX), MIPSSTATE_VAR(fcr31));
|
||||
AND(32, R(EAX), Imm32(0x01000003));
|
||||
|
||||
// If it's 0 (nearest + no flush0), we don't actually bother setting - we cleared the rounding
|
||||
// mode out in restoreRoundingMode anyway. This is the most common.
|
||||
FixupBranch skip = J_CC(CC_Z);
|
||||
STMXCSR(M(&mips_->temp));
|
||||
STMXCSR(MIPSSTATE_VAR(temp));
|
||||
|
||||
// The MIPS bits don't correspond exactly, so we have to adjust.
|
||||
// 0 -> 0 (skip2), 1 -> 3, 2 -> 2 (skip2), 3 -> 1
|
||||
@ -96,15 +96,15 @@ void Jit::GenerateFixedCode(JitOptions &jo) {
|
||||
// Adjustment complete, now reconstruct MXCSR
|
||||
SHL(32, R(EAX), Imm8(13));
|
||||
// Before setting new bits, we must clear the old ones.
|
||||
AND(32, M(&mips_->temp), Imm32(~(7 << 13))); // Clearing bits 13-14 (rounding mode) and 15 (flush to zero)
|
||||
OR(32, M(&mips_->temp), R(EAX));
|
||||
AND(32, MIPSSTATE_VAR(temp), Imm32(~(7 << 13))); // Clearing bits 13-14 (rounding mode) and 15 (flush to zero)
|
||||
OR(32, MIPSSTATE_VAR(temp), R(EAX));
|
||||
|
||||
TEST(32, M(&mips_->fcr31), Imm32(1 << 24));
|
||||
TEST(32, MIPSSTATE_VAR(fcr31), Imm32(1 << 24));
|
||||
FixupBranch skip3 = J_CC(CC_Z);
|
||||
OR(32, M(&mips_->temp), Imm32(1 << 15));
|
||||
OR(32, MIPSSTATE_VAR(temp), Imm32(1 << 15));
|
||||
SetJumpTarget(skip3);
|
||||
|
||||
LDMXCSR(M(&mips_->temp));
|
||||
LDMXCSR(MIPSSTATE_VAR(temp));
|
||||
SetJumpTarget(skip);
|
||||
RET();
|
||||
}
|
||||
@ -112,7 +112,7 @@ void Jit::GenerateFixedCode(JitOptions &jo) {
|
||||
updateRoundingMode = AlignCode16(); {
|
||||
// If it's only ever 0, we don't actually bother applying or restoring it.
|
||||
// This is the most common situation.
|
||||
TEST(32, M(&mips_->fcr31), Imm32(0x01000003));
|
||||
TEST(32, MIPSSTATE_VAR(fcr31), Imm32(0x01000003));
|
||||
FixupBranch skip = J_CC(CC_Z);
|
||||
#ifdef _M_X64
|
||||
// TODO: Move the hasSetRounding flag somewhere we can reach it through the context pointer, or something.
|
||||
@ -167,7 +167,7 @@ void Jit::GenerateFixedCode(JitOptions &jo) {
|
||||
|
||||
dispatcherNoCheck = GetCodePtr();
|
||||
|
||||
MOV(32, R(EAX), M(&mips_->pc));
|
||||
MOV(32, R(EAX), MIPSSTATE_VAR(pc));
|
||||
dispatcherInEAXNoCheck = GetCodePtr();
|
||||
|
||||
#ifdef MASKED_PSP_MEMORY
|
||||
@ -185,9 +185,8 @@ void Jit::GenerateFixedCode(JitOptions &jo) {
|
||||
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, M(&mips_->debugCount), Imm8(1));
|
||||
if (enableDebug) {
|
||||
ADD(32, MIPSSTATE_VAR(debugCount), Imm8(1));
|
||||
}
|
||||
//grab from list and jump to it
|
||||
AND(32, R(EAX), Imm32(MIPS_EMUHACK_VALUE_MASK));
|
||||
|
@ -686,7 +686,7 @@ void Jit::Comp_JumpReg(MIPSOpcode op)
|
||||
{
|
||||
// If this is a syscall, write the pc (for thread switching and other good reasons.)
|
||||
gpr.MapReg(rs, true, false);
|
||||
MOV(32, M(&mips_->pc), gpr.R(rs));
|
||||
MOV(32, MIPSSTATE_VAR(pc), gpr.R(rs));
|
||||
if (andLink)
|
||||
gpr.SetImm(rd, GetCompilerPC() + 8);
|
||||
CompileDelaySlot(DELAYSLOT_FLUSH);
|
||||
@ -788,7 +788,7 @@ void Jit::Comp_Syscall(MIPSOpcode op)
|
||||
js.downcountAmount = -offset;
|
||||
|
||||
if (!js.inDelaySlot) {
|
||||
MOV(32, M(&mips_->pc), Imm32(GetCompilerPC() + 4));
|
||||
MOV(32, MIPSSTATE_VAR(pc), Imm32(GetCompilerPC() + 4));
|
||||
}
|
||||
|
||||
#ifdef USE_PROFILER
|
||||
|
@ -249,8 +249,8 @@ void Jit::Comp_FPU2op(MIPSOpcode op) {
|
||||
MOV(32, R(TEMPREG), M(&mxcsrTemp));
|
||||
AND(32, R(TEMPREG), Imm32(~(3 << 13)));
|
||||
OR(32, R(TEMPREG), Imm32(setMXCSR << 13));
|
||||
MOV(32, M(&mips_->temp), R(TEMPREG));
|
||||
LDMXCSR(M(&mips_->temp));
|
||||
MOV(32, MIPSSTATE_VAR(temp), R(TEMPREG));
|
||||
LDMXCSR(MIPSSTATE_VAR(temp));
|
||||
}
|
||||
|
||||
(this->*conv)(TEMPREG, fpr.R(fs));
|
||||
@ -388,7 +388,7 @@ void Jit::Comp_mxc1(MIPSOpcode op) {
|
||||
gpr.MapReg(MIPS_REG_FPCOND, true, false);
|
||||
}
|
||||
gpr.MapReg(rt, false, true);
|
||||
MOV(32, gpr.R(rt), M(&mips_->fcr31));
|
||||
MOV(32, gpr.R(rt), MIPSSTATE_VAR(fcr31));
|
||||
if (wasImm) {
|
||||
if (gpr.GetImm(MIPS_REG_FPCOND) & 1) {
|
||||
OR(32, gpr.R(rt), Imm32(1 << 23));
|
||||
@ -426,7 +426,7 @@ void Jit::Comp_mxc1(MIPSOpcode op) {
|
||||
RestoreRoundingMode();
|
||||
if (gpr.IsImm(rt)) {
|
||||
gpr.SetImm(MIPS_REG_FPCOND, (gpr.GetImm(rt) >> 23) & 1);
|
||||
MOV(32, M(&mips_->fcr31), Imm32(gpr.GetImm(rt) & 0x0181FFFF));
|
||||
MOV(32, MIPSSTATE_VAR(fcr31), Imm32(gpr.GetImm(rt) & 0x0181FFFF));
|
||||
if ((gpr.GetImm(rt) & 0x1000003) == 0) {
|
||||
// Default nearest / no-flush mode, just leave it cleared.
|
||||
} else {
|
||||
@ -440,8 +440,8 @@ void Jit::Comp_mxc1(MIPSOpcode op) {
|
||||
MOV(32, gpr.R(MIPS_REG_FPCOND), gpr.R(rt));
|
||||
SHR(32, gpr.R(MIPS_REG_FPCOND), Imm8(23));
|
||||
AND(32, gpr.R(MIPS_REG_FPCOND), Imm32(1));
|
||||
MOV(32, M(&mips_->fcr31), gpr.R(rt));
|
||||
AND(32, M(&mips_->fcr31), Imm32(0x0181FFFF));
|
||||
MOV(32, MIPSSTATE_VAR(fcr31), gpr.R(rt));
|
||||
AND(32, MIPSSTATE_VAR(fcr31), Imm32(0x0181FFFF));
|
||||
gpr.UnlockAll();
|
||||
UpdateRoundingMode();
|
||||
ApplyRoundingMode();
|
||||
|
@ -1831,8 +1831,8 @@ void Jit::Comp_Vf2i(MIPSOpcode op) {
|
||||
if (setMXCSR != 0) {
|
||||
OR(32, R(TEMPREG), Imm32(setMXCSR << 13));
|
||||
}
|
||||
MOV(32, M(&mips_->temp), R(TEMPREG));
|
||||
LDMXCSR(M(&mips_->temp));
|
||||
MOV(32, MIPSSTATE_VAR(temp), R(TEMPREG));
|
||||
LDMXCSR(MIPSSTATE_VAR(temp));
|
||||
}
|
||||
|
||||
u8 sregs[4], dregs[4];
|
||||
|
@ -193,7 +193,7 @@ void Jit::FlushPrefixV() {
|
||||
|
||||
void Jit::WriteDowncount(int offset) {
|
||||
const int downcount = js.downcountAmount + offset;
|
||||
SUB(32, M(&mips_->downcount), downcount > 127 ? Imm32(downcount) : Imm8(downcount));
|
||||
SUB(32, MIPSSTATE_VAR(downcount), downcount > 127 ? Imm32(downcount) : Imm8(downcount));
|
||||
}
|
||||
|
||||
void Jit::RestoreRoundingMode(bool force) {
|
||||
@ -226,13 +226,13 @@ void Jit::SaveFlags() {
|
||||
#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, MDisp(X64JitConstants::CTXREG, offsetof(MIPSState, saved_flags)), R(EAX));
|
||||
MOV(64, MIPSSTATE_VAR(saved_flags), R(EAX));
|
||||
#endif
|
||||
}
|
||||
|
||||
void Jit::LoadFlags() {
|
||||
#if defined(_M_X64)
|
||||
MOV(64, R(EAX), MDisp(X64JitConstants::CTXREG, offsetof(MIPSState, saved_flags)));
|
||||
MOV(64, R(EAX), MIPSSTATE_VAR(saved_flags));
|
||||
PUSH(64, R(EAX));
|
||||
#endif
|
||||
POPF();
|
||||
@ -347,7 +347,7 @@ const u8 *Jit::DoJit(u32 em_address, JitBlock *b)
|
||||
b->checkedEntry = (u8 *)GetCodePtr();
|
||||
// Downcount flag check. The last block decremented downcounter, and the flag should still be available.
|
||||
FixupBranch skip = J_CC(CC_NS);
|
||||
MOV(32, M(&mips_->pc), Imm32(js.blockStart));
|
||||
MOV(32, MIPSSTATE_VAR(pc), Imm32(js.blockStart));
|
||||
JMP(outerLoop, true); // downcount hit zero - go advance.
|
||||
SetJumpTarget(skip);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user