I'm having trouble getting GCC inline assembler to accept some inline assembly for Power9.
The regular assembly I am trying to get GCC to accept is darn 3, 1
, where 3
is r3
and 1
is parameter called L
in the docs. It disassembles to this on big-endian:
0: e6 05 61 7c darn r3,1
And on little-endian:
0: 7c 61 05 e6 darn r3,1
Due to various reasons and problems, including old compilers and compilers that pretend to be other compilers, I want to issue byte codes for the instruction. My test program:
gcc112:~$ cat test.c
#include <stdint.h>
void random()
{
volatile uint64_t x = __builtin_darn();
__asm__ __volatile__ ("darn 3, 1");
uint64_t y;
__asm__ __volatile__ (".byte 0x7c, 0x61, 0x05, 0xe6 \n" : "=r3" (y));
}
Compiling it results in:
$ /opt/cfarm/gcc-latest/bin/gcc -mcpu=power9 -c test.c
test.c: In function 'random':
test.c:10:3: error: matching constraint not valid in output operand
__asm__ __volatile__ (".byte 0x7c, 0x61, 0x05, 0xe6 \n" : "=r3" (y));
^~~~~~~
test.c:10:3: error: matching constraint not valid in output operand
test.c:10:3: error: invalid lvalue in asm output 0
Here's the section of the GCC inline assembly manual that should cover it, but I don't see it expalined: 6.45.2.3 Output Operands. I also checked simple and machine constraints but did not see it.
How do I tell GCC to execute the instruction, and then move r3
into y
?
We do the same thing on x86 with rdrand
. It works without problems on all version of GCC going back to 2.9:
uint64_t temp;
__asm__ __volatile__
(
// radrand rax with retry
"1:\n"
".byte 0x48, 0x0f, 0xc7, 0xf0;\n"
"jnc 1b;\n"
: "=a" (temp)
: : "cc"
);