Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
45 changes: 43 additions & 2 deletions src/mips/psyqo/fixed-point.hh
Original file line number Diff line number Diff line change
Expand Up @@ -37,10 +37,51 @@ namespace psyqo {

namespace FixedPointInternals {

uint32_t iDiv(uint64_t rem, uint32_t base, unsigned scale);
int32_t dDiv(int32_t a, int32_t b, unsigned scale);
void printInt(uint32_t value, const eastl::function<void(char)>&, unsigned scale);

constexpr uint32_t iDiv(uint64_t rem, uint32_t base, unsigned scale) {
rem *= scale;
uint64_t b = base;
uint64_t res, d = 1;
uint32_t high = rem >> 32;

res = 0;
if (high >= base) {
high /= base;
res = static_cast<uint64_t>(high) << 32;
rem -= static_cast<uint64_t>(high * base) << 32;
}

while (static_cast<int64_t>(b) > 0 && b < rem) {
b = b + b;
d = d + d;
}

do {
if (rem >= b) {
rem -= b;
res += d;
}
b >>= 1;
d >>= 1;
} while (d);

return res;
}

constexpr int32_t dDiv(int32_t a, int32_t b, unsigned scale) {
int s = 1;
if (a < 0) {
a = -a;
s = -1;
}
if (b < 0) {
b = -b;
s = -s;
}
return iDiv(a, b, scale) * s;
}
Comment on lines +72 to +83

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Find compile-time (constexpr/consteval) usages that could feed dDiv with signed division.
rg -nP -C3 '\bdDiv\s*\(' src/mips/psyqo
# Look for constexpr/consteval contexts invoking FixedPoint division on signed 32-bit types.
rg -nP -C3 'operator/|operator/=' src/mips/psyqo/fixed-point.hh

Repository: grumpycoders/pcsx-redux

Length of output: 3784


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Inspect the relevant parts of fixed-point.hh around dDiv and the signed operators.
sed -n '1,140p' src/mips/psyqo/fixed-point.hh
printf '\n---\n'
sed -n '300,430p' src/mips/psyqo/fixed-point.hh
printf '\n---\n'
sed -n '470,520p' src/mips/psyqo/fixed-point.hh

Repository: grumpycoders/pcsx-redux

Length of output: 10563


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Find constructors, raw accessors, and any direct uses of INT32_MIN / numeric_limits in the fixed-point implementation.
rg -n -C2 'raw\(|INT32_MIN|numeric_limits|FixedPoint\s*\(|constexpr\s+FixedPoint' src/mips/psyqo/fixed-point.hh

Repository: grumpycoders/pcsx-redux

Length of output: 6974


Guard INT32_MIN before negating in dDiv

FixedPoint::operator/ and operator/= for signed 32-bit values call this directly, so a raw INT32_MIN still makes constant evaluation ill-formed when a = -a; or b = -b;. Widen the temporary or special-case the minimum value.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/mips/psyqo/fixed-point.hh` around lines 72 - 83, The dDiv helper in
fixed-point.hh negates signed inputs directly, which still breaks when a or b is
INT32_MIN. Update dDiv (used by FixedPoint::operator/ and
FixedPoint::operator/=) to guard the minimum 32-bit value before negation,
either by widening to a larger temporary type or by special-casing INT32_MIN so
constant evaluation remains valid.


} // namespace FixedPointInternals

/**
Expand Down
42 changes: 0 additions & 42 deletions src/mips/psyqo/src/fixed-point.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,48 +26,6 @@ SOFTWARE.

#include "psyqo/fixed-point.hh"

uint32_t psyqo::FixedPointInternals::iDiv(uint64_t rem, uint32_t base, unsigned scale) {
rem *= scale;
uint64_t b = base;
uint64_t res, d = 1;
uint32_t high = rem >> 32;

res = 0;
if (high >= base) {
high /= base;
res = static_cast<uint64_t>(high) << 32;
rem -= static_cast<uint64_t>(high * base) << 32;
}

while (static_cast<int64_t>(b) > 0 && b < rem) {
b = b + b;
d = d + d;
}

do {
if (rem >= b) {
rem -= b;
res += d;
}
b >>= 1;
d >>= 1;
} while (d);

return res;
}

int32_t psyqo::FixedPointInternals::dDiv(int32_t a, int32_t b, unsigned scale) {
int s = 1;
if (a < 0) {
a = -a;
s = -1;
}
if (b < 0) {
b = -b;
s = -s;
}
return iDiv(a, b, scale) * s;
}

void psyqo::FixedPointInternals::printInt(uint32_t value, const eastl::function<void(char)>& charPrinter,
unsigned scale) {
Expand Down
Loading