I’m writing inline assembly statements using a GNU-based toolchain, and there are three instructions within the inline assembly to update a single bit of a system register. The steps will be:
- move(read) a system register to a general register
- ‘AND’ it with the variable value from C code
- move(write) back to the system register just read
in the instruction set I’m using, the inline assembly syntax is like this:
unsigned int OV_TMP = 0xffefffff;
asm volatile ( "mfsr %0, $PSW\n\t"
"and %0, %0, %1\n\t"
"mtsr %0, $PSW"
: : "r"(OV_TMP) : );
%1 is the register which I want to forward the value of OV_TMP into.
%0 is the problem for me, and my problem is :
How to write the inline assembly code once there is a register used internally and is not assigned from nor copy to the C variables in the C code?
The thing to consider here is that, from the compiler’s perspective, the register is assigned-to by the inline assembly, even if you don’t use it again later. That is, you’re generating the equivalent of:
The magic and/or more_magic steps cannot be moved or combined away because of the
volatile, so the compiler cannot simply delete the written-but-unused register.The
mfsrandmtsrlook like powerpc instructions to me, and I would probably do theandstep in C code (see footnote); but the following should generally work:Here the “=&r” constraint says that the output operand (
%0) is written before the input operand (%1) is read.Footnote: As far as I know (which is not very far, I’ve only ever done a tiny bit of ppc assembly) there’s no need to keep the
mfsrandmtsrinstructions a specific distance apart, unlike certain lock-step sequences on other processors. If so, I would write something more like this: