arm-elf-gcc optimizer thinks swi is basically a nop??
void foo (void)
{
struct something s;
s.randomArgument = 1;
asm volatile ("mov r0,%0" : : \
"r" (&s) : \
"r0", "r12", "r14", "cc");
asm volatile ("swi 13" : : );
}
If this is compiled with optimization-Os, s.randomArgument = 1 is
OMITTED and the software interrupt handler sees garbage inside structure
s. Why? I think it's because gcc doesn't know that swi is related to
branch/link. It thinks swi doesn't need the values to which s points
any more than a nop would, so why assign them in the first place?
The problem is cured by making s a volatile. But does anyone know if
there is a more elegant way to do this? I have been trying to hide the
swi's inside function-call wrappers so the code looks like it's calling
an ordinary routine. Using the volatile approach, I'd have to be sure
that structure addresses are always marked volatile if they're going to
be passed to a swi-based function (but not necessarily a normal
function) -- ugh.
I could just mark all structures that could ever possibly get passed to
an SWI as volatile at the typedef level but that causes other headaches
and optimization could suffer.
Thanks for any wisdom anyone might have on this!
--Bill

OK, I found a solution. It is awful to look at but all the other
permutations I tried failed either when unoptimized, when optimized, or
when gcc 4.1.0 itself crashed during compilation (!!!).
static inline int Do_SWI_9 (int arg1, struct something *arg2)
{
register long __res ;
asm volatile ("mov r0,%2\n\tmov r1,%3" : \
"=X" (*(char *)(long)arg1), "=X" (*(char *)(long)arg2) : \
"r" ((long)arg1), "r" ((long)arg2) : \
"r0", "r1");
asm volatile ("swi 9" : : :
"r0", "r12", "r14", "cc");
asm volatile ("mov %0, r0" : "=r" (__res) : );
return((int)__res);
}
The "=X" *(char *)(long)argx operands tell the compiler that argx points
to something that will be used, and this forces the optimizer to load
contents to the structure before calling Do_SWI_9, rather than optimize
them out in the mistaken belief that those contents are not used by
Do_SWI_9. The crazy casting makes sure this works even if argx happens
to be a char instead of a long or a pointer (in a more general case than
the example shown here).
When unoptimized, this creates some pretty awful code, as the compiler
loads the values of arg1 and arg2 twice before copying them into r0 and
r1; however when optimized it's better, not great, but better.
I tried all sorts of more elegant approaches, including assigning the
__res variable to r0 and indicating that the swi command wrote a result
to __res, but none of them worked. Believe it or not the above approach
was the only way I could get reliable compilation under both optimized
and unoptimized conditions.
Hope this helps somebody avoid the pain I just went through.
--Bill