Is it possible to rewrite or improve this function to not require volatile or a generic memory clobber in its inline assembly?
// do stuff with the input Foo structure and write the result to the
// output Bar structure.
static inline void MemFrob(const struct Foo* input, struct Bar* output) {
register const Foo* r0 asm("r0") = input;
register Bar* r1 asm("r1") = output;
__asm__ __volatile__(
"svc #0x0f0000 \n\t"
: "+r" (r0), "+r" (r1)
:
: "r2", "r3", "cc", "memory"
);
}
For this specific situation, the target platform is an ARM7 system, and the code is being compiled with GCC 5.3.0. The system call being performed has the same calling convention as a C function call. After some trial and error, I've arrived at the above which "works" but I am not yet confident that it is correct and will always work, subject to the whims and fancies of the optimizing compiler.
I'd like to be able to remove the "memory" clobber and tell GCC exactly which memory will be modified, but the GCC Extended Asm documentation discusses how to assign values to specific registers, and then memory constraints, but not if they both can be combined. As of now, removing the "memory" clobber from the above example can cause GCC to not use the output in proceeding code.
I'd also like to be able to remove the volatile in the cases where the output is not used. But as of now, removing volatile from the above example causes GCC to not emit the assembly at all.
Adding additional inline assembly to move the system call parameters into r0/r1 manually or un-inlining by moving the code to an external compilation unit are wasteful workarounds that I'd much rather avoid.
r0
andr1
. But since the optimizers can see that the variablesr0
andr1
are not used again after the asm before they go out of scope, the asm is discarded. – David Wohlferd