|
56 | 56 | //! *Import constants as `sym` operands*. Interestingly, the `#[export_name]`
|
57 | 57 | //! attributes can be used to give symbol names entirely comprised of numbers,
|
58 | 58 | //! and when such symbols are used in `sym` operands, they are indeed
|
59 |
| -//! interpreted as the intended numbers. The catch is that we have to specify |
| 59 | +//! interpreted as the intended numbers. A catch is that we have to specify |
60 | 60 | //! `#[export_name]` for each possible value (i.e., we can't easily cover the
|
61 |
| -//! whole range of `usize`). |
| 61 | +//! whole range of `usize`). Another catch is that the compiler enforces that |
| 62 | +//! unique symbol names are used in a whole compiled binary. To avoid the issues |
| 63 | +//! caused by this, the symbol names must augmented with crate-specific metadata |
| 64 | +//! (e.g., `#[export_name = "r3_port_riscv-1.2.3*/ 42 /*"]`). |
62 | 65 | use core::arch::asm;
|
| 66 | +use macro_find_and_replace::replace_token_sequence as replace; |
63 | 67 | use unstringify::unstringify;
|
64 | 68 |
|
65 | 69 | #[derive(Clone, Copy)]
|
@@ -148,11 +152,12 @@ macro_rules! define_set {
|
148 | 152 | (
|
149 | 153 | impl<Traits: super::ThreadingOptions> CsrSet<Traits> {}
|
150 | 154 |
|
| 155 | + #[substitute($S:tt $PRIV:ident => PRIV)] |
151 | 156 | $( #[$csrexpr_meta:meta] )*
|
152 | 157 | macro csrexpr {
|
153 | 158 | $(
|
154 | 159 | $( #[$const_meta:meta] )*
|
155 |
| - ($CONST:ident) => { $const_value:literal } |
| 160 | + ($CONST:ident) => { $($const_value:tt)* } |
156 | 161 | ),*
|
157 | 162 | $(,)?
|
158 | 163 | }
|
@@ -183,17 +188,21 @@ macro_rules! define_set {
|
183 | 188 |
|
184 | 189 | $(
|
185 | 190 | pub const $CONST: usize = {
|
186 |
| - #[allow(non_snake_case)] |
187 |
| - let PRIV = Self::PRIV; // provide a value for `{PRIV}` in `$const_value` |
188 |
| - unstringify!($const_value) |
| 191 | + // `unstringify!` is unable to expand `replace!`. Replace |
| 192 | + // `$PRIV` using a macro-by-example and then pass the |
| 193 | + // resultant tokens to `unstringify!`. |
| 194 | + macro m($$ $PRIV:tt) { unstringify!($($const_value)*) } |
| 195 | + m!("Self::PRIV") |
189 | 196 | };
|
190 | 197 | )*
|
191 | 198 | }
|
192 | 199 |
|
193 | 200 | $( #[$csrexpr_meta] )*
|
194 | 201 | pub(crate) macro csrexpr {
|
195 | 202 | $(
|
196 |
| - ($CONST) => { $const_value } |
| 203 | + // An eager-expanded string literal is expected in the output. |
| 204 | + // Use `replace!` and let `asm!` expand it. |
| 205 | + ($CONST) => { replace!([$$ $PRIV], ["(/*{PRIV}*/)"], $($const_value)*) } |
197 | 206 | ),*
|
198 | 207 | }
|
199 | 208 |
|
@@ -257,40 +266,42 @@ pub const XSTATUS_FS_1: usize = 1 << 14;
|
257 | 266 | pub const XCAUSE_INTERRUPT: usize = usize::MAX - usize::MAX / 2;
|
258 | 267 | pub const XCAUSE_EXCEPTIONCODE_MASK: usize = usize::MAX / 2;
|
259 | 268 |
|
| 269 | +#[macropol::macropol(concat = "concat!($parts_comma_sep)")] |
260 | 270 | define_set! {
|
261 | 271 | impl<Traits: super::ThreadingOptions> CsrSet<Traits> {
|
262 | 272 | /* `csrexpr!` is also exposed as `const`s here */
|
263 | 273 | }
|
264 | 274 |
|
| 275 | + #[substitute($PRIV => PRIV)] |
265 | 276 | /// Create an assembly expression that evaluates to a CSR number or value.
|
266 | 277 | /// Assumes the presence of an operand `PRIV = sym Traits::Priv::value`.
|
267 | 278 | macro csrexpr {
|
268 | 279 | // CSRs
|
269 |
| - (XSTATUS) => { "{PRIV} * 0x100" }, |
270 |
| - (XIE) => { "{PRIV} * 0x100 + 0x04" }, |
271 |
| - (XEPC) => { "{PRIV} * 0x100 + 0x41" }, |
272 |
| - (XCAUSE) => { "{PRIV} * 0x100 + 0x42" }, |
273 |
| - (XIP) => { "{PRIV} * 0x100 + 0x44" }, |
| 280 | + (XSTATUS) => { "$PRIV * 0x100" }, |
| 281 | + (XIE) => { "$PRIV * 0x100 + 0x04" }, |
| 282 | + (XEPC) => { "$PRIV * 0x100 + 0x41" }, |
| 283 | + (XCAUSE) => { "$PRIV * 0x100 + 0x42" }, |
| 284 | + (XIP) => { "$PRIV * 0x100 + 0x44" }, |
274 | 285 |
|
275 | 286 | // CSR values
|
276 | 287 | // Machine/Supervisor/... Interrupt Enable
|
277 |
| - (XSTATUS_XIE) => { "1 << ({PRIV})" }, |
| 288 | + (XSTATUS_XIE) => { "1 << 0 << $PRIV" }, |
278 | 289 | // Machine/Supervisor/... Previous Interrupt Enable
|
279 |
| - (XSTATUS_XPIE) => { "1 << ({PRIV} + 4)" }, |
| 290 | + (XSTATUS_XPIE) => { "1 << 4 << $PRIV" }, |
280 | 291 |
|
281 | 292 | /// Machine/Supervisor/... Software Interrupt Enable
|
282 |
| - (XIE_XSIE) => { "1 << ({PRIV})" }, |
| 293 | + (XIE_XSIE) => { "1 << 0 << $PRIV" }, |
283 | 294 | /// Machine/Supervisor/... Timer Interrupt Enable
|
284 |
| - (XIE_XTIE) => { "1 << ({PRIV} + 4)" }, |
| 295 | + (XIE_XTIE) => { "1 << 4 << $PRIV" }, |
285 | 296 | /// Machine/Supervisor/... External Interrupt Enable
|
286 |
| - (XIE_XEIE) => { "1 << ({PRIV} + 8)" }, |
| 297 | + (XIE_XEIE) => { "1 << 8 << $PRIV" }, |
287 | 298 |
|
288 | 299 | /// Machine/Supervisor/... Software Interrupt Pending
|
289 |
| - (XIP_XSIP) => { "1 << ({PRIV})" }, |
| 300 | + (XIP_XSIP) => { "1 << 0 << $PRIV" }, |
290 | 301 | /// Machine/Supervisor/... Timer Interrupt Pending
|
291 |
| - (XIP_XTIP) => { "1 << ({PRIV} + 4)" }, |
| 302 | + (XIP_XTIP) => { "1 << 4 << $PRIV" }, |
292 | 303 | /// Machine/Supervisor/... External Interrupt Pending
|
293 |
| - (XIP_XEIP) => { "1 << ({PRIV} + 8)" }, |
| 304 | + (XIP_XEIP) => { "1 << 8 << $PRIV" }, |
294 | 305 | }
|
295 | 306 |
|
296 | 307 | impl<Traits> CsrSetAccess for CsrSet<Traits> {
|
@@ -338,10 +349,11 @@ pub trait Num {
|
338 | 349 | /// `<NumTy<N> as Num>::value` has a symbol name `N`.
|
339 | 350 | pub struct NumTy<const N: usize>;
|
340 | 351 |
|
| 352 | +#[macropol::macropol] |
341 | 353 | seq_macro::seq!(N in 0..4 {
|
342 | 354 | #[doc(hidden)]
|
343 | 355 | impl Num for NumTy<N> {
|
344 |
| - #[export_name = stringify!(N)] |
| 356 | + #[export_name = r#"r3_port_riscv-${env!("CARGO_PKG_VERSION")}*/$&{N}/*"#] |
345 | 357 | fn value() {}
|
346 | 358 | }
|
347 | 359 | });
|
0 commit comments