Illegal instructions generated for Arm Cortex-R5 processor when compiling code using floating-point operations
Nobody has claimed this yet.
- Dominant language
- Rust
- Stars
- 119k
- Forks
- 16.1k
- PR merge metrics
- PR metrics pending
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
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Reproduce the issue with the Rust target and code-generation flags shown, then inspect the Cortex-R5 CPU definition in LLVM's ARM.td and the rustc target-feature handling. Compare the generated assembly with the soft-float case; done means armv7r-none-eabi with cortex-r5 emits legal software-floating-point calls without requiring an unstable feature override.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- rust
- Domain
- compilers, embedded-iot
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 50/100