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

Add armv5te-none-eabi and thumbv5te-none-eabi targets #101329

Merged
merged 3 commits into from
Sep 21, 2022
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 48 additions & 0 deletions compiler/rustc_target/src/spec/armv5te_none_eabi.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
//! Targets the ARMv5TE, with code as `a32` code by default.

use crate::spec::{cvs, LinkerFlavor, LldFlavor, PanicStrategy, RelocModel, Target, TargetOptions};

pub fn target() -> Target {
Target {
llvm_target: "armv5te-none-eabi".into(),
pointer_width: 32,
arch: "arm".into(),
/* Data layout args are '-' separated:
* little endian
* stack is 64-bit aligned (EABI)
* pointers are 32-bit
* i64 must be 64-bit aligned (EABI)
* mangle names with ELF style
* native integers are 32-bit
* All other elements are default
*/
data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".into(),

options: TargetOptions {
abi: "eabi".into(),
linker_flavor: LinkerFlavor::Lld(LldFlavor::Ld),
linker: Some("rust-lld".into()),
// extra args passed to the external assembler (assuming `arm-none-eabi-as`):
// * activate t32/a32 interworking
// * use arch ARMv5TE
// * use little-endian
asm_args: cvs!["-mthumb-interwork", "-march=armv5te", "-mlittle-endian",],
// minimum extra features, these cannot be disabled via -C
// Also force-enable 32-bit atomics, which allows the use of atomic load/store only.
// The resulting atomics are ABI incompatible with atomics backed by libatomic.
features: "+soft-float,+strict-align,+atomics-32".into(),
main_needs_argc_argv: false,
// don't have atomic compare-and-swap
atomic_cas: false,
has_thumb_interworking: true,
relocation_model: RelocModel::Static,
panic_strategy: PanicStrategy::Abort,
// from thumb_base, rust-lang/rust#44993.
emit_debug_gdb_scripts: false,
// from thumb_base, apparently gcc/clang give enums a minimum of 8 bits on no-os targets
c_enum_min_bits: 8,

..Default::default()
Copy link
Member

Choose a reason for hiding this comment

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

I would argue that the thumb_base::opts ought to be changed so that it is also applicable to the bare-metal a32 targets, since the baremetal a32 and t32 targets will be way more similar for the same architecture than the thumb* targets between different arm architecture revisions. That said, ultimately I’d be happy with any solution here that does not produce ~the same options for the two targets added here in very different ways. In particular the two different methods to obtain largely the same TargetOptions is both difficult to review and will be more difficult to maintain in the future.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yeah, I was thinking the same. How about for now, I just modify armv5te-none-eabi to use thumb_base so the two new targets are consistent, and a new issue can be opened to make thumb_base more generic?

},
}
}
2 changes: 2 additions & 0 deletions compiler/rustc_target/src/spec/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1082,6 +1082,8 @@ supported_targets! {
("mipsel-unknown-none", mipsel_unknown_none),
("thumbv4t-none-eabi", thumbv4t_none_eabi),
("armv4t-none-eabi", armv4t_none_eabi),
("thumbv5te-none-eabi", thumbv5te_none_eabi),
("armv5te-none-eabi", armv5te_none_eabi),

("aarch64_be-unknown-linux-gnu", aarch64_be_unknown_linux_gnu),
("aarch64-unknown-linux-gnu_ilp32", aarch64_unknown_linux_gnu_ilp32),
Expand Down
41 changes: 41 additions & 0 deletions compiler/rustc_target/src/spec/thumbv5te_none_eabi.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
//! Targets the ARMv5TE, with code as `t32` code by default.

use crate::spec::{cvs, FramePointer, Target, TargetOptions};

pub fn target() -> Target {
Target {
llvm_target: "thumbv5te-none-eabi".into(),
pointer_width: 32,
arch: "arm".into(),
/* Data layout args are '-' separated:
* little endian
* stack is 64-bit aligned (EABI)
* pointers are 32-bit
* i64 must be 64-bit aligned (EABI)
* mangle names with ELF style
* native integers are 32-bit
* All other elements are default
*/
data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".into(),

options: TargetOptions {
abi: "eabi".into(),
// extra args passed to the external assembler (assuming `arm-none-eabi-as`):
// * activate t32/a32 interworking
// * use arch ARMv5TE
// * use little-endian
asm_args: cvs!["-mthumb-interwork", "-march=armv5te", "-mlittle-endian",],
// minimum extra features, these cannot be disabled via -C
// Also force-enable 32-bit atomics, which allows the use of atomic load/store only.
// The resulting atomics are ABI incompatible with atomics backed by libatomic.
features: "+soft-float,+strict-align,+atomics-32".into(),
frame_pointer: FramePointer::MayOmit,
main_needs_argc_argv: false,
// don't have atomic compare-and-swap
atomic_cas: false,
has_thumb_interworking: true,

..super::thumb_base::opts()
},
}
}
1 change: 1 addition & 0 deletions src/doc/rustc/src/SUMMARY.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
- [\*-apple-watchos\*](platform-support/apple-watchos.md)
- [aarch64-nintendo-switch-freestanding](platform-support/aarch64-nintendo-switch-freestanding.md)
- [armv4t-none-eabi](platform-support/armv4t-none-eabi.md)
- [armv5te-none-eabi](platform-support/armv5te-none-eabi.md)
- [armv6k-nintendo-3ds](platform-support/armv6k-nintendo-3ds.md)
- [armv7-unknown-linux-uclibceabi](platform-support/armv7-unknown-linux-uclibceabi.md)
- [armv7-unknown-linux-uclibceabihf](platform-support/armv7-unknown-linux-uclibceabihf.md)
Expand Down
2 changes: 2 additions & 0 deletions src/doc/rustc/src/platform-support.md
Original file line number Diff line number Diff line change
Expand Up @@ -225,6 +225,7 @@ target | std | host | notes
[`arm64_32-apple-watchos`](platform-support/apple-watchos.md) | ✓ | | ARM Apple WatchOS 64-bit with 32-bit pointers
`armv4t-none-eabi` | * | | ARMv4T A32
`armv4t-unknown-linux-gnueabi` | ? | |
[`armv5te-none-eabi`](platform-support/armv5te-none-eabi.md) | * | | ARMv5TE A32
`armv5te-unknown-linux-uclibceabi` | ? | | ARMv5TE Linux with uClibc
`armv6-unknown-freebsd` | ✓ | ✓ | ARMv6 FreeBSD
`armv6-unknown-netbsd-eabihf` | ? | |
Expand Down Expand Up @@ -291,6 +292,7 @@ target | std | host | notes
`sparc64-unknown-netbsd` | ✓ | ✓ | NetBSD/sparc64
[`sparc64-unknown-openbsd`](platform-support/openbsd.md) | ✓ | ✓ | OpenBSD/sparc64
`thumbv4t-none-eabi` | * | | ARMv4T T32
[`thumbv5te-none-eabi`](platform-support/armv5te-none-eabi.md) | * | | ARMv5TE T32
`thumbv7a-pc-windows-msvc` | ? | |
`thumbv7a-uwp-windows-msvc` | ✓ | |
`thumbv7neon-unknown-linux-musleabihf` | ? | | Thumb2-mode ARMv7a Linux with NEON, MUSL
Expand Down
75 changes: 75 additions & 0 deletions src/doc/rustc/src/platform-support/armv5te-none-eabi.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
# `armv5te-none-eabi`

**Tier: 3**

Bare-metal target for any cpu in the ARMv5TE architecture family, supporting
ARM/Thumb code interworking (aka `a32`/`t32`), with ARM code as the default code
generation.

The `thumbv5te-none-eabi` target is the same as this one, but with THUMB code as the default.
Copy link
Member

Choose a reason for hiding this comment

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

Rust supports switching the “mode” via the (currently unstable) instruction_set attribute, so I would argue that describing this in terms of that attribute would make the intent here clearer:

Suggested change
The `thumbv5te-none-eabi` target is the same as this one, but with THUMB code as the default.
The `thumbv5te-none-eabi` target is the same as this one, but the instruction set defaults to `t32` instead of `a32`.


In particular this supports the main CPU of the Nintendo DS, but there's nothing DS
Copy link
Member

Choose a reason for hiding this comment

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

This sentence is probably superfluous/excessive for the documentation of the very generic baremetal target that *-none-* tend to be. There are a wide variety of applications in which v5te has been used (phones, PDAs, etc. and more recently a Kindle which is also a common homebrew/custom firmware target.)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

That's fair, the DS specific parts can be removed. I was mostly basing this off of armv4t-none-eabi, which makes particular note of the GBA.

specific with this target, so any ARMv5TE device should work fine.

## Target Maintainers

* [@QuinnPainter](https://github.com/QuinnPainter)

## Requirements

The target is cross-compiled, and uses static linking.

By default, the `lld` linker included with Rust will be used.

However, you may want to use the `arm-none-eabi-ld` linker instead. This can be obtained for Windows/Mac/Linux from the [ARM
Developer Website][arm-dev], or possibly from your OS's package manager. To use it, add the following to your `.cargo/config.toml`:

```toml
[target.armv5te-none-eabi]
linker = "arm-none-eabi-ld"
```

[arm-dev]: https://developer.arm.com/Tools%20and%20Software/GNU%20Toolchain

This target doesn't provide a linker script, you'll need to bring your own
according to the specific device you want to target. Pass
`-Clink-arg=-Tyour_script.ld` as a rustc argument to make the linker use
`your_script.ld` during linking.

## Building Rust Programs

Because it is Tier 3, rust does not yet ship pre-compiled artifacts for this target.

Just use the `build-std` nightly cargo feature to build the `core` library. You
can pass this as a command line argument to cargo, or your `.cargo/config.toml`
file might include the following lines:

```toml
[unstable]
build-std = ["core"]
```

Most of `core` should work as expected, with the following notes:
* the target is "soft float", so `f32` and `f64` operations are emulated in
software.
* integer division is also emulated in software.
* the target is old enough that it doesn't have atomic instructions.

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

Rust programs are output as ELF files.

For running on DS hardware, you'll need to use an external tool to bundle this ELF file into an NDS binary. The `ndstool` utility included with devkitARM is one such tool that can do this for you:

```shell
ndstool -c [out_nds] -9 [in_elf]
```
Copy link
Member

Choose a reason for hiding this comment

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

Similarly this DS-specific note is probably overly specific for the generic target that *v5te-none-eabi is.


## Testing

This is a cross-compiled target that you will need to emulate during testing.

Because this is a device-agnostic target, and the exact emulator that you'll
need depends on the specific device you want to run your code on.

For example, when programming for the DS, you can use one of the several available DS emulators, such as [melonDS](https://melonds.kuribo64.net/).