x86-64 的 32 位立即数是否有内联汇编约束

问题描述 投票:0回答:1

x86-64 是否有类似于“i”约束的约束,但仅当操作数值适合 32 位有符号立即数时才匹配?

对于下面所示的函数,我希望 gcc 在操作数适合 32 位有符号立即数时使用

lock add mem, imm
,并且我希望它使用“r”约束并在立即数不适合时生成
mov r, imm; lock add mem, r
不适合。

v
是非常量值或适合有符号 32 位立即数的常量时,所示代码可以正常工作,但当与不适合有符号 32 位立即数的常量值一起使用时,gcc 会生成无效指令32 位立即数操作数。*

static inline void atomic_add(volatile unsigned long *m, unsigned long v) 
{
    asm volatile ("lock addq %1, %0" : "+m"(*m) : "ri"(v));
}

我尝试在约束中使用“n”而不是“i”,但它的工作原理似乎与“i”相同。 删除“i”约束在所有情况下都有效,但即使没有必要,它也会将立即数移至寄存器中。由于绝大多数用途都有适合 8 或 32 位的常量,因此我宁愿不使用该解决方案。

这是演示该问题的示例:https://godbolt.org/z/nPY46Kfdh

extern unsigned long  x;

unsigned long m(volatile unsigned long *v)
{
    atomic_add(v, 12ul);
    atomic_add(v, 12345ul);
    atomic_add(v, 123456789000ul);
    atomic_add(v, x);
    return *v;
}

* 这里有很多答案解释了为什么 add 指令中不允许使用 64 位立即数,因此不需要再解释为什么不支持它。

gcc x86-64 inline-assembly immediate-operand
1个回答
0
投票

将评论变成答案...

查看 x86 系列的机器限制(向下滚动 way、way),我们看到:

e    32-bit signed integer constant, or a symbolic reference known to fit that range (for immediate operands in sign-extending x86-64 instructions).

这似乎符合您的要求。

而且,Peter 和我似乎都属于“不要使用内联汇编”的思想流派。因此,只要有可能,我建议使用内在函数而不是 asm 块。在这种情况下,可能是 __atomic_fetch_add(m, v, __ATOMIC_SEQ_CST)

我知道您现在可能不想花时间重新设计整个项目以使用较新的原子函数,但从这个函数开始迁移可能是有意义的。特别是如果有一个包装器,您可以在其中放入新代码。

最后一个想法:我注意到你没有在 asm 中使用内存破坏器。根据您使用此例程的方式,您可能会在此处引入计时错误。您可能需要快速检查一下,以确保它按照您的预期进行。

© www.soinside.com 2019 - 2024. All rights reserved.