Add ARMv6 bare-metal targets

Three targets, covering A32 and T32 instructions, and soft-float and
hard-float ABIs. Hard-float not available in Thumb mode. Atomics
in Thumb mode require __sync* functions from compiler-builtins.
This commit is contained in:
Jonathan 'theJPster' Pallant 2025-11-16 20:21:42 +00:00
parent a18e6d9d14
commit 96897f016e
12 changed files with 164 additions and 4 deletions

View file

@ -1746,10 +1746,14 @@ supported_targets! {
("mipsel-unknown-none", mipsel_unknown_none),
("mips-mti-none-elf", mips_mti_none_elf),
("mipsel-mti-none-elf", mipsel_mti_none_elf),
("thumbv4t-none-eabi", thumbv4t_none_eabi),
("armv4t-none-eabi", armv4t_none_eabi),
("thumbv5te-none-eabi", thumbv5te_none_eabi),
("armv5te-none-eabi", armv5te_none_eabi),
("armv6-none-eabi", armv6_none_eabi),
("armv6-none-eabihf", armv6_none_eabihf),
("thumbv4t-none-eabi", thumbv4t_none_eabi),
("thumbv5te-none-eabi", thumbv5te_none_eabi),
("thumbv6-none-eabi", thumbv6_none_eabi),
("aarch64_be-unknown-linux-gnu", aarch64_be_unknown_linux_gnu),
("aarch64-unknown-linux-gnu_ilp32", aarch64_unknown_linux_gnu_ilp32),

View file

@ -0,0 +1,29 @@
//! Targets the ARMv6K architecture, with `a32` code by default.
use crate::spec::{Abi, Arch, FloatAbi, Target, TargetMetadata, TargetOptions, base, cvs};
pub(crate) fn target() -> Target {
Target {
llvm_target: "armv6-none-eabi".into(),
metadata: TargetMetadata {
description: Some("Bare ARMv6 soft-float".into()),
tier: Some(3),
host_tools: Some(false),
std: Some(false),
},
pointer_width: 32,
arch: Arch::Arm,
data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".into(),
options: TargetOptions {
abi: Abi::Eabi,
llvm_floatabi: Some(FloatAbi::Soft),
asm_args: cvs!["-mthumb-interwork", "-march=armv6", "-mlittle-endian",],
features: "+soft-float,+strict-align,+v6k".into(),
atomic_cas: true,
has_thumb_interworking: true,
// LDREXD/STREXD available as of ARMv6K
max_atomic_width: Some(64),
..base::arm_none::opts()
},
}
}

View file

@ -0,0 +1,29 @@
//! Targets the ARMv6K architecture, with `a32` code by default, and hard-float ABI
use crate::spec::{Abi, Arch, FloatAbi, Target, TargetMetadata, TargetOptions, base, cvs};
pub(crate) fn target() -> Target {
Target {
llvm_target: "armv6-none-eabihf".into(),
metadata: TargetMetadata {
description: Some("Bare ARMv6 hard-float".into()),
tier: Some(3),
host_tools: Some(false),
std: Some(false),
},
pointer_width: 32,
arch: Arch::Arm,
data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".into(),
options: TargetOptions {
abi: Abi::EabiHf,
llvm_floatabi: Some(FloatAbi::Hard),
asm_args: cvs!["-mthumb-interwork", "-march=armv6", "-mlittle-endian",],
features: "+strict-align,+v6k,+vfp2,-d32".into(),
atomic_cas: true,
has_thumb_interworking: true,
// LDREXD/STREXD available as of ARMv6K
max_atomic_width: Some(64),
..base::arm_none::opts()
},
}
}

View file

@ -0,0 +1,30 @@
//! Targets the ARMv6K architecture, with `t32` code by default.
use crate::spec::{Abi, Arch, FloatAbi, Target, TargetMetadata, TargetOptions, base, cvs};
pub(crate) fn target() -> Target {
Target {
llvm_target: "thumbv6-none-eabi".into(),
metadata: TargetMetadata {
description: Some("Thumb-mode Bare ARMv6 soft-float".into()),
tier: Some(3),
host_tools: Some(false),
std: Some(false),
},
pointer_width: 32,
arch: Arch::Arm,
data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".into(),
options: TargetOptions {
abi: Abi::Eabi,
llvm_floatabi: Some(FloatAbi::Soft),
asm_args: cvs!["-mthumb-interwork", "-march=armv6", "-mlittle-endian",],
features: "+soft-float,+strict-align,+v6k".into(),
// CAS atomics are implemented in LLVM on this target using __sync* functions,
// which were added to compiler-builtins in https://github.com/rust-lang/compiler-builtins/pull/1050
atomic_cas: true,
has_thumb_interworking: true,
max_atomic_width: Some(32),
..base::arm_none::opts()
},
}
}

View file

@ -292,7 +292,15 @@ pub fn spin_loop() {
// SAFETY: the `cfg` attr ensures that we only execute this on aarch64 targets.
unsafe { crate::arch::aarch64::__isb(crate::arch::aarch64::SY) }
}
all(target_arch = "arm", target_feature = "v6") => {
all(
target_arch = "arm",
any(
all(target_feature = "v6k", not(target_feature = "thumb-mode")),
target_feature = "v6t2",
all(target_feature = "v6", target_feature = "mclass"),
target_feature = "v7",
)
) => {
// SAFETY: the `cfg` attr ensures that we only execute this on arm targets
// with support for the v6 feature.
unsafe { crate::arch::arm::__yield() }

View file

@ -83,8 +83,12 @@ pub unsafe fn __sevl() {
/// improve overall system performance.
// Section 10.1 of ACLE says that the supported arches are: 8, 6K, 6-M
// LLVM says "instruction requires: armv6k"
// On ARMv6 in Thumb mode, T2 is required.
#[cfg(any(
target_feature = "v6",
all(target_feature = "v6k", not(target_feature = "thumb-mode")),
target_feature = "v6t2",
all(target_feature = "v6", target_feature = "mclass"),
target_feature = "v7",
target_arch = "aarch64",
target_arch = "arm64ec",
doc

View file

@ -43,6 +43,9 @@ const STAGE0_MISSING_TARGETS: &[&str] = &[
"thumbv7r-none-eabi",
"thumbv7r-none-eabihf",
"thumbv8r-none-eabihf",
"armv6-none-eabi",
"armv6-none-eabihf",
"thumbv6-none-eabi",
];
/// Minimum version threshold for libstdc++ required when using prebuilt LLVM

View file

@ -56,6 +56,7 @@
- [arm-none-eabi](platform-support/arm-none-eabi.md)
- [{arm,thumb}v4t-none-eabi](platform-support/armv4t-none-eabi.md)
- [{arm,thumb}v5te-none-eabi](platform-support/armv5te-none-eabi.md)
- [{arm,thumb}v6-none-eabi{,hf}](platform-support/armv6-none-eabi.md)
- [{arm,thumb}v7a-none-eabi{,hf}](platform-support/armv7a-none-eabi.md)
- [{arm,thumb}v7r-none-eabi{,hf}](platform-support/armv7r-none-eabi.md)
- [{arm,thumb}v8r-none-eabihf](platform-support/armv8r-none-eabihf.md)

View file

@ -292,6 +292,8 @@ target | std | host | notes
`armv4t-unknown-linux-gnueabi` | ? | | Armv4T Linux
[`armv5te-none-eabi`](platform-support/armv5te-none-eabi.md) | * | | Bare Armv5TE
`armv5te-unknown-linux-uclibceabi` | ? | | Armv5TE Linux with uClibc
[`armv6-none-eabi`](platform-support/armv6-none-eabi.md) | * | | Bare Armv6
[`armv6-none-eabihf`](platform-support/armv6-none-eabi.md) | * | | Bare Armv6, hardfloat
[`armv6-unknown-freebsd`](platform-support/freebsd.md) | ✓ | ✓ | Armv6 FreeBSD
[`armv6-unknown-netbsd-eabihf`](platform-support/netbsd.md) | ✓ | ✓ | Armv6 NetBSD w/hard-float
[`armv6k-nintendo-3ds`](platform-support/armv6k-nintendo-3ds.md) | ? | | Armv6k Nintendo 3DS, Horizon (Requires devkitARM toolchain)
@ -410,6 +412,7 @@ target | std | host | notes
[`sparc64-unknown-openbsd`](platform-support/openbsd.md) | ✓ | ✓ | OpenBSD/sparc64
[`thumbv4t-none-eabi`](platform-support/armv4t-none-eabi.md) | * | | Thumb-mode Bare Armv4T
[`thumbv5te-none-eabi`](platform-support/armv5te-none-eabi.md) | * | | Thumb-mode Bare Armv5TE
[`thumbv6-none-eabi`](platform-support/armv6-none-eabi.md) | * | | Thumb-mode Bare Armv6
[`thumbv6m-nuttx-eabi`](platform-support/nuttx.md) | ✓ | | ARMv6M with NuttX
[`thumbv7a-none-eabi`](platform-support/armv7a-none-eabi.md) | * | | Thumb-mode Bare Armv7-A
[`thumbv7a-none-eabihf`](platform-support/armv7a-none-eabi.md) | * | | Thumb-mode Bare Armv7-A, hardfloat

View file

@ -37,6 +37,7 @@ their own document.
- *Legacy* Arm Architectures
- [`armv4t-none-eabi` and `thumbv4t-none-eabi`](armv4t-none-eabi.md)
- [`armv5te-none-eabi` and `thumbv5te-none-eabi`](armv5te-none-eabi.md)
- [`armv6-none-eabi`, `armv6-none-eabihf`, `thumbv6-none-eabi`](armv6-none-eabi.md)
## Instruction Sets

View file

@ -0,0 +1,39 @@
# `armv6-none-eabi*` and `thumbv6-none-eabi`
* **Tier: 3**
* **Library Support:** core and alloc (bare-metal, `#![no_std]`)
Bare-metal target for any cpu in the Armv6 architecture family, supporting
ARM/Thumb code interworking (aka `Arm`/`Thumb`), with `Arm` code as the default
code generation. The most common processor family using the Armv6 architecture
is the ARM11, which includes the ARM1176JZF-S used in the original Raspberry Pi
and in the Raspberry Pi Zero.
This target assumes your processor has the Armv6K extensions, as basically all
Armv6 processors do[^1]. The Armv6K extension adds the `LDREXB` and `STREXB`
instructions required to efficiently implement CAS on the [`AtomicU8`] and
[`AtomicI8`] types.
The `thumbv6-none-eabi` target is the same as this one, but the instruction set
defaults to `Thumb`. Note that this target only supports the old Thumb-1
instruction set, not the later Thumb-2 instruction set that was added in the
Armv6T2 extension. Note that the Thumb-1 instruction set does not support
atomics.
The `armv6-none-eabihf` target uses the EABIHF hard-float ABI, and requires an
FPU - it assumes a VFP2D16 FPU is present. The FPU is not available from Thumb
mode so there is no `thumbv6-none-eabihf` target.
See [`arm-none-eabi`](arm-none-eabi.md) for information applicable to all
`arm-none-eabi` targets.
[`AtomicU8`]: https://docs.rust-lang.org/stable/core/sync/atomic/struct.AtomicU8.html
[`AtomicI8`]: https://docs.rust-lang.org/stable/core/sync/atomic/struct.AtomicI8.html
## Target Maintainers
[@thejpster](https://github.com/thejpster)
[^1]: The only ARMv6 processor without the Armv6k extensions is the first (r0)
revision of the ARM1136 - in the unlikely event you have a chip with one of
these processors, use the ARMv5TE target instead.

View file

@ -139,6 +139,12 @@
//@ revisions: armv5te_unknown_linux_uclibceabi
//@ [armv5te_unknown_linux_uclibceabi] compile-flags: --target armv5te-unknown-linux-uclibceabi
//@ [armv5te_unknown_linux_uclibceabi] needs-llvm-components: arm
//@ revisions: armv6_none_eabi
//@ [armv6_none_eabi] compile-flags: --target armv6-none-eabi
//@ [armv6_none_eabi] needs-llvm-components: arm
//@ revisions: armv6_none_eabihf
//@ [armv6_none_eabihf] compile-flags: --target armv6-none-eabihf
//@ [armv6_none_eabihf] needs-llvm-components: arm
//@ revisions: armv6_unknown_freebsd
//@ [armv6_unknown_freebsd] compile-flags: --target armv6-unknown-freebsd
//@ [armv6_unknown_freebsd] needs-llvm-components: arm
@ -559,6 +565,9 @@
//@ revisions: thumbv5te_none_eabi
//@ [thumbv5te_none_eabi] compile-flags: --target thumbv5te-none-eabi
//@ [thumbv5te_none_eabi] needs-llvm-components: arm
//@ revisions: thumbv6_none_eabi
//@ [thumbv6_none_eabi] compile-flags: --target thumbv6-none-eabi
//@ [thumbv6_none_eabi] needs-llvm-components: arm
//@ revisions: thumbv7a_none_eabi
//@ [thumbv7a_none_eabi] compile-flags: --target thumbv7a-none-eabi
//@ [thumbv7a_none_eabi] needs-llvm-components: arm