From 7d9966a8ee730127d7cc43a9370f3950d3eba365 Mon Sep 17 00:00:00 2001 From: Nixitov Date: Sun, 11 Oct 2026 23:51:54 +0200 Subject: [PATCH] feat(libc): implement __divti3 Kart PS5 (PPSA99611) imports __divti3 and stops at start-up on main. The guest has no signed 128-bit division; add it alongside __udivti3, dividing the magnitudes and negating the quotient, and throwing on a zero divisor like the unsigned routine. --- core/libs/prx/libc/include/SonyCrt.hpp | 13 ++++++++++++ core/libs/prx/libc/src/RuntimeSupport.cpp | 4 ++++ core/libs/tests/GuestCrt.cpp | 24 +++++++++++++++++++++++ 3 files changed, 41 insertions(+) diff --git a/core/libs/prx/libc/include/SonyCrt.hpp b/core/libs/prx/libc/include/SonyCrt.hpp index 2016da156..cc544b21c 100644 --- a/core/libs/prx/libc/include/SonyCrt.hpp +++ b/core/libs/prx/libc/include/SonyCrt.hpp @@ -194,6 +194,19 @@ inline unsigned __int128 SonyUdivti3(unsigned __int128 dividend, unsigned __int1 return quotient; } +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); + const unsigned __int128 magnitudeDividend = dividend < 0 + ? (unsigned __int128)0 - (unsigned __int128)dividend + : (unsigned __int128)dividend; + const unsigned __int128 magnitudeDivisor = divisor < 0 + ? (unsigned __int128)0 - (unsigned __int128)divisor + : (unsigned __int128)divisor; + const unsigned __int128 magnitude = SonyUdivti3(magnitudeDividend, magnitudeDivisor); + return (__int128)(negative ? (unsigned __int128)0 - magnitude : magnitude); +} + } #endif diff --git a/core/libs/prx/libc/src/RuntimeSupport.cpp b/core/libs/prx/libc/src/RuntimeSupport.cpp index 69be0d848..6731cbb4c 100644 --- a/core/libs/prx/libc/src/RuntimeSupport.cpp +++ b/core/libs/prx/libc/src/RuntimeSupport.cpp @@ -181,6 +181,10 @@ void APS5_VABI _Unlocksyslock_nid_postfix() { g_sysLock.unlock(); } +__int128 APS5_VABI __divti3_nid_postfix(__int128 dividend, __int128 divisor) { + return SonyDivti3(dividend, divisor); +} + unsigned __int128 APS5_VABI __udivti3_nid_postfix(unsigned __int128 dividend, unsigned __int128 divisor) { return SonyUdivti3(dividend, divisor); } diff --git a/core/libs/tests/GuestCrt.cpp b/core/libs/tests/GuestCrt.cpp index 7bd72ca01..10257c096 100644 --- a/core/libs/tests/GuestCrt.cpp +++ b/core/libs/tests/GuestCrt.cpp @@ -31,6 +31,7 @@ std::size_t APS5_VABI mbstowcs_nid_postfix(std::uint16_t* dest, const char* src, char* APS5_VABI strtok_s_nid_postfix(char* str, const char* delim, char** context); 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); SonyLconv* APS5_VABI localeconv_nid_postfix(void); int APS5_VABI sceAmprFpclassifyd(double value); } @@ -84,6 +85,29 @@ int main() { } Require(trapped); + Require(__divti3_nid_postfix(100, 3) == 33); + Require(__divti3_nid_postfix(-100, 3) == -33); + Require(__divti3_nid_postfix(100, -3) == -33); + Require(__divti3_nid_postfix(-100, -3) == 33); + Require(SonyDivti3(0, 5) == 0); + const __int128 large = (__int128)1 << 100; + Require(SonyDivti3(large, 3) == large / 3); + Require(SonyDivti3(-large, 3) == -(large / 3)); + Require(SonyDivti3(large, -3) == -(large / 3)); + Require(SonyDivti3(-large, -3) == large / 3); + const __int128 minimum = (__int128)((unsigned __int128)1 << 127); + const __int128 maximum = (__int128)(((unsigned __int128)1 << 127) - 1); + Require(SonyDivti3(minimum, 1) == minimum); + Require(SonyDivti3(minimum, -1) == minimum); + Require(SonyDivti3(maximum, -1) == -maximum); + trapped = false; + try { + SonyDivti3(1, 0); + } catch (const std::exception&) { + trapped = true; + } + Require(trapped); + void* previous = sceAmprSetConstraintHandlerS(reinterpret_cast(&CountingHandler)); Require(previous != nullptr); Require(previous != reinterpret_cast(&CountingHandler));