Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Arm bare-metal target doc changes #124404

Merged
merged 8 commits into from
May 2, 2024
5 changes: 5 additions & 0 deletions src/doc/rustc/src/SUMMARY.md
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,11 @@
- [riscv32imac-unknown-xous-elf](platform-support/riscv32imac-unknown-xous-elf.md)
- [riscv32*-unknown-none-elf](platform-support/riscv32-unknown-none-elf.md)
- [sparc-unknown-none-elf](./platform-support/sparc-unknown-none-elf.md)
- [thumbv6m-none-eabi](./platform-support/thumbv6m-none-eabi.md)
- [thumbv7m-none-eabi](./platform-support/thumbv7m-none-eabi.md)
- [thumbv7em-none-eabi\*](./platform-support/thumbv7em-none-eabi.md)
- [thumbv8m.base-none-eabi](./platform-support/thumbv8m.base-none-eabi.md)
- [thumbv8m.main-none-eabi\*](./platform-support/thumbv8m.main-none-eabi.md)
- [*-pc-windows-gnullvm](platform-support/pc-windows-gnullvm.md)
- [\*-nto-qnx-\*](platform-support/nto-qnx.md)
- [*-unikraft-linux-musl](platform-support/unikraft-linux-musl.md)
Expand Down
14 changes: 7 additions & 7 deletions src/doc/rustc/src/platform-support.md
Original file line number Diff line number Diff line change
Expand Up @@ -178,15 +178,15 @@ target | std | notes
`riscv64imac-unknown-none-elf` | * | Bare RISC-V (RV64IMAC ISA)
`sparc64-unknown-linux-gnu` | ✓ | SPARC Linux (kernel 4.4, glibc 2.23)
`sparcv9-sun-solaris` | ✓ | SPARC Solaris 11, illumos
[`thumbv6m-none-eabi`](platform-support/arm-none-eabi.md) | * | Bare ARMv6-M
[`thumbv7em-none-eabi`](platform-support/arm-none-eabi.md) | * | Bare ARMv7E-M
[`thumbv7em-none-eabihf`](platform-support/arm-none-eabi.md) | * | Bare ARMV7E-M, hardfloat
[`thumbv7m-none-eabi`](platform-support/arm-none-eabi.md) | * | Bare ARMv7-M
[`thumbv6m-none-eabi`](platform-support/thumbv6m-none-eabi.md) | * | Bare ARMv6-M
[`thumbv7em-none-eabi`](platform-support/thumbv7em-none-eabi.md) | * | Bare ARMv7E-M
[`thumbv7em-none-eabihf`](platform-support/thumbv7em-none-eabi.md) | * | Bare ARMV7E-M, hardfloat
[`thumbv7m-none-eabi`](platform-support/thumbv7m-none-eabi.md) | * | Bare ARMv7-M
[`thumbv7neon-linux-androideabi`](platform-support/android.md) | ✓ | Thumb2-mode ARMv7-A Android with NEON
`thumbv7neon-unknown-linux-gnueabihf` | ✓ | Thumb2-mode ARMv7-A Linux with NEON (kernel 4.4, glibc 2.23)
[`thumbv8m.base-none-eabi`](platform-support/arm-none-eabi.md) | * | Bare ARMv8-M Baseline
[`thumbv8m.main-none-eabi`](platform-support/arm-none-eabi.md) | * | Bare ARMv8-M Mainline
[`thumbv8m.main-none-eabihf`](platform-support/arm-none-eabi.md) | * | Bare ARMv8-M Mainline, hardfloat
[`thumbv8m.base-none-eabi`](platform-support/thumbv8m.base-none-eabi.md) | * | Bare ARMv8-M Baseline
[`thumbv8m.main-none-eabi`](platform-support/thumbv8m.main-none-eabi.md) | * | Bare ARMv8-M Mainline
[`thumbv8m.main-none-eabihf`](platform-support/thumbv8m.main-none-eabi.md) | * | Bare ARMv8-M Mainline, hardfloat
`wasm32-unknown-emscripten` | ✓ | WebAssembly via Emscripten
`wasm32-unknown-unknown` | ✓ | WebAssembly
`wasm32-wasi` | ✓ | WebAssembly with WASI (undergoing a [rename to `wasm32-wasip1`][wasi-rename])
Expand Down
157 changes: 125 additions & 32 deletions src/doc/rustc/src/platform-support/arm-none-eabi.md
Original file line number Diff line number Diff line change
@@ -1,25 +1,106 @@
# `{arm,thumb}*-none-eabi(hf)?`

**Tier: 2**
- [arm(eb)?v7r-none-eabi(hf)?](armv7r-none-eabi.md)
- armv7a-none-eabi
- thumbv6m-none-eabi
- thumbv7m-none-eabi
- thumbv7em-none-eabi(hf)?
- thumbv8m.base-none-eabi
- thumbv8m.main-none-eabi(hf)?

