From 11880459a51bb39eb9a3da6e487d9ad3fac32a80 Mon Sep 17 00:00:00 2001 From: Alyssa Rosenzweig Date: Fri, 1 Mar 2024 10:31:52 -0400 Subject: [PATCH] OpcodeDispatcher: use SETF for DEC Signed-off-by: Alyssa Rosenzweig --- .../Interface/Core/OpcodeDispatcher.cpp | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/FEXCore/Source/Interface/Core/OpcodeDispatcher.cpp b/FEXCore/Source/Interface/Core/OpcodeDispatcher.cpp index 17c607e49..19c91a05f 100644 --- a/FEXCore/Source/Interface/Core/OpcodeDispatcher.cpp +++ b/FEXCore/Source/Interface/Core/OpcodeDispatcher.cpp @@ -3593,7 +3593,24 @@ void OpDispatchBuilder::DECOp(OpcodeArgs) { } CalculateDeferredFlags(); - Result = CalculateFlags_SUB(OpSizeFromSrc(Op), Dest, OneConst, false); + + if (Size < 32 && CTX->HostFeatures.SupportsFlagM) { + // Subtraction producing upper garbage + Result = _Sub(OpSize::i32Bit, Dest, OneConst); + CalculatePF(Result); + CalculateAF(Dest, OneConst); + + // Correctly set NZ flags, preserving C + HandleNZCV_RMW(); + _SetSmallNZV(OpSizeFromSrc(Op), Result); + + // Fix up V flag. DEC overflows only when decrementing a negative and + // getting a positive. So compare the sign bits to calculate V. + _RmifNZCV(_Andn(OpSize::i32Bit, Dest, Result), Size - 1, 1); + } else { + Result = CalculateFlags_SUB(OpSizeFromSrc(Op), Dest, OneConst, false); + } + if (!IsLocked) { StoreResult(GPRClass, Op, Result, -1); }