1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
//! Enables the CPU's hardware floating-point / SIMD unit (VFP + NEON).
//!
//! Both the Cortex-A7 (BCM2836) and Cortex-A53 (BCM2837) ship with the
//! FP/SIMD unit disabled out of reset: executing any VFP or NEON
//! instruction before enabling coprocessor access traps -- an undefined
//! instruction on AArch32, an EL1 FP/SIMD trap on AArch64.
//!
//! `rt`'s boot sequence calls [`enable`](crate::fpu::enable) (via the
//! `rpi_hal_fpu_init` symbol below) on *every* core before any Rust code runs
//! -- the primary
//! core in `boot.s`/`boot64.s` and each secondary in its bring-up path --
//! so even a hard-float build, where the compiler may emit FP/SIMD
//! instructions in ordinary code (register spills, `memcpy`), cannot
//! execute one ahead of the enable.
//!
//! The default targets are soft-float, so ordinary float arithmetic
//! lowers to `compiler_builtins` software routines and never touches the
//! unit regardless: enabling it costs nothing until something is built
//! against a hard-float target (`armv7a-none-eabihf` /
//! `aarch64-unknown-none`). See `examples/fpu_demo.rs` for such a build,
//! including how to confirm hardware FP opcodes are actually emitted.
//!
//! One thing to keep in mind if that ever changes: with the unit enabled,
//! the FP/SIMD registers become live state. Nothing in this crate saves
//! or restores them across an interrupt today, which is fine because the
//! IRQ path is integer-only. If FP is ever used inside an interrupt
//! handler, or a preemptive scheduler is added that switches between
//! tasks that use FP, the ~32 D-registers + `FPSCR`/`FPCR` would need
//! saving on that boundary.
/// Enables the VFP/NEON floating-point unit on the calling core.
///
/// Idempotent and safe to call from any core at PL1 (AArch32) or EL1
/// (AArch64). `rt`'s boot code already calls this on every core before
/// `kmain`, so an application using the default features never needs to.
/// A consumer supplying their own boot sequence
/// (`default-features = false`) must call it themselves, on each core,
/// before running any hard-float code.
/// The enable primitive, also called directly from the boot stubs
/// (`boot.s`/`boot64.s`/`secondary64.s`) via its unmangled name, before
/// the first Rust call. `#[naked]` so its body is exactly the assembly
/// below with no compiler-inserted prologue/epilogue -- on a hard-float
/// build that guarantees the routine that *turns FP on* cannot itself be
/// the first thing to touch an FP register.
unsafe extern "C"
/// See the AArch32 sibling above.
unsafe extern "C"