X86/X64: We have the context register loaded, let's use it more.

This commit is contained in:
Henrik Rydgård 2017-07-05 13:12:42 +02:00
parent 385204bec6
commit 730e9ced6c
6 changed files with 36 additions and 29 deletions

View File

@ -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:

View File

@ -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));

View File

@ -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

View File

@ -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();

View File

@ -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];

View File

@ -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);