【问题标题】:What does "matching constraint" in inline assembly mean?内联汇编中的“匹配约束”是什么意思?
【发布时间】:2013-09-03 09:52:13
【问题描述】:

当我尝试在 powerpc 架构上编译它们时,这个展台宏会导致警告。

#define INNERMUL asm( \
   " mullw    16,%3,%4       \n\t" \
   " mulhwu   17,%3,%4       \n\t" \
   " addc     16,16,%0       \n\t" \
   " addze    17,17          \n\t" \
   " lwz      18,%1          \n\t" \
   " addc     16,16,18       \n\t" \
   " addze    %0,17          \n\t" \
   " stw      16,%1          \n\t" \
:"=r"(cy),"=m"(_c[0]):"0"(cy),"r"(mu),"r"(tmpm[0]),"1"(_c[0]):"16", "17", "18","%cc"); ++tmpm;

#define PROPCARRY \
asm( \
   " lwz      16,%1         \n\t" \
   " addc     16,16,%0      \n\t" \
   " stw      16,%1         \n\t" \
   " xor      %0,%0,%0      \n\t" \
   " addze    %0,%0         \n\t" \
:"=r"(cy),"=m"(_c[0]):"0"(cy),"1"(_c[0]):"16","%cc");

在调用宏的每一行中,编译器都会收到以下警告:

../../src/math/mont.c:650: warning: matching constraint does not allow a register

任何人都可以告诉我这意味着什么,以及它以何种方式影响代码? 而且由于我真的不习惯汇编程序,也许有人可以帮助我,在我的情况下是什么特别导致警告?

我的系统是 32 位的 freeBSD 我正在使用 gcc4.8.2

编辑:

这里是对应的x86_64代码,在x86上执行编译没有问题:

#define INNERMUL \
asm( \
   "movq %5,%%rax \n\t" \
   "mulq %4       \n\t" \
   "addq %1,%%rax \n\t" \
   "adcq $0,%%rdx \n\t" \
   "addq %%rax,%0 \n\t" \
   "adcq $0,%%rdx \n\t" \
   "movq %%rdx,%1 \n\t" \
:"=g"(_c[LO]), "=r"(cy) \
:"0"(_c[LO]), "1"(cy), "r"(mu), "r"(*tmpm++) \
: "%rax", "%rdx", "%cc")

#define PROPCARRY \
asm( \
   "addq   %1,%0    \n\t" \
   "setb   %%al     \n\t" \
   "movzbq %%al,%1 \n\t" \
:"=g"(_c[LO]), "=r"(cy) \
:"0"(_c[LO]), "1"(cy) \
: "%rax", "%cc")

也许这可以更清楚地说明代码在 powerpc 上的行为应该是什么。

【问题讨论】:

  • 我不知道 PowerPC,但您要求参数 0 作为寄存器 - 是否所有使用 %0 作为操作数的操作都允许在该位置使用寄存器操作数?
  • @KerrekSB 如果是这种情况,他会收到汇编错误,而不是 C 警告。 C 编译器不会检查 asm 是否有意义。
  • 由于我做了很多 x86 汇编,我可以向你保证"%rax""%cc" 不是有效的clobber 标识符,编译器会直接忽略它们。正确的方法是"rax", "cc"
  • @Sergey L. 你确定吗?因为这段代码是 libtom 的一部分,如果它被忽略,mathlib 不应该运行。
  • 我不相信,我相信这是一个偶然“好”的错误。我在 gcc 扩展 asm 文档中的任何地方都找不到必须在 clobber 标识符前面加上 % 的前缀。这是 AT&T 汇编器特定的语法,gcc 支持各种汇编器语法。 Clobbers 向编译器指示您打算覆盖的那些寄存器,而这些寄存器是编译器无法知道的。但是正如我之前所说的,rax 是一个非常常用的寄存器,许多指令都隐含地使用它,所以很可能在使用该代码的任何地方,该部分并不重要。但这是猜测。

标签: c gcc freebsd inline-assembly powerpc


【解决方案1】:

在这两种情况下,您都有 cy_c[0] 作为输入/输出变量。您已正确地将它们指定为具有匹配约束的输出和输入。这可能是 PPC 特定的,因为 "1" 在扩展 asm(注册号)中具有模棱两可的含义,我自己只在 x86 上工作。

您可以通过使用"+" 输出量词而不是"=" 将变量指定为输入/输出变量一次来消除警告(以及可能与之相关的任何错误):

#define INNERMUL asm( \
   " mullw    16,%2,%3       \n\t" \
   " mulhwu   17,%2,%3       \n\t" \
   " addc     16,16,%0       \n\t" \
   " addze    17,17          \n\t" \
   " lwz      18,%1          \n\t" \
   " addc     16,16,18       \n\t" \
   " addze    %0,17          \n\t" \
   " stw      16,%1          \n\t" \
:"+r"(cy) \
,"+m"(_c[0]) \
:"r"(mu) \
,"r"(tmpm[0]) \
:"16", "17", "18","cc"); ++tmpm;

#define PROPCARRY \
asm( \
   " lwz      16,%1         \n\t" \
   " addc     16,16,%0      \n\t" \
   " stw      16,%1         \n\t" \
   " xor      %0,%0,%0      \n\t" \
   " addze    %0,%0         \n\t" \
:"+r"(cy) \
,"+m"(_c[0]) \
: \
:"16","cc");

编辑:来自 gcc 扩展 asm 手册:

扩展 asm 支持输入输出或读写操作数。使用约束字符“+”表示这样的操作数,并与输出操作数一起列出。

我也不确定"%cc" 是否是一个有效的clobber 标识符,通常你不会在前面加上"%"。在 x86 上,适当的标识符是 "cc"

【讨论】:

  • 这让我有点困惑,特别是你所说的关于 cc 的事情,所以看看我的 eddit,也许这让我们俩更清楚:)
  • @Zaibis "1" 不是 x86 的有效存储约束,因此编译器将其明确解释为匹配约束。适当的寄存器名称是r1rax。据我所知,PPC 寄存器只有数字标识符。在这种情况下,编译器将不知道如何解释 "1" 约束——因此是警告。我敢肯定,%cc 不是 x86 的有效破坏者。在 x86 扩展 asm 中,clobber 标识符从不以 % 为前缀。对于 PPC,我会假设相同,但我不确定,因为我这里没有 PPC 机器来测试。
  • 我刚刚尝试了将= 更改为+ 的提示,但警告仍然相同。
  • @Zaibis 您还必须从 asm 的输入部分中删除匹配的变量,请查看我的示例。
  • 当我这样做时,我得到mont.c:649: error:invalid 'asm': operand number out of range。所以它把警告变成了错误。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-10-24
  • 1970-01-01
  • 2015-12-27
  • 2010-12-12
  • 1970-01-01
  • 2011-04-23
  • 1970-01-01
相关资源
最近更新 更多