diff --git a/Common/ArmEmitter.cpp b/Common/ArmEmitter.cpp index fa795c4bf3..c1193d544c 100644 --- a/Common/ArmEmitter.cpp +++ b/Common/ArmEmitter.cpp @@ -877,7 +877,13 @@ void ARMXEmitter::VCMP(ARMReg Vd, bool E) } void ARMXEmitter::VMRS_APSR() { - Write32(0xEEF10A10 | (15 << 12)); + Write32(NO_COND | 0xEF10A10 | (15 << 12)); +} +void ARMXEmitter::VMRS(ARMReg Rt) { + Write32(NO_COND | (0xEF << 20) | (1 << 16) | (Rt << 12) | 0xA10); +} +void ARMXEmitter::VMSR(ARMReg Rt) { + Write32(NO_COND | (0xEE << 20) | (1 << 16) | (Rt << 12) | 0xA10); } void ARMXEmitter::VDIV(ARMReg Vd, ARMReg Vn, ARMReg Vm) diff --git a/Common/ArmEmitter.h b/Common/ArmEmitter.h index 3d76ee3bde..d68a2390ad 100644 --- a/Common/ArmEmitter.h +++ b/Common/ArmEmitter.h @@ -560,6 +560,8 @@ public: void VCVT(ARMReg Dest, ARMReg Src, int flags); void VMRS_APSR(); + void VMRS(ARMReg Rt); + void VMSR(ARMReg Rt); void QuickCallFunction(ARMReg scratchreg, void *func); diff --git a/Core/MIPS/ARM/ArmCompFPU.cpp b/Core/MIPS/ARM/ArmCompFPU.cpp index 061f98fec2..821d581974 100644 --- a/Core/MIPS/ARM/ArmCompFPU.cpp +++ b/Core/MIPS/ARM/ArmCompFPU.cpp @@ -223,9 +223,9 @@ void Jit::Comp_FPU2op(u32 op) break; case 36: //FsI(fd) = (int) F(fs); break; //cvt.w.s DISABLE; - // Seems to round wrong in hardware + // Requires correct floating mode set fpr.MapDirtyIn(fd, fs); - VCVT(fpr.R(fd), fpr.R(fs), TO_INT | ROUND_TO_ZERO); + VCVT(fpr.R(fd), fpr.R(fs), TO_INT); break; default: DISABLE; @@ -260,6 +260,32 @@ void Jit::Comp_mxc1(u32 op) return; case 6: //currentMIPS->WriteFCR(fs, R(rt)); break; //ctc1 + // Rounding isn't right. + /*if (fs == 31) + { + fpr.MapReg(rt, 0); + AND(R0, gpr.R(rt), Operand2(3)); + // MIPS Rounding Mode <-> ARM Rounding Mode + // 0, 1, 2, 3 <-> 0, 3, 1, 2 + CMP(R0, Operand2(1)); + SetCC(CC_EQ); + SUB(R0, R0, Operand2(1)); + SetCC(CC_GT); + ADD(R0, R0, Operand2(2)); + SetCC(CC_AL); + + // Load and Store RM to FPSCR + VMRS(R1); + BIC(R1, R1, Operand2(0x3 << 22)); + ORR(R1, R1, Operand2(R0, ST_LSL, 22)); + VMSR(R1); + + // For interpreter (currently doesn't replace properly) + STR(gpr.R(rt), CTXREG, offsetof(MIPSState, fcr31)); + MOV(R0, Operand2(gpr.R(rt), ST_LSR, 23)); + AND(R0, R0, Operand2(1)); + STR(R0, CTXREG, offsetof(MIPSState, fpcond)); + }*/ Comp_Generic(op); return; }