diff --git a/rp2040-hal/Cargo.toml b/rp2040-hal/Cargo.toml index 293120799..aad5773dc 100644 --- a/rp2040-hal/Cargo.toml +++ b/rp2040-hal/Cargo.toml @@ -16,6 +16,7 @@ targets = ["thumbv6m-none-eabi"] # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] +compiler_builtins = { version = "0.1.104", features = ["weak-intrinsics"] } cortex-m = "0.7.2" embedded-hal = { version = "0.2.5", features = ["unproven"] } eh1_0_alpha = { package = "embedded-hal", version = "=1.0.0-rc.1", optional = true } diff --git a/rp2040-hal/src/intrinsics.rs b/rp2040-hal/src/intrinsics.rs index ca77da106..89ff1a43b 100644 --- a/rp2040-hal/src/intrinsics.rs +++ b/rp2040-hal/src/intrinsics.rs @@ -1,46 +1,46 @@ /// Generate a series of aliases for an intrinsic function. macro_rules! intrinsics_aliases { ( - extern $abi:tt fn $name:ident( $($argname:ident: $ty:ty),* ) -> $ret:ty, + extern $abi:tt fn $name:ident( $($argname:ident: $ty:ty),* ) $(-> $ret:ty)?, ) => {}; ( - unsafe extern $abi:tt fn $name:ident( $($argname:ident: $ty:ty),* ) -> $ret:ty, + unsafe extern $abi:tt fn $name:ident( $($argname:ident: $ty:ty),* ) $(-> $ret:ty)?, ) => {}; ( - extern $abi:tt fn $name:ident( $($argname:ident: $ty:ty),* ) -> $ret:ty, + extern $abi:tt fn $name:ident( $($argname:ident: $ty:ty),* ) $(-> $ret:ty)?, $alias:ident $($rest:ident)* ) => { #[cfg(all(target_arch = "arm", not(feature = "disable-intrinsics")))] mod $alias { #[no_mangle] - pub extern $abi fn $alias( $($argname: $ty),* ) -> $ret { + pub extern $abi fn $alias( $($argname: $ty),* ) $(-> $ret)? { super::$name($($argname),*) } } intrinsics_aliases! { - extern $abi fn $name( $($argname: $ty),* ) -> $ret, + extern $abi fn $name( $($argname: $ty),* ) $(-> $ret)?, $($rest)* } }; ( - unsafe extern $abi:tt fn $name:ident( $($argname:ident: $ty:ty),* ) -> $ret:ty, + unsafe extern $abi:tt fn $name:ident( $($argname:ident: $ty:ty),* ) $(-> $ret:ty)?, $alias:ident $($rest:ident)* ) => { #[cfg(all(target_arch = "arm", not(feature = "disable-intrinsics")))] mod $alias { #[no_mangle] - unsafe extern $abi fn $alias( $($argname: $ty),* ) -> $ret { + unsafe extern $abi fn $alias( $($argname: $ty),* ) $(-> $ret)? { super::$name($($argname),*) } } intrinsics_aliases! { - unsafe extern $abi fn $name( $($argname: $ty),* ) -> $ret, + unsafe extern $abi fn $name( $($argname: $ty),* ) $(-> $ret)?, $($rest)* } }; @@ -88,7 +88,7 @@ macro_rules! intrinsics { ( #[slower_than_default] $(#[$($attr:tt)*])* - extern $abi:tt fn $name:ident( $($argname:ident: $ty:ty),* ) -> $ret:ty { + extern $abi:tt fn $name:ident( $($argname:ident: $ty:ty),* ) $(-> $ret:ty)? { $($body:tt)* } @@ -97,7 +97,7 @@ macro_rules! intrinsics { // Not exported, but defined so the actual implementation is // considered used #[allow(dead_code)] - fn $name( $($argname: $ty),* ) -> $ret { + fn $name( $($argname: $ty),* ) $(-> $ret)? { $($body)* } @@ -107,7 +107,7 @@ macro_rules! intrinsics { ( #[bootrom_v2] $(#[$($attr:tt)*])* - extern $abi:tt fn $name:ident( $($argname:ident: $ty:ty),* ) -> $ret:ty { + extern $abi:tt fn $name:ident( $($argname:ident: $ty:ty),* ) $(-> $ret:ty)? { $($body:tt)* } @@ -117,14 +117,14 @@ macro_rules! intrinsics { // considered used #[cfg(not(feature = "rom-v2-intrinsics"))] #[allow(dead_code)] - fn $name( $($argname: $ty),* ) -> $ret { + fn $name( $($argname: $ty),* ) $(-> $ret)? { $($body)* } #[cfg(feature = "rom-v2-intrinsics")] intrinsics! { $(#[$($attr)*])* - extern $abi fn $name( $($argname: $ty),* ) -> $ret { + extern $abi fn $name( $($argname: $ty),* ) $(-> $ret)? { $($body)* } } @@ -135,7 +135,7 @@ macro_rules! intrinsics { ( #[alias = $($alias:ident),*] $(#[$($attr:tt)*])* - extern $abi:tt fn $name:ident( $($argname:ident: $ty:ty),* ) -> $ret:ty { + extern $abi:tt fn $name:ident( $($argname:ident: $ty:ty),* ) $(-> $ret:ty)? { $($body:tt)* } @@ -143,13 +143,13 @@ macro_rules! intrinsics { ) => { intrinsics! { $(#[$($attr)*])* - extern $abi fn $name( $($argname: $ty),* ) -> $ret { + extern $abi fn $name( $($argname: $ty),* ) $(-> $ret)? { $($body)* } } intrinsics_aliases! { - extern $abi fn $name( $($argname: $ty),* ) -> $ret, + extern $abi fn $name( $($argname: $ty),* ) $(-> $ret)?, $($alias) * } @@ -159,7 +159,7 @@ macro_rules! intrinsics { ( #[alias = $($alias:ident),*] $(#[$($attr:tt)*])* - unsafe extern $abi:tt fn $name:ident( $($argname:ident: $ty:ty),* ) -> $ret:ty { + unsafe extern $abi:tt fn $name:ident( $($argname:ident: $ty:ty),* ) $(-> $ret:ty)? { $($body:tt)* } @@ -167,13 +167,13 @@ macro_rules! intrinsics { ) => { intrinsics! { $(#[$($attr)*])* - unsafe extern $abi fn $name( $($argname: $ty),* ) -> $ret { + unsafe extern $abi fn $name( $($argname: $ty),* ) $(-> $ret)? { $($body)* } } intrinsics_aliases! { - unsafe extern $abi fn $name( $($argname: $ty),* ) -> $ret, + unsafe extern $abi fn $name( $($argname: $ty),* ) $(-> $ret)?, $($alias) * } @@ -183,7 +183,7 @@ macro_rules! intrinsics { ( #[aeabi = $($alias:ident),*] $(#[$($attr:tt)*])* - extern $abi:tt fn $name:ident( $($argname:ident: $ty:ty),* ) -> $ret:ty { + extern $abi:tt fn $name:ident( $($argname:ident: $ty:ty),* ) $(-> $ret:ty)? { $($body:tt)* } @@ -191,13 +191,13 @@ macro_rules! intrinsics { ) => { intrinsics! { $(#[$($attr)*])* - extern $abi fn $name( $($argname: $ty),* ) -> $ret { + extern $abi fn $name( $($argname: $ty),* ) $(-> $ret)? { $($body)* } } intrinsics_aliases! { - extern "aapcs" fn $name( $($argname: $ty),* ) -> $ret, + extern "aapcs" fn $name( $($argname: $ty),* ) $(-> $ret)?, $($alias) * } @@ -206,7 +206,7 @@ macro_rules! intrinsics { ( $(#[$($attr:tt)*])* - extern $abi:tt fn $name:ident( $($argname:ident: $ty:ty),* ) -> $ret:ty { + extern $abi:tt fn $name:ident( $($argname:ident: $ty:ty),* ) $(-> $ret:ty)? { $($body:tt)* } @@ -214,7 +214,7 @@ macro_rules! intrinsics { ) => { #[cfg(all(target_arch = "arm", not(feature = "disable-intrinsics")))] $(#[$($attr)*])* - extern $abi fn $name( $($argname: $ty),* ) -> $ret { + extern $abi fn $name( $($argname: $ty),* ) $(-> $ret)? { $($body)* } @@ -222,7 +222,7 @@ macro_rules! intrinsics { mod $name { #[no_mangle] $(#[$($attr)*])* - pub extern $abi fn $name( $($argname: $ty),* ) -> $ret { + pub extern $abi fn $name( $($argname: $ty),* ) $(-> $ret)? { super::$name($($argname),*) } } @@ -231,16 +231,39 @@ macro_rules! intrinsics { // considered used #[cfg(not(all(target_arch = "arm", not(feature = "disable-intrinsics"))))] #[allow(dead_code)] - fn $name( $($argname: $ty),* ) -> $ret { + fn $name( $($argname: $ty),* ) $(-> $ret)? { $($body)* } intrinsics!($($rest)*); }; + // Naked functions are special: we can't generate wrappers for them since + // they use a custom calling convention. ( + #[naked] $(#[$($attr:tt)*])* - unsafe extern $abi:tt fn $name:ident( $($argname:ident: $ty:ty),* ) -> $ret:ty { + unsafe extern $abi:tt fn $name:ident( $($argname:ident: $ty:ty),* ) $(-> $ret:ty)? { + $($body:tt)* + } + + $($rest:tt)* + ) => ( + mod $name { + #[naked] + $(#[$($attr)*])* + #[no_mangle] + pub unsafe extern $abi fn $name( $($argname: $ty),* ) $(-> $ret)? { + $($body)* + } + } + + intrinsics!($($rest)*); + ); + + ( + $(#[$($attr:tt)*])* + unsafe extern $abi:tt fn $name:ident( $($argname:ident: $ty:ty),* ) $(-> $ret:ty)? { $($body:tt)* } @@ -248,7 +271,7 @@ macro_rules! intrinsics { ) => { #[cfg(all(target_arch = "arm", not(feature = "disable-intrinsics")))] $(#[$($attr)*])* - unsafe extern $abi fn $name( $($argname: $ty),* ) -> $ret { + unsafe extern $abi fn $name( $($argname: $ty),* ) $(-> $ret)? { $($body)* } @@ -256,7 +279,7 @@ macro_rules! intrinsics { mod $name { #[no_mangle] $(#[$($attr)*])* - pub unsafe extern $abi fn $name( $($argname: $ty),* ) -> $ret { + pub unsafe extern $abi fn $name( $($argname: $ty),* ) $(-> $ret)? { super::$name($($argname),*) } } @@ -265,7 +288,7 @@ macro_rules! intrinsics { // considered used #[cfg(not(all(target_arch = "arm", not(feature = "disable-intrinsics"))))] #[allow(dead_code)] - unsafe fn $name( $($argname: $ty),* ) -> $ret { + unsafe fn $name( $($argname: $ty),* ) $(-> $ret)? { $($body)* } diff --git a/rp2040-hal/src/lib.rs b/rp2040-hal/src/lib.rs index 3f14385dc..fbb0bb894 100644 --- a/rp2040-hal/src/lib.rs +++ b/rp2040-hal/src/lib.rs @@ -37,6 +37,7 @@ #![warn(missing_docs)] #![no_std] +#![feature(naked_functions)] #[doc(hidden)] pub use paste; @@ -94,6 +95,7 @@ pub use sio::Sio; pub use spi::Spi; pub use timer::Timer; pub use watchdog::Watchdog; +extern crate compiler_builtins; // Re-export crates used in rp2040-hal's public API pub extern crate fugit; diff --git a/rp2040-hal/src/sio.rs b/rp2040-hal/src/sio.rs index ead75c858..c5df6ea43 100644 --- a/rp2040-hal/src/sio.rs +++ b/rp2040-hal/src/sio.rs @@ -278,29 +278,32 @@ core::arch::global_asm!( macro_rules! division_function { ( - $name:ident $($intrinsic:ident)* ( $argty:ty ) { + $name:ident $intrinsic:ident $intrinsic_alias:ident ( $argty:ty ) { $($begin:literal),+ } ) => { #[cfg(all(target_arch = "arm", not(feature = "disable-intrinsics")))] - core::arch::global_asm!( - // Mangle the name slightly, since this is a global symbol. - concat!(".global _rphal_", stringify!($name)), - concat!(".type _rphal_", stringify!($name), ", %function"), - ".align 2", - concat!("_rphal_", stringify!($name), ":"), - $( - concat!(".global ", stringify!($intrinsic)), - concat!(".type ", stringify!($intrinsic), ", %function"), - concat!(stringify!($intrinsic), ":"), - )* - - "hwdivider_head", - $($begin),+ , - "hwdivider_tail", - ); + intrinsics! { + #[naked] + unsafe extern "C" fn $intrinsic() { + core::arch::asm!( + "hwdivider_head", + $($begin),+ , + "hwdivider_tail", + options(noreturn) + ); + } + #[naked] + unsafe extern "C" fn $intrinsic_alias() { + core::arch::asm!( + "hwdivider_head", + $($begin),+ , + "hwdivider_tail", + options(noreturn) + ); + } + } - #[cfg(all(target_arch = "arm", feature = "disable-intrinsics"))] core::arch::global_asm!( // Mangle the name slightly, since this is a global symbol. concat!(".global _rphal_", stringify!($name)),