【问题标题】:Error: matching constraint not valid in output operand错误:匹配约束在输出操作数中无效
【发布时间】:2019-04-28 00:26:54
【问题描述】:

我无法让 GCC 内联汇编器接受 Power9 的一些内联汇编。

我试图让 GCC 接受的常规程序集是darn 3, 1,其中3r31 是文档中称为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 Output Operands。我还检查了简单和机器约束,但没有看到。

如何告诉 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"
);

【问题讨论】:

标签: gcc inline-assembly powerpc altivec


【解决方案1】:

将我的(未经测试的)评论移至答案以尝试关闭它

我不熟悉 r3 作为输出约束。我猜这是为了表明输出将在 'r3' 寄存器中,但我认为你不能这样做(尽管我不是 powerpc 的machine constraints 专家)。相反,也许您可​​以尝试:

register uint64_t y asm("r3");

(即使y 成为local register variable)然后只使用“=r”作为约束?

【讨论】:

  • 谢谢大卫。我尝试了本地寄存器和指向本地寄存器的指针,但都没有奏效。两者都导致了程序段错误的疯狂写入。拆解显示发生了两家商店。这就是为什么我想让=r3 按预期工作(我认为这是不可能的)。
  • 查看godbolt 的输出,我看到 __builtin_darn 的结果与使用本地寄存器时看到的结果相同。如果有一个野指针,我不相信它来自这段代码。您是否删除了“额外的”__asm__ __volatile__ ("darn 3, 1");?该代码无效,因为它在不通知编译器的情况下覆盖了 r3。
猜你喜欢
  • 1970-01-01
  • 2016-08-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-08-02
  • 2017-03-03
  • 2017-03-06
  • 2022-10-06
相关资源
最近更新 更多