The code in C is as follows:
asm volatile("msr " x2 ", %x0" : : "rZ"((u64)(input)));
How to do it in rust:
asm!("msr x2, {0}", in(reg) input); //Doesn't feel right
Not sure how to replace "%x0" and "rZ"
The code in C is as follows:
asm volatile("msr " x2 ", %x0" : : "rZ"((u64)(input)));
How to do it in rust:
asm!("msr x2, {0}", in(reg) input); //Doesn't feel right
Not sure how to replace "%x0" and "rZ"
The documentation is here: Inline assembly - The Rust Reference
What ISA are you targeting? It looks like it might be AArch64. But it isn't clear whether you want an mrs
or msr
instruction. mrs
expects the expression in the first operand so it can select a GPR, and msr
expects a system register in the first operand (not a GPR).
Doing my best to reconcile the conflicts in your code samples, maybe this example will be helpful:
Also, please use triple backticks to highlight code to clearly delimit: Forum Code Formatting and Syntax Highlighting
Thank you for your answer.
Whether " "rZ"((u64)(input)" and " in(reg) input)" are equivalent。
In my knowledge:" "r"((u64)(input)" and " in(reg) input)" are equivalent。
What does "rZ"((u64)(input)
mean?
According to the gcc manual:
'r'
:
A register operand is allowed provided that it is in a general register.
'Z'
:
Integer constant zero
Does that mean you want it to use the xzr
or wzr
register? If so, just specify it. If not, I cannot understand what you are trying to do.
i want to use xzr. so I need to write that : in(xzr) input ? the compilation cannot be successful.
Just specify the register you want if it's not supposed to be an input argument from a Rust variable.
asm!("msr SCTLR_EL1, xzr");
Thank you very much !
asm volatile("msr " x2 ", %x0" : : "rZ"((u64)(input))); Indicates that the reg and xzr registers are used.
When you list more than one possible location (for example, ‘"rZ"’), the compiler chooses the most efficient one based on the current context. That mean, When the input parameter is 0, xzr is used. When the input parameter is not 0, reg is used. Can it be achieved in rust?
Thank you, that additional context is helpful. This feature does not currently exist in Rust inline assembly. I don't know of any proposals or issues tracking this as a feature. Consider creating a feature request at Rust Internals.
You can get the effect with a macro:
macro_rules! set_msr {
(0) => {
::std::arch::asm!("msr SCTLR_EL1, xzr");
};
($value:expr) => {
::std::arch::asm!("msr SCTLR_EL1, {0:x}", in(reg) $value);
};
}
Using it with set_msr!(0)
outputs xzr
, and any other value is copied into a GPR.
Thank you very much. this will solve my problem
There is a new problem. If the input parameter is 0x00, $value:expr is matched.
(0) Whether all values can be matched
if let x = 0, set_msr(x), $value:expr is matched. It wasn't expected
(Please stop sending so many small replies, you can say multiple things within one post, like I’m doing here. These aren’t texts.)
Yes, that is intended behavior and not possible to fix. If a macro is called: set_msr!(x)
, all the macro sees is the token x
. The macro has no access to type information or the value of x
. Macros run before type checking is done.
You’ll have to restructure your code to call a literal set_msr!(0)
.
Add a branch matching 0x00
to the macro, like so:
macro_rules! set_msr {
(0) => {
::core::arch::asm!("msr SCTLR_EL1, xzr");
};
(0x00) => { set_msr{0} };
($value:expr) => {
::core::arch::asm!("msr SCTLR_EL1, {0:x}", in(reg) $value);
};
}
(No, macros can’t magically determine whether your given expression is equal to 0. If you really want, make a new macro[1])
macro_rules! set_msr_zero {
() => {
::core::arch::asm!("msr SCTLR_EL1, xzr");
}
}
↩︎I created a thread on IRLO for designing a real solution: Inline assembly constant zero optimizations - Rust Internals
The "best" thing you can do right now is duplicate the compiler's expression evaluation logic in a procedural macro. Declarative macros cannot do any kind of evaluation, which leads to multiple patterns like shown above.