From d30294e33c67a19a52f4d2b126c460dae2b87a8f Mon Sep 17 00:00:00 2001 From: "Jonathan Pallant (Ferrous Systems)" Date: Fri, 7 Jul 2023 11:55:04 +0100 Subject: [PATCH 1/4] Add a sparc-unknown-none-elf target. Tested with the Gaisler bcc2 toolchain (both gcc and clang) and the Leon3 simulator. --- compiler/rustc_target/src/spec/mod.rs | 2 ++ .../src/spec/sparc_unknown_none_elf.rs | 27 +++++++++++++++++++ src/doc/rustc/src/platform-support.md | 1 + src/tools/build-manifest/src/main.rs | 1 + 4 files changed, 31 insertions(+) create mode 100644 compiler/rustc_target/src/spec/sparc_unknown_none_elf.rs diff --git a/compiler/rustc_target/src/spec/mod.rs b/compiler/rustc_target/src/spec/mod.rs index 2365dfaf1af80..b615165822550 100644 --- a/compiler/rustc_target/src/spec/mod.rs +++ b/compiler/rustc_target/src/spec/mod.rs @@ -1433,6 +1433,8 @@ supported_targets! { ("riscv64gc-unknown-linux-gnu", riscv64gc_unknown_linux_gnu), ("riscv64gc-unknown-linux-musl", riscv64gc_unknown_linux_musl), + ("sparc-unknown-none-elf", sparc_unknown_none_elf), + ("loongarch64-unknown-none", loongarch64_unknown_none), ("loongarch64-unknown-none-softfloat", loongarch64_unknown_none_softfloat), diff --git a/compiler/rustc_target/src/spec/sparc_unknown_none_elf.rs b/compiler/rustc_target/src/spec/sparc_unknown_none_elf.rs new file mode 100644 index 0000000000000..7e908a0f36552 --- /dev/null +++ b/compiler/rustc_target/src/spec/sparc_unknown_none_elf.rs @@ -0,0 +1,27 @@ +use crate::abi::Endian; +use crate::spec::{Cc, LinkerFlavor, Lld, PanicStrategy, RelocModel, Target, TargetOptions}; + +pub fn target() -> Target { + let options = TargetOptions { + linker_flavor: LinkerFlavor::Gnu(Cc::Yes, Lld::No), + linker: Some("sparc-elf-gcc".into()), + endian: Endian::Big, + cpu: "v7".into(), + abi: "elf".into(), + max_atomic_width: Some(32), + atomic_cas: true, + panic_strategy: PanicStrategy::Abort, + relocation_model: RelocModel::Static, + no_default_libraries: false, + emit_debug_gdb_scripts: false, + eh_frame_header: false, + ..Default::default() + }; + Target { + data_layout: "E-m:e-p:32:32-i64:64-f128:64-n32-S64".into(), + llvm_target: "sparc-unknown-none-elf".into(), + pointer_width: 32, + arch: "sparc".into(), + options, + } +} diff --git a/src/doc/rustc/src/platform-support.md b/src/doc/rustc/src/platform-support.md index d2a25e612ec7b..d287cf7a5fe40 100644 --- a/src/doc/rustc/src/platform-support.md +++ b/src/doc/rustc/src/platform-support.md @@ -176,6 +176,7 @@ target | std | notes `thumbv8m.base-none-eabi` | * | Bare ARMv8-M Baseline `thumbv8m.main-none-eabi` | * | Bare ARMv8-M Mainline `thumbv8m.main-none-eabihf` | * | Bare ARMv8-M Mainline, hardfloat +`sparc-unknown-none-elf` | * | Bare 32-bit SPARC V7+ `wasm32-unknown-emscripten` | ✓ | WebAssembly via Emscripten `wasm32-unknown-unknown` | ✓ | WebAssembly `wasm32-wasi` | ✓ | WebAssembly with WASI diff --git a/src/tools/build-manifest/src/main.rs b/src/tools/build-manifest/src/main.rs index 8b28c68e04fe9..14618f89aedbf 100644 --- a/src/tools/build-manifest/src/main.rs +++ b/src/tools/build-manifest/src/main.rs @@ -127,6 +127,7 @@ static TARGETS: &[&str] = &[ "s390x-unknown-linux-gnu", "sparc64-unknown-linux-gnu", "sparcv9-sun-solaris", + "sparc-unknown-none-elf", "thumbv6m-none-eabi", "thumbv7em-none-eabi", "thumbv7em-none-eabihf", From 4bccf832a3ea62318c82adae33e0a2cce1e6572f Mon Sep 17 00:00:00 2001 From: "Jonathan Pallant (Ferrous Systems)" Date: Tue, 11 Jul 2023 11:59:07 +0100 Subject: [PATCH 2/4] Add platform support information. --- src/doc/rustc/src/SUMMARY.md | 1 + src/doc/rustc/src/platform-support.md | 2 +- .../sparc-unknown-none-elf.md | 164 ++++++++++++++++++ 3 files changed, 166 insertions(+), 1 deletion(-) create mode 100644 src/doc/rustc/src/platform-support/sparc-unknown-none-elf.md diff --git a/src/doc/rustc/src/SUMMARY.md b/src/doc/rustc/src/SUMMARY.md index f8af26326a734..4d4dc3f499650 100644 --- a/src/doc/rustc/src/SUMMARY.md +++ b/src/doc/rustc/src/SUMMARY.md @@ -38,6 +38,7 @@ - [mipsel-sony-psx](platform-support/mipsel-sony-psx.md) - [nvptx64-nvidia-cuda](platform-support/nvptx64-nvidia-cuda.md) - [riscv32imac-unknown-xous-elf](platform-support/riscv32imac-unknown-xous-elf.md) + - [sparc-unknown-none-elf](./platform-support/sparc-unknown-none-elf.md) - [*-pc-windows-gnullvm](platform-support/pc-windows-gnullvm.md) - [\*-nto-qnx-\*](platform-support/nto-qnx.md) - [\*-unknown-netbsd\*](platform-support/netbsd.md) diff --git a/src/doc/rustc/src/platform-support.md b/src/doc/rustc/src/platform-support.md index d287cf7a5fe40..14fe7242ab951 100644 --- a/src/doc/rustc/src/platform-support.md +++ b/src/doc/rustc/src/platform-support.md @@ -176,7 +176,7 @@ target | std | notes `thumbv8m.base-none-eabi` | * | Bare ARMv8-M Baseline `thumbv8m.main-none-eabi` | * | Bare ARMv8-M Mainline `thumbv8m.main-none-eabihf` | * | Bare ARMv8-M Mainline, hardfloat -`sparc-unknown-none-elf` | * | Bare 32-bit SPARC V7+ +[`sparc-unknown-none-elf`](./platform-support/sparc-unknown-none-elf.md) | * | Bare 32-bit SPARC V7+ `wasm32-unknown-emscripten` | ✓ | WebAssembly via Emscripten `wasm32-unknown-unknown` | ✓ | WebAssembly `wasm32-wasi` | ✓ | WebAssembly with WASI diff --git a/src/doc/rustc/src/platform-support/sparc-unknown-none-elf.md b/src/doc/rustc/src/platform-support/sparc-unknown-none-elf.md new file mode 100644 index 0000000000000..efd58e8302fd7 --- /dev/null +++ b/src/doc/rustc/src/platform-support/sparc-unknown-none-elf.md @@ -0,0 +1,164 @@ +# `sparc-unknown-none-elf` + +**Tier: 3** + +Rust for bare-metal 32-bit SPARC V7 and V8 systems, e.g. the Gaisler LEON3. + +| Target | Descriptions | +| ---------------------- | ----------------------------------------- | +| sparc-unknown-none-elf | SPARC V7 32-bit (freestanding, hardfloat) | + +## Target maintainers + +- Jonathan Pallant, , https://ferrous-systems.com + +## Requirements + +This target is cross-compiled. There is no support for `std`. There is no +default allocator, but it's possible to use `alloc` by supplying an allocator. + +This allows the generated code to run in environments, such as kernels, which +may need to avoid the use of such registers or which may have special +considerations about the use of such registers (e.g. saving and restoring them +to avoid breaking userspace code using the same registers). You can change code +generation to use additional CPU features via the `-C target-feature=` codegen +options to rustc, or via the `#[target_feature]` mechanism within Rust code. + +By default, code generated with this target should run on any `SPARC` hardware; +enabling additional target features may raise this baseline. + +- `-Ctarget-cpu=v8` adds the extra SPARC V8 instructions. + +- `-Ctarget-cpu=leon3` adds the SPARC V8 instructions and sets up scheduling to + suit the Gaisler Leon3. + +Functions marked `extern "C"` use the [standard SPARC architecture calling +convention](https://sparc.org/technical-documents/). + +This target generates ELF binaries. Any alternate formats or special +considerations for binary layout will require linker options or linker scripts. + +## Building the target + +You can build Rust with support for the target by adding it to the `target` +list in `config.toml`: + +```toml +[build] +build-stage = 1 +target = ["sparc-unknown-none-elf"] +``` + +## Building Rust programs + +```text +cargo build --target sparc-unknown-none-elf +``` + +This target uses GCC as a linker, and so you will need an appropriate GCC +compatible `sparc-unknown-none` toolchain. + +The default linker name is `sparc-elf-gcc`, but you can override this in your +project configuration. + +## Testing + +As `sparc-unknown-none-elf` supports a variety of different environments and does +not support `std`, this target does not support running the Rust test suite. + +## Cross-compilation toolchains and C code + +This target was initially tested using [BCC2] from Gaisler, along with the TSIM +Leon3 processor simulator. Both [BCC2] GCC and [BCC2] Clang have been shown to +work. To work with these tools, your project configuration should contain +something like: + +[BCC2]: https://www.gaisler.com/index.php/downloads/compilers + +`.cargo/config.toml`: +```toml +[target.sparc-unknown-none-elf] +linker = "sparc-gaisler-elf-gcc" +runner = "tsim-leon3" + +[build] +target = ["sparc-unknown-none-elf"] +rustflags = "-Ctarget-cpu=leon3" + +[unstable] +build-std = ["core"] +``` + +With this configuration, running `cargo run` will compile your code for the +SPARC V8 compatible Gaisler Leon3 processor and then start the `tsim-leon3` +simulator. Once the simulator is running, simply enter the command +`run` to start the code executing in the simulator. + +The default C toolchain libraries are linked in, so with the Gaisler [BCC2] +toolchain, and using its default Leon3 BSP, you can use call the C `putchar` +function and friends to output to the simulator console. + +Here's a complete example: + +```rust,ignore (cannot-test-this-because-it-assumes-special-libc-functions) +#![no_std] +#![no_main] + +extern "C" { + fn putchar(ch: i32); + fn _exit(code: i32) -> !; +} + +#[no_mangle] +extern "C" fn main() -> i32 { + let message = "Hello, this is Rust!"; + for b in message.bytes() { + unsafe { + putchar(b as i32); + } + } + 0 +} + +#[panic_handler] +fn panic(_panic: &core::panic::PanicInfo) -> ! { + unsafe { + _exit(1); + } +} +``` + +```console +$ cargo run --target=sparc-unknown-none-elf + Compiling sparc-demo-rust v0.1.0 (/work/sparc-demo-rust) + Finished dev [unoptimized + debuginfo] target(s) in 3.44s + Running `tsim-leon3 target/sparc-unknown-none-elf/debug/sparc-demo-rust` + + TSIM3 LEON3 SPARC simulator, version 3.1.9 (evaluation version) + + Copyright (C) 2023, Frontgrade Gaisler - all rights reserved. + This software may only be used with a valid license. + For latest updates, go to https://www.gaisler.com/ + Comments or bug-reports to support@gaisler.com + + This TSIM evaluation version will expire 2023-11-28 + +Number of CPUs: 2 +system frequency: 50.000 MHz +icache: 1 * 4 KiB, 16 bytes/line (4 KiB total) +dcache: 1 * 4 KiB, 16 bytes/line (4 KiB total) +Allocated 8192 KiB SRAM memory, in 1 bank at 0x40000000 +Allocated 32 MiB SDRAM memory, in 1 bank at 0x60000000 +Allocated 8192 KiB ROM memory at 0x00000000 +section: .text, addr: 0x40000000, size: 20528 bytes +section: .rodata, addr: 0x40005030, size: 128 bytes +section: .data, addr: 0x400050b0, size: 1176 bytes +read 347 symbols + +tsim> run + Initializing and starting from 0x40000000 +Hello, this is Rust! + + Program exited normally on CPU 0. +tsim> +``` From 9efc683df868514a508cec8a5ca91798db2a9841 Mon Sep 17 00:00:00 2001 From: "Jonathan Pallant (Ferrous Systems)" Date: Mon, 17 Jul 2023 13:22:29 +0100 Subject: [PATCH 3/4] Remove redundant note. This came from x86_64-unknown-none and doesn't make sense here. --- .../rustc/src/platform-support/sparc-unknown-none-elf.md | 7 ------- 1 file changed, 7 deletions(-) diff --git a/src/doc/rustc/src/platform-support/sparc-unknown-none-elf.md b/src/doc/rustc/src/platform-support/sparc-unknown-none-elf.md index efd58e8302fd7..3e59717dfd935 100644 --- a/src/doc/rustc/src/platform-support/sparc-unknown-none-elf.md +++ b/src/doc/rustc/src/platform-support/sparc-unknown-none-elf.md @@ -17,13 +17,6 @@ Rust for bare-metal 32-bit SPARC V7 and V8 systems, e.g. the Gaisler LEON3. This target is cross-compiled. There is no support for `std`. There is no default allocator, but it's possible to use `alloc` by supplying an allocator. -This allows the generated code to run in environments, such as kernels, which -may need to avoid the use of such registers or which may have special -considerations about the use of such registers (e.g. saving and restoring them -to avoid breaking userspace code using the same registers). You can change code -generation to use additional CPU features via the `-C target-feature=` codegen -options to rustc, or via the `#[target_feature]` mechanism within Rust code. - By default, code generated with this target should run on any `SPARC` hardware; enabling additional target features may raise this baseline. From 3f3a855510b86ac63f1e5332b7e1657a42407259 Mon Sep 17 00:00:00 2001 From: "Jonathan Pallant (Ferrous Systems)" Date: Mon, 17 Jul 2023 13:49:06 +0100 Subject: [PATCH 4/4] Add clarification about build-std and using newer instructions. --- .../sparc-unknown-none-elf.md | 53 +++++++++++++++---- 1 file changed, 42 insertions(+), 11 deletions(-) diff --git a/src/doc/rustc/src/platform-support/sparc-unknown-none-elf.md b/src/doc/rustc/src/platform-support/sparc-unknown-none-elf.md index 3e59717dfd935..f579b1fb8d487 100644 --- a/src/doc/rustc/src/platform-support/sparc-unknown-none-elf.md +++ b/src/doc/rustc/src/platform-support/sparc-unknown-none-elf.md @@ -39,20 +39,31 @@ list in `config.toml`: ```toml [build] build-stage = 1 -target = ["sparc-unknown-none-elf"] +host = [""] +target = ["", "sparc-unknown-none-elf"] ``` +Replace `` with `x86_64-unknown-linux-gnu` or whatever +else is appropriate for your host machine. + ## Building Rust programs -```text +To build with this target, pass it to the `--target` argument, like: + +```console cargo build --target sparc-unknown-none-elf ``` This target uses GCC as a linker, and so you will need an appropriate GCC -compatible `sparc-unknown-none` toolchain. +compatible `sparc-unknown-none` toolchain. The default linker binary is +`sparc-elf-gcc`, but you can override this in your project configuration, as +follows: -The default linker name is `sparc-elf-gcc`, but you can override this in your -project configuration. +`.cargo/config.toml`: +```toml +[target.sparc-unknown-none-elf] +linker = "sparc-custom-elf-gcc" +``` ## Testing @@ -74,6 +85,26 @@ something like: linker = "sparc-gaisler-elf-gcc" runner = "tsim-leon3" +[build] +target = ["sparc-unknown-none-elf"] +rustflags = "-Ctarget-cpu=leon3" +``` + +With this configuration, running `cargo run` will compile your code for the +SPARC V8 compatible Gaisler Leon3 processor and then start the `tsim-leon3` +simulator. The `libcore` was pre-compiled as part of the `rustc` compilation +process using the SPARC V7 baseline, but if you are using a nightly toolchain +you can use the +[`-Z build-std=core`](https://doc.rust-lang.org/cargo/reference/unstable.html#build-std) +option to rebuild `libcore` from source. This may be useful if you want to +compile it for SPARC V8 and take advantage of the extra instructions. + +`.cargo/config.toml`: +```toml +[target.sparc-unknown-none-elf] +linker = "sparc-gaisler-elf-gcc" +runner = "tsim-leon3" + [build] target = ["sparc-unknown-none-elf"] rustflags = "-Ctarget-cpu=leon3" @@ -82,16 +113,16 @@ rustflags = "-Ctarget-cpu=leon3" build-std = ["core"] ``` -With this configuration, running `cargo run` will compile your code for the -SPARC V8 compatible Gaisler Leon3 processor and then start the `tsim-leon3` -simulator. Once the simulator is running, simply enter the command -`run` to start the code executing in the simulator. +Either way, once the simulator is running, simply enter the command `run` to +start the code executing in the simulator. The default C toolchain libraries are linked in, so with the Gaisler [BCC2] toolchain, and using its default Leon3 BSP, you can use call the C `putchar` -function and friends to output to the simulator console. +function and friends to output to the simulator console. The default linker +script is also appropriate for the Leon3 simulator, so no linker script is +required. -Here's a complete example: +Here's a complete example using the above config file: ```rust,ignore (cannot-test-this-because-it-assumes-special-libc-functions) #![no_std]