У меня проблемы с тем, чтобы встроенный ассемблер GCC мог принять некоторую встроенную сборку для Power9.
Обычная сборка, которую я пытаюсь заставить GCC принять, это darn 3, 1
, где 3
равно r3
и 1
- это параметр, называемый L
в документации.Он разбирается с этим на big-endian:
0: e6 05 61 7c darn r3,1
и на little-endian:
0: 7c 61 05 e6 darn r3,1
Из-за различных причин и проблем, в том числе старых компиляторов и компиляторов, которые претендуют на другоекомпиляторы, я хочу выдавать байтовые коды для инструкции.Моя тестовая программа:
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));
}
Компиляция приводит к следующему:
$ /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
Вот раздел руководства по сборке GCC, который должен охватывать его, но я не вижу его подробного объяснения: 6.45.2.3 Операнды вывода .Я также проверил простые и машинные ограничения, но не увидел его.
Как мне сказать GCC выполнить инструкцию, а затем переместить r3
в y
?
Мысделать то же самое на x86 с rdrand
.Работает без проблем на всех версиях GCC, начиная с 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"
);