Skip to content
Merged
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
22 changes: 20 additions & 2 deletions core/libs/prx/libc/include/SonyCrt.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -181,8 +181,7 @@ inline int SonyFltrounds(void) {
}
}

inline unsigned __int128 SonyUdivti3(unsigned __int128 dividend, unsigned __int128 divisor) {
if (divisor == 0) throw std::runtime_error("__udivti3: integer divide by zero");
inline unsigned __int128 SonyUdivmod128(unsigned __int128 dividend, unsigned __int128 divisor, unsigned __int128* remainderOut) {
unsigned __int128 quotient = 0;
unsigned __int128 remainder = 0;
for (int i = 127; i >= 0; --i) {
Expand All @@ -192,9 +191,28 @@ inline unsigned __int128 SonyUdivti3(unsigned __int128 dividend, unsigned __int1
quotient |= (unsigned __int128)1 << i;
}
}
*remainderOut = remainder;
return quotient;
}

inline unsigned __int128 SonyUdivti3(unsigned __int128 dividend, unsigned __int128 divisor) {
if (divisor == 0) throw std::runtime_error("__udivti3: integer divide by zero");
unsigned __int128 remainder = 0;
return SonyUdivmod128(dividend, divisor, &remainder);
}

inline unsigned __int128 SonyUmodti3(unsigned __int128 dividend, unsigned __int128 divisor) {
if (divisor == 0) {
char message[96];
std::snprintf(message, sizeof(message), "__umodti3: integer divide by zero (0x%016llx%016llx %% 0)",
(unsigned long long)(dividend >> 64), (unsigned long long)dividend);
throw std::runtime_error(message);
}
unsigned __int128 remainder = 0;
SonyUdivmod128(dividend, divisor, &remainder);
return remainder;
}

inline __int128 SonyDivti3(__int128 dividend, __int128 divisor) {
if (divisor == 0) throw std::runtime_error("__divti3: integer divide by zero");
const bool negative = (dividend < 0) != (divisor < 0);
Expand Down
4 changes: 4 additions & 0 deletions core/libs/prx/libc/src/RuntimeSupport.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -188,4 +188,8 @@ unsigned __int128 APS5_VABI __udivti3_nid_postfix(unsigned __int128 dividend, un
return SonyUdivti3(dividend, divisor);
}

unsigned __int128 APS5_VABI __umodti3_nid_postfix(unsigned __int128 dividend, unsigned __int128 divisor) {
return SonyUmodti3(dividend, divisor);
}

}
24 changes: 24 additions & 0 deletions core/libs/tests/GuestCrt.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ char* APS5_VABI strtok_s_nid_postfix(char* str, const char* delim, char** contex
int APS5_VABI __fpclassifyd_nid_postfix(double value);
unsigned __int128 APS5_VABI __udivti3_nid_postfix(unsigned __int128 dividend, unsigned __int128 divisor);
__int128 APS5_VABI __divti3_nid_postfix(__int128 dividend, __int128 divisor);
unsigned __int128 APS5_VABI __umodti3_nid_postfix(unsigned __int128 dividend, unsigned __int128 divisor);
SonyLconv* APS5_VABI localeconv_nid_postfix(void);
int APS5_VABI sceAmprFpclassifyd(double value);
unsigned int APS5_VABI _ZSt14_Random_devicev_nid_postfix();
Expand Down Expand Up @@ -109,6 +110,29 @@ int main() {
}
Require(trapped);

const unsigned __int128 unsignedMaximum = ~(unsigned __int128)0;
const unsigned __int128 largeDivisor = ((unsigned __int128)1 << 64) + 3;
Require(__umodti3_nid_postfix(100, 3) == 1);
Require(__umodti3_nid_postfix(0, 5) == 0);
Require(__umodti3_nid_postfix(3, 100) == 3);
Require(__umodti3_nid_postfix(unsignedMaximum, 1) == 0);
Require(__umodti3_nid_postfix(unsignedMaximum, unsignedMaximum) == 0);
Require(__umodti3_nid_postfix(largeDivisor, largeDivisor) == 0);
Require(__umodti3_nid_postfix(unsignedMaximum, 10) == 5);
Require(__umodti3_nid_postfix((unsigned __int128)1 << 100, 3) == 1);
Require(__umodti3_nid_postfix(unsignedMaximum, (unsigned __int128)1 << 64) == 0xFFFFFFFFFFFFFFFFull);
Require(__umodti3_nid_postfix(unsignedMaximum, largeDivisor) == 8);
Require(__umodti3_nid_postfix((unsigned __int128)1 << 127, largeDivisor) == 0x8000000000000006ull);
Require(__umodti3_nid_postfix(unsignedMaximum - 1, unsignedMaximum) == unsignedMaximum - 1);
Require(__umodti3_nid_postfix(unsignedMaximum, (unsigned __int128)1 << 127) == ((unsigned __int128)1 << 127) - 1);
trapped = false;
try {
__umodti3_nid_postfix(((unsigned __int128)0x1234 << 64) | 0x5678, 0);
} catch (const std::runtime_error& error) {
trapped = std::strcmp(error.what(), "__umodti3: integer divide by zero (0x00000000000012340000000000005678 % 0)") == 0;
}
Require(trapped);

void* previous = sceAmprSetConstraintHandlerS(reinterpret_cast<void*>(&CountingHandler));
Require(previous != nullptr);
Require(previous != reinterpret_cast<void*>(&CountingHandler));
Expand Down
1 change: 1 addition & 0 deletions docs/dev/TechnicalDebt.md
Original file line number Diff line number Diff line change
Expand Up @@ -343,6 +343,7 @@ Throughout the project, every function at every stage either **does exactly what
- [localeconv](../../core/libs/prx/libc/src/LocaleSupport.cpp) (libc, re-exported by libSceAmpr) - the 0x90-byte Dinkumware struct (empty monetary strings, `CHAR_MAX` for the 14 `char` fields, `decimal_point` ".", `_False`/`_True` "false"/"true") is read from the `libc.prx` that Astro's Playroom ships. It is a fixed C-locale table: whether the console changes it with `setlocale` is not known, and `_Frac_grouping`, `_Frac_sep`, `_No`, `_Yes` are empty strings as in that dump
- [set_constraint_handler_s](../../core/libs/prx/libc/src/WideConversion.cpp) (libc, re-exported by libSceAmpr) - the default handler is assumed to abort; each module keeps its own handler state, so a handler set through one library is not seen by the other. `ctime_s` and `asctime_s` follow the Dinkumware 26-byte format with `EINVAL` for a buffer under 26 bytes, a null pointer or an out-of-range weekday/month; `ctime_s` uses the guest time zone of `localtime_s`, and the console's exact checks are not verified
- [__udivti3](../../core/libs/prx/libc/src/RuntimeSupport.cpp) (libc, re-exported by libSceAmpr) - the hardware traps on a zero divisor; this throws instead
- [__umodti3](../../core/libs/prx/libc/src/RuntimeSupport.cpp) (libc) - the hardware traps on a zero divisor; this throws instead
- [AC1FtjqMCL0](../../core/libs/prx/libkernel/Unimplemented.cpp) (libkernel) - unknown name, signature
- [0iEKNAvT600](../../core/libs/prx/libkernel/Unimplemented.cpp) (libkernel) - unknown name, signature
- [2cELEBPdYQ0](../../core/libs/prx/libkernel/Unimplemented.cpp) (libkernel) - unknown name, signature
Expand Down
Loading