Description
When targeting the Arm Cortex-R5 processor, rustc and llvm generate assembly containing floating-point instructions. These are not available on the Cortex-R5 (only on the Cortex-R5F) and cause the processor to halt.
Details
For example, the following code:
fn add_s(a: f32, b: f32) -> f32 {
a + b
}
fn add_d(a: f64, b: f64) -> f64 {
a + b
}
compiled with flags --target armv7r-none-eabi -C opt-level=3 -C target-cpu=cortex-r5
generates the assembly (compiler explorer link):
add_s:
vmov s0, r1
vmov s2, r0
vadd.f32 s0, s2, s0
vmov r0, s0
bx lr
add_d:
vmov d0, r2, r3
vmov d1, r0, r1
vadd.f64 d0, d1, d0
vmov r0, r1, d0
bx lr
Note the vadd.f32
and vadd.f64
instructions, that are available on the Cortex-R5F which has an FPU, but that are illegal instructions on the Cortex-R5 without an FPU.
My expectation is that, using the target armv7r-none-eabi
(rather than armv7r-none-eabihf
) and the target CPU cortex-r5
(rather than cortex-r5f
), rustc and llvm would generate legal instructions for the processor, i.e. use software floating-point features rather than hard-float instructions.
Relevant information
Original thread on URLO: Unexpected codegen for Cortex-R5 without FPU.
The upstream LLVM CPU model for cortex-r5 includes the flag FeatureVFP3_D16, which seems OK for the R5F but wrong for the R5. However, manually disabling that feature doesn't seem to help (see below). Link to llvm repo at tag 18.1.7.
Information from the ARM Cortex-R Series Programmer's Guide: 6.1.6. VFP in the Cortex-R processors.
Things that do work
Skipping the target-cpu flag
Compiling the snippet above with flags --target armv7r-none-eabi -C opt-level=3
generates:
add_s:
push {r11, lr}
bl __aeabi_fadd
pop {r11, pc}
add_d:
push {r11, lr}
bl __aeabi_dadd
pop {r11, pc}
Adding the soft-float target feature
Compiling the snippet above with flags --target armv7r-none-eabi -C opt-level=3 -C target-cpu=cortex-r5 -C target-feature=+soft-float
generates:
add_s:
push {r11, lr}
bl __aeabi_fadd
pop {r11, pc}
add_d:
push {r11, lr}
bl __aeabi_dadd
pop {r11, pc}
However, rustc generates the warning:
warning: unknown and unstable feature specified for `-Ctarget-feature`: `soft-float`
|
= note: it is still passed through to the codegen backend, but use of this feature might be unsound and the behavior of this feature can change in the future
= help: consider filing a feature request
warning: 1 warning emitted
Things that don't work
Removing the vfp3d16 target feature
Compiling the snippet above with flags --target armv7r-none-eabi -C opt-level=3 -C target-cpu=cortex-r5 -C target-feature=-vfp3d16
generates:
add_s:
vmov s0, r1
vmov s2, r0
vadd.f32 s0, s2, s0
vmov r0, s0
bx lr
add_d:
vmov d0, r2, r3
vmov d1, r0, r1
vadd.f64 d0, d1, d0
vmov r0, r1, d0
bx lr
Meta
I've tested both stable and nightly toolchains, with same results.
rustc --version --verbose
:
rustc 1.80.0 (051478957 2024-07-21)
binary: rustc
commit-hash: 051478957371ee0084a7c0913941d2a8c4757bb9
commit-date: 2024-07-21
host: x86_64-unknown-linux-gnu
release: 1.80.0
LLVM version: 18.1.7