Skip to content

Commit

Permalink
xtensa: Support load/store (experimental)
Browse files Browse the repository at this point in the history
  • Loading branch information
taiki-e committed Oct 27, 2024
1 parent 7043da4 commit baef992
Show file tree
Hide file tree
Showing 15 changed files with 463 additions and 7 deletions.
4 changes: 4 additions & 0 deletions .github/.cspell/project-dictionary.txt
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ cmpxchg
cset
dbar
DWCAS
espup
fild
fistp
Halfword
Expand All @@ -41,6 +42,7 @@ ldsetp
ldxp
lgcc
libunwind
linkall
lmul
lqarx
lrcpc
Expand Down Expand Up @@ -94,12 +96,14 @@ stwcx
stxp
subarch
swpp
uart
usart
uwrite
uwriteln
uxtb
uxth
virt
wokwi
xchg
xmmword
xorps
Expand Down
2 changes: 2 additions & 0 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,9 @@ updates:
- /
# crates with [workspace] table are not recognized by the above 'directory: /'
- /tests/avr
- /tests/msp430
- /tests/no-std-qemu
- /tests/xtensa
schedule:
interval: daily
commit-message:
Expand Down
11 changes: 11 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -374,6 +374,10 @@ jobs:
- uses: taiki-e/github-actions/install-rust@main
with:
toolchain: ${{ matrix.rust }}
- uses: taiki-e/install-action@cargo-hack
if: startsWith(matrix.rust, 'nightly')
- uses: taiki-e/install-action@espup
if: startsWith(matrix.rust, 'nightly')
- run: |
retry() {
for i in {1..10}; do
Expand Down Expand Up @@ -411,10 +415,17 @@ jobs:
retry curl --proto '=https' --tlsv1.2 -fsSL --retry 10 --retry-connrefused https://dr-download.ti.com/software-development/ide-configuration-compiler-or-debugger/MD-LlCjWuAbzH/9.3.1.2/msp430-gcc-9.3.1.11_linux64.tar.bz2 \
| tar xjf - --strip-components 1 -C "${HOME}"/msp430-gcc
printf '%s\n' "${HOME}"/msp430-gcc/bin >>"${GITHUB_PATH}"
retry espup install --targets esp32,esp32s2,esp32s3
fi
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- run: rm -- tests/avr/rust-toolchain.toml
if: startsWith(matrix.rust, 'nightly-')
- run: tools/no-std.sh
- run: tools/build.sh +esp xtensa-esp32-none-elf xtensa-esp32s2-none-elf xtensa-esp32s3-none-elf
if: startsWith(matrix.rust, 'nightly')
- run: tools/no-std.sh +esp xtensa-esp32-none-elf xtensa-esp32s2-none-elf xtensa-esp32s3-none-elf
if: startsWith(matrix.rust, 'nightly')

valgrind:
needs: tidy
Expand Down
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ non_ascii_idents = "warn"
rust_2018_idioms = "warn"
single_use_lifetimes = "warn"
unexpected_cfgs = { level = "warn", check-cfg = [
'cfg(target_arch,values("xtensa"))', # 1.81+ https://github.com/rust-lang/rust/pull/125141
'cfg(target_feature,values("lse2","lse128","rcpc3"))', # 1.82+ https://github.com/rust-lang/rust/pull/128192
'cfg(target_feature,values("partword-atomics","quadword-atomics"))', # 1.83+ https://github.com/rust-lang/rust/pull/130873
'cfg(target_feature,values("zaamo","zabha"))', # 1.83+ https://github.com/rust-lang/rust/pull/130877
Expand Down
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ This crate provides a way to soundly perform such operations.

## Platform Support

Currently, x86, x86_64, Arm, AArch64, RISC-V, LoongArch64, MIPS32, MIPS64, PowerPC, s390x, MSP430, Arm64EC, AVR, and Hexagon are supported.
Currently, x86, x86_64, Arm, AArch64, RISC-V, LoongArch64, MIPS32, MIPS64, PowerPC, s390x, MSP430, Arm64EC, AVR, Hexagon, and Xtensa are supported.

| target_arch | primitives | load/store | swap/CAS |
| -------------------------------- | --------------------------------------------------- |:----------:|:--------:|
Expand All @@ -41,6 +41,7 @@ Currently, x86, x86_64, Arm, AArch64, RISC-V, LoongArch64, MIPS32, MIPS64, Power
| msp430 \[4] (experimental) | isize,usize,i8,u8,i16,u16 |||
| avr \[4] (experimental) | isize,usize,i8,u8,i16,u16 |||
| hexagon \[4] (experimental) | isize,usize,i8,u8,i16,u16,i32,u32,i64,u64 |||
| xtensa \[4] (experimental) | isize,usize,i8,u8,i16,u16,i32,u32 || |

\[1] Arm's atomic RMW operations are not available on v6-m (thumbv6m). RISC-V's atomic RMW operations are not available on targets without the A (or G which means IMAFD) extension such as riscv32i, riscv32imc, etc.<br>
\[2] Armv6+ or Linux/Android, except for M-profile architecture such as thumbv6m, thumbv7m, etc.<br>
Expand Down
2 changes: 1 addition & 1 deletion build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ fn main() {
}
}
"arm64ec" | "avr" | "hexagon" | "mips" | "mips32r6" | "mips64" | "mips64r6" | "msp430"
| "powerpc" | "powerpc64" => {
| "powerpc" | "powerpc64" | "xtensa" => {
if version.nightly && is_allowed_feature("asm_experimental_arch") {
println!("cargo:rustc-cfg=atomic_maybe_uninit_unstable_asm_experimental_arch");
}
Expand Down
52 changes: 52 additions & 0 deletions src/arch/cfgs/xtensa.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
// SPDX-License-Identifier: Apache-2.0 OR MIT

#![allow(missing_docs)]

#[macro_export]
macro_rules! cfg_has_atomic_8 {
($($tt:tt)*) => { $($tt)* };
}
#[macro_export]
macro_rules! cfg_no_atomic_8 {
($($tt:tt)*) => {};
}
#[macro_export]
macro_rules! cfg_has_atomic_16 {
($($tt:tt)*) => { $($tt)* };
}
#[macro_export]
macro_rules! cfg_no_atomic_16 {
($($tt:tt)*) => {};
}
#[macro_export]
macro_rules! cfg_has_atomic_32 {
($($tt:tt)*) => { $($tt)* };
}
#[macro_export]
macro_rules! cfg_no_atomic_32 {
($($tt:tt)*) => {};
}
#[macro_export]
macro_rules! cfg_has_atomic_64 {
($($tt:tt)*) => {};
}
#[macro_export]
macro_rules! cfg_no_atomic_64 {
($($tt:tt)*) => { $($tt)* };
}
#[macro_export]
macro_rules! cfg_has_atomic_128 {
($($tt:tt)*) => {};
}
#[macro_export]
macro_rules! cfg_no_atomic_128 {
($($tt:tt)*) => { $($tt)* };
}
#[macro_export]
macro_rules! cfg_has_atomic_cas {
($($tt:tt)*) => {};
}
#[macro_export]
macro_rules! cfg_no_atomic_cas {
($($tt:tt)*) => { $($tt)* };
}
4 changes: 4 additions & 0 deletions src/arch/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
target_arch = "powerpc",
target_arch = "powerpc64",
target_arch = "s390x",
target_arch = "xtensa",
),
atomic_maybe_uninit_unstable_asm_experimental_arch,
),
Expand Down Expand Up @@ -105,3 +106,6 @@ mod riscv;
mod s390x;
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
mod x86;
#[cfg(target_arch = "xtensa")]
#[cfg(atomic_maybe_uninit_unstable_asm_experimental_arch)]
mod xtensa;
90 changes: 90 additions & 0 deletions src/arch/xtensa.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
// SPDX-License-Identifier: Apache-2.0 OR MIT

/*
Xtensa
Refs:
- Xtensa Instruction Set Architecture (ISA) Reference Manual https://web.archive.org/web/20241005102231/https://0x04.net/~mwk/doc/xtensa.pdf
- https://github.com/espressif/llvm-project/blob/xtensa_release_18.1.2/llvm/test/CodeGen/Xtensa/atomic-load-store.ll
*/

#[path = "cfgs/xtensa.rs"]
mod cfgs;

use core::{arch::asm, mem::MaybeUninit, sync::atomic::Ordering};

use crate::raw::{AtomicLoad, AtomicStore};

macro_rules! atomic {
($int_type:ident, $asm_size:tt, $asm_suffix:tt, $asm_load_ext:tt) => {
impl AtomicLoad for $int_type {
#[inline]
unsafe fn atomic_load(
src: *const MaybeUninit<Self>,
order: Ordering,
) -> MaybeUninit<Self> {
let out: MaybeUninit<Self>;

// SAFETY: the caller must uphold the safety contract.
unsafe {
macro_rules! atomic_load {
($acquire:tt) => {
asm!(
concat!("l", $asm_size, $asm_load_ext, "i", $asm_suffix, " {out}, {src}, 0"),
$acquire,
src = in(reg) ptr_reg!(src),
out = lateout(reg) out,
options(nostack, preserves_flags),
)
};
}
match order {
Ordering::Relaxed => atomic_load!(""),
Ordering::Acquire | Ordering::SeqCst => atomic_load!("memw"),
_ => unreachable!(),
}
}
out
}
}
impl AtomicStore for $int_type {
#[inline]
unsafe fn atomic_store(
dst: *mut MaybeUninit<Self>,
val: MaybeUninit<Self>,
order: Ordering,
) {
// SAFETY: the caller must uphold the safety contract.
unsafe {
macro_rules! atomic_store {
($acquire:tt, $release:tt) => {
asm!(
$release,
concat!("s", $asm_size, "i", $asm_suffix, " {val}, {dst}, 0"),
$acquire,
dst = in(reg) ptr_reg!(dst),
val = in(reg) val,
options(nostack, preserves_flags),
)
};
}
match order {
Ordering::Relaxed => atomic_store!("", ""),
Ordering::Release => atomic_store!("", "memw"),
Ordering::SeqCst => atomic_store!("memw", "memw"),
_ => unreachable!(),
}
}
}
}
};
}

atomic!(i8, "8", "", "u");
atomic!(u8, "8", "", "u");
atomic!(i16, "16", "", "u");
atomic!(u16, "16", "", "u");
atomic!(i32, "32", ".n", "");
atomic!(u32, "32", ".n", "");
atomic!(isize, "32", ".n", "");
atomic!(usize, "32", ".n", "");
3 changes: 2 additions & 1 deletion src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ This crate provides a way to soundly perform such operations.
## Platform Support
Currently, x86, x86_64, Arm, AArch64, RISC-V, LoongArch64, MIPS32, MIPS64, PowerPC, s390x, MSP430, Arm64EC, AVR, and Hexagon are supported.
Currently, x86, x86_64, Arm, AArch64, RISC-V, LoongArch64, MIPS32, MIPS64, PowerPC, s390x, MSP430, Arm64EC, AVR, Hexagon, and Xtensa are supported.
| target_arch | primitives | load/store | swap/CAS |
| -------------------------------- | --------------------------------------------------- |:----------:|:--------:|
Expand All @@ -35,6 +35,7 @@ Currently, x86, x86_64, Arm, AArch64, RISC-V, LoongArch64, MIPS32, MIPS64, Power
| msp430 \[4] (experimental) | isize,usize,i8,u8,i16,u16 | ✓ | ✓ |
| avr \[4] (experimental) | isize,usize,i8,u8,i16,u16 | ✓ | ✓ |
| hexagon \[4] (experimental) | isize,usize,i8,u8,i16,u16,i32,u32,i64,u64 | ✓ | ✓ |
| xtensa \[4] (experimental) | isize,usize,i8,u8,i16,u16,i32,u32 | ✓ | |
\[1] Arm's atomic RMW operations are not available on v6-m (thumbv6m). RISC-V's atomic RMW operations are not available on targets without the A (or G which means IMAFD) extension such as riscv32i, riscv32imc, etc.<br>
\[2] Armv6+ or Linux/Android, except for M-profile architecture such as thumbv6m, thumbv7m, etc.<br>
Expand Down
6 changes: 6 additions & 0 deletions tests/xtensa/.cargo/config.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
[target.xtensa-esp32-none-elf]
runner = "wokwi-server --chip esp32"
[target.xtensa-esp32s2-none-elf]
runner = "wokwi-server --chip esp32s2"
[target.xtensa-esp32s3-none-elf]
runner = "wokwi-server --chip esp32s3"
34 changes: 34 additions & 0 deletions tests/xtensa/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
[package]
name = "xtensa-test"
version = "0.0.0"
edition = "2021"
publish = false

[dependencies]
atomic-maybe-uninit = { path = "../.." }

paste = "1"

[target.xtensa-esp32-none-elf.dependencies]
esp-println = { version = "0.12", default-features = false, features = ["uart", "esp32"] }
esp-hal = { version = "0.21", features = ["esp32"] }
[target.xtensa-esp32s2-none-elf.dependencies]
esp-println = { version = "0.12", default-features = false, features = ["uart", "esp32s2"] }
esp-hal = { version = "0.21", features = ["esp32s2"] }
[target.xtensa-esp32s3-none-elf.dependencies]
esp-println = { version = "0.12", default-features = false, features = ["uart", "esp32s3"] }
esp-hal = { version = "0.21", features = ["esp32s3"] }

[workspace]
resolver = "2"

[lints.rust]
rust_2018_idioms = "warn"
single_use_lifetimes = "warn"
# unsafe_op_in_unsafe_fn = "warn" # Set at crate-level instead since https://github.com/rust-lang/rust/pull/100081 is not available on MSRV

[profile.dev]
opt-level = 'z'

[profile.release]
opt-level = 'z'
Loading

0 comments on commit baef992

Please sign in to comment.