Reference: GCC docs. A lot of the material here seems to have been written assuming that the inline assembly consists of a single instruction which reads inputs and then writes outputs (possibly overwriting inputs).
Inline assembler code for the memory management package uses the GNU extension of named operands, e.g., "%\[foo\]". We generally use the "&" constraint for output operands; otherwise, the compiler assumes that the output operands are set as the very last actions of the code, after all input operands have been used. In such a case the compiler may use the same register for an input operand and an output operand. Using "&" marks the output operand as "early clobber",i.e., the register is altered early on, perhaps before all the inputs have been used. Wiki Markup
We also use the trick of creating a register variable to use as an output only ("=") or input-output ("+") operand when we want the compiler to pick which register to use. Sometimes when we do that we want the compiler to avoid r0 because it can't be used as a base register. Then we use the "b" constraint instead of "r", where "b" means "register that can be a base register".
...
Code Block |
---|
register unsigned msr; asm volatile ( // Make sure that address translation is disabled. "mfmsr %[msr] \n\t" "rlwimi %[msr],%[zero],0,26,27 \n\t" // Clear translation bits (26-27) in the PPC405 MSR. "mtmsr %[msr] \n\t" // Perform a context sync since we need to wait for translation // to turn off. This will also purge any shadowed TLB entries // which must be done before we turn translation back on. "isync \n\t" // Clear the zone-protection and PID registers. "mtzpr %[zero] \n\t" "mtpid %[zero] \n\t" // Mark all TLB entries as invalid. "tlbia" : [msr]"=&r"(msr) : [zero]"r"(0) : "memory" ); |
...
*Example 2.* This code changes a specific memory location so it uses the "m" constraint; the compiler will replace "%\[saved]" in the instruction with the correct addressing mode, e.g., base + offset. Note that if necessary the compiler will generate extra code to load the value of "this" into a base register.
Code Block |
---|
register unsigned oldmsr; register unsigned newmsr; asm volatile ( // Save the exception-enabling bits of the current PPC405 MSR value. "mfmsr %[oldmsr] \n\t" "and %[newmsr],%[oldmsr],%[mask] \n\t" "stw %[newmsr],%[save] \n\t" // Reset those enabling bits in the MSR. "andc %[newmsr],%[oldmsr],%[mask] \n\t" "mtmsr %[newmsr] \n\t" // Perform a context sync since the MSR value may have changed. "isync" :[save]"=m"(this->mSavedExcBits), [oldmsr]"=&r"(oldmsr), [newmsr]"=&r"(newmsr) :[mask]"r"(ExceptionBitMask) : ); |
...