How to pass variable value for asm macro in rust

Hi.

I am trying to implement an "Asm" instruction in rust as follows:
In instructions_lib.rs file i have:

pub fn rotate(result: u32, a: u32, imm_val: u32) -> u32 {
    mylib::rot!(4, result, a, (imm_val| 0xC0))
}

In myasm.rs file I have:

#[macro_export]
macro_rules! rot{ ($input:expr, $result:expr, $a:expr, $imm_val:expr) => {
        {
            let mut result: u32 = $result;
            unsafe {
                core::arch::asm!(concat!("rot p", stringify!($input), ", {}, {}, #", stringify!($imm_val)), inout(reg) result, in(reg) $a);
            }
            result
        }
    };
}

However when i do cargo run i get the following error:

note: instantiated into assembly here
 --> <inline asm>:1:19
  |
1 |     rot p4, r0, r1, #(imm_val| 0xC0)
  |                      ^

error: operand must be an immediate in the range [0,511]

This assembly function should take any input value from the user and then do the OR with 0xC0 and then pass the result value to the asm instruction but instead it is using the string. How can i solve this issue.

Thank you.

1 Like

You should probably replace stringify!($imm_val) with $imm_val.

The warning that you are ignoring is trying to point this out:

warning: unused variable: `imm_val`
  --> <source>:13:36
   |
13 | pub fn rotate(result: u32, a: u32, imm_val: u32) -> u32 {
   |                                    ^^^^^^^ help: if this is intentional, prefix it with an underscore: `_imm_val`
   |
   = note: `#[warn(unused_variables)]` on by default

You can't pass a runtime value as immediate. An immediate is by definition defined at compile time. (unless you use self-modifying code) You have to pass it as register and then use this register in the rot instruction.

if your imm_val is a constant and you can use nightly you could do it like this:

#![feature(asm_const)]

pub fn rotate<const imm: u32>(result: u32, a: u32) -> u32 {
    mylib::rot!(4, result, a, (imm | 0xC0))
}
#[macro_export]
macro_rules! rot{ ($input:expr, $result:expr, $a:expr, $imm_val:expr) => {
        {
            let mut result: u32 = $result;
            unsafe {
                core::arch::asm!(concat!("rot p", stringify!($input), ", {}, {}, #{}"), inout(reg) result, in(reg) $a, const $imm);
            }
            result
        }
    };

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.