From fc3b3449ed680004831a0b40adbb539faa58202f Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Tue, 12 Nov 2013 23:53:17 -0800 Subject: [PATCH 1/7] Enable frameskipping in the null gpu. In case it's used (I used it to check cpu-only perf on Android.) --- GPU/Null/NullGpu.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/GPU/Null/NullGpu.h b/GPU/Null/NullGpu.h index f080503c1..050588cdd 100644 --- a/GPU/Null/NullGpu.h +++ b/GPU/Null/NullGpu.h @@ -46,6 +46,10 @@ public: fullInfo = "NULL"; } + virtual bool FramebufferReallyDirty() { + return !(gstate_c.skipDrawReason & SKIPDRAW_SKIPFRAME); + } + protected: virtual void FastRunLoop(DisplayList &list); }; From 98fb2e04020182f0b80a414ce46f3108ac312702 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Tue, 12 Nov 2013 01:21:04 -0800 Subject: [PATCH 2/7] armjit: Refer to R11 as MEMBASEREG for clarity. --- Core/MIPS/ARM/ArmAsm.cpp | 2 +- Core/MIPS/ARM/ArmCompFPU.cpp | 4 +-- Core/MIPS/ARM/ArmCompLoadStore.cpp | 40 +++++++++++++++--------------- Core/MIPS/ARM/ArmCompVFPU.cpp | 8 +++--- Core/MIPS/ARM/ArmRegCache.cpp | 4 +-- Core/MIPS/ARM/ArmRegCache.h | 1 + 6 files changed, 30 insertions(+), 29 deletions(-) diff --git a/Core/MIPS/ARM/ArmAsm.cpp b/Core/MIPS/ARM/ArmAsm.cpp index 7e5845722..2764cc120 100644 --- a/Core/MIPS/ARM/ArmAsm.cpp +++ b/Core/MIPS/ARM/ArmAsm.cpp @@ -159,7 +159,7 @@ void Jit::GenerateFixedCode() LDR(R0, CTXREG, offsetof(MIPSState, pc)); BIC(R0, R0, Operand2(0xC0, 4)); // &= 0x3FFFFFFF - LDR(R0, R11, R0); + LDR(R0, MEMBASEREG, R0); AND(R1, R0, Operand2(0xFC, 4)); // rotation is to the right, in 2-bit increments. BIC(R0, R0, Operand2(0xFC, 4)); CMP(R1, Operand2(MIPS_EMUHACK_OPCODE >> 24, 4)); diff --git a/Core/MIPS/ARM/ArmCompFPU.cpp b/Core/MIPS/ARM/ArmCompFPU.cpp index 1a5381cd7..f615808b4 100644 --- a/Core/MIPS/ARM/ArmCompFPU.cpp +++ b/Core/MIPS/ARM/ArmCompFPU.cpp @@ -117,7 +117,7 @@ void Jit::Comp_FPULS(MIPSOpcode op) SetCCAndR0ForSafeAddress(rs, offset, R1); doCheck = true; } - ADD(R0, R0, R11); + ADD(R0, R0, MEMBASEREG); } #ifdef __ARM_ARCH_7S__ FixupBranch skip; @@ -161,7 +161,7 @@ void Jit::Comp_FPULS(MIPSOpcode op) SetCCAndR0ForSafeAddress(rs, offset, R1); doCheck = true; } - ADD(R0, R0, R11); + ADD(R0, R0, MEMBASEREG); } #ifdef __ARM_ARCH_7S__ FixupBranch skip2; diff --git a/Core/MIPS/ARM/ArmCompLoadStore.cpp b/Core/MIPS/ARM/ArmCompLoadStore.cpp index 1786c45c0..5e4be873c 100644 --- a/Core/MIPS/ARM/ArmCompLoadStore.cpp +++ b/Core/MIPS/ARM/ArmCompLoadStore.cpp @@ -162,31 +162,31 @@ namespace MIPSComp switch (o) { case 34: // lwl - LDR(R0, R11, R0); + LDR(R0, MEMBASEREG, R0); ANDI2R(gpr.R(rt), gpr.R(rt), 0x00ffffff >> shift, R1); ORR(gpr.R(rt), gpr.R(rt), Operand2(R0, ST_LSL, 24 - shift)); break; case 38: // lwr - LDR(R0, R11, R0); + LDR(R0, MEMBASEREG, R0); ANDI2R(gpr.R(rt), gpr.R(rt), 0xffffff00 << (24 - shift), R1); ORR(gpr.R(rt), gpr.R(rt), Operand2(R0, ST_LSR, shift)); break; case 42: // swl - LDR(R1, R11, R0); + LDR(R1, MEMBASEREG, R0); // Don't worry, can't use temporary. ANDI2R(R1, R1, 0xffffff00 << shift, R0); ORR(R1, R1, Operand2(gpr.R(rt), ST_LSR, 24 - shift)); - STR(R1, R11, R0); + STR(R1, MEMBASEREG, R0); break; case 46: // swr - LDR(R1, R11, R0); + LDR(R1, MEMBASEREG, R0); // Don't worry, can't use temporary. ANDI2R(R1, R1, 0x00ffffff >> (24 - shift), R0); ORR(R1, R1, Operand2(gpr.R(rt), ST_LSL, shift)); - STR(R1, R11, R0); + STR(R1, MEMBASEREG, R0); break; } return; @@ -223,7 +223,7 @@ namespace MIPSComp switch (o) { case 34: // lwl MOVI2R(R10, 0x00ffffff); - LDR(R0, R11, R0); + LDR(R0, MEMBASEREG, R0); AND(gpr.R(rt), gpr.R(rt), Operand2(R10, ST_LSR, R1)); RSB(R1, R1, 24); ORR(gpr.R(rt), gpr.R(rt), Operand2(R0, ST_LSL, R1)); @@ -231,7 +231,7 @@ namespace MIPSComp case 38: // lwr MOVI2R(R10, 0xffffff00); - LDR(R0, R11, R0); + LDR(R0, MEMBASEREG, R0); LSR(R0, R0, R1); RSB(R1, R1, 24); AND(gpr.R(rt), gpr.R(rt), Operand2(R10, ST_LSL, R1)); @@ -240,21 +240,21 @@ namespace MIPSComp case 42: // swl MOVI2R(R10, 0xffffff00); - LDR(R9, R11, R0); + LDR(R9, MEMBASEREG, R0); AND(R9, R9, Operand2(R10, ST_LSL, R1)); RSB(R1, R1, 24); ORR(R9, R9, Operand2(gpr.R(rt), ST_LSR, R1)); - STR(R9, R11, R0); + STR(R9, MEMBASEREG, R0); break; case 46: // swr MOVI2R(R10, 0x00ffffff); - LDR(R9, R11, R0); + LDR(R9, MEMBASEREG, R0); RSB(R1, R1, 24); AND(R9, R9, Operand2(R10, ST_LSR, R1)); RSB(R1, R1, 24); ORR(R9, R9, Operand2(gpr.R(rt), ST_LSL, R1)); - STR(R9, R11, R0); + STR(R9, MEMBASEREG, R0); break; } @@ -353,15 +353,15 @@ namespace MIPSComp switch (o) { // Load - case 35: LDR (gpr.R(rt), R11, addrReg); break; - case 37: LDRH (gpr.R(rt), R11, addrReg); break; - case 33: LDRSH(gpr.R(rt), R11, addrReg); break; - case 36: LDRB (gpr.R(rt), R11, addrReg); break; - case 32: LDRSB(gpr.R(rt), R11, addrReg); break; + case 35: LDR (gpr.R(rt), MEMBASEREG, addrReg); break; + case 37: LDRH (gpr.R(rt), MEMBASEREG, addrReg); break; + case 33: LDRSH(gpr.R(rt), MEMBASEREG, addrReg); break; + case 36: LDRB (gpr.R(rt), MEMBASEREG, addrReg); break; + case 32: LDRSB(gpr.R(rt), MEMBASEREG, addrReg); break; // Store - case 43: STR (gpr.R(rt), R11, addrReg); break; - case 41: STRH (gpr.R(rt), R11, addrReg); break; - case 40: STRB (gpr.R(rt), R11, addrReg); break; + case 43: STR (gpr.R(rt), MEMBASEREG, addrReg); break; + case 41: STRH (gpr.R(rt), MEMBASEREG, addrReg); break; + case 40: STRB (gpr.R(rt), MEMBASEREG, addrReg); break; } if (doCheck) { if (load) { diff --git a/Core/MIPS/ARM/ArmCompVFPU.cpp b/Core/MIPS/ARM/ArmCompVFPU.cpp index 916fa8402..99f1bd145 100644 --- a/Core/MIPS/ARM/ArmCompVFPU.cpp +++ b/Core/MIPS/ARM/ArmCompVFPU.cpp @@ -263,7 +263,7 @@ namespace MIPSComp SetCCAndR0ForSafeAddress(rs, imm, R1); doCheck = true; } - ADD(R0, R0, R11); + ADD(R0, R0, MEMBASEREG); } #ifdef __ARM_ARCH_7S__ FixupBranch skip; @@ -301,7 +301,7 @@ namespace MIPSComp SetCCAndR0ForSafeAddress(rs, imm, R1); doCheck = true; } - ADD(R0, R0, R11); + ADD(R0, R0, MEMBASEREG); } #ifdef __ARM_ARCH_7S__ FixupBranch skip; @@ -357,7 +357,7 @@ namespace MIPSComp SetCCAndR0ForSafeAddress(rs, imm, R1); doCheck = true; } - ADD(R0, R0, R11); + ADD(R0, R0, MEMBASEREG); } #ifdef __ARM_ARCH_7S__ @@ -406,7 +406,7 @@ namespace MIPSComp SetCCAndR0ForSafeAddress(rs, imm, R1); doCheck = true; } - ADD(R0, R0, R11); + ADD(R0, R0, MEMBASEREG); } #ifdef __ARM_ARCH_7S__ diff --git a/Core/MIPS/ARM/ArmRegCache.cpp b/Core/MIPS/ARM/ArmRegCache.cpp index 33e9d8968..c8f4f8650 100644 --- a/Core/MIPS/ARM/ArmRegCache.cpp +++ b/Core/MIPS/ARM/ArmRegCache.cpp @@ -91,7 +91,7 @@ ARMReg ArmRegCache::MapRegAsPointer(MIPSGPReg mipsReg) { // read-only, non-dirt // Convert to a pointer by adding the base and clearing off the top bits. // If SP, we can probably avoid the top bit clear, let's play with that later. emit_->BIC(armReg, armReg, Operand2(0xC0, 4)); // &= 0x3FFFFFFF - emit_->ADD(armReg, R11, armReg); + emit_->ADD(armReg, MEMBASEREG, armReg); ar[armReg].isDirty = false; ar[armReg].mipsReg = mipsReg; mr[mipsReg].loc = ML_ARMREG_AS_PTR; @@ -356,7 +356,7 @@ void ArmRegCache::FlushArmReg(ARMReg r) { if (ar[r].mipsReg != MIPS_REG_INVALID) { auto &mreg = mr[ar[r].mipsReg]; if (mreg.loc == ML_ARMREG_IMM) { - // We know it's immedate value, no need to STR now. + // We know its immedate value, no need to STR now. mreg.loc = ML_IMM; mreg.reg = INVALID_REG; } else { diff --git a/Core/MIPS/ARM/ArmRegCache.h b/Core/MIPS/ARM/ArmRegCache.h index 23555b447..cb980b43e 100644 --- a/Core/MIPS/ARM/ArmRegCache.h +++ b/Core/MIPS/ARM/ArmRegCache.h @@ -24,6 +24,7 @@ using namespace ArmGen; #define CTXREG (R10) +#define MEMBASEREG (R11) // R2 to R8: mapped MIPS regs // R9 = code pointers From 26f5922174e8ebb1c8a1859817a20044b035b12f Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Wed, 13 Nov 2013 22:41:25 -0800 Subject: [PATCH 3/7] Return the correct value for fcr0/fir. This is what the PSP actually returns, it's read only. --- Core/HLE/sceKernelThread.cpp | 8 ++++++-- Core/HLE/sceKernelThread.h | 1 - Core/MIPS/ARM/ArmCompFPU.cpp | 10 +++------- Core/MIPS/MIPS.cpp | 10 ++++++---- Core/MIPS/MIPS.h | 3 ++- 5 files changed, 17 insertions(+), 15 deletions(-) diff --git a/Core/HLE/sceKernelThread.cpp b/Core/HLE/sceKernelThread.cpp index a2dcc4885..85a5d2348 100644 --- a/Core/HLE/sceKernelThread.cpp +++ b/Core/HLE/sceKernelThread.cpp @@ -520,7 +520,7 @@ public: virtual void DoState(PointerWrap &p) { - auto s = p.Section("Thread", 1, 2); + auto s = p.Section("Thread", 1, 3); if (!s) return; @@ -531,6 +531,11 @@ public: p.Do(currentMipscallId); p.Do(currentCallbackId); p.Do(context); + if (s <= 2) + { + context.other[4] = context.other[5]; + context.other[3] = context.other[4]; + } p.Do(callbacks); @@ -1928,7 +1933,6 @@ void ThreadContext::reset() vfpuCtrl[VFPU_CTRL_RCX6] = 0x3f800000; vfpuCtrl[VFPU_CTRL_RCX7] = 0x3f800000; fpcond = 0; - fcr0 = 0; fcr31 = 0; hi = 0xDEADBEEF; lo = 0xDEADBEEF; diff --git a/Core/HLE/sceKernelThread.h b/Core/HLE/sceKernelThread.h index 4562509f7..b33582b58 100644 --- a/Core/HLE/sceKernelThread.h +++ b/Core/HLE/sceKernelThread.h @@ -132,7 +132,6 @@ struct ThreadContext u32 hi; u32 lo; - u32 fcr0; u32 fcr31; u32 fpcond; }; diff --git a/Core/MIPS/ARM/ArmCompFPU.cpp b/Core/MIPS/ARM/ArmCompFPU.cpp index f615808b4..47ec38c4c 100644 --- a/Core/MIPS/ARM/ArmCompFPU.cpp +++ b/Core/MIPS/ARM/ArmCompFPU.cpp @@ -339,8 +339,7 @@ void Jit::Comp_mxc1(MIPSOpcode op) return; case 2: //cfc1 - if (fs == 31) - { + if (fs == 31) { gpr.MapDirtyIn(rt, MIPS_REG_FPCOND); LDR(gpr.R(rt), CTXREG, offsetof(MIPSState, fcr31)); #ifdef HAVE_ARMV7 @@ -350,11 +349,8 @@ void Jit::Comp_mxc1(MIPSOpcode op) ANDI2R(gpr.R(rt), gpr.R(rt), ~(0x1 << 23), R1); // R1 won't be used, this turns into a simple BIC. ORR(gpr.R(rt), gpr.R(rt), Operand2(R0, ST_LSL, 23)); #endif - } - else if (fs == 0) - { - gpr.MapReg(rt, MAP_DIRTY | MAP_NOINIT); - LDR(gpr.R(rt), CTXREG, offsetof(MIPSState, fcr0)); + } else if (fs == 0) { + gpr.SetImm(rt, MIPSState::FCR0_VALUE); } return; diff --git a/Core/MIPS/MIPS.cpp b/Core/MIPS/MIPS.cpp index f1a4214e1..153a2f415 100644 --- a/Core/MIPS/MIPS.cpp +++ b/Core/MIPS/MIPS.cpp @@ -134,7 +134,6 @@ void MIPSState::Reset() hi = 0; lo = 0; fpcond = 0; - fcr0 = 0; fcr31 = 0; debugCount = 0; currentMIPS = this; @@ -147,7 +146,7 @@ void MIPSState::Reset() } void MIPSState::DoState(PointerWrap &p) { - auto s = p.Section("MIPSState", 1); + auto s = p.Section("MIPSState", 1, 2); if (!s) return; @@ -169,7 +168,10 @@ void MIPSState::DoState(PointerWrap &p) { p.Do(hi); p.Do(lo); p.Do(fpcond); - p.Do(fcr0); + if (s <= 1) { + u32 fcr0_unusued = 0; + p.Do(fcr0_unusued); + } p.Do(fcr31); p.Do(rng.m_w); p.Do(rng.m_z); @@ -225,7 +227,7 @@ u32 MIPSState::ReadFCR(int reg) } else if (reg == 0) { - return fcr0; + return FCR0_VALUE; } else { diff --git a/Core/MIPS/MIPS.h b/Core/MIPS/MIPS.h index 53b2349ce..84c047c64 100644 --- a/Core/MIPS/MIPS.h +++ b/Core/MIPS/MIPS.h @@ -146,7 +146,6 @@ public: u32 hi; u32 lo; - u32 fcr0; u32 fcr31; //fpu control register u32 fpcond; // cache the cond flag of fcr31 (& 1 << 23) }; @@ -165,6 +164,8 @@ public: // Debug stuff u32 debugCount; // can be used to count basic blocks before crashes, etc. + static const u32 FCR0_VALUE = 0x00003351; + void WriteFCR(int reg, int value); u32 ReadFCR(int reg); From 763eff181dcd3949f7c30614ca3dc2ceb15538aa Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Wed, 13 Nov 2013 23:44:15 -0800 Subject: [PATCH 4/7] Fix handling of jalr when delay slot changes rd. --- Core/MIPS/ARM/ArmCompBranch.cpp | 18 ++++++++++-------- Core/MIPS/x86/CompBranch.cpp | 16 ++++++++++------ 2 files changed, 20 insertions(+), 14 deletions(-) diff --git a/Core/MIPS/ARM/ArmCompBranch.cpp b/Core/MIPS/ARM/ArmCompBranch.cpp index 00dac7fa0..4577a4604 100644 --- a/Core/MIPS/ARM/ArmCompBranch.cpp +++ b/Core/MIPS/ARM/ArmCompBranch.cpp @@ -461,23 +461,28 @@ void Jit::Comp_JumpReg(MIPSOpcode op) } MIPSGPReg rs = _RS; MIPSGPReg rd = _RD; + bool andLink = (op & 0x3f) == 9; MIPSOpcode delaySlotOp = Memory::Read_Instruction(js.compilerPC + 4); bool delaySlotIsNice = IsDelaySlotNiceReg(op, delaySlotOp, rs); + if (andLink && rs == rd) + delaySlotIsNice = false; CONDITIONAL_NICE_DELAYSLOT; ARMReg destReg = R8; if (IsSyscall(delaySlotOp)) { - _dbg_assert_msg_(JIT, (op & 0x3f) == 8, "jalr followed by syscall not supported."); - gpr.MapReg(rs); MovToPC(gpr.R(rs)); // For syscall to be able to return. + if (andLink) + gpr.SetImm(rd, js.compilerPC + 8); CompileDelaySlot(DELAYSLOT_FLUSH); return; // Syscall wrote exit code. } else if (delaySlotIsNice) { + if (andLink) + gpr.SetImm(rd, js.compilerPC + 8); CompileDelaySlot(DELAYSLOT_NICE); - if (rs == MIPS_REG_RA && g_Config.bDiscardRegsOnJRRA) { + if (!andLink && rs == MIPS_REG_RA && g_Config.bDiscardRegsOnJRRA) { // According to the MIPS ABI, there are some regs we don't need to preserve. // Let's discard them so we don't need to write them back. // NOTE: Not all games follow the MIPS ABI! Tekken 6, for example, will crash @@ -492,9 +497,6 @@ void Jit::Comp_JumpReg(MIPSOpcode op) if (jo.continueJumps && gpr.IsImm(rs) && js.numInstructions < jo.continueMaxInstructions) { // Account for the increment in the loop. js.compilerPC = gpr.GetImm(rs) - 4; - if ((op & 0x3f) == 9) { - gpr.SetImm(rd, js.compilerPC + 8); - } // In case the delay slot was a break or something. js.compiling = true; return; @@ -507,6 +509,8 @@ void Jit::Comp_JumpReg(MIPSOpcode op) // Delay slot - this case is very rare, might be able to free up R8. gpr.MapReg(rs); MOV(R8, gpr.R(rs)); + if (andLink) + gpr.SetImm(rd, js.compilerPC + 8); CompileDelaySlot(DELAYSLOT_NICE); FlushAll(); } @@ -516,8 +520,6 @@ void Jit::Comp_JumpReg(MIPSOpcode op) case 8: //jr break; case 9: //jalr - gpr.SetRegImm(R0, js.compilerPC + 8); - STR(R0, CTXREG, (int)rd * 4); break; default: _dbg_assert_msg_(CPU,0,"Trying to compile instruction that can't be compiled"); diff --git a/Core/MIPS/x86/CompBranch.cpp b/Core/MIPS/x86/CompBranch.cpp index 20763a6cb..9f96118cb 100644 --- a/Core/MIPS/x86/CompBranch.cpp +++ b/Core/MIPS/x86/CompBranch.cpp @@ -587,18 +587,21 @@ void Jit::Comp_JumpReg(MIPSOpcode op) } MIPSGPReg rs = _RS; MIPSGPReg rd = _RD; + bool andLink = (op & 0x3f) == 9; MIPSOpcode delaySlotOp = Memory::Read_Instruction(js.compilerPC + 4); bool delaySlotIsNice = IsDelaySlotNiceReg(op, delaySlotOp, rs); + if (andLink && rs == rd) + delaySlotIsNice = false; CONDITIONAL_NICE_DELAYSLOT; if (IsSyscall(delaySlotOp)) { - _dbg_assert_msg_(JIT, (op & 0x3f) == 8, "jalr followed by syscall not supported."); - // If this is a syscall, write the pc (for thread switching and other good reasons.) gpr.MapReg(rs, true, false); MOV(32, M(¤tMIPS->pc), gpr.R(rs)); + if (andLink) + gpr.SetImm(rd, js.compilerPC + 8); CompileDelaySlot(DELAYSLOT_FLUSH); // Syscalls write the exit code for us. @@ -607,9 +610,11 @@ void Jit::Comp_JumpReg(MIPSOpcode op) } else if (delaySlotIsNice) { + if (andLink) + gpr.SetImm(rd, js.compilerPC + 8); CompileDelaySlot(DELAYSLOT_NICE); - if (rs == MIPS_REG_RA && g_Config.bDiscardRegsOnJRRA) { + if (!andLink && rs == MIPS_REG_RA && g_Config.bDiscardRegsOnJRRA) { // According to the MIPS ABI, there are some regs we don't need to preserve. // Let's discard them so we don't need to write them back. // NOTE: Not all games follow the MIPS ABI! Tekken 6, for example, will crash @@ -625,8 +630,6 @@ void Jit::Comp_JumpReg(MIPSOpcode op) { // Account for the increment in the loop. js.compilerPC = gpr.GetImm(rs) - 4; - if ((op & 0x3f) == 9) - gpr.SetImm(rd, js.compilerPC + 8); // In case the delay slot was a break or something. js.compiling = true; return; @@ -640,6 +643,8 @@ void Jit::Comp_JumpReg(MIPSOpcode op) // Latch destination now - save it in memory. gpr.MapReg(rs, true, false); MOV(32, M(&savedPC), gpr.R(rs)); + if (andLink) + gpr.SetImm(rd, js.compilerPC + 8); CompileDelaySlot(DELAYSLOT_NICE); MOV(32, R(EAX), M(&savedPC)); FlushAll(); @@ -650,7 +655,6 @@ void Jit::Comp_JumpReg(MIPSOpcode op) case 8: //jr break; case 9: //jalr - MOV(32, M(&mips_->r[rd]), Imm32(js.compilerPC + 8)); break; default: _dbg_assert_msg_(CPU,0,"Trying to compile instruction that can't be compiled"); From 3c73d0d1f14841e437f3c8ddc94a1628e30002be Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Thu, 14 Nov 2013 00:36:06 -0800 Subject: [PATCH 5/7] armjit: Read fpu control regs other than 0/31 as 0. Always seem to give zero, regardless of the value of fcr31, etc. --- Core/MIPS/ARM/ArmCompFPU.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Core/MIPS/ARM/ArmCompFPU.cpp b/Core/MIPS/ARM/ArmCompFPU.cpp index 47ec38c4c..df7cf6901 100644 --- a/Core/MIPS/ARM/ArmCompFPU.cpp +++ b/Core/MIPS/ARM/ArmCompFPU.cpp @@ -351,6 +351,9 @@ void Jit::Comp_mxc1(MIPSOpcode op) #endif } else if (fs == 0) { gpr.SetImm(rt, MIPSState::FCR0_VALUE); + } else { + // Unsupported regs are always 0. + gpr.SetImm(rt, 0); } return; From 21c9577801881d6e7153c54650a97889083fdf6f Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Thu, 14 Nov 2013 23:44:49 -0800 Subject: [PATCH 6/7] Initialize fcr31 correctly (even though unsup.) --- Core/HLE/sceKernelThread.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Core/HLE/sceKernelThread.cpp b/Core/HLE/sceKernelThread.cpp index 85a5d2348..1544e8d01 100644 --- a/Core/HLE/sceKernelThread.cpp +++ b/Core/HLE/sceKernelThread.cpp @@ -1933,7 +1933,7 @@ void ThreadContext::reset() vfpuCtrl[VFPU_CTRL_RCX6] = 0x3f800000; vfpuCtrl[VFPU_CTRL_RCX7] = 0x3f800000; fpcond = 0; - fcr31 = 0; + fcr31 = 0x00000e00; hi = 0xDEADBEEF; lo = 0xDEADBEEF; } From 5128083d934b91f548598efe5f139fa982b3d306 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Thu, 14 Nov 2013 23:57:28 -0800 Subject: [PATCH 7/7] Mask out fcr31 bits that can't be set on a PSP. --- Core/MIPS/ARM/ArmCompFPU.cpp | 1 + Core/MIPS/MIPS.cpp | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/Core/MIPS/ARM/ArmCompFPU.cpp b/Core/MIPS/ARM/ArmCompFPU.cpp index df7cf6901..19f11f2a3 100644 --- a/Core/MIPS/ARM/ArmCompFPU.cpp +++ b/Core/MIPS/ARM/ArmCompFPU.cpp @@ -385,6 +385,7 @@ void Jit::Comp_mxc1(MIPSOpcode op) VMSR(R1); */ // Update MIPS state + // TODO: Technically, should mask by 0x0181FFFF. Maybe just put all of FCR31 in the reg? STR(gpr.R(rt), CTXREG, offsetof(MIPSState, fcr31)); #ifdef HAVE_ARMV7 UBFX(gpr.R(MIPS_REG_FPCOND), gpr.R(rt), 23, 1); diff --git a/Core/MIPS/MIPS.cpp b/Core/MIPS/MIPS.cpp index 153a2f415..edc8d4f5b 100644 --- a/Core/MIPS/MIPS.cpp +++ b/Core/MIPS/MIPS.cpp @@ -206,7 +206,7 @@ void MIPSState::WriteFCR(int reg, int value) { if (reg == 31) { - fcr31 = value; + fcr31 = value & 0x0181FFFF; fpcond = (value >> 23) & 1; } else