**Tier: 3**
- [{arm,thumb}v4t-none-eabi](armv4t-none-eabi.md)
- [{arm,thumb}v5te-none-eabi](armv5te-none-eabi.md)
- armv7a-none-eabihf
- [armv8r-none-eabihf](armv8r-none-eabihf.md)

Bare-metal target for 32-bit ARM CPUs.

If a target has a `*hf` variant, that variant uses the hardware floating-point
ABI and enables some minimum set of floating-point features based on the FPU(s)
available in that processor family.
## Tier 2 Target List

- Arm A-Profile Architectures
- `armv7a-none-eabi`
- Arm R-Profile Architectures
- [`armv7r-none-eabi` and `armv7r-none-eabihf`](armv7r-none-eabi.md)
- [`armebv7r-none-eabi` and `armebv7r-none-eabihf`](armv7r-none-eabi.md)
- Arm M-Profile Architectures
- [`thumbv6m-none-eabi`](thumbv6m-none-eabi.md)
- [`thumbv7m-none-eabi`](thumbv7m-none-eabi.md)
- [`thumbv7em-none-eabi` and `thumbv7em-none-eabihf`](thumbv7em-none-eabi.md)
- [`thumbv8m.base-none-eabi`](thumbv8m.base-none-eabi.md)
- [`thumbv8m.main-none-eabi` and `thumbv8m.main-none-eabihf`](thumbv8m.main-none-eabi.md)
- *Legacy* Arm Architectures
- None

## Tier 3 Target List

- Arm A-Profile Architectures
- `armv7a-none-eabihf`
- Arm R-Profile Architectures
- [`armv8r-none-eabihf`](armv8r-none-eabihf.md)
- Arm M-Profile Architectures
- None
- *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)

## Common Target Details

This documentation covers details that apply to a range of bare-metal targets
for 32-bit ARM CPUs. In addition, target specific details may be covered in
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Arm

their own document.

If a target ends in `eabi`, that target uses the so-called *soft-float ABI*:
functions which take `f32` or `f64` as arguments will have those values packed
into integer registers. This means that an FPU is not required from an ABI
perspective, but within a function floating-point instructions may still be used
if the code is compiled with a `target-cpu` or `target-feature` option that
enables FPU support.

If a target ends in `eabihf`, that target uses the so-called *hard-float ABI*:
functions which take `f32` or `f64` as arguments will have them passed via FPU
registers. These targets therefore require the availability of an FPU and will
assume some baseline level of floating-point support is available (which can
vary depending on the target). More advanced floating-point instructions may be
generated if the code is compiled with a `target-cpu` or `target-feature` option
that enables such additional FPU support. For example, if a given hard-float
target has baseline *single-precision* (`f32`) support in hardware, there may be
`target-cpu` or `target-feature` options that tell LLVM to assume your processor
in fact also has *double-precision* (`f64`) support.

You may of course use the `f32` and `f64` types in your code, regardless of the
ABI being used, or the level of support your processor has for performing such
operations in hardware. Any floating-point operations that LLVM assumes your
processor cannot support will be lowered to library calls (like `__aeabi_dadd`)
which perform the floating-point operation in software using integer
instructions.

## Target CPU and Target Feature options

It is possible to tell Rust (or LLVM) that you have a specific model of Arm
processor, using the [`-C target-cpu`][target-cpu] option. You can also control
whether Rust (or LLVM) will include instructions that target optional hardware
features, e.g. hardware floating point, or vector maths operations, using [`-C
jonathanpallant marked this conversation as resolved.
Show resolved Hide resolved
target-feature`][target-feature].

It is important to note that selecting a *target-cpu* will typically enable
*all* the optional features available from Arm on that model of CPU and your
particular implementation of that CPU may not have those features available. In
that case, you can use `-C target-feature=-option` to turn off the specific CPU
features you do not have available, leaving you with the optimized instruction
scheduling and support for the features you do have. More details are available
in the detailed target-specific documentation.

**Note:** Many target-features are currently unstable and subject to change, and
if you use them you should disassemble the compiler output and manually inspect
it to ensure only appropriate instructions for your CPU have been generated.

If you wish to use the *target-cpu* and *target-feature* options, you can add
them to your `.cargo/config.toml` file alongside any other flags your project
uses (likely linker related ones):

```toml
rustflags = [
# Usual Arm bare-metal linker setup
"-Clink-arg=-Tlink.x",
"-Clink-arg=--nmagic",
# tell Rust we have a Cortex-M55
"-Ctarget-cpu=cortex-m55",
# tell Rust our Cortex-M55 doesn't have Floating-Point M-Profile Vector
# Extensions (but it does have everything else a Cortex-M55 could have).
"-Ctarget-feature=-mve.fp"
]

[build]
target = "thumbv8m.main-none-eabihf"
```

