Skip to content

Commit 9939f1c

Browse files
committed
CPU/Interpreter: Use __builtin_{add,sub}_overflow for exceptions
Recompiler already does this.
1 parent 7eb7ad6 commit 9939f1c

1 file changed

Lines changed: 26 additions & 13 deletions

File tree

src/core/cpu_core.cpp

Lines changed: 26 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -811,14 +811,26 @@ const std::array<CPU::DebuggerRegisterListEntry, CPU::NUM_DEBUGGER_REGISTER_LIST
811811
{"ZSF4", &CPU::g_state.gte_regs.r32[62]},
812812
{"FLAG", &CPU::g_state.gte_regs.r32[63]}}};
813813

814-
ALWAYS_INLINE static constexpr bool AddOverflow(u32 old_value, u32 add_value, u32 new_value)
814+
ALWAYS_INLINE static constexpr bool AddOverflow(u32 old_value, u32 add_value, u32* new_value)
815815
{
816-
return (((new_value ^ old_value) & (new_value ^ add_value)) & UINT32_C(0x80000000)) != 0;
816+
#if defined(__clang__) || defined(__GNUC__)
817+
return __builtin_add_overflow(static_cast<s32>(old_value), static_cast<s32>(add_value),
818+
reinterpret_cast<s32*>(new_value));
819+
#else
820+
*new_value = old_value + add_value;
821+
return (((*new_value ^ old_value) & (*new_value ^ add_value)) & UINT32_C(0x80000000)) != 0;
822+
#endif
817823
}
818824

819-
ALWAYS_INLINE static constexpr bool SubOverflow(u32 old_value, u32 sub_value, u32 new_value)
825+
ALWAYS_INLINE static constexpr bool SubOverflow(u32 old_value, u32 sub_value, u32* new_value)
820826
{
821-
return (((new_value ^ old_value) & (old_value ^ sub_value)) & UINT32_C(0x80000000)) != 0;
827+
#if defined(__clang__) || defined(__GNUC__)
828+
return __builtin_sub_overflow(static_cast<s32>(old_value), static_cast<s32>(sub_value),
829+
reinterpret_cast<s32*>(new_value));
830+
#else
831+
*new_value = old_value - sub_value;
832+
return (((*new_value ^ old_value) & (old_value ^ sub_value)) & UINT32_C(0x80000000)) != 0;
833+
#endif
822834
}
823835

824836
void CPU::DisassembleAndPrint(u32 addr, bool regs, const char* prefix)
@@ -999,8 +1011,8 @@ ALWAYS_INLINE_RELEASE void CPU::ExecuteInstruction()
9991011
{
10001012
const u32 rsVal = ReadReg(inst.r.rs);
10011013
const u32 rtVal = ReadReg(inst.r.rt);
1002-
const u32 rdVal = rsVal + rtVal;
1003-
if (AddOverflow(rsVal, rtVal, rdVal))
1014+
u32 rdVal;
1015+
if (AddOverflow(rsVal, rtVal, &rdVal)) [[unlikely]]
10041016
{
10051017
RaiseException(Exception::Ov);
10061018
return;
@@ -1033,8 +1045,8 @@ ALWAYS_INLINE_RELEASE void CPU::ExecuteInstruction()
10331045
{
10341046
const u32 rsVal = ReadReg(inst.r.rs);
10351047
const u32 rtVal = ReadReg(inst.r.rt);
1036-
const u32 rdVal = rsVal - rtVal;
1037-
if (SubOverflow(rsVal, rtVal, rdVal))
1048+
u32 rdVal;
1049+
if (SubOverflow(rsVal, rtVal, &rdVal)) [[unlikely]]
10381050
{
10391051
RaiseException(Exception::Ov);
10401052
return;
@@ -1296,8 +1308,8 @@ ALWAYS_INLINE_RELEASE void CPU::ExecuteInstruction()
12961308
{
12971309
const u32 rsVal = ReadReg(inst.i.rs);
12981310
const u32 imm = inst.i.imm_sext32();
1299-
const u32 rtVal = rsVal + imm;
1300-
if (AddOverflow(rsVal, imm, rtVal))
1311+
u32 rtVal;
1312+
if (AddOverflow(rsVal, imm, &rtVal)) [[unlikely]]
13011313
{
13021314
RaiseException(Exception::Ov);
13031315
return;
@@ -1844,7 +1856,7 @@ ALWAYS_INLINE_RELEASE void CPU::ExecuteInstruction()
18441856

18451857
case InstructionOp::cop2:
18461858
{
1847-
if (!g_state.cop0_regs.sr.CE2)
1859+
if (!g_state.cop0_regs.sr.CE2) [[unlikely]]
18481860
{
18491861
WARNING_LOG("Coprocessor 2 not enabled");
18501862
RaiseException(Exception::CpU);
@@ -1916,7 +1928,7 @@ ALWAYS_INLINE_RELEASE void CPU::ExecuteInstruction()
19161928

19171929
case InstructionOp::lwc2:
19181930
{
1919-
if (!g_state.cop0_regs.sr.CE2)
1931+
if (!g_state.cop0_regs.sr.CE2) [[unlikely]]
19201932
{
19211933
WARNING_LOG("Coprocessor 2 not enabled");
19221934
RaiseException(Exception::CpU);
@@ -1937,7 +1949,7 @@ ALWAYS_INLINE_RELEASE void CPU::ExecuteInstruction()
19371949

19381950
case InstructionOp::swc2:
19391951
{
1940-
if (!g_state.cop0_regs.sr.CE2)
1952+
if (!g_state.cop0_regs.sr.CE2) [[unlikely]]
19411953
{
19421954
WARNING_LOG("Coprocessor 2 not enabled");
19431955
RaiseException(Exception::CpU);
@@ -1969,6 +1981,7 @@ ALWAYS_INLINE_RELEASE void CPU::ExecuteInstruction()
19691981
break;
19701982

19711983
// everything else is reserved/invalid
1984+
[[unlikely]]
19721985
default:
19731986
{
19741987
u32 ram_value;

0 commit comments

Comments
 (0)