rustc_target/spec/targets/powerpc64_sony_ps3.rs
1use crate::spec::{
2 Arch, Cc, CfgAbi, CodeModel, Endian, FramePointer, LinkerFlavor, Lld, LlvmAbi, Os,
3 PanicStrategy, RelocModel, Target, TargetMetadata, TargetOptions,
4};
5
6pub(crate) fn target() -> Target {
7 let pre_link_args = TargetOptions::link_args(
8 LinkerFlavor::Gnu(Cc::No, Lld::No),
9 &[
10 // We strictly need ELFv1 PPC64.
11 "-m",
12 "elf64ppc",
13 // PS3 LV2 reserves the first 64KB page for unmapped memory protection.
14 "--image-base=0x10000",
15 // Should be default, but relying on automatic behavior appears to be brittle.
16 "-e",
17 "_start",
18 // CellOS expects .rodata to be merged into the executable Text segment (RX)
19 // so there are only 2 loadable segments (RX and RW)
20 "--no-rosegment",
21 // CellOS uses 64 KB memory pages. Without this flag, `mold` might align data segments to 4 KB boundaries.
22 "-z",
23 "separate-loadable-segments",
24 // Prevents mold from creating a `PT_GNU_RELRO` segment that GameOS does not support.
25 "-z",
26 "norelro",
27 // CellOS's loader doesn't behave like `ld`. PRXs are stubbed in the binary already.
28 "-Bstatic",
29 // The following are segments that might never be referenced by the code,
30 // but are expected to exist by the PS3's loader.
31 "-u",
32 "sys_process_param",
33 "-u",
34 "sys_proc_prx_param",
35 "--undefined-glob=*_prx_header",
36 "--undefined-glob=*_fnid_table",
37 "--undefined-glob=*_name",
38 "--undefined-glob=*_fstub_table",
39 ],
40 );
41
42 Target {
43 // LLVM will default to a compatible ELF backend.
44 llvm_target: "powerpc64-sony-ps3".into(),
45
46 metadata: TargetMetadata {
47 description: Some("PowerPC64 (big endian) Sony PlayStation 3 (PS3)".into()),
48 tier: Some(3),
49 host_tools: Some(false),
50 std: Some(false),
51 },
52
53 // We declare pointers to be 64-bit as the PPU _is_ a 64-bit core.
54 // However, for all real usage the OS limits us to **32-bit pointers**.
55 // SDKs should therefore take this into account, specifically when handling syscalls.
56 pointer_width: 64,
57
58 data_layout: "E-m:e-Fi64-i64:64-i128:128-n32:64".into(),
59 arch: Arch::PowerPC64,
60
61 options: TargetOptions {
62 // Base PS3 hardware.
63 vendor: "sony".into(),
64 endian: Endian::Big,
65 os: Os::Ps3,
66 cfg_abi: CfgAbi::ElfV1,
67 llvm_abiname: LlvmAbi::ElfV1,
68 features: "+altivec".into(),
69
70 // CellOS requiring ELFv1 makes LLVM's `lld` incompatible.
71 // See:
72 // - [rust-lang/rust#85589](https://github.com/rust-lang/rust/issues/85589)
73 // - [llvm/llvm-project#27630](https://github.com/llvm/llvm-project/issues/27630)
74 linker: Some("mold".into()),
75 linker_flavor: LinkerFlavor::Gnu(Cc::No, Lld::No),
76
77 // CellOS _is_ case-sensitive, but the PS3's binaries vary
78 // in casing depending on whether they are games in `/dev_hdd0`
79 // or system binaries (such as PRX files).
80 //
81 // All games use the .ELF (uppercase) suffix, and Sony's own
82 // documentation and tools expect user app binaries to be uppercase.
83 exe_suffix: ".ELF".into(),
84
85 // This limits us to 64KB of ToC, but yields smaller binaries and less assembly.
86 // Only becomes a problem for binaries with thousands of dependencies.
87 code_model: Some(CodeModel::Small),
88 // Prevents LLVM from emitting modern linker relaxation relocations.
89 relax_elf_relocations: false,
90 // CellOS main executables (`EBOOT.ELF`) **must be static executables** (ET_EXEC).
91 relocation_model: RelocModel::Static,
92
93 // Locking defaults against future changes.
94 c_int_width: 32,
95 executables: true,
96 frame_pointer: FramePointer::MayOmit,
97 // Change this to `true` for developing kernel-mode applications.
98 // This target defaults to user-mode, and the kernel already handles
99 // this for us, so keeping it off is a performance gain.
100 disable_redzone: false,
101
102 panic_strategy: PanicStrategy::Abort,
103 pre_link_args,
104 ..Default::default()
105 },
106 }
107}