[target-cpu]: https://doc.rust-lang.org/rustc/codegen-options/index.html#target-cpu
[target-feature]: https://doc.rust-lang.org/rustc/codegen-options/index.html#target-feature

## Requirements

Expand All @@ -45,14 +126,15 @@ according to the specific device you are using. Pass
`-Clink-arg=-Tyour_script.ld` as a rustc argument to make the linker use
`your_script.ld` during linking.

Targets named `thumb*` instead of `arm*`
generate Thumb-mode code by default. M-profile processors (`thumbv*m*-*`
targets) only support Thumb-mode code.
For the `arm*` targets, Thumb-mode code generation can be enabled by using
`-C target-feature=+thumb-mode`. Using the unstable
`#![feature(arm_target_feature)]`, the attribute
`#[target_feature(enable = "thumb-mode")]` can be applied to individual
`unsafe` functions to cause those functions to be compiled to Thumb-mode code.
Targets named `thumb*` instead of `arm*` generate Thumb (T32) code by default
instead of Arm (A32) code. Most Arm chips support both Thumb mode and Arm mode,
except that M-profile processors (`thumbv*m*-*` targets) only support Thumb-mode.

For the `arm*` targets, Thumb-mode code generation can be enabled by using `-C
target-feature=+thumb-mode`. Using the unstable
`#![feature(arm_target_feature)]`, the attribute `#[target_feature(enable =
"thumb-mode")]` can be applied to individual `unsafe` functions to cause those
functions to be compiled to Thumb-mode code.

## Building Rust Programs

