4
votes

I am trying to let the inline assembler copy some values into specific registers but it only complains. This is a short version of the code that will trigger the error:

asm("" :: "r0" (value));
asm("" :: "a1" (value));

Both lines will trigger:

Error: matching constraint references invalid operand number

So how do I specify the register to take directly? I know i could introduce names for the values and then copy them by my own but I would like to avoid this as this code would be shorter and more readable.

Why I am asking Currently I am working on some syscalls. I want to use a syscall macro like this:

#define SYSCALL0(NUMBER) asm("swi #" STRINGIFY(NUMBER));
#define SYSCALL1(NUMBER, A) asm("swi #" STRINGIFY(NUMBER) :: "r0"(A));
#define SYSCALL2(NUMBER, A, B) asm("swi #" STRINGIFY(NUMBER) :: "r0"(A), "r1"(B));
...

As you can see this fits neatly on on line. Of course I could do something like:

#define SYSCALL1(NUMBER, A) register type R0 asm("r0") = A;
                            SYSCALL0(NUMBER)

but then I would have to convert A to type to get no type errors or give type correctly everytime I use the macro in different functions.

1

1 Answers

2
votes

With GCC, there is a shortcut:

register long r0 asm ("r0");

Then r0 "aliases" that register.

Combine that with a statement expression, and you can even get r0 as a "return value".

#define SYSCALL1(NUMBER,A) ({\
  register long r0 asm("r0") = (long) (A); \
  asm("swi #" STRINGIFY(NUMBER) : "=r"(r0) : "r"(r0) : "memory"); \
  r0; })

(I have no idea if the clobber is legitimate or not, the uClibc syscall implementation has that though.)

See extended assembly and local reg vars.