|
| 1 | +// This defines the amd64 target for UEFI systems as described in the UEFI specification. See the |
| 2 | +// uefi-base module for generic UEFI options. On aarch64 systems UEFI systems always run in long-mode, |
| 3 | +// have the interrupt-controller pre-configured and force a single-CPU execution. |
| 4 | +// |
| 5 | +// The win64 ABI is used. It differs from the sysv64 ABI, so we must use a windows target with |
| 6 | +// LLVM. "aarch64-unknown-windows" is used to get the minimal subset of windows-specific features. |
| 7 | + |
| 8 | +use super::uefi_msvc_base; |
| 9 | +use crate::spec::{CodeModel, Target}; |
| 10 | + |
| 11 | +pub fn target() -> Target { |
| 12 | + let mut base = uefi_msvc_base::opts(); |
| 13 | + |
| 14 | + base.cpu = "aarch64".to_string(); |
| 15 | + base.max_atomic_width = Some(64); |
| 16 | + |
| 17 | + // We disable MMX and SSE for now, even though UEFI allows using them. Problem is, you have to |
| 18 | + // enable these CPU features explicitly before their first use, otherwise their instructions |
| 19 | + // will trigger an exception. Rust does not inject any code that enables AVX/MMX/SSE |
| 20 | + // instruction sets, so this must be done by the firmware. However, existing firmware is known |
| 21 | + // to leave these uninitialized, thus triggering exceptions if we make use of them. Which is |
| 22 | + // why we avoid them and instead use soft-floats. This is also what GRUB and friends did so |
| 23 | + // far. |
| 24 | + // |
| 25 | + // If you initialize FP units yourself, you can override these flags with custom linker |
| 26 | + // arguments, thus giving you access to full MMX/SSE acceleration. |
| 27 | + base.features = "-mmx,-sse,+soft-float".to_string(); |
| 28 | + |
| 29 | + let pre_link_args_msvc = vec!["/machine:arm64"]; |
| 30 | + |
| 31 | + base.pre_link_args.get_mut(&LinkerFlavor::Msvc).unwrap().extend(pre_link_args_msvc.clone()); |
| 32 | + base.pre_link_args |
| 33 | + .get_mut(&LinkerFlavor::Lld(LldFlavor::Link)) |
| 34 | + .unwrap() |
| 35 | + .extend(pre_link_args_msvc); |
| 36 | + |
| 37 | + // UEFI systems run without a host OS, hence we cannot assume any code locality. We must tell |
| 38 | + // LLVM to expect code to reference any address in the address-space. The "large" code-model |
| 39 | + // places no locality-restrictions, so it fits well here. |
| 40 | + base.code_model = Some(CodeModel::Large); |
| 41 | + |
| 42 | + Target { |
| 43 | + llvm_target: "aarch64-unknown-windows".to_string(), |
| 44 | + pointer_width: 64, |
| 45 | + data_layout: "e-m:e-i64:64-f80:128-n8:16:32:64-S128".to_string(), |
| 46 | + arch: "aarch64".to_string(), |
| 47 | + options: base, |
| 48 | + } |
| 49 | +} |
0 commit comments