arm_sysregs/
aarch64.rs

1// SPDX-FileCopyrightText: Copyright The arm-sysregs Contributors.
2// SPDX-License-Identifier: MIT OR Apache-2.0
3
4/// Generates a public function named `read_$ident` to read the system register `$sysreg` as a value
5/// of type `$type`.
6///
7/// `safe` should only be specified for system registers which are indeed safe to read.
8#[cfg(not(any(test, feature = "fakes")))]
9#[macro_export]
10macro_rules! read_sysreg {
11    ($sysreg:ident : $asm_sysreg:ident, $type:ty, safe $(, $fake_sysregs:expr)?) => {
12        $crate::_paste::paste! {
13            #[doc = "Returns the value of the `"]
14            #[doc = stringify!($sysreg)]
15            #[doc = "` system register."]
16            #[inline(always)]
17            pub fn [< read_ $sysreg >]() -> $type {
18                let value;
19                // SAFETY: The macro call site's author (i.e. see below) has determined that it is
20                // always safe to read the given `$sysreg.`
21                unsafe {
22                    core::arch::asm!(
23                        concat!("mrs {value}, ", stringify!($asm_sysreg)),
24                        options(nomem, nostack, preserves_flags),
25                        value = out(reg) value,
26                    );
27                }
28                value
29            }
30        }
31    };
32    ($(#[$attributes:meta])* $sysreg:ident : $asm_sysreg:ident, $type:ty $(, $fake_sysregs:expr)?) => {
33        $crate::_paste::paste! {
34            #[doc = "Returns the value of the `"]
35            #[doc = stringify!($sysreg)]
36            #[doc = "` system register."]
37            $(#[$attributes])*
38            #[inline(always)]
39            pub unsafe fn [< read_ $sysreg >]() -> $type {
40                let value;
41                // SAFETY: The caller promises that it is safe to read the given `$sysreg`.
42                unsafe {
43                    core::arch::asm!(
44                        concat!("mrs {value}, ", stringify!($asm_sysreg)),
45                        options(nomem, nostack, preserves_flags),
46                        value = out(reg) value,
47                    );
48                }
49                value
50            }
51        }
52    };
53    ($sysreg:ident : $asm_sysreg:ident, $type:ty : $bitflags_type:ty, safe $(, $fake_sysregs:expr)?) => {
54        $crate::_paste::paste! {
55            #[doc = "Returns the value of the `"]
56            #[doc = stringify!($sysreg)]
57            #[doc = "` system register."]
58            #[inline(always)]
59            pub fn [< read_ $sysreg >]() -> $bitflags_type {
60                let value: $type;
61                // SAFETY: The macro call site's author (i.e. see below) has determined that it is
62                // always safe to read the given `$sysreg.`
63                unsafe {
64                    core::arch::asm!(
65                        concat!("mrs {value}, ", stringify!($asm_sysreg)),
66                        options(nomem, nostack, preserves_flags),
67                        value = out(reg) value,
68                    );
69                }
70                <$bitflags_type>::from_bits_retain(value)
71            }
72        }
73    };
74    ($(#[$attributes:meta])* $sysreg:ident : $asm_sysreg:ident, $type:ty : $bitflags_type:ty $(, $fake_sysregs:expr)?) => {
75        $crate::_paste::paste! {
76            #[doc = "Returns the value of the `"]
77            #[doc = stringify!($sysreg)]
78            #[doc = "` system register."]
79            $(#[$attributes])*
80            #[inline(always)]
81            pub unsafe fn [< read_ $sysreg >]() -> $bitflags_type {
82                let value: $type;
83                // SAFETY: The caller promises that it is safe to read the given `$sysreg`.
84                unsafe {
85                    core::arch::asm!(
86                        concat!("mrs {value}, ", stringify!($asm_sysreg)),
87                        options(nomem, nostack, preserves_flags),
88                        value = out(reg) value,
89                    );
90                }
91                <$bitflags_type>::from_bits_retain(value)
92            }
93        }
94    };
95    ($sysreg:ident, $type:ty, safe $(, $fake_sysregs:expr)?) => {
96        $crate::read_sysreg!($sysreg : $sysreg, $type, safe $(, $fake_sysregs)?);
97    };
98    ($(#[$attributes:meta])* $sysreg:ident, $type:ty $(, $fake_sysregs:expr)?) => {
99        $crate::read_sysreg!($(#[$attributes])* $sysreg : $sysreg, $type $(, $fake_sysregs)?);
100    };
101    ($sysreg:ident, $type:ty : $bitflags_type:ty, safe $(, $fake_sysregs:expr)?) => {
102        $crate::read_sysreg!($sysreg : $sysreg, $type : $bitflags_type, safe $(, $fake_sysregs)?);
103    };
104    ($(#[$attributes:meta])* $sysreg:ident, $type:ty : $bitflags_type:ty $(, $fake_sysregs:expr)?) => {
105        $crate::read_sysreg($(#[$attributes])* $sysreg : $sysreg, $type : $bitflags_type $(, $fake_sysregs)?);
106    };
107}
108
109/// Generates a public function named `write_$sysreg` to write a value of type `$type` to the system
110/// register `$sysreg`.
111///
112/// `safe` should only be specified for system registers which are indeed safe to write any value
113/// to.
114#[cfg(not(any(test, feature = "fakes")))]
115#[macro_export]
116macro_rules! write_sysreg {
117    ($sysreg:ident : $asm_sysreg:ident, $type:ty, safe $(, $fake_sysregs:expr)?) => {
118        $crate::_paste::paste! {
119            #[doc = "Writes `value` to the `"]
120            #[doc = stringify!($sysreg)]
121            #[doc = "` system register."]
122            #[inline(always)]
123            pub fn [< write_ $sysreg >](value: $type) {
124                // SAFETY: The macro call site's author (i.e. see below) has determined that it is safe
125                // to write any value to the given `$sysreg.`
126                unsafe {
127                    core::arch::asm!(
128                        concat!("msr ", stringify!($asm_sysreg), ", {value}"),
129                        options(nomem, nostack, preserves_flags),
130                        value = in(reg) value,
131                    );
132                }
133            }
134        }
135    };
136    (
137        $(#[$attributes:meta])*
138        $sysreg:ident : $asm_sysreg:ident, $type:ty $(, $fake_sysregs:expr)?
139    ) => {
140        $crate::_paste::paste! {
141            #[doc = "Writes `value` to the `"]
142            #[doc = stringify!($sysreg)]
143            #[doc = "` system register."]
144            $(#[$attributes])*
145            #[inline(always)]
146            pub unsafe fn [< write_ $sysreg >](value: $type) {
147                // SAFETY: The caller promises that it is safe to write `value` to the given `$sysreg`.
148                unsafe {
149                    core::arch::asm!(
150                        concat!("msr ", stringify!($asm_sysreg), ", {value}"),
151                        options(nostack, preserves_flags),
152                        value = in(reg) value,
153                    );
154                }
155            }
156        }
157    };
158    ($sysreg:ident : $asm_sysreg:ident, $type:ty : $bitflags_type:ty, safe $(, $fake_sysregs:expr)?) => {
159        $crate::_paste::paste! {
160            #[doc = "Writes `value` to the `"]
161            #[doc = stringify!($sysreg)]
162            #[doc = "` system register."]
163            #[inline(always)]
164            pub fn [< write_ $sysreg >](value: $bitflags_type) {
165                let value: $type = value.bits();
166                // SAFETY: The macro call site's author (i.e. see below) has determined that it is safe
167                // to write any value to the given `$sysreg.`
168                unsafe {
169                    core::arch::asm!(
170                        concat!("msr ", stringify!($asm_sysreg), ", {value}"),
171                        options(nomem, nostack, preserves_flags),
172                        value = in(reg) value,
173                    );
174                }
175            }
176        }
177    };
178    (
179        $(#[$attributes:meta])*
180        $sysreg:ident : $asm_sysreg:ident, $type:ty : $bitflags_type:ty $(, $fake_sysregs:expr)?
181    ) => {
182        $crate::_paste::paste! {
183            #[doc = "Writes `value` to the `"]
184            #[doc = stringify!($sysreg)]
185            #[doc = "` system register."]
186            $(#[$attributes])*
187            #[inline(always)]
188            pub unsafe fn [< write_ $sysreg >](value: $bitflags_type) {
189                let value: $type = value.bits();
190                // SAFETY: The caller promises that it is safe to write `value` to the given `$sysreg`.
191                unsafe {
192                    core::arch::asm!(
193                        concat!("msr ", stringify!($asm_sysreg), ", {value}"),
194                        options(nostack, preserves_flags),
195                        value = in(reg) value,
196                    );
197                }
198            }
199        }
200    };
201    ($sysreg:ident, $type:ty, safe $(, $fake_sysregs:expr)?) => {
202        $crate::write_sysreg!($sysreg : $sysreg, $type, safe $(, $fake_sysregs)?);
203    };
204    (
205        $(#[$attributes:meta])*
206        $sysreg:ident, $type:ty $(, $fake_sysregs:expr)?
207    ) => {
208        $crate::write_sysreg!($(#[$attributes])* $sysreg : $sysreg, $type $(, $fake_sysregs)?);
209    };
210    ($sysreg:ident, $type:ty : $bitflags_type:ty, safe $(, $fake_sysregs:expr)?) => {
211        $crate::write_sysreg!($sysreg : $sysreg, $type : $bitflags_type, safe $(, $fake_sysregs)?);
212    };
213    (
214        $(#[$attributes:meta])*
215        $sysreg:ident, $type:ty : $bitflags_type:ty $(, $fake_sysregs:expr)?
216    ) => {
217        $crate::write_sysreg!($(#[$attributes])* $sysreg : $sysreg, $type : $bitflags_type $(, $fake_sysregs)?);
218    };
219}