Expand All @@ -69,16 +151,27 @@ build-std = ["core"]
```

Most of `core` should work as expected, with the following notes:
* If the target is not `*hf`, then floating-point operations are emulated in
software.

* Floating-point operations are emulated in software unless LLVM is told to
enable FPU support (either by using an `eabihf` target, specifying a
`target-cpu` with FPU support, or using a `target-feature` to support for a
specific kind of FPU)
* Integer division is also emulated in software on some targets, depending on
the CPU.
* Architectures prior to ARMv7 don't have atomic instructions.
the target, `target-cpu` and `target-feature`s.
* Older Arm architectures (e.g. Armv4, Armv5TE and Armv6-M) are limited to basic
[`load`][atomic-load] and [`store`][atomic-store] operations, and not more
advanced operations like [`fetch_add`][fetch-add] or
[`compare_exchange`][compare-exchange].

`alloc` is also supported, as long as you provide your own global allocator.

Rust programs are output as ELF files.

[atomic-load]: https://doc.rust-lang.org/stable/core/sync/atomic/struct.AtomicU32.html#method.load
[atomic-store]: https://doc.rust-lang.org/stable/core/sync/atomic/struct.AtomicU32.html#method.store
[fetch-add]: https://doc.rust-lang.org/stable/core/sync/atomic/struct.AtomicU32.html#method.fetch_add
[compare-exchange]: https://doc.rust-lang.org/stable/core/sync/atomic/struct.AtomicU32.html#method.compare_exchange

## Testing

This is a cross-compiled target that you will need to emulate during testing.
Expand Down
62 changes: 62 additions & 0 deletions src/doc/rustc/src/platform-support/thumbv6m-none-eabi.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
# `thumbv6m-none-eabi`

**Tier: 2**

Bare-metal target for CPUs in the [ARMv6-M] architecture family, supporting a
subset of the [T32 ISA][t32-isa].

Processors in this family include the:

* [Arm Cortex-M0][cortex-m0]
* [Arm Cortex-M0+][cortex-m0plus]
* [Arm Cortex-M1][cortex-m1]

See [`arm-none-eabi`](arm-none-eabi.md) for information applicable to all
`arm-none-eabi` targets.

This target uses the soft-float ABI: functions which take `f32` or `f64` as
arguments will have those values packed into integer registers. This is the
only option because there is no FPU support in [ARMv6-M].

[t32-isa]: https://developer.arm.com/Architectures/T32%20Instruction%20Set%20Architecture
[ARMv6-M]: https://developer.arm.com/documentation/ddi0419/latest/
[cortex-m0]: https://developer.arm.com/Processors/Cortex-M0
[cortex-m0plus]: https://developer.arm.com/Processors/Cortex-M0+
[cortex-m1]: https://developer.arm.com/Processors/Cortex-M1

## Target maintainers

* [Rust Embedded Devices Working Group Cortex-M
Team](https://github.com/rust-embedded), `[email protected]`

## Target CPU and Target Feature options

See [the bare-metal Arm
docs](arm-none-eabi.md#target-cpu-and-target-feature-options) for details on how
to use these flags.

### Table of supported CPUs

| CPU | FPU | Target CPU | Target Features |
| ---------- | --- | --------------- | --------------------- |
| Cortex-M0 | No | `cortex-m0` | None |
| Cortex-M0+ | No | `cortex-m0plus` | None |
| Cortex-M1 | No | `cortex-m1` | None |

### Arm Cortex-M0

The target CPU option is `cortex-m0`.

There are no relevant feature flags, and the FPU is not available.

### Arm Cortex-M0+

The target CPU option is `cortex-m0plus`.

There are no relevant feature flags, and the FPU is not available.

### Arm Cortex-M1

The target CPU option is `cortex-m1`.

There are no relevant feature flags, and the FPU is not available.
74 changes: 74 additions & 0 deletions src/doc/rustc/src/platform-support/thumbv7em-none-eabi.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
# `thumbv7em-none-eabi` and `thumbv7em-none-eabihf`

**Tier: 2**

Bare-metal target for CPUs in the [ARMv7E-M] architecture family, supporting a
subset of the [T32 ISA][t32-isa].

Processors in this family include the:

* [Arm Cortex-M4][cortex-m4] and Arm Cortex-M4F
* [Arm Cortex-M7][cortex-m7] and Arm Cortex-M7F

See [`arm-none-eabi`](arm-none-eabi.md) for information applicable to all
`arm-none-eabi` targets, in particular the difference between the `eabi` and
`eabihf` ABI.

[t32-isa]: https://developer.arm.com/Architectures/T32%20Instruction%20Set%20Architecture
[ARMv7E-M]: https://developer.arm.com/documentation/ddi0403/latest/
[cortex-m4]: https://developer.arm.com/Processors/Cortex-M4
[cortex-m7]: https://developer.arm.com/Processors/Cortex-M7

## Target maintainers

* [Rust Embedded Devices Working Group Cortex-M
Team](https://github.com/rust-embedded), `[email protected]`

## Target CPU and Target Feature options

See [the bare-metal Arm
docs](arm-none-eabi.md#target-cpu-and-target-feature-options) for details on how
to use these flags.

### Table of supported CPUs for `thumbv7em-none-eabi`

| CPU | FPU | DSP | Target CPU | Target Features |
| ---------- | --- | --- | ----------- | --------------- |
| Any | No | Yes | None | None |
| Cortex-M4 | No | Yes | `cortex-m4` | `+soft-float` |
| Cortex-M4F | SP | Yes | `cortex-m4` | None |
| Cortex-M7 | No | Yes | `cortex-m7` | `+soft-float` |
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FWIW this is a problematic piece of advice to give, since this target feature is also implicated in the soundness issue tracked at #116344.

Copy link
Contributor

@thejpster thejpster Sep 28, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Although as we discussed extensively on Zulip currently we know of no other way of stopping target-cpu=cortex-m7 (or similar) from emitting FPU instructions like vadd.f32, yet it's reasonable to want the Cortex-M7 specific instruction scheduling optimisations even if your Cortex-M7 doesn't have an FPU.

This feature is totally unsound on *-unknown-none-eabihf, but it's both sound and useful on *-unknown-none-eabi. The 'target-feature' checker can currently only look at the target-architecture, and not the full target triple, so it's unclear where we go from here.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The target-feature checker is still WIP, and will be improved to handle this, somehow.

But the docs maybe should call out that this same flag is unsound to use on other targets (until rustc reaches the point where it is able to tell users about this directly).

| Cortex-M7F | SP | Yes | `cortex-m7` | `-fp64` |
| Cortex-M7F | DP | Yes | `cortex-m7` | None |

### Table of supported CPUs for `thumbv7em-none-eabihf`

| CPU | FPU | DSP | Target CPU | Target Features |
| ---------- | --- | --- | ----------- | --------------- |
| Any | SP | Yes | None | None |
| Cortex-M4F | SP | Yes | `cortex-m4` | None |
| Cortex-M7F | SP | Yes | `cortex-m7` | `-fp64` |
| Cortex-M7F | DP | Yes | `cortex-m7` | None |

### Arm Cortex-M4 and Arm Cortex-M4F

The target CPU is `cortex-m4`.

* All Cortex-M4 have DSP extensions
* support is controlled by the `dsp` *target-feature*
* enabled by default with this *target*
* Cortex-M4F has a single precision FPU
* support is enabled by default with this *target-cpu*
* disable support using the `+soft-float` feature (`eabi` only)

### Arm Cortex-M7 and Arm Cortex-M7F

The target CPU is `cortex-m7`.

* All Cortex-M7 have DSP extensions
* support is controlled by the `dsp` *target-feature*
* enabled by default with this *target*
* Cortex-M7F have either a single-precision or double-precision FPU
* double-precision support is enabled by default with this *target-cpu*
* opt-out by using the `-f64` *target-feature*
* disable support entirely using the `+soft-float` feature (`eabi` only)
Loading
Loading