From 6cd3310171734788013cec7956d11a00b11ad76c Mon Sep 17 00:00:00 2001 From: Andrew Church Date: Sun, 18 Jan 2015 07:02:11 +0900 Subject: [PATCH] Fix FPSCR manipulation instructions. --- rpcs3/Emu/Cell/PPUInterpreter.h | 36 +++++++++------------------------ rpcs3/Emu/Cell/PPUThread.h | 21 +++++++++++++++++++ 2 files changed, 30 insertions(+), 27 deletions(-) diff --git a/rpcs3/Emu/Cell/PPUInterpreter.h b/rpcs3/Emu/Cell/PPUInterpreter.h index cee189cf89..868cb4252f 100644 --- a/rpcs3/Emu/Cell/PPUInterpreter.h +++ b/rpcs3/Emu/Cell/PPUInterpreter.h @@ -3631,41 +3631,23 @@ private: void MTFSB1(u32 crbd, bool rc) { u64 mask = (1ULL << (31 - crbd)); + if ((crbd >= 3 && crbd <= 6) && !(CPU.FPSCR.FPSCR & mask)) mask |= 1ULL << 31; //FPSCR.FX if ((crbd == 29) && !CPU.FPSCR.NI) LOG_WARNING(PPU, "Non-IEEE mode enabled"); - CPU.FPSCR.FPSCR |= mask; + CPU.SetFPSCR(CPU.FPSCR.FPSCR | mask); if(rc) CPU.UpdateCR1(); } void MCRFS(u32 crbd, u32 crbs) { - CPU.SetCR(crbd, (CPU.FPSCR.FPSCR >> ((7 - crbs) * 4)) & 0xf); - - switch (crbs) - { - case 0: - CPU.FPSCR.FX = CPU.FPSCR.OX = 0; - break; - case 1: - CPU.FPSCR.UX = CPU.FPSCR.ZX = CPU.FPSCR.XX = CPU.FPSCR.VXSNAN = 0; - break; - case 2: - CPU.FPSCR.VXISI = CPU.FPSCR.VXIDI = CPU.FPSCR.VXZDZ = CPU.FPSCR.VXIMZ = 0; - break; - case 3: - CPU.FPSCR.VXVC = 0; - break; - case 5: - CPU.FPSCR.VXSOFT = CPU.FPSCR.VXSQRT = CPU.FPSCR.VXCVI = 0; - break; - default: - break; - } + CPU.SetCR(crbd, (CPU.FPSCR.FPSCR >> ((7 - crbs) * 4)) & 0xf); + const u32 exceptions_mask = 0x9FF80700; + CPU.SetFPSCR(CPU.FPSCR.FPSCR & ~(exceptions_mask & 0xf << ((7 - crbs) * 4))); } void MTFSB0(u32 crbd, bool rc) { u64 mask = (1ULL << (31 - crbd)); if ((crbd == 29) && !CPU.FPSCR.NI) LOG_WARNING(PPU, "Non-IEEE mode disabled"); - CPU.FPSCR.FPSCR &= ~mask; + CPU.SetFPSCR(CPU.FPSCR.FPSCR & ~mask); if(rc) CPU.UpdateCR1(); } @@ -3675,8 +3657,7 @@ private: u32 val = (i & 0xF) << ((7 - crfd) * 4); const u32 oldNI = CPU.FPSCR.NI; - CPU.FPSCR.FPSCR &= ~mask; - CPU.FPSCR.FPSCR |= val; + CPU.SetFPSCR((CPU.FPSCR.FPSCR & ~mask) | val); if (CPU.FPSCR.NI != oldNI) { if (oldNI) @@ -3699,9 +3680,10 @@ private: { if(flm & (1 << i)) mask |= 0xf << (i * 4); } + mask &= ~0x60000000; const u32 oldNI = CPU.FPSCR.NI; - CPU.FPSCR.FPSCR = (CPU.FPSCR.FPSCR & ~mask) | ((u32&)CPU.FPR[frb] & mask); + CPU.SetFPSCR((CPU.FPSCR.FPSCR & ~mask) | ((u32&)CPU.FPR[frb] & mask)); if (CPU.FPSCR.NI != oldNI) { if (oldNI) diff --git a/rpcs3/Emu/Cell/PPUThread.h b/rpcs3/Emu/Cell/PPUThread.h index f107f1db03..5256eaa0e5 100644 --- a/rpcs3/Emu/Cell/PPUThread.h +++ b/rpcs3/Emu/Cell/PPUThread.h @@ -53,6 +53,8 @@ enum FPSCR_EXP FPSCR_VXSOFT = 0x00000400, FPSCR_VXSQRT = 0x00000200, FPSCR_VXCVI = 0x00000100, + + FPSCR_VX_ALL = FPSCR_VXSNAN | FPSCR_VXISI | FPSCR_VXIDI | FPSCR_VXZDZ | FPSCR_VXIMZ | FPSCR_VXVC | FPSCR_VXSOFT | FPSCR_VXSQRT | FPSCR_VXCVI, }; enum FPSCR_RN @@ -677,6 +679,25 @@ public: XER.SO |= set; } + void UpdateFPSCR_FEX() + { + const u32 exceptions = (FPSCR.FPSCR >> 25) & 0x1F; + const u32 enabled = (FPSCR.FPSCR >> 3) & 0x1F; + if (exceptions & enabled) FPSCR.FEX = 1; + } + + void UpdateFPSCR_VX() + { + if (FPSCR.FPSCR & FPSCR_VX_ALL) FPSCR.VX = 1; + } + + void SetFPSCR(const u32 val) + { + FPSCR.FPSCR = val & ~(FPSCR_FEX | FPSCR_VX); + UpdateFPSCR_VX(); + UpdateFPSCR_FEX(); + } + void SetFPSCRException(const FPSCR_EXP mask) { if ((FPSCR.FPSCR & mask) != mask) FPSCR.FX = 1;