Skip to content

Commit

Permalink
Fix potential overflow in FixedDiv, re-add gcc asm implementation (#1832
Browse files Browse the repository at this point in the history
)

* Revert "remove GCC variant of `div64_32` (#1818)"

This reverts commit fac7cf7.

* Remove asm multi-constraint

clang generates poor code otherwise:

https://stackoverflow.com/questions/16850309/clang-llvm-inline-assembly-multiple-constraints-with-useless-spills-reload

* Fix potential FixedDiv overflow when passed INT_MIN as first arg
  • Loading branch information
gendlin authored Dec 7, 2024
1 parent 89aae9c commit 458c61a
Showing 1 changed file with 15 additions and 1 deletion.
16 changes: 15 additions & 1 deletion src/m_fixed.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,20 @@

#define div64_32(a, b) _div64((a), (b), NULL)

#elif defined(__GNUC__) && defined(__x86_64__)

inline static int32_t div64_32(int64_t a, int32_t b)
{
if (__builtin_constant_p(b))
{
return a / b;
}
int32_t lo = a;
int32_t hi = a >> 32;
asm("idivl %[divisor]" : "+a" (lo), "+d" (hi) : [divisor] "r" (b));
return lo;
}

#else

#define div64_32(a, b) ((fixed_t)((a) / (b)))
Expand Down Expand Up @@ -72,7 +86,7 @@ inline static int64_t FixedMul64(int64_t a, int64_t b)
inline static fixed_t FixedDiv(fixed_t a, fixed_t b)
{
// [FG] avoid 31-bit shift (from Chocolate Doom)
if ((abs(a) >> 14) >= abs(b))
if (((unsigned)abs(a) >> 14) >= (unsigned)abs(b))
{
return (a ^ b) < 0 ? INT_MIN : INT_MAX;
}
Expand Down

0 comments on commit 458c61a

Please sign in to comment.