I need to implement a small fragment of code in assembly for an 32 bit AVR (memory test testing RAM under the running C program, no other way to solve it), however I can't find any documentation on the AVR-32 specifics of inline assembler, and trial and error neither led me to success.
First thing: Does anyone know about any docs describing the AVR-32 specifics of inline ASM? (Particularly the input / output register specifications)
I managed to get to the point where I was able to write the inline fragment with automatic input / output register allocation, however a strange behavior prevents me to complete it. Take the following fragment of code:
int ret;
int ad0;
int ad1;
/* ... */
__asm__ volatile(
"mov r2, %0 \n\t"
"mov r3, %1 \n\t"
"mov %2, 0 \n\t"
: "=r"(ret)
: "r"(ad0), "r"(ad1)
: "r2", "r3"
);
Compiled with optimizations off using avr32-gcc it produces the following assembly output (-S
):
#APP
# 95 "svramt.c" 1
mov r2, r8
mov r3, r8
mov r9, 0
# 0 "" 2
#NO_APP
Notice how %0 and %1 mapped to the same register (r8). This seems to happen if an output register is present. To check whether I used inline assembly improperly here, I also tried X86 with the native gcc on the host:
int ret;
int ad0;
int ad1;
/* ... */
__asm__ volatile(
"mov %0, %%eax \n\t"
"mov %1, %%ebx \n\t"
"mov 0, %2, \n\t"
: "=r"(ret)
: "r"(ad0), "r"(ad1)
: "eax", "ebx"
);
This fragment compiles to:
#APP
# 7 "asmtest.c" 1
mov %esi, %eax
mov %edx, %ebx
mov 0, %ecx,
# 0 "" 2
#NO_APP
This is what I expected to happen with the AVR-32 counterpart, all inputs and outputs mapping to different registers.
I would have liked to work around the problem (if it is a bug in avr32-gcc) by specifying the registers directly (trying "=r8" and such as input / output specs), but it doesn't compile that way.
If there is no documentation, does anyone know where the register specs for inline asm could be found in (a "normal" x86 or ARM) GCC's source? It would worth a try, but GCC is a huge beast to wade through without any prior knowledge.
I don't believe I have enough karma to get this done with an ASM module (with near zero knowledge of AVR-32 assembly), and that would at least need the documentation of the calling convention anyway which I neither found so far...
EDIT: Further experimenting shown that using =&r
for output specifier seems to solve the register mapping problem. Why so, I am clueless (two inputs mapped to the same register). At least the thing may be tested since it now produces the intended assembly fragment.
Further research revealed this AVR 8 bit document which offers part of a solution by describing square brackets for providing names for the operands which names can be used in the assembly fragment. This eliminates probable ambiguity between which operand would map to which %n
specification in the fragment. (I couldn't see this syntax described in other documents, but works in avr32-gcc as well, so was useful)