Ошибка: ограничение соответствия недопустимо в выходном операнде - PullRequest
0 голосов
/ 26 ноября 2018

У меня проблемы с тем, чтобы встроенный ассемблер 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"
);

1 Ответ

0 голосов
/ 30 ноября 2018

Перемещение моего (непроверенного) комментария в ответ, чтобы попытаться закрыть это

Я не знаком с r3 как выходным ограничением.Я предполагаю, что это предназначено для указания того, что выходные данные будут в регистре 'r3', но я не думаю, что вы можете сделать это таким образом (хотя я не эксперт по машинным ограничениям powerpc ).Вместо этого, возможно, вы могли бы попробовать:

register uint64_t y asm("r3");

(то есть сделать y локальную переменную регистра ), а затем просто использовать "= r" в качестве ограничения?

...