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
2 changes: 2 additions & 0 deletions compiler/rustc_target/src/spec/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1615,6 +1615,7 @@ supported_targets! {
("armv7a-kmc-solid_asp3-eabi", armv7a_kmc_solid_asp3_eabi),
("armv7a-kmc-solid_asp3-eabihf", armv7a_kmc_solid_asp3_eabihf),

("powerpc64-sony-ps3", powerpc64_sony_ps3),
("mipsel-sony-psp", mipsel_sony_psp),
("mipsel-sony-psx", mipsel_sony_psx),
("mipsel-unknown-none", mipsel_unknown_none),
Expand Down Expand Up @@ -1862,6 +1863,7 @@ crate::target_spec_enum! {
Nto = "nto",
NuttX = "nuttx",
OpenBsd = "openbsd",
Ps3 = "ps3",
Psp = "psp",
Psx = "psx",
Qnx = "qnx",
Expand Down
107 changes: 107 additions & 0 deletions compiler/rustc_target/src/spec/targets/powerpc64_sony_ps3.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
use crate::spec::{
Arch, Cc, CfgAbi, CodeModel, Endian, FramePointer, LinkerFlavor, Lld, LlvmAbi, Os,
PanicStrategy, RelocModel, Target, TargetMetadata, TargetOptions,
};

pub(crate) fn target() -> Target {
let pre_link_args = TargetOptions::link_args(
LinkerFlavor::Gnu(Cc::No, Lld::No),
&[
// We strictly need ELFv1 PPC64.
"-m",
"elf64ppc",
// PS3 LV2 reserves the first 64KB page for unmapped memory protection.
"--image-base=0x10000",
// Should be default, but relying on automatic behavior appears to be brittle.
"-e",
"_start",
// CellOS expects .rodata to be merged into the executable Text segment (RX)
// so there are only 2 loadable segments (RX and RW)
"--no-rosegment",
// CellOS uses 64 KB memory pages. Without this flag, `mold` might align data segments to 4 KB boundaries.
"-z",
"separate-loadable-segments",
// Prevents mold from creating a `PT_GNU_RELRO` segment that GameOS does not support.
"-z",
"norelro",
// CellOS's loader doesn't behave like `ld`. PRXs are stubbed in the binary already.
"-Bstatic",
// The following are segments that might never be referenced by the code,
// but are expected to exist by the PS3's loader.
"-u",
"sys_process_param",
"-u",
"sys_proc_prx_param",
"--undefined-glob=*_prx_header",
"--undefined-glob=*_fnid_table",
"--undefined-glob=*_name",
"--undefined-glob=*_fstub_table",
],
);

Target {
// LLVM will default to a compatible ELF backend.
llvm_target: "powerpc64-sony-ps3".into(),

metadata: TargetMetadata {
description: Some("PowerPC64 (big endian) Sony PlayStation 3 (PS3)".into()),
tier: Some(3),
host_tools: Some(false),
std: Some(false),
},

// We declare pointers to be 64-bit as the PPU _is_ a 64-bit core.
// However, for all real usage the OS limits us to **32-bit pointers**.
// SDKs should therefore take this into account, specifically when handling syscalls.
pointer_width: 64,

data_layout: "E-m:e-Fi64-i64:64-i128:128-n32:64".into(),
arch: Arch::PowerPC64,

options: TargetOptions {
// Base PS3 hardware.
vendor: "sony".into(),
endian: Endian::Big,
os: Os::Ps3,
cfg_abi: CfgAbi::ElfV1,
llvm_abiname: LlvmAbi::ElfV1,
features: "+altivec".into(),

// CellOS requiring ELFv1 makes LLVM's `lld` incompatible.
// See:
// - [rust-lang/rust#85589](https://github.com/rust-lang/rust/issues/85589)
// - [llvm/llvm-project#27630](https://github.com/llvm/llvm-project/issues/27630)
linker: Some("mold".into()),
linker_flavor: LinkerFlavor::Gnu(Cc::No, Lld::No),

// CellOS _is_ case-sensitive, but the PS3's binaries vary
// in casing depending on whether they are games in `/dev_hdd0`
// or system binaries (such as PRX files).
//
// All games use the .ELF (uppercase) suffix, and Sony's own
// documentation and tools expect user app binaries to be uppercase.
exe_suffix: ".ELF".into(),
Comment thread
ZephyrCodesStuff marked this conversation as resolved.

// This limits us to 64KB of ToC, but yields smaller binaries and less assembly.
// Only becomes a problem for binaries with thousands of dependencies.
code_model: Some(CodeModel::Small),
// Prevents LLVM from emitting modern linker relaxation relocations.
relax_elf_relocations: false,
// CellOS main executables (`EBOOT.ELF`) **must be static executables** (ET_EXEC).
relocation_model: RelocModel::Static,

// Locking defaults against future changes.
c_int_width: 32,
executables: true,
frame_pointer: FramePointer::MayOmit,
// Change this to `true` for developing kernel-mode applications.
// This target defaults to user-mode, and the kernel already handles
// this for us, so keeping it off is a performance gain.
disable_redzone: false,

panic_strategy: PanicStrategy::Abort,
pre_link_args,
..Default::default()
},
}
}
2 changes: 2 additions & 0 deletions library/compiler-builtins/crates/symcheck/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -210,6 +210,7 @@ impl Target {
"nto" => Os::Nto,
"nuttx" => Os::Nuttx,
"openbsd" => Os::OpenBsd,
"ps3" => Os::Ps3,
"psp" => Os::Psp,
"psx" => Os::Psx,
"qurt" => Os::Qurt,
Expand Down Expand Up @@ -324,6 +325,7 @@ enum Os {
Nto,
Nuttx,
OpenBsd,
Ps3,
Psp,
Psx,
Qurt,
Expand Down
1 change: 1 addition & 0 deletions src/doc/rustc/src/SUMMARY.md
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,7 @@
- [powerpc-unknown-linux-gnuspe](platform-support/powerpc-unknown-linux-gnuspe.md)
- [powerpc-unknown-linux-muslspe](platform-support/powerpc-unknown-linux-muslspe.md)
- [powerpc64-ibm-aix](platform-support/aix.md)
- [powerpc64-sony-ps3](platform-support/powerpc64-sony-ps3.md)
- [powerpc64-unknown-linux-gnuelfv2](platform-support/powerpc64-unknown-linux-gnuelfv2.md)
- [powerpc64-unknown-linux-musl](platform-support/powerpc64-unknown-linux-musl.md)
- [powerpc64le-unknown-linux-gnu](platform-support/powerpc64le-unknown-linux-gnu.md)
Expand Down
1 change: 1 addition & 0 deletions src/doc/rustc/src/platform-support.md
Original file line number Diff line number Diff line change
Expand Up @@ -388,6 +388,7 @@ target | std | host | notes
[`powerpc-wrs-vxworks`](platform-support/vxworks.md) | ✓ | |
[`powerpc-wrs-vxworks-spe`](platform-support/vxworks.md) | ✓ | |
[`powerpc64-ibm-aix`](platform-support/aix.md) | ? | | 64-bit AIX (7.2 and newer)
[`powerpc64-sony-ps3`](platform-support/powerpc64-sony-ps3.md) | * | | PowerPC64 (BE) Sony PlayStation 3 (PS3)
[`powerpc64-unknown-freebsd`](platform-support/freebsd.md) | ✓ | ✓ | PPC64 FreeBSD (ELFv2)
[`powerpc64-unknown-linux-gnuelfv2`](platform-support/powerpc64-unknown-linux-gnuelfv2.md) | ✓ | ✓ | PPC64 Linux (ELFv2 ABI, kernel 3.2, glibc 2.17)
[`powerpc64-unknown-openbsd`](platform-support/openbsd.md) | ✓ | ✓ | OpenBSD/powerpc64
Expand Down
93 changes: 93 additions & 0 deletions src/doc/rustc/src/platform-support/powerpc64-sony-ps3.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
# `powerpc64-sony-ps3`

**Tier: 3**

Target for the Sony PlayStation 3 (shortened to "PS3"), for the PowerPC Processor Element (PPU) of the [Cell Broadband Engine Architecture (CBEA)](https://ieeexplore.ieee.org/document/5388675).

## Target maintainers

- [@ZephyrCodesStuff](https://github.com/ZephyrCodesStuff) (Primary developer and maintainer)
- [@RipleyTom](https://github.com/RipleyTom) (Fallback maintainer)

## Requirements

The target is a **big-endian PowerPC64 ELFv1** platform (the Cell Broadband Engine's PPE), and intended only for use on Sony PlayStation 3 systems, under the official operating system, "CellOS".

The linker must support **Big-Endian PowerPC64 ELFv1**: the recommended and tested linker is [mold](https://github.com/rui314/mold). LLVM's `lld` does not correctly handle ELFv1 call relocations in freestanding `no_std` environments, making it incompatible. (See: [rust-lang/rust#85589](https://github.com/rust-lang/rust/issues/85589), [llvm/llvm-project#27630](https://github.com/llvm/llvm-project/issues/27630))

@tgross35 tgross35 Sep 3, 2026

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

@Gelbpunkt are you familiar with this? Seems like something to note for the proposed ppc bare metal targets

View changes since the review

@ZephyrCodesStuff ZephyrCodesStuff Sep 4, 2026

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

For further clarification:

  1. lld emits 32-bit opd addresses
  2. mold and GNU's ld for PowerPC64 emit 64-bit ones

lld makes the PS3 try jumping to a 64-bit mashup of two completely separate addresses, immediately crashing the process.

Note: normally lld is hardened against this and would refuse to link ELFv1. In this case, it seems like something is not setting e_flags = 1 (the ABI version, 1 for ELFv1 and 2 for ELFv2) in the ELF header, leaving it to 0 instead and confusing lld into trying to link it.

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.

@Gelbpunkt are you familiar with this? Seems like something to note for the proposed ppc bare metal targets

Yes, I am. LLD does not support ELFv1. This is one of the reasons I quoted for making powerpc64-unknown-linux-gnu use ELFv2 in this MCP.

Linux already prefers ELFv2 on powerpc64, but the proposed bare metal target was for ELFv1, which is weird 🤷‍♀️


Resulting binaries require additional patching after linking to adhere to the PlayStation 3 operating system, in order to be bootable. An open-source patcher is available [here](https://github.com/ZephyrCodesStuff/rust-ps3/tree/main/moldier). Generally, a patcher must perform the following:

- Rewrite the ELF OS/ABI to `0x66` (`ELFOSABI_CELLLV2`)
- Strip any GNU/Linux headers
- Add Sony-specific flags, sections (`.sys_proc_param` and `.sys_proc_prx_param`) and headers
- Add "stubs" for Sony SPRX dynamic-link libraries, by adding a section (`.lib.stub`) for CellOS to be able to link them
- Patch OPD function descriptors (in the `.opd` section)

_**Note**: this list may not be exhaustive for all use cases, but is sufficient for producing a runnable binary. Producing a PRX dynamic library may require more/different steps._


The target _fully supports_:

- The Rust `core` features
- The Rust `alloc` feature, as the CellOS Lv2 kernel provides virtual memory allocation (`sys_memory_allocate`) on top of which a heap allocator (such as [talc](https://github.com/SFBdragon/talc)) can be implemented.
- AltiVec / VMX SIMD vector extensions (natively supported by LLVM via `+altivec`)

## Building the target

If `rustc` is built with this target enabled, no external C cross-compilation toolchain is strictly required to build the compiler host artifacts, but `mold` must be installed on the host system to perform linking.

Support for using `lld` as a linker is unlikely, until support for ELFv1 is implemented on `lld`.

## Building Rust programs

Because this is a Tier 3 target, pre-compiled standard library artifacts (`core`, `alloc`) are not distributed via rustup. Programs must be built using a nightly toolchain with the `rust-src` component and `-Z build-std`.

A Rust SDK ready for development exists open-sourced [here](https://github.com/Zephyrcodesstuff/rust-ps3) and is licensed `MIT OR Apache-2.0`.

Configure your project `.cargo/config.toml`:
```toml
[target.powerpc64-sony-ps3]
linker = "mold"
rustflags = [
"-C", "relocation-model=static",
"-C", "code-model=small",
"-C", "target-feature=+altivec",
]
```

**Prerequisites:**

- A nightly Rust compiler with the `rust-src` component
- The [mold](https://github.com/rui314/mold) linker
- The [moldier](https://github.com/ZephyrCodesStuff/rust-ps3/tree/main/moldier) post-linker tool
- *(Optional)* `make_fself` or `scetool` for converting the output `.ELF` into an encrypted/signed `EBOOT.BIN` for running on real hardware.

**Build process:**

```bash
# Compile the binary
cargo +nightly build \
--target powerpc64-sony-ps3 \
-Z build-std=core,alloc \
--release

# Patch the linked executable
moldier patch target/powerpc64-sony-ps3/release/my_program.ELF

# (Optional) Sign the binary for official hardware
make_fself "target/powerpc64-sony-ps3/release/my_program.ELF" "target/powerpc64-sony-ps3/release/my_program.BIN"
```

## Testing

The target fully supports running binaries (once they're patched), both on official hardware and on [open-source emulators](https://github.com/rpcs3/rpcs3).

As official firmware for the system forbids running unsigned code, the system must first be jailbroken in order to run binaries. This is not optional.

Emulators do not impose any requirement regarding codesigning, thus testing on emulators is straightforward.

Debugging is fully possible, either via debug firmware APIs on the official hardware, or on emulators via either their integrated debuggers, or a GDB server the emulator provides.

## Cross-compilation toolchains and C code

The target fully supports C/C++ code. Any compiler capable of producing binaries for a PowerPC64 big-endian processor can produce code to be embedded into the Rust program.
1 change: 1 addition & 0 deletions src/librustdoc/clean/cfg.rs
Original file line number Diff line number Diff line change
Expand Up @@ -685,6 +685,7 @@ fn human_readable_target_os(os: Symbol) -> Option<&'static str> {
Nto => "QNX SDP 7.x",
NuttX => "NuttX",
OpenBsd => "OpenBSD",
Ps3 => "Play Station 3",
Psp => "Play Station Portable",
Psx => "Play Station 1",
Qnx => "QNX SDP 8.0+",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ const KNOWN_ARCH: [&str; 20] = [

const KNOWN_ENV: [&str; 7] = ["eabihf", "gnu", "gnueabihf", "msvc", "relibc", "sgx", "uclibc"];

const KNOWN_OS: [&str; 20] = [
const KNOWN_OS: [&str; 21] = [
"cuda",
"dragonfly",
"emscripten",
Expand All @@ -128,6 +128,7 @@ const KNOWN_OS: [&str; 20] = [
"netbsd",
"none",
"openbsd",
"ps3",
"psp",
"redox",
"solaris",
Expand Down
3 changes: 3 additions & 0 deletions tests/assembly-llvm/targets/targets-elf.rs
Original file line number Diff line number Diff line change
Expand Up @@ -403,6 +403,9 @@
//@ revisions: msp430_none_elf
//@ [msp430_none_elf] compile-flags: --target msp430-none-elf
//@ [msp430_none_elf] needs-llvm-components: msp430
//@ revisions: powerpc64_sony_ps3
//@ [powerpc64_sony_ps3] compile-flags: --target powerpc64-sony-ps3
//@ [powerpc64_sony_ps3] needs-llvm-components: powerpc
//@ revisions: powerpc64_unknown_freebsd
//@ [powerpc64_unknown_freebsd] compile-flags: --target powerpc64-unknown-freebsd
//@ [powerpc64_unknown_freebsd] needs-llvm-components: powerpc
Expand Down
11 changes: 6 additions & 5 deletions tests/rustdoc-html/doc-cfg/all-targets.rs
Original file line number Diff line number Diff line change
Expand Up @@ -79,11 +79,11 @@ pub fn bar() {}
// Emscripten and ESP-IDF and FreeBSD and Fuchsia and GNU/Hurd and Haiku \
// and HelenOS and Hermit and Horizon and illumos and iOS and L4Re and Linux \
// and LynxOS-178 and macOS and Managarm and Motor OS and NetBSD and NuttX \
// and OpenBSD and Play Station 1 and Play Station Portable and Play Station Vita \
// and QNX SDP 7.x and QNX SDP 8.0+ and QuRT and Redox OS and RTEMS OS and Solaris and \
// SOLID ASP3 and TEEOS and Trusty and tvOS and UEFI and VEXos and visionOS \
// and VxWorks and WASI and watchOS and Windows and Xous and zero knowledge \
// Virtual Machine only.'
// and OpenBSD and Play Station 1 and Play Station 3 and Play Station Portable \
// and Play Station Vita and QNX SDP 7.x and QNX SDP 8.0+ and QuRT and Redox OS \
// and RTEMS OS and Solaris and SOLID ASP3 and TEEOS and Trusty and tvOS and UEFI \
// and VEXos and visionOS and VxWorks and WASI and watchOS and Windows and Xous \
// and zero knowledge Virtual Machine only.'
#[doc(cfg(all(
target_os = "aix",
target_os = "amdhsa",
Expand Down Expand Up @@ -114,6 +114,7 @@ pub fn bar() {}
target_os = "qnx",
target_os = "nuttx",
target_os = "openbsd",
target_os = "ps3",
target_os = "psp",
target_os = "psx",
target_os = "qurt",
Expand Down
2 changes: 1 addition & 1 deletion tests/ui/check-cfg/cfg-crate-features.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ warning: unexpected `cfg` condition value: `does_not_exist`
LL | #![cfg(not(target(os = "does_not_exist")))]
| ^^^^^^^^^^^^^^^^^^^^^
|
= note: expected values for `target_os` are: `aix`, `amdhsa`, `android`, `cuda`, `cygwin`, `dragonfly`, `emscripten`, `espidf`, `freebsd`, `fuchsia`, `haiku`, `helenos`, `hermit`, `horizon`, `hurd`, `illumos`, `ios`, `l4re`, `linux`, `lynxos178`, `macos`, `managarm`, `motor`, `netbsd`, `none`, `nto`, `nuttx`, `openbsd`, `psp`, `psx`, `qnx`, `qurt`, `redox`, `rtems`, and `solaris` and 15 more
= note: expected values for `target_os` are: `aix`, `amdhsa`, `android`, `cuda`, `cygwin`, `dragonfly`, `emscripten`, `espidf`, `freebsd`, `fuchsia`, `haiku`, `helenos`, `hermit`, `horizon`, `hurd`, `illumos`, `ios`, `l4re`, `linux`, `lynxos178`, `macos`, `managarm`, `motor`, `netbsd`, `none`, `nto`, `nuttx`, `openbsd`, `ps3`, `psp`, `psx`, `qnx`, `qurt`, `redox`, and `rtems` and 16 more
= note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
= note: `#[warn(unexpected_cfgs)]` on by default

Expand Down
4 changes: 2 additions & 2 deletions tests/ui/check-cfg/well-known-values.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -232,7 +232,7 @@ warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE`
LL | target_os = "_UNEXPECTED_VALUE",
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: expected values for `target_os` are: `aix`, `amdhsa`, `android`, `cuda`, `cygwin`, `dragonfly`, `emscripten`, `espidf`, `freebsd`, `fuchsia`, `haiku`, `helenos`, `hermit`, `horizon`, `hurd`, `illumos`, `ios`, `l4re`, `linux`, `lynxos178`, `macos`, `managarm`, `motor`, `netbsd`, `none`, `nto`, `nuttx`, `openbsd`, `psp`, `psx`, `qnx`, `qurt`, `redox`, `rtems`, `solaris`, `solid_asp3`, `teeos`, `trusty`, `tvos`, `uefi`, `unknown`, `vexos`, `visionos`, `vita`, `vxworks`, `wasi`, `watchos`, `windows`, `xous`, and `zkvm`
= note: expected values for `target_os` are: `aix`, `amdhsa`, `android`, `cuda`, `cygwin`, `dragonfly`, `emscripten`, `espidf`, `freebsd`, `fuchsia`, `haiku`, `helenos`, `hermit`, `horizon`, `hurd`, `illumos`, `ios`, `l4re`, `linux`, `lynxos178`, `macos`, `managarm`, `motor`, `netbsd`, `none`, `nto`, `nuttx`, `openbsd`, `ps3`, `psp`, `psx`, `qnx`, `qurt`, `redox`, `rtems`, `solaris`, `solid_asp3`, `teeos`, `trusty`, `tvos`, `uefi`, `unknown`, `vexos`, `visionos`, `vita`, `vxworks`, `wasi`, `watchos`, `windows`, `xous`, and `zkvm`
= note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration

warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE`
Expand Down Expand Up @@ -305,7 +305,7 @@ LL | #[cfg(target_os = "linuz")] // testing that we suggest `linux`
| |
| help: there is a expected value with a similar name: `"linux"`
|
= note: expected values for `target_os` are: `aix`, `amdhsa`, `android`, `cuda`, `cygwin`, `dragonfly`, `emscripten`, `espidf`, `freebsd`, `fuchsia`, `haiku`, `helenos`, `hermit`, `horizon`, `hurd`, `illumos`, `ios`, `l4re`, `linux`, `lynxos178`, `macos`, `managarm`, `motor`, `netbsd`, `none`, `nto`, `nuttx`, `openbsd`, `psp`, `psx`, `qnx`, `qurt`, `redox`, `rtems`, `solaris`, `solid_asp3`, `teeos`, `trusty`, `tvos`, `uefi`, `unknown`, `vexos`, `visionos`, `vita`, `vxworks`, `wasi`, `watchos`, `windows`, `xous`, and `zkvm`
= note: expected values for `target_os` are: `aix`, `amdhsa`, `android`, `cuda`, `cygwin`, `dragonfly`, `emscripten`, `espidf`, `freebsd`, `fuchsia`, `haiku`, `helenos`, `hermit`, `horizon`, `hurd`, `illumos`, `ios`, `l4re`, `linux`, `lynxos178`, `macos`, `managarm`, `motor`, `netbsd`, `none`, `nto`, `nuttx`, `openbsd`, `ps3`, `psp`, `psx`, `qnx`, `qurt`, `redox`, `rtems`, `solaris`, `solid_asp3`, `teeos`, `trusty`, `tvos`, `uefi`, `unknown`, `vexos`, `visionos`, `vita`, `vxworks`, `wasi`, `watchos`, `windows`, `xous`, and `zkvm`
= note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration

warning: 31 warnings emitted
Expand Down
Loading