Portability Is a Negotiation: CPUs, GPUs, and Caches
AnyPS5 does not solve portability with one universal switch. It uses targeted CPU instruction lowering for a narrow AMD-to-Intel problem, interrogates the host GPU before choosing Vulkan paths, and caches translated work only when the source, interface, device, and driver conditions match. This chapter diagnoses those choices as different causes of portability cost: code that the CPU cannot execute, features the GPU cannot provide, and repeated translation that can be reused only with safe identity checks.
The CPU problem is narrower than emulation
The optional --to-intel path addresses a specific symptom: a PS5 binary or bundled module contains an AMD-only x86-64 instruction that an Intel host may not execute. The converter scans executable code segments, matches supported AMD-only instructions or instruction sequences, and chooses a lowering strategy. If the replacement fits the original instruction length, it can be applied in place. If it does not, the converter can create an out-of-line trampoline that executes the replacement and branches back to the original flow.
That sounds small because it is intentionally small. The converter does not interpret every guest instruction, schedule a virtual CPU, or provide a general fallback for unknown opcodes. It preserves the title's x86-64 process model and changes only the instruction forms it knows how to lower. The result remains x86-64 Linux ELF or Windows PE output; the project is not changing the title into a platform-independent bytecode program.
The safety checks explain why this path can fail even when an instruction has a theoretical replacement. The converter scans branch targets and refuses to place a trampoline where another branch would enter the instruction sequence being replaced. If an AMD-only instruction is too short for a jump and the following instructions cannot be moved safely, the conversion fails. An optional substitution may be kept when it cannot be lowered and the project marks it as optional, but an unsupported required instruction throws. The relinker reports in-place substitutions, stubs, and kept instructions so the operator can see what happened.
The converter's order of operations is what makes the safety check meaningful. It first scans the code segment and identifies instruction boundaries. It then matches possible AMD-only instructions and determines which ones need an out-of-line lowering. For trampoline candidates, it collects branch targets from the surrounding code and checks whether moving the affected sequence would create an entry point into the middle of the replacement site. The output report records the original offset and replacement shape, so a user can tell whether the host-specific rewrite happened in place or through a stub.
This is a localized form of binary rewriting. The surrounding code remains in the original segment, and the trampoline returns to the point after the consumed instruction sequence. If an instruction sequence must absorb adjacent instructions to make room for a jump, only sequential instructions that can be relocated are considered. A branch, a non-sequential flow instruction, or an instruction whose movement changes a target can make the sequence unsafe. The converter does not solve that case by assuming that the code will never reach it.
This diagnosis separates three cases that are often conflated. A CPU incompatibility is solved by rewriting a known instruction. A code-layout problem is solved only if a safe trampoline can be made.