From 9939f1cd05cf4ffbe4bfae65efb3a56d1269101c Mon Sep 17 00:00:00 2001 From: Stenzek Date: Fri, 7 Mar 2025 15:48:25 +1000 Subject: [PATCH] CPU/Interpreter: Use __builtin_{add,sub}_overflow for exceptions Recompiler already does this. --- src/core/cpu_core.cpp | 39 ++++++++++++++++++++++++++------------- 1 file changed, 26 insertions(+), 13 deletions(-) diff --git a/src/core/cpu_core.cpp b/src/core/cpu_core.cpp index 26c86e3b4..3197b0b6c 100644 --- a/src/core/cpu_core.cpp +++ b/src/core/cpu_core.cpp @@ -811,14 +811,26 @@ const std::array(old_value), static_cast(add_value), + reinterpret_cast(new_value)); +#else + *new_value = old_value + add_value; + return (((*new_value ^ old_value) & (*new_value ^ add_value)) & UINT32_C(0x80000000)) != 0; +#endif } -ALWAYS_INLINE static constexpr bool SubOverflow(u32 old_value, u32 sub_value, u32 new_value) +ALWAYS_INLINE static constexpr bool SubOverflow(u32 old_value, u32 sub_value, u32* new_value) { - return (((new_value ^ old_value) & (old_value ^ sub_value)) & UINT32_C(0x80000000)) != 0; +#if defined(__clang__) || defined(__GNUC__) + return __builtin_sub_overflow(static_cast(old_value), static_cast(sub_value), + reinterpret_cast(new_value)); +#else + *new_value = old_value - sub_value; + return (((*new_value ^ old_value) & (old_value ^ sub_value)) & UINT32_C(0x80000000)) != 0; +#endif } void CPU::DisassembleAndPrint(u32 addr, bool regs, const char* prefix) @@ -999,8 +1011,8 @@ restart_instruction: { const u32 rsVal = ReadReg(inst.r.rs); const u32 rtVal = ReadReg(inst.r.rt); - const u32 rdVal = rsVal + rtVal; - if (AddOverflow(rsVal, rtVal, rdVal)) + u32 rdVal; + if (AddOverflow(rsVal, rtVal, &rdVal)) [[unlikely]] { RaiseException(Exception::Ov); return; @@ -1033,8 +1045,8 @@ restart_instruction: { const u32 rsVal = ReadReg(inst.r.rs); const u32 rtVal = ReadReg(inst.r.rt); - const u32 rdVal = rsVal - rtVal; - if (SubOverflow(rsVal, rtVal, rdVal)) + u32 rdVal; + if (SubOverflow(rsVal, rtVal, &rdVal)) [[unlikely]] { RaiseException(Exception::Ov); return; @@ -1296,8 +1308,8 @@ restart_instruction: { const u32 rsVal = ReadReg(inst.i.rs); const u32 imm = inst.i.imm_sext32(); - const u32 rtVal = rsVal + imm; - if (AddOverflow(rsVal, imm, rtVal)) + u32 rtVal; + if (AddOverflow(rsVal, imm, &rtVal)) [[unlikely]] { RaiseException(Exception::Ov); return; @@ -1844,7 +1856,7 @@ restart_instruction: case InstructionOp::cop2: { - if (!g_state.cop0_regs.sr.CE2) + if (!g_state.cop0_regs.sr.CE2) [[unlikely]] { WARNING_LOG("Coprocessor 2 not enabled"); RaiseException(Exception::CpU); @@ -1916,7 +1928,7 @@ restart_instruction: case InstructionOp::lwc2: { - if (!g_state.cop0_regs.sr.CE2) + if (!g_state.cop0_regs.sr.CE2) [[unlikely]] { WARNING_LOG("Coprocessor 2 not enabled"); RaiseException(Exception::CpU); @@ -1937,7 +1949,7 @@ restart_instruction: case InstructionOp::swc2: { - if (!g_state.cop0_regs.sr.CE2) + if (!g_state.cop0_regs.sr.CE2) [[unlikely]] { WARNING_LOG("Coprocessor 2 not enabled"); RaiseException(Exception::CpU); @@ -1969,6 +1981,7 @@ restart_instruction: break; // everything else is reserved/invalid + [[unlikely]] default: { u32 ram_value;