diff options
| -rw-r--r-- | .cargo/rp-pico-2040.toml | 10 | ||||
| -rw-r--r-- | Cargo.lock | 277 | ||||
| -rw-r--r-- | Cargo.toml | 1 | ||||
| -rw-r--r-- | crates/rp-pico-2040/Cargo.toml | 13 | ||||
| -rw-r--r-- | crates/rp-pico-2040/build.rs | 7 | ||||
| -rw-r--r-- | crates/rp-pico-2040/memory.x | 15 | ||||
| -rw-r--r-- | crates/rp-pico-2040/src/lib.rs | 94 | ||||
| -rw-r--r-- | crates/rp-pico-2040/src/main.rs | 11 | ||||
| -rw-r--r-- | crates/sync-single-core/Cargo.toml | 6 | ||||
| -rw-r--r-- | crates/sync-single-core/src/lib.rs | 178 |
10 files changed, 611 insertions, 1 deletions
diff --git a/.cargo/rp-pico-2040.toml b/.cargo/rp-pico-2040.toml new file mode 100644 index 0000000..7bb6886 --- /dev/null +++ b/.cargo/rp-pico-2040.toml @@ -0,0 +1,10 @@ +[build] +target = "thumbv6m-threadx-eabi" + +[target.thumbv6m-threadx-eabi] +runner = "elf2uf2-rs -d" +rustflags = [ + "-Clink-arg=-Tweak-symbols.x", + "-Clink-arg=-Tlink.x", + "-Ctarget-cpu=cortex-m0", +] @@ -3,6 +3,12 @@ version = 4 [[package]] +name = "arrayvec" +version = "0.7.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3fb67a6e08acf24fdeccbac2cb6ac4305825bd1f117462e0e6f2f193345ad56" + +[[package]] name = "bare-metal" version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -18,6 +24,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "46afbd2983a5d5a7bd740ccb198caf5b82f45c40c09c0eed36052d91cb92e719" [[package]] +name = "bitfield" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2d7e60934ceec538daadb9d8432424ed043a904d8e0243f3c6446bce549a46ac" + +[[package]] name = "bitflags" version = "2.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -41,7 +53,7 @@ version = "0.7.7" source = "git+https://github.com/rust-embedded/cortex-m?rev=8c62cc47314445346851b0d0664f9cc34c50b24d#8c62cc47314445346851b0d0664f9cc34c50b24d" dependencies = [ "bare-metal", - "bitfield", + "bitfield 0.13.2", "cortex-m-macros", "critical-section", "embedded-hal 0.2.7", @@ -89,12 +101,42 @@ dependencies = [ ] [[package]] +name = "crc-any" +version = "2.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "46db9f663dfb869b80fcf59e32d7a80fc6c464a4f6328f3f06a00f5e36d05f8c" +dependencies = [ + "debug-helper", +] + +[[package]] name = "critical-section" version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "790eea4361631c5e7d22598ecd5723ff611904e3344ce8720784c93e3d83d40b" [[package]] +name = "debug-helper" +version = "0.3.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "80a4af69c60438a1a82af89d362f4729fd38db7b73f305a237636fad31ceb2bf" + +[[package]] +name = "either" +version = "1.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "252afb9ae5eaa683babdc6a068b3f5726eb19e05070c731f9b2a23a7c3e8ed34" + +[[package]] +name = "embedded-dma" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "994f7e5b5cb23521c22304927195f236813053eb9c065dd2226a32ba64695446" +dependencies = [ + "stable_deref_trait", +] + +[[package]] name = "embedded-hal" version = "0.2.7" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -111,6 +153,25 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "361a90feb7004eca4019fb28352a9465666b24f840f5c3cddf0ff13920590b89" [[package]] +name = "embedded-hal-async" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c4c685bbef7fe13c3c6dd4da26841ed3980ef33e841cddfa15ce8a8fb3f1884" +dependencies = [ + "embedded-hal 1.0.0", +] + +[[package]] +name = "embedded-hal-nb" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fba4268c14288c828995299e59b12babdbe170f6c6d73731af1b4648142e8605" +dependencies = [ + "embedded-hal 1.0.0", + "nb 1.1.0", +] + +[[package]] name = "embedded-io" version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -123,6 +184,60 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9eb1aa714776b75c7e67e1da744b81a129b3ff919c8712b5e1b32252c1f07cc7" [[package]] +name = "frunk" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "28aef0f9aa070bce60767c12ba9cb41efeaf1a2bc6427f87b7d83f11239a16d7" +dependencies = [ + "frunk_core 0.4.4", + "frunk_derives", +] + +[[package]] +name = "frunk_core" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "476eeaa382e3462b84da5d6ba3da97b5786823c2d0d3a0d04ef088d073da225c" + +[[package]] +name = "frunk_core" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0bd3c9ba2e323e8b19e77f15873f60974a7d82f89b80e50c53be44b8b92927c1" + +[[package]] +name = "frunk_derives" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a0b4095fc99e1d858e5b8c7125d2638372ec85aa0fe6c807105cf10b0265ca6c" +dependencies = [ + "frunk_proc_macro_helpers", + "quote", + "syn 2.0.119", +] + +[[package]] +name = "frunk_proc_macro_helpers" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b70229a1347a20d4af9c06116cc452acef34f798668c6b69e97dd5c8a88052bd" +dependencies = [ + "frunk_core 0.5.0", + "proc-macro2", + "quote", + "syn 2.0.119", +] + +[[package]] +name = "fugit" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4e639847d312d9a82d2e75b0edcc1e934efcc64e6cb7aa94f0b1fbec0bc231d6" +dependencies = [ + "gcd", +] + +[[package]] name = "futures" version = "0.3.34" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -195,6 +310,12 @@ dependencies = [ ] [[package]] +name = "gcd" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d758ba1b47b00caf47f24925c0074ecb20d6dfcffe7f6d53395c0465674841a" + +[[package]] name = "hash32" version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -394,6 +515,15 @@ dependencies = [ ] [[package]] +name = "itertools" +version = "0.10.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473" +dependencies = [ + "either", +] + +[[package]] name = "lm3s6965" version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -419,6 +549,26 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8d5439c4ad607c3c23abf66de8c8bf57ba8adcd1f129e699851a6e43935d339d" [[package]] +name = "num_enum" +version = "0.5.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f646caf906c20226733ed5b1374287eb97e3c2a5c227ce668c1f2ce20ae57c9" +dependencies = [ + "num_enum_derive", +] + +[[package]] +name = "num_enum_derive" +version = "0.5.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dcbff9bc912032c62bf65ef1d5aea88983b420f4f839db1e9b0c281a25c9c799" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] name = "panic-semihosting" version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -429,12 +579,29 @@ dependencies = [ ] [[package]] +name = "paste" +version = "1.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" + +[[package]] name = "pin-project-lite" version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a89322df9ebe1c1578d689c92318e070967d1042b512afbe49518723f4e6d5cd" [[package]] +name = "pio" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76e09694b50f89f302ed531c1f2a7569f0be5867aee4ab4f8f729bbeec0078e3" +dependencies = [ + "arrayvec", + "num_enum", + "paste", +] + +[[package]] name = "portable-atomic" version = "1.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -470,6 +637,87 @@ version = "0.2.0" source = "git+https://git.mciantyre.dev/ral-registers?branch=v0.2#495fbc58b6f4d2e751b16883a2c5cee3c598fd79" [[package]] +name = "rand_core" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" + +[[package]] +name = "rp-pico" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9342d3ac7011ac688300979e9b52a81f0add1d05feb02868cf94bfee0705b28" +dependencies = [ + "cortex-m-rt", + "fugit", + "rp2040-boot2", + "rp2040-hal", + "usb-device", +] + +[[package]] +name = "rp2040-boot2" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c92f344f63f950ee36cf4080050e4dce850839b9175da38f9d2ffb69b4dbb21" +dependencies = [ + "crc-any", +] + +[[package]] +name = "rp2040-hal" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d11e711940087f2cdff8aeae9f4b902e2014c06a00b39a1092686b81ec973d6f" +dependencies = [ + "bitfield 0.14.0", + "cortex-m", + "critical-section", + "embedded-dma", + "embedded-hal 0.2.7", + "embedded-hal 1.0.0", + "embedded-hal-async", + "embedded-hal-nb", + "embedded-io 0.6.1", + "frunk", + "fugit", + "itertools", + "nb 1.1.0", + "paste", + "pio", + "rand_core", + "rp2040-hal-macros", + "rp2040-pac", + "usb-device", + "vcell", + "void", +] + +[[package]] +name = "rp2040-hal-macros" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "86479063e497efe1ae81995ef9071f54fd1c7427e04d6c5b84cde545ff672a5e" +dependencies = [ + "cortex-m-rt", + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "rp2040-pac" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "83cbcd3f7a0ca7bbe61dc4eb7e202842bee4e27b769a7bf3a4a72fa399d6e404" +dependencies = [ + "cortex-m", + "cortex-m-rt", + "critical-section", + "vcell", +] + +[[package]] name = "rust-threadx-cortex-m" version = "0.1.0" @@ -520,6 +768,18 @@ dependencies = [ ] [[package]] +name = "rust-threadx-rp-pico-2040" +version = "0.1.0" +dependencies = [ + "cortex-m", + "embedded-hal 1.0.0", + "rp-pico", + "rust-threadx-cortex-m", + "rust-threadx-stdio-semihosting", + "rust-threadx-sync-single-core", +] + +[[package]] name = "rust-threadx-stdio-imxrt-usbd" version = "0.1.0" dependencies = [ @@ -538,6 +798,10 @@ dependencies = [ ] [[package]] +name = "rust-threadx-sync-single-core" +version = "0.1.0" + +[[package]] name = "rust-threadx-teensy4" version = "0.1.0" dependencies = [ @@ -579,6 +843,17 @@ checksum = "6ce2be8dc25455e1f91df71bfa12ad37d7af1092ae736f3a6cd0e37bc7810596" [[package]] name = "syn" +version = "1.0.109" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "syn" version = "2.0.119" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "872831b642d1a07999a962a351ed35b955ea2cfc8f3862091e2a240a84f17297" @@ -9,6 +9,7 @@ rust-threadx-net-phys = { path = "crates/net-phys" } rust-threadx-qemu = { path = "crates/qemu" } rust-threadx-stdio-imxrt-usbd = { path = "crates/stdio-imxrt-usbd" } rust-threadx-stdio-semihosting = { path = "crates/stdio-semihosting" } +rust-threadx-sync-single-core = { path = "crates/sync-single-core" } cortex-m = { version = "0.7" } cortex-m-rt = { version = "0.7" } diff --git a/crates/rp-pico-2040/Cargo.toml b/crates/rp-pico-2040/Cargo.toml new file mode 100644 index 0000000..6603bf4 --- /dev/null +++ b/crates/rp-pico-2040/Cargo.toml @@ -0,0 +1,13 @@ +[package] +name = "rust-threadx-rp-pico-2040" +version = "0.1.0" +edition = "2024" + +[dependencies] +embedded-hal = "1.0" +rp-pico = "0.9.0" + +rust-threadx-cortex-m.workspace = true +rust-threadx-stdio-semihosting.workspace = true +rust-threadx-sync-single-core.workspace = true +cortex-m.workspace = true diff --git a/crates/rp-pico-2040/build.rs b/crates/rp-pico-2040/build.rs new file mode 100644 index 0000000..f8ac67a --- /dev/null +++ b/crates/rp-pico-2040/build.rs @@ -0,0 +1,7 @@ +use std::path::PathBuf; + +fn main() { + let out_dir = std::env::var("OUT_DIR").map(PathBuf::from).unwrap(); + std::fs::copy("memory.x", out_dir.join("memory.x")).unwrap(); + println!("cargo::rustc-link-search={}", out_dir.display()); +} diff --git a/crates/rp-pico-2040/memory.x b/crates/rp-pico-2040/memory.x new file mode 100644 index 0000000..4077aab --- /dev/null +++ b/crates/rp-pico-2040/memory.x @@ -0,0 +1,15 @@ +MEMORY { + BOOT2 : ORIGIN = 0x10000000, LENGTH = 0x100 + FLASH : ORIGIN = 0x10000100, LENGTH = 2048K - 0x100 + RAM : ORIGIN = 0x20000000, LENGTH = 256K +} + +EXTERN(BOOT2_FIRMWARE) + +SECTIONS { + /* ### Boot loader */ + .boot2 ORIGIN(BOOT2) : + { + KEEP(*(.boot2)); + } > BOOT2 +} INSERT BEFORE .text; diff --git a/crates/rp-pico-2040/src/lib.rs b/crates/rp-pico-2040/src/lib.rs new file mode 100644 index 0000000..8f877aa --- /dev/null +++ b/crates/rp-pico-2040/src/lib.rs @@ -0,0 +1,94 @@ +//! Standard library support crate for an Raspberry Pi Pico with an RP2040. +//! +//! The blinky support example comes from the rp-hal-boards example, available +//! <https://github.com/rp-rs/rp-hal-boards/blob/5135e3dafe3e69b112e6d2d72cfb1856a7679b82/boards/rp-pico/examples/pico_blinky.rs#L1> +//! and licensed MIT or APACHE-2.0. + +#![no_std] +#![feature(rustc_private)] +extern crate fusible; + +use core::pin::Pin; + +use rust_threadx_cortex_m as _; +use rust_threadx_stdio_semihosting as _; +use rust_threadx_sync_single_core as _; + +use embedded_hal::digital::OutputPin; +use rp_pico::hal; +use rp_pico::hal::pac; + +#[doc(hidden)] +#[unsafe(no_mangle)] +pub unsafe extern "C" fn _tx_initialize_low_level() { + use cortex_m::{ + Peripherals, + peripheral::{scb::SystemHandler, syst::SystClkSource}, + }; + + cortex_m::interrupt::disable(); + + unsafe { + let Peripherals { + mut SYST, mut SCB, .. + } = Peripherals::steal(); + + SCB.set_priority(SystemHandler::SysTick, 0x40); + SCB.set_priority(SystemHandler::PendSV, 0xff); + SCB.set_priority(SystemHandler::SVCall, 0xff); + + SYST.set_clock_source(SystClkSource::Core); + SYST.set_reload(125_000_000 / 100 - 1); + SYST.clear_current(); + SYST.enable_interrupt(); + SYST.enable_counter(); + } +} + +use fusible::thread::{StaticStack, Thread, ThreadContext}; +static STACK: StaticStack<512> = StaticStack::new(); +static THREAD: ThreadContext = Thread::context(); + +#[unsafe(no_mangle)] +#[doc(hidden)] +pub extern "C" fn __rust_threadx_app_define() { + let mut pac = pac::Peripherals::take().unwrap(); + + let mut watchdog = hal::Watchdog::new(pac.WATCHDOG); + + hal::clocks::init_clocks_and_plls( + rp_pico::XOSC_CRYSTAL_FREQ, + pac.XOSC, + pac.CLOCKS, + pac.PLL_SYS, + pac.PLL_USB, + &mut pac.RESETS, + &mut watchdog, + ) + .ok() + .unwrap(); + + let sio = hal::Sio::new(pac.SIO); + + let pins = rp_pico::Pins::new( + pac.IO_BANK0, + pac.PADS_BANK0, + sio.gpio_bank0, + &mut pac.RESETS, + ); + + let mut led_pin = pins.led.into_push_pull_output(); + + Thread::create( + Pin::static_ref(&THREAD), + STACK.take().unwrap(), + &Default::default(), + move || loop { + led_pin.set_high().unwrap(); + fusible::thread::sleep(50); + led_pin.set_low().unwrap(); + fusible::thread::sleep(50); + }, + ) + .unwrap(); +} diff --git a/crates/rp-pico-2040/src/main.rs b/crates/rp-pico-2040/src/main.rs new file mode 100644 index 0000000..b155870 --- /dev/null +++ b/crates/rp-pico-2040/src/main.rs @@ -0,0 +1,11 @@ +use rust_threadx_rp_pico_2040 as _; + +use std::{thread, time::Duration}; + +fn main() { + // Nothing interesting yet. Nevertheless, the LED should + // be blinking on a background thread. + loop { + thread::sleep(Duration::from_millis(100)); + } +} diff --git a/crates/sync-single-core/Cargo.toml b/crates/sync-single-core/Cargo.toml new file mode 100644 index 0000000..6970bd3 --- /dev/null +++ b/crates/sync-single-core/Cargo.toml @@ -0,0 +1,6 @@ +[package] +name = "rust-threadx-sync-single-core" +version = "0.1.0" +edition = "2024" + +[dependencies] diff --git a/crates/sync-single-core/src/lib.rs b/crates/sync-single-core/src/lib.rs new file mode 100644 index 0000000..08f7887 --- /dev/null +++ b/crates/sync-single-core/src/lib.rs @@ -0,0 +1,178 @@ +//! `__sync_*` atomic builtins for Armv6-M. +//! +//! Some Rust ThreadX targets, like `thumbv6m-threadx-eabi`, declares `atomic_cas: true` +//! and emulate them with OS support. Right now, we handle this by disabling interrupts. +//! This should be OK for single core support. +//! +//! <https://llvm.org/docs/Atomics.html> + +#![no_std] +#![feature(rustc_private)] +extern crate fusible; + +use fusible::interrupt_control::with_disabled; + +/// Atomically apply `op` to `*ptr`, returning the previous value. +/// +/// # Safety +/// +/// `ptr` must be valid for reads and writes and aligned to `size_of::<T>()`. +unsafe fn rmw<T, O>(ptr: *mut T, op: O) -> T +where + T: Copy, + O: FnOnce(T) -> T, +{ + // Safety: interrupt control sufficient for single-core access. Caller + // (LLVM) assumed to uphold safety contract. + with_disabled(|| unsafe { + let old = ptr.read(); + ptr.write(op(old)); + old + }) +} + +/// Atomically store `new` into `*ptr` if `*ptr` equals `old`, returning the +/// previous value either way. +/// +/// # Safety +/// +/// `ptr` must be valid for reads and writes and aligned to `size_of::<T>()`. +unsafe fn cas<T>(ptr: *mut T, old: T, new: T) -> T +where + T: Copy + PartialEq, +{ + // Safety: Same as rmw. + with_disabled(|| unsafe { + let current = ptr.read(); + if current == old { + ptr.write(new); + } + current + }) +} + +macro_rules! fetch_and_op { + ($name:ident, $ty:ty, $op:expr) => { + #[unsafe(no_mangle)] + pub unsafe extern "C" fn $name(ptr: *mut $ty, val: $ty) -> $ty { + unsafe { rmw(ptr, |cur| $op(cur, val)) } + } + }; +} + +macro_rules! val_compare_and_swap { + ($name:ident, $ty:ty) => { + #[unsafe(no_mangle)] + pub unsafe extern "C" fn $name(ptr: *mut $ty, oldval: $ty, newval: $ty) -> $ty { + unsafe { cas(ptr, oldval, newval) } + } + }; +} + +fetch_and_op!(__sync_fetch_and_add_1, u8, |a: u8, b: u8| a.wrapping_add(b)); +fetch_and_op!(__sync_fetch_and_add_2, u16, |a: u16, b: u16| a + .wrapping_add(b)); +fetch_and_op!(__sync_fetch_and_add_4, u32, |a: u32, b: u32| a + .wrapping_add(b)); + +fetch_and_op!(__sync_fetch_and_sub_1, u8, |a: u8, b: u8| a.wrapping_sub(b)); +fetch_and_op!(__sync_fetch_and_sub_2, u16, |a: u16, b: u16| a + .wrapping_sub(b)); +fetch_and_op!(__sync_fetch_and_sub_4, u32, |a: u32, b: u32| a + .wrapping_sub(b)); + +fetch_and_op!(__sync_fetch_and_and_1, u8, |a: u8, b: u8| a & b); +fetch_and_op!(__sync_fetch_and_and_2, u16, |a: u16, b: u16| a & b); +fetch_and_op!(__sync_fetch_and_and_4, u32, |a: u32, b: u32| a & b); + +fetch_and_op!(__sync_fetch_and_or_1, u8, |a: u8, b: u8| a | b); +fetch_and_op!(__sync_fetch_and_or_2, u16, |a: u16, b: u16| a | b); +fetch_and_op!(__sync_fetch_and_or_4, u32, |a: u32, b: u32| a | b); + +fetch_and_op!(__sync_fetch_and_xor_1, u8, |a: u8, b: u8| a ^ b); +fetch_and_op!(__sync_fetch_and_xor_2, u16, |a: u16, b: u16| a ^ b); +fetch_and_op!(__sync_fetch_and_xor_4, u32, |a: u32, b: u32| a ^ b); + +fetch_and_op!(__sync_fetch_and_nand_1, u8, |a: u8, b: u8| !(a & b)); +fetch_and_op!(__sync_fetch_and_nand_2, u16, |a: u16, b: u16| !(a & b)); +fetch_and_op!(__sync_fetch_and_nand_4, u32, |a: u32, b: u32| !(a & b)); + +fetch_and_op!(__sync_fetch_and_max_1, i8, |a: i8, b: i8| if a > b { + a +} else { + b +}); +fetch_and_op!(__sync_fetch_and_max_2, i16, |a: i16, b: i16| if a > b { + a +} else { + b +}); +fetch_and_op!(__sync_fetch_and_max_4, i32, |a: i32, b: i32| if a > b { + a +} else { + b +}); + +fetch_and_op!(__sync_fetch_and_umax_1, u8, |a: u8, b: u8| if a > b { + a +} else { + b +}); +fetch_and_op!(__sync_fetch_and_umax_2, u16, |a: u16, b: u16| if a > b { + a +} else { + b +}); +fetch_and_op!(__sync_fetch_and_umax_4, u32, |a: u32, b: u32| if a > b { + a +} else { + b +}); + +fetch_and_op!(__sync_fetch_and_min_1, i8, |a: i8, b: i8| if a < b { + a +} else { + b +}); +fetch_and_op!(__sync_fetch_and_min_2, i16, |a: i16, b: i16| if a < b { + a +} else { + b +}); +fetch_and_op!(__sync_fetch_and_min_4, i32, |a: i32, b: i32| if a < b { + a +} else { + b +}); + +fetch_and_op!(__sync_fetch_and_umin_1, u8, |a: u8, b: u8| if a < b { + a +} else { + b +}); +fetch_and_op!(__sync_fetch_and_umin_2, u16, |a: u16, b: u16| if a < b { + a +} else { + b +}); +fetch_and_op!(__sync_fetch_and_umin_4, u32, |a: u32, b: u32| if a < b { + a +} else { + b +}); + +// +// From the GCC docs, linked from the LLVM docs: +// +// > This built-in function, as described by Intel, is not a traditional +// > test-and-set operation, but rather an atomic exchange operation. It +// > writes value into *ptr, and returns the previous contents of *ptr. +// + +fetch_and_op!(__sync_lock_test_and_set_1, u8, |_: u8, new: u8| new); +fetch_and_op!(__sync_lock_test_and_set_2, u16, |_: u16, new: u16| new); +fetch_and_op!(__sync_lock_test_and_set_4, u32, |_: u32, new: u32| new); + +val_compare_and_swap!(__sync_val_compare_and_swap_1, u8); +val_compare_and_swap!(__sync_val_compare_and_swap_2, u16); +val_compare_and_swap!(__sync_val_compare_and_swap_4, u32); |
