Commit Graph
78 Commits
Author SHA1 Message Date
Claude 91d8416fdd fix(ssl): compile out the Mbed TLS self-test counters
With MBEDTLS_SELF_TEST, ecp.c counts point additions, doublings and
field multiplications in unsynchronized globals. Handshakes on separate
connections run in parallel, each under its own session lock, so the
counters race; ThreadSanitizer reports it on the parallel transport
test. Nothing calls the self-test functions.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RoU3ZF76A6uR8sCA7NMLch
2026-10-17 11:00:59 +00:00
Claude 9766ea7781 Merge upstream/main into claude/brave-ride-lz92qi
Brings in main's connection verify options, minimum version, ALPN and
certificate readers. The conflicts in libSceSsl/Export.cpp and the
libSceSsl debt entry take the resolution from blawesom's rebase of this
pull request (blawesom/AnyPS5 rebase/6828 at 925c37aa0): SslConnection
keeps main's verifyOptions, minimumVersion and alpn next to the session,
and the debt entries follow main's structure.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RoU3ZF76A6uR8sCA7NMLch
2026-10-17 11:00:59 +00:00
Claude 9ce634af21 Merge loyalburrito main (PR #1 merged) into claude/brave-ride-lz92qi
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RoU3ZF76A6uR8sCA7NMLch
2026-10-16 13:36:07 +00:00
Claude e4ede0e9e1 test(ssl): run four connections on one context in parallel
Each client thread handshakes, writes, reads the reply and the end of
the stream, so session setup and record allocations from several
threads contend for the same context pool. The pool memory must return
to its loaded size afterwards.

Initialize the pool's mutex explicitly, which -Wextra asks for.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RoU3ZF76A6uR8sCA7NMLch
2026-10-16 13:27:13 +00:00
Claude 19c82d2ec0 Merge upstream/main into claude/brave-ride-lz92qi
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RoU3ZF76A6uR8sCA7NMLch
2026-10-16 13:08:13 +00:00
Claude e37137241d feat(ssl): run TLS 1.2 client connections over Mbed TLS
sceSslConnect performs the client handshake on the host socket that the
guest number maps to in the libkernel or libSceNet socket table, and
sceSslRead and sceSslWrite carry application data. Session state comes
from the context's memory pool, and the server is verified against the
CAs loaded with sceSslLoadCert; a loaded client certificate is sent when
the server asks for one.

libkernel exports KernelLookupSocketNative_nid_no_patch, which checks
its own socket table before the one libSceNet registers. Pools take a
lock so connections can allocate outside the library lock.

TLS 1.3 is compiled out. A missing CA, a verify callback, would-block
sockets and every failure whose console code is unknown throw, as
recorded in the libSceSsl debt entry.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RoU3ZF76A6uR8sCA7NMLch
2026-10-16 11:37:32 +00:00
Claude 76cc70c245 fix(agc): overestimate single-sample draws with centroid inputs
A draw with PA_SC_CONSERVATIVE_RASTERIZATION_CNTL 0x6001 and
SPI_PS_INPUT_ENA.PERSP_CENTROID or LINEAR_CENTROID threw in DecodeState,
whatever its rasterized sample count. With PA_SC_AA_CONFIG.MSAA_NUM_SAMPLES
0 the single rasterized sample is the pixel centre, which is where the
recompiler already puts the centroid barycentrics, so such a draw now
decodes to overestimation. More rasterized samples, and a single-sample
draw raised to a multisampled color target, still throw.

Extends agc_driver_graphics and records the inference in the driver's
technical debt.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XJ3RTcWpqBBdVE8QRtKxJD
2026-10-15 15:47:02 +00:00
Claude 411ce81a6e test(agc): cover ordered-append modifiers on indirect dispatches
DISPATCH_INDIRECT accepts ORDERED_APPEND_ENBL like DISPATCH_DIRECT and
still refuses ORDERED_APPEND_MODE.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019hfwvntiwabeqdZ6avJssk
2026-10-15 07:37:40 +00:00
Claude fcc426b6a2 fix(shader): add the ordered count of a first active lane in the upper wave64 half
The ordered count's amount was shuffled from the first half's value of
the first active lane's host lane, so a wave64 program whose active lanes
were all in lanes 32 to 63 added the inactive lane's value from the lower
half. Read the amount through the context shuffle, which selects the half
the first active guest lane lives in, as v_readfirstlane_b32 does.

The GDS test now masks the ordered count to the upper part of each wave,
including a wave64 whose first active lane is lane 40, prefills the
result register to check that inactive lanes stay untouched, and keeps
the M0 cases of the counter addressing.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019hfwvntiwabeqdZ6avJssk
2026-10-15 07:37:40 +00:00
Claude 793224067f fix(shader): round and flush f16 conversion results by FLOAT_MODE in every denormal mode
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Ha6Tsy62AFUyp9a5Mf7vjA
2026-10-14 16:25:23 +00:00
Claude 9399cc93aa fix(shader): flush v_cvt_pknorm_*_f16 denormal inputs by FLOAT_MODE
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Ha6Tsy62AFUyp9a5Mf7vjA
2026-10-14 16:18:32 +00:00
Claude f5d856d85e test(libkernel): take the summer time amount from the C runtime on Windows
A TZ variable does not set the UCRT's _dstbias, so after the system zone
of a CI runner without daylight saving it stays 0.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017iLxaSz4qjmirfqKZdhVQk
2026-10-14 07:56:03 +00:00
Claude bb5f7d7e07 Merge remote-tracking branch 'upstream/main' into pr-main
# Conflicts:
#	core/libs/tests/GuestFreebsdClocks.cpp
2026-10-14 06:49:51 +00:00
Claude 15969f2753 fix(libkernel): report the zone's daylight saving amount from sceKernelConvertLocaltimeToUtc
libc mktime subtracts it when tm_isdst is set outside summer time, so it
must not be zero there.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017iLxaSz4qjmirfqKZdhVQk
2026-10-13 12:19:55 +00:00
Claude 1614d82fc8 fix(libkernel): call tzset before reading the host zone offsets
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017iLxaSz4qjmirfqKZdhVQk
2026-10-13 11:48:31 +00:00
Claude 6c8ef3d469 docs(libkernel): move the time zone debt entry away from the end of its section
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017iLxaSz4qjmirfqKZdhVQk
2026-10-13 11:38:56 +00:00
Claude ae7f5e3aaa fix(libkernel): report west_sec as seconds east of UTC
PPSA99203 (PS5SX2) documents that the console fills west_sec with the
offset east of UTC despite the field's name.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017iLxaSz4qjmirfqKZdhVQk
2026-10-13 11:37:12 +00:00
Claude 56c8f346fb fix(libkernel): convert local time with the host time zone
sceKernelConvertUtcToLocaltime and sceKernelConvertLocaltimeToUtc returned
the time unchanged while libc localtime follows the host zone, so a title
that mixes them shows UTC as local time (#5067).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017iLxaSz4qjmirfqKZdhVQk
2026-10-13 11:27:28 +00:00
Claude d0df62bd1f fix(libc): format strftime and asctime as FreeBSD 11 does
strftime handed most conversions to the host's strftime, which differs
from FreeBSD 11's for E and O modifiers on conversions glibc does not
pair with them (%Ea was printed literally), padding flags on %+ and %v,
years outside 1000 to 9999 (%Y printed 899 and -1 where FreeBSD prints
0899 and -001), and out-of-range fields (%I of hour 100, %u of weekday
8). On Windows the padding flags printed nothing. strftime now follows
FreeBSD 11 strftime.c with the C locale on every host, and asctime
follows FreeBSD 11 asctime.c, padding years to four digits and setting
longer years apart.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VZWLdTjf1S57iLgn2rcaFb
2026-10-13 10:12:15 +00:00
Claude 13444c82e9 fix(libc): print NaN without a sign in the guest printf formatter
The guest formatter handed NaN to the host's snprintf, which prints
-nan for a negative NaN and +nan or " nan" with the + and space flags.
FreeBSD 11's vfprintf clears the sign of every NaN and prints nan (NAN
for the upper-case conversions), keeping the width and the - flag and
ignoring 0. The formatter now does the same for a, e, f and g and
their long double forms.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VZWLdTjf1S57iLgn2rcaFb
2026-10-13 08:26:41 +00:00
Claude 1285ee06f5 fix(shader): keep a folded selection's branch when SPIR-V 1.6 forbids one label
The previous commit pointed the untaken side of a folded branch that
keeps its selection merge at the merge block. That adds an edge from the
header to the merge block: the merge block's phis have no operand for it,
and values from the taken arm no longer dominate the merge block, as
fuzzing with validation on found once the repeated label stopped hiding
it.

For SPIR-V 1.6 the branch is now left as it is, so the control flow and
the untaken arm stay; earlier versions keep naming the taken label twice,
which they allow, and drop the untaken arm as before.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VZWLdTjf1S57iLgn2rcaFb
2026-10-12 16:40:43 +00:00
Claude 52b679c552 fix(shader): keep the back-edge of a loop whose continue block is dead
Pipeline specialization replaced every unreachable block with
OpUnreachable. When a loop's continue target became unreachable, either
because the latch exited on a constant condition or because the emitter
had already folded it, that removed the header's only back-edge, and
validation rejects a loop header targeted by no back-edge block.

An unreachable continue target of a live loop header now keeps an
OpBranch to its header, as SPIRV-Tools' dead branch elimination does.
The header's phis keep an operand for it, naming the phi itself, since
the edge is never taken and the continue block's values are gone.

Found by recompiling mutated compute shaders with SPIR-V validation on,
for loops with a literal bound such as s_cmp_lt_u32 with two constants.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VZWLdTjf1S57iLgn2rcaFb
2026-10-12 16:25:22 +00:00
Claude 7fd423dfe9 fix(shader): never branch conditionally to one label twice
SPIR-V 1.6 requires the true and false labels of OpBranchConditional to
differ. Two places produced the same label for both:

- The structured terminator emitter, for a conditional branch whose
  targets are the same block, such as s_cbranch_scc0 to the next
  instruction. It now emits OpBranch, keeping OpLoopMerge on a loop
  header.
- Pipeline specialization, when it folded a branch on a constant and
  kept the selection merge because the taken path is not linear. It
  wrote the taken label twice; the untaken side now names the
  selection's merge block, which the constant condition never takes.

Found by recompiling mutated compute shaders with SPIR-V validation on;
before this, 169 of 20000 were rejected for this rule, and builds
without SPIRV-Tools handed the module to the driver.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VZWLdTjf1S57iLgn2rcaFb
2026-10-12 16:04:13 +00:00
Claude ef09cda468 fix(libc): sort with FreeBSD 11's qsort so equal elements keep its order
qsort was a heapsort. It sorted correctly, but elements that compare
equal ended in a different order from FreeBSD's Bentley-McIlroy qsort,
in 18947 of 20000 random arrays with repeated keys, and below 7
elements, where FreeBSD's insertion sort keeps equal elements in
place, a heapsort does not. qsort now follows FreeBSD 11 qsort.c,
including its comparator call sequence.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VZWLdTjf1S57iLgn2rcaFb
2026-10-12 15:01:35 +00:00
Claude fd0d55ce21 fix(tools): follow Depends on chains in pr_overlap
pr_overlap only skipped a pair when one pull request named the other
directly. In a stack where #3 depends on #2 and #2 on #1, #1 and #3 were
reported as overlapping, and two pull requests built on the same #1 were
reported for the files and exports both inherit from it. Dependencies are
now followed through open pull requests, and what a shared dependency adds
is left out of the same-file and same-export columns.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0189deyapHNNqKQJboZBJQei
2026-10-12 06:10:56 +00:00
Claude c35d05395d fix(libc): reject 16-bit wide conversions in sscanf_s and after the ' flag on Linux
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Ha6Tsy62AFUyp9a5Mf7vjA
2026-10-11 23:37:17 +00:00
Claude 36c78ba143 fix(relinker): report the ModRM of 3DNow! instructions in decoded instruction info
DecodeInstruction did not treat 0F 0F as having a ModRM byte, so a
RIP-relative 3DNow! operand was not reported to the analyses and the
--to-intel stub relocation that read HasRipRelativeDisp.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VZWLdTjf1S57iLgn2rcaFb
2026-10-11 22:34:39 +00:00
Claude feb19a844d fix(relinker): decode 3DNow! instructions with their ModRM and opcode suffix
0F 0F was decoded as a two-byte instruction. 3DNow! instructions are
0F 0F ModRM [SIB] [displacement] imm8, the trailing byte selecting the
operation (AMD64 Architecture Programmer's Manual Volume 3, Appendix A,
3DNow! opcodes).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VZWLdTjf1S57iLgn2rcaFb
2026-10-11 22:21:32 +00:00
Claude db49377bef fix(libkernel): return SCE error codes from sceKernelFsync
sceKernelFsync returned the host fsync or _commit result, so a failure
returned -1 instead of an SCE error code, and a guest socket descriptor
reached the host call. fsync then set the guest errno from the host
errno rather than from that result.

Handle sockets and return SCE error codes as sceKernelFdatasync does
(EINVAL for an open socket, EBADF for a closed one or an unknown
descriptor), and have fsync take the errno from sceKernelFsync's result
like the other POSIX wrappers.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Ha6Tsy62AFUyp9a5Mf7vjA
2026-10-11 23:53:00 +02:00
Claude 11fa3ab843 fix(libc): keep getenv results valid when other variables change
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Ha6Tsy62AFUyp9a5Mf7vjA
2026-10-11 21:07:20 +00:00
Claude 1489400189 fix(libc): set EINVAL when getenv gets an invalid name
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Ha6Tsy62AFUyp9a5Mf7vjA
2026-10-11 21:06:35 +00:00
Claude fe4a2cf7d8 fix(libc): run atexit handlers in one order with __cxa_atexit destructors
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Ha6Tsy62AFUyp9a5Mf7vjA
2026-10-11 21:05:51 +00:00
Claude e463c5d11f fix(libkernel): clamp POSIX deadlines beyond the clock range instead of overflowing
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Ha6Tsy62AFUyp9a5Mf7vjA
2026-10-11 21:01:57 +00:00
Claude 74d44b8e6c fix(libkernel): try the lock before checking the pthread_mutex_timedlock deadline
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Ha6Tsy62AFUyp9a5Mf7vjA
2026-10-11 21:00:30 +00:00
Claude 29af23e718 fix(libkernel): apply the memory type in sceKernelMemoryPoolBatch type-protect entries
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Ha6Tsy62AFUyp9a5Mf7vjA
2026-10-11 20:58:50 +00:00
Claude 602a76fc26 fix(libkernel): let pthread_barrier_destroy wait for released waiters
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Ha6Tsy62AFUyp9a5Mf7vjA
2026-10-11 20:57:22 +00:00
Claude f40bb479e2 fix(libkernel): report the remaining time from sceKernelWaitSema
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Ha6Tsy62AFUyp9a5Mf7vjA
2026-10-11 20:09:33 +00:00
Claude d358374ac8 fix(libc): throw for 16-bit wide scanf conversions on Linux
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Ha6Tsy62AFUyp9a5Mf7vjA
2026-10-11 20:07:20 +00:00
Claude 6b72296ef5 fix(libc): format 16-bit wide arguments in asprintf on Linux
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Ha6Tsy62AFUyp9a5Mf7vjA
2026-10-11 20:02:20 +00:00
Claude 4a419397cb fix(libkernel_sys): translate host errors to guest errno numbers
GuestError passed host error values up to 34 through and reported every
other value as EIO, so readlink failed with EIO for a name that is too
long or a symbolic link loop, and a host EAGAIN would have been reported
as the guest's EDEADLK. The values whose numbering differs are now
mapped to FreeBSD's.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Ha6Tsy62AFUyp9a5Mf7vjA
2026-10-11 19:50:38 +00:00
Claude 54e5aad214 test(libkernel): skip the read-only truncate cases when running as root
Root ignores the file mode, so truncating a file with only the owner
read bit succeeds and guest_truncate aborted when the suite ran as root,
as it does in containers. The read-only cases now run only for other
users and the test says on stderr when it skips them.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Ha6Tsy62AFUyp9a5Mf7vjA
2026-10-11 14:59:10 +00:00
Claude bd0998a7a8 fix(build): keep libc.prx needed by every executable that links a prx
Ubuntu's GCC links with --as-needed, so a test that calls nothing in
libc.prx directly dropped it from DT_NEEDED and satisfied the prx
libraries' __cxa_* and __gxx_personality_v0 references from the static
libstdc++ instead. Those copies interpose libc.prx's, so exceptions
thrown inside the prx libraries were searched by libgcc and resumed by
the guest unwinder, which aborted guest_kernel_stack_protect. libc now
propagates to every consumer of a prx with --no-as-needed on Linux.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Ha6Tsy62AFUyp9a5Mf7vjA
2026-10-11 14:56:57 +00:00
Claude d7f1a6d3d5 fix(libkernel): translate host errno in the file functions' SCE errors
SceErrorFromErrno in the libkernel file functions passed host errno
values 1-34 through and turned every other value into EIO. Linux numbers
EAGAIN 11, which is FreeBSD's EDEADLK, so a read from an empty
non-blocking pipe returned SCE_KERNEL_ERROR_EDEADLK, and ENAMETOOLONG,
ELOOP, ENOTEMPTY, EDQUOT and EOVERFLOW, whose host values differ from
FreeBSD's, all became EIO.

Map those host values to the guest's FreeBSD numbers, as
SceIoErrorFromErrno in Open.cpp already does for EAGAIN, EDEADLK,
EDQUOT and EOVERFLOW. The guest constants the callers pass are all at
most 34 and never 11, or GUEST_ENOTEMPTY, so they are unchanged.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Ha6Tsy62AFUyp9a5Mf7vjA
2026-10-11 14:32:44 +00:00
Claude c356112f32 fix(libkernel): keep raises off unregistered threads and clamp the handler's MXCSR
Two defects found in review of the Linux delivery:

A raise right after scePthreadCreate reached the new thread before
RunThread set currentThread, so scePthreadSelf() in the handler adopted
a second handle, and could deadlock on glibc's thread lock when the
signal interrupted pthread_getattr_np. The creator now blocks all
signals around the std::thread construction, so the child starts with
them blocked, and RunThread restores the creator's mask once the thread
is registered, as libthr does. A raise in that window stays pending and
is delivered just before the entry runs.

A handler that set reserved MXCSR bits made rt_sigreturn fail with
SIGSEGV. The MXCSR the handler leaves is now masked with the frame's
MXCSR_MASK (0xffbf when it reads 0), as FreeBSD's fpusetregs does, on
both platforms; Windows also keeps CONTEXT.MxCsr equal to
FltSave.MxCsr.

guest_raise_exception raises right after each of 50 thread creations and
checks scePthreadSelf() in the handler, and its context round trip sets
a reserved MXCSR bit and FZ and checks that only FZ is kept.

AI-assisted: yes

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LwJx7AHrSUaMGSpEGhL1Kb
2026-10-11 11:12:02 +02:00
Claude dca5a88ef2 feat(libkernel): deliver sceKernelRaiseException on Linux
sceKernelRaiseException threw on Linux, so a title whose garbage
collector stops threads with it (Unity's PS5Util raises SIGUSR1 on each
thread and reads mc_rsp from the handler's context) could not run there.

The raise now sends the host SIGUSR1 to the target thread with
pthread_kill. The host handler, installed on first use with SA_SIGINFO
and SA_RESTART, builds the FreeBSD-layout ucontext from the interrupted
registers and the FXSAVE area, calls the guest handler on the target's
own stack and writes the registers back, so the handler's changes reach
the interrupted code, as they do on Windows. errno is left as the
handler leaves it, as libthr does.

A raise on another thread takes the target's join lock with the host
signal blocked and returns ESRCH once the thread has finished, so a
detached thread's pthread_t is never signalled after it exits. The
pthread_t is recorded when the thread is created or adopted. Handlers
are now lock-free atomics, as the host handler reads them.

guest_raise_exception now runs on every platform. It also checks that
r13 and xmm8 reach the handler and that r12 and xmm8 written by the
handler reach the interrupted code.

AI-assisted: yes

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LwJx7AHrSUaMGSpEGhL1Kb
2026-10-11 11:11:23 +02:00
Claude b87dd8d845 docs(shader): note the per-bit f16 denormal field against the f32 mode 1 and 2 refusals
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01K9MzdVqDf6wHUKzNymQSze
2026-10-11 04:24:00 -04:00
Claude 3bfb0445e5 fix(libSceSysmodule): link and run guest_sysmodule_tests like the other guest tests
Link libc, configure Windows unwinding for the test so its runtime_error
checks are caught, and run it from libSceFiber's output directory so
openHostModule finds the unpatched libSceFiber.prx next to the modules the
test already loads.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01K9MzdVqDf6wHUKzNymQSze
2026-10-11 03:27:59 -04:00
Claude 7c4f9381d4 Merge upstream main into fix-shader-f16-directed-rounding
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01K9MzdVqDf6wHUKzNymQSze
2026-10-11 01:33:16 +00:00
Claude 2243e17f34 fix(libc): return a 64-bit unsigned long from _Stoul on Windows
The guest's unsigned long is 64 bits. _Stoul was declared with the
host's unsigned long and returned std::strtoul, which are 32 bits on
Windows (LLP64): "4294967296" clamped to 4294967295 with ERANGE and
"-1" gave 0xffffffff, so a guest std::stoul threw out_of_range on values
the console accepts. It now returns std::uint64_t from std::strtoull,
as strtoul_nid_postfix and _Stoull already do; on Linux nothing changes.
The binary-prefix check stays in front of the host call.

Reported in #2424 by AchrafReyani; the same change was proposed in #2442
by SurajKhanna, whose two guest_math cases are taken here. Folded in at
MarcZX100's suggestion on #1459.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-10-09 21:33:08 +00:00
Claude 8c714f76af fix(libc): stop the wcstol family at a binary prefix on Linux
wcstol, wcstoll, wcstoul and wcstoull parse the ASCII prefix of the
guest's UTF-16 text with std::strtoll and std::strtoull, which glibc 2.38
and later bind to the C23 __isoc23_* functions: wcstol(u"0b101", &end, 0)
returned 5 with the end pointer after the whole string. They now check
StopAtBinaryPrefix_nid_no_patch first, like the narrow functions, and the
end pointer maps back through ParseAsciiPrefix as before.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 21:26:13 +00:00
Claude b5c9945e1f fix(libc): stop the strtol family at a binary prefix on Linux
C17 has no binary prefix: with base 0 or 2, strtol("0b101", &end, base)
reads the subject "0", returns 0 and leaves end at the 'b'. With glibc
2.38 or later, g++ (which defines _GNU_SOURCE) binds std::strtoll,
strtoull, strtoul, strtoimax and strtoumax to the C23 __isoc23_*
functions, which accept 0b/0B: the Linux exports returned 5 and
consumed the whole string. The Windows UCRT already follows C17, so the
same guest call gave different results on the two hosts.

strtol, strtoul, strtoll, strtoull, _Stoull, strtoimax, strtoumax and
_Stoul now return 0 with the end pointer after the '0' when, after
white space and an optional sign, the text starts with 0b or 0B and a
binary digit, in base 0 or 2. Everything else still goes to the host
function. The scanf family's %i has the same glibc behaviour; it is
recorded in TechnicalDebt.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 21:26:13 +00:00
Claude 4a2769f26d test(net): skip only the IPv6 socket checks on a host without IPv6
On a host without IPv6, socket(AF_INET6) fails with EAFNOSUPPORT, so
guest_sce_net aborted at its first IPv6 socket and never ran the TCP,
UDP, epoll, sendmsg/recvmsg, resolver and NetCtl checks after it.

When sceNetSocket reports guest EAFNOSUPPORT (47) for the IPv6 socket,
skip those socket checks, run the rest of the test, and exit with 77,
which ctest reports as skipped. Hosts with IPv6 run every check.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Ha6Tsy62AFUyp9a5Mf7vjA
2026-10-09 10:30:28 +00:00
Claude 9bd8089cbb test(agc): compare llvmpipe shader clocks modulo 2^32
llvmpipe builds the high dword of the shader clock with a left shift by
32 (emit_clock in Mesa's lp_bld_nir_soa.c), so it is always 0 and
s_memtime and s_memrealtime wrap every 2^32 ns. A pass of
agc_driver_shader_clock whose two reads straddle a wrap failed with
"memtime: lane N went back from 4294921902 to 3823"; dispatching right
before the boundary fails every lane of that pass.

On llvmpipe compare the low dwords modulo 2^32, which stays correct if
Mesa fixes the shift. Other devices keep the 64-bit comparison.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Ha6Tsy62AFUyp9a5Mf7vjA
2026-10-09 10:30:28 +00:00
Claude c7b95bc6c5 fix(agc): fail a failed submission's flips before reporting the failure
When a queue worker failed, it published the failure and woke the idle
waiters before failing the flips of the submission it was executing.
A thread returning from AgcDriverWaitIdle with that failure could still
see one of those flips neither completed nor failed, which made
agc_driver_flip fail with "failed flip was completed successfully" in
2 of 240 runs under four-way parallel load on lavapipe.

Fail the executing submission's flips first, as ReportFailure already
does for the pending submissions it drops before it notifies.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Ha6Tsy62AFUyp9a5Mf7vjA
2026-10-09 10:30:28 +00:00
Claude c0519cc814 feat(shader): implement the 32-bit DS src2 operations
The decoder threw on the GFX10.1 DS src2 opcodes 0x80-0x8b, 0x8d,
0x92, 0x93 and 0x95. Each reads DS[B], where B is the address plus
four times the 15-bit signed offset in offset1[6:0]:offset0, and
applies the matching operation to DS[A]: add, sub, rsub, inc, dec,
signed and unsigned min and max, and, or, xor, f32 min, max and add
through the 32-bit LDS atomics, and a plain write for
ds_write_src2_b32. The form that takes the offset from the address
bits (offset1[7]), the 64-bit forms and GDS still throw.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-08 23:06:15 +02:00
Claude 3ed954fb90 feat(libSceHttp): accept the SSL version, SSL error and redirect and cookie callback calls
No request reaches the network, so sceHttpsSetSslVersion has no TLS
connection to configure, sceHttpSetRedirectCallback and
sceHttpSetCookieRecvCallback register callbacks that are never called,
and sceHttpsGetSslError reports error 0 with detail 0. A null errNum or
detail returns SCE_HTTP_ERROR_INVALID_VALUE like sceHttpGetLastErrno.
Signatures follow shadPS4.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-08 10:57:14 +02:00
Claude 9abc931a18 refactor(libkernel): share eh_frame_hdr parsing between module info calls
sceKernelGetModuleInfoForUnwind and sceKernelGetModuleInfoFromAddr each
parsed .ehmeta and the eh_frame_hdr it names. Both now read them through
Module/EhFrame.hpp, so a bad table fails the same way in both: an
eh_frame_hdr version other than 1, an indirect or non-absptr/pcrel
encoding, a 64-bit record length or anything outside the image throws.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JkiyF6p7oDAaTtVe8ci5zP
2026-10-08 06:47:14 +00:00
Claude 2a253b376b fix(libc): raise FE_INVALID from hypotf for a signaling NaN with infinity
hypotf now widens both arguments to double and calls the double hypot.
The float-to-double conversion raises FE_INVALID for a signaling NaN and
quiets it, so hypotf(sNaN, inf) returns +inf with the invalid flag set in
either argument order, matching the PS5 libc routine. Before, MinGW UCRT's
hypotf returned +inf without the flag and glibc's returned NaN.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Scr6DkuJDqiUcJHr9mJv6T
2026-10-08 02:27:31 +00:00
Claude ace10fdba3 feat(agc): detile the display, T and 4 KiB XOR swizzle modes
Textures in SW_256B_D, SW_4KB_D, SW_64KB_D, SW_64KB_S_T, SW_64KB_D_T,
SW_4KB_S_X and SW_4KB_D_X (tile modes 2, 6, 10, 17, 18, 21 and 22)
threw while their T# was decoded. They are detiled with address
equations generated from AMD addrlib's GFX10 swizzle patterns for the
same 16-pipe non-RB+ configuration as the 64 KiB XOR table, and share
the block shape and mip tail placement of the standard mode of their
block size. The pipe/bank XOR base check of the XOR and T modes now
uses the block size.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-07 16:11:05 -05:00
Claude 495aa94ec4 feat(shader): implement 1D array gathers
image_gather4_lz(_o) on a 1D array view threw. The 1D gather emulation
now takes the width from the array view's size, keeps the layer
coordinate and samples both texel centres of that layer, so 1D array
gathers return the same footprint as 1D ones.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-07 23:01:09 +02:00
Claude 121d9332b5 build(libs): strip the MinGW static runtime flags once for all libraries
Every library CMakeLists.txt ended with the same block removing -static,
-static-libgcc and -static-libstdc++ from CMAKE_EXE_LINKER_FLAGS on MinGW,
because core/libs/CMakeLists.txt only removed them after adding the library
directories. Remove them before the libc and library directories are added
so each directory inherits the stripped flags, and drop the 52 copies.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017pTZqAyVSZy2FZmaqakPHZ
2026-10-07 10:10:38 +00:00
Claude 2eebe84f25 feat(agc): accept texel offsets, LOD biases and LOD clamps in color comparison sampling
Comparison sampling of a color texture threw on the _o, _b and _cl
forms and on a sampler LOD bias. The emulation fetches the texels
itself, so the 6-bit offsets of the address are added to the point or
bilinear texel indices, as on the hardware and in Vulkan. The emulation
runs only at level zero or on a single-level view, where an LOD bias or
clamp cannot select another level, so they are accepted with no effect.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-07 11:30:00 +02:00
Claude cc4d8ec07e refactor(recompiler): dispatch image atomics through ImageOpcodeInfoOf
EmitImage listed all 27 image atomic opcodes by hand to reach
EmitAtomicOp, although it already looks up ImageOpcodeInfoOf for the
instruction. Route every opcode whose access is ImageAccess::Atomic to
EmitAtomicOp before the switch; the set of opcodes is unchanged.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017pTZqAyVSZy2FZmaqakPHZ
2026-10-07 09:19:01 +00:00
Claude 5625fe6043 refactor(libSceAvPlayer): build libSceAvPlayer.native from the shared Export.cpp
libSceAvPlayer.native/Export.cpp was a byte-identical copy of
libSceAvPlayer/Export.cpp. Point add_sce_avplayer_library at the guest
directory's Export.cpp, as the Audiodec and Font library functions do, and
remove the copy.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017pTZqAyVSZy2FZmaqakPHZ
2026-10-07 06:19:46 +00:00
Claude fb1ef4f404 refactor(recompiler): share the SPIR-V emission failure helper
Nine SPIR-V backend sources each defined an identical FailEmit in an
anonymous namespace. Declare it once in SpirvEmitterHelpers.hpp and
define it in SpirvEmitterHelpers.cpp; the message is unchanged.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MBXJqzgohLeVAeHsn4Jpm7
2026-10-07 06:05:14 +00:00
Claude 928cf9b42d fix(savedata): serialize mount slot access in libSceSaveData.native
Mount, unmount, param, icon and mount-info calls read and wrote the
global mount slot table without a lock, so two threads mounting at
once could take the same slot and one would later fail to unmount its
own mount point. Guard the table with a mutex and make the initialization
count atomic.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MBXJqzgohLeVAeHsn4Jpm7
2026-10-07 05:26:59 +00:00
Claude c10401e390 feat(agc): detile 3D textures in SW_64KB_Z_X and SW_64KB_S_X
3D textures in the 64 KiB Z and S XOR swizzles threw. As in AMD
addrlib's GFX10 rules, a Z_X volume is thin: each depth slice is laid
out like an array slice with the 2D Z_X equation, as the R_X and D_X
volumes already were. An S_X volume is thick: it takes the standard
64 KiB thick block and mip tail with its own S3 XOR equation, generated
from addrlib for the same configuration as the other equations.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-06 16:19:11 +00:00
Claude fef66c1406 feat(agc): implement 1D array textures
A T# of type 12 (1D array) threw while decoding. It now decodes to a
1D array dimension, checked like a 2D array with a height of one, and
holds depth + 1 layers laid out as a 2D array's. Its Vulkan image is
1D with that many layers, viewed as VK_IMAGE_VIEW_TYPE_1D_ARRAY for
sampling and storage, and the recompiler declares a 1D array shape for
arrayed 1D image resources instead of failing.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-06 15:56:14 +00:00
Claude f6ce77bb7f feat(shader): accept texel offsets in 1D gathers
image_gather4_lz_o on a 1D view threw. The 1D gather emulation picks
the two texels around the coordinate itself, so the 6-bit x offset of
the address is added to the left texel index before both texel
centres are sampled, as the hardware offsets the footprint.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-06 15:49:37 +00:00
Claude 16e76301ab feat(libSceAgc): implement the WRITE_DATA destination and cache policy patches
sceAgcWriteDataPatchSetDst, sceAgcWriteDataPatchSetCachePolicy, their
Async forms and sceAgcAsyncWriteDataPatchSetAddressOrOffset threw. They
now rewrite a WRITE_DATA packet in place: the destination in the
graphics (sceAgcDcbWriteData) or compute (sceAgcAcbWriteData) encoding,
the cache policy in bits 25-26 and the address in dwords 2-3, so the
patched packet equals the one written with those values. A register
destination is rejected when the packet requests write confirmation,
as when the packet is written.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-06 14:51:07 +00:00
Claude 8d7ff94689 feat(libSceKeyboard): translate the 106-key arrangement in sceKeyboardGetKey2Char
The 106-key (Japanese) arrangement threw. Its alphanumeric layer now
follows the JIS layout of the HID usages: the symbol keys right of the
digits and letters, the Ro key (0x87) and the Yen key (0x89). With the
Kana LED set it still throws, as the kana the console returns are
unknown.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-06 14:02:11 +00:00
Claude 897d538649 refactor(relinker): use the shared ELF constants
The relinker redefined 61 ELF constants 93 times across seven files,
38 of them already in elfpatcher's ElfConstants.hpp. Add the missing
dynamic tags, relocation types and symbol constants to that header and
remove the local copies; every value is unchanged. strict_nid_filter_tests
compiles these sources and now gets the elfpatcher include directory.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MBXJqzgohLeVAeHsn4Jpm7
2026-10-06 08:26:50 +00:00
Claude 89ba1019e6 Merge upstream main into refactor/kernel-error-header
Upstream merged #25 and #26. Resolve DirectMemory.hpp and Equeue.hpp
by keeping this branch's side: the local error constants #26 fixed are
replaced by KernelErrors.hpp here.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018emyZ4Rk8yoSJvxTFBe4DL
2026-09-28 08:34:25 +00:00
Claude 0b560c6af1 Merge fix/audit-2026-09 into refactor/kernel-error-header
Bring in the Linux scePthreadExit fix from #25.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018emyZ4Rk8yoSJvxTFBe4DL
2026-09-28 07:47:20 +00:00
Claude a60256ea4d fix(kernel): exit POSIX guest threads without forced unwinding
On Linux scePthreadExit called pthread_exit, whose forced unwind runs
the personality routine of every guest frame. Those resolve to
libc.prx's __gxx_personality_v0, which cannot read libgcc's unwind
context and aborts, so guest_thread_self crashed on Linux.

Record a jump target in the thread start routine and longjmp back to it
from scePthreadExit instead. Like _endthreadex on Windows, this skips
the guest frames without unwinding them; the start routine still
releases the thread normally. Threads not created by scePthreadCreate
keep the pthread_exit fallback.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018emyZ4Rk8yoSJvxTFBe4DL
2026-09-28 07:47:12 +00:00
Claude 2aced8e8d9 Merge fix/audit-2026-09 (with upstream main) into refactor/kernel-error-header
Bring in the resolved #25 branch, which already carries upstream main
including boykopovar/AnyPS5#10, and re-apply the KernelErrors.hpp
refactor onto the rewritten files:

- Equeue: drop the local EQUEUE_ERROR_* constants and use the shared
  SCE_KERNEL_ERROR_* names.
- Pthread Attr/Thread: drop local error constants and include
  KernelErrors.hpp.
- Pthread Cond/Mutex: take upstream; they no longer define local
  SCE_KERNEL_ERROR_* constants.
- Semaphore: drop KERNEL_SEMA_ERROR_* in favour of KernelErrors.hpp.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018emyZ4Rk8yoSJvxTFBe4DL
2026-09-28 07:40:42 +00:00
Claude a28cfb7585 Merge upstream main into fix/kernel-error-codes
Resolve the conflict with boykopovar/AnyPS5#10 in Pthread/src/Mutex.cpp
by taking upstream: its rewrite already returns EDEADLK as 0x8002000B.
The equeue and direct memory error code fixes are unaffected.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018emyZ4Rk8yoSJvxTFBe4DL
2026-09-28 07:36:16 +00:00
Claude 210987745c Merge upstream main into fix/audit-2026-09
Resolve conflicts with boykopovar/AnyPS5#10 (sce module loading) and
later upstream changes.

- Pthread Cond/Mutex: take upstream. It already releases mutex
  ownership across condition waits, returns ETIMEDOUT 0x8002003C, and
  rejects unlocks from non-owners for every mutex type.
- Pthread Thread: keep upstream's lifecycle, Windows adoption and job
  affinity; re-apply the POSIX fixes on top: reference-counted
  release on join/detach/exit, self-join rejection on both platforms,
  and scePthreadSelf adoption for threads not created by
  scePthreadCreate.
- Semaphore: keep upstream's TimedWait::Condition and wait tracing;
  re-apply sceKernelDeleteSema waking waiters with EACCES.
- Relinker: keep --windows-gui alongside upstream's --skip-sce-module,
  trampoline-aware Patch signature and new Python tests.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018emyZ4Rk8yoSJvxTFBe4DL
2026-09-28 07:34:25 +00:00