【问题标题】:Clang integrated assembler and "invalid operand for instruction"Clang 集成汇编器和“指令的无效操作数”
【发布时间】:2015-07-22 09:17:24
【问题描述】:

我们在默认配置中使用 Clang。在默认配置中,使用 Clang 的集成汇编器(而不是系统汇编器,如 GAS)。我无法确定以下问题的确切问题(并修复):

$ make
clang++ -DNDEBUG -g2 -O3 -Wall -fPIC -march=native -pipe -c gcm.cpp
...
gcm.cpp:676:3: error: invalid operand for instruction
                AS2(    movd    WORD_REG(di), xmm...
                ^
./cpu.h:221:20: note: expanded from macro 'AS2'
        #define AS2(x, y) GNU_AS2(x, y)
                          ^
./cpu.h:216:27: note: expanded from macro 'GNU_AS2'
        #define GNU_AS2(x, y) "\n\t" #x ", " #y ";"
                             ^
<inline asm>:110:12: note: instantiated into assembly here
        movd rdi, xmm0;
                  ^~~~~
gcm.cpp:685:3: error: invalid operand for instruction
                AS2(    movd    WORD_REG(di), xmm...
                ^
./cpu.h:221:20: note: expanded from macro 'AS2'
        #define AS2(x, y) GNU_AS2(x, y)
                          ^
./cpu.h:216:27: note: expanded from macro 'GNU_AS2'
        #define GNU_AS2(x, y) "\n\t" #x ", " #y ";"
                                 ^
<inline asm>:117:12: note: instantiated into assembly here
        movd rdi, xmm1;
                  ^~~~~

认为以上错误可能与Inline Assembly and Compatibility有关。但据我所知,rdi 是 64 位,xmm1 是 128 位,movd 指定了操作数大小,所以不存在兼容性问题。

上面的代码有什么问题?


您可以通过Crypto++ gcm.cpp Source File 在线检查源文件。如果你安装了 Clang,这个问题应该很容易复制:

git clone https://github.com/weidai11/cryptopp.git cryptopp-asm
cd cryptopp-asm
export CXX=clang++
make GAS210_OR_LATER=1 GAS219_OR_LATER=1 GAS219_OR_LATER=1

或者:

# Try to make just gcm.o
make GAS210_OR_LATER=1 GAS219_OR_LATER=1 GAS219_OR_LATER=1 gcm.o

奇怪的make 行是由于LLVM Bug 24200 - With integrated assembler enabled, failed to fetch version string of assembler

【问题讨论】:

  • 我没有看到 r/m64, xmm 在英特尔手册中被列为 MOVD 的有效操作数组合。您的意思是使用MOVQ(或edi 而不是rdi)?

标签: c assembly clang llvm inline-assembly


【解决方案1】:

r/m64, xmm 在英特尔的软件开发人员手册中未列为MOVD 指令的有效操作数组合。但是,支持以下两种形式:

MOVD r/m32, xmm
SSE2 Move doubleword from xmm register to r/m32.

MOVQ r/m64, xmm
SSE2 Move quadword from xmm register to r/m64.

这让我怀疑在为 64 位目标构建时,MOVD 指令需要是 MOVQ,或者 rdi 应该被 edi 替换(尽管这可能会影响其他部分依赖rdi的前32位的代码)。

【讨论】:

  • 谢谢迈克尔。今天确实是我清除所有这些 Clang 遗留问题的日子......看起来同样的几组问题正在反复出现......
  • @Peter - 原谅我的无知...你是说我需要在movq 之前将rdi 的高32 位设置为0?或者可能在movq 之后将xmm1 的高32 位设置为0?还是我可以放心忽略的操作性微量因素?
  • movd edi,xmm1 将清除 rdi 的高 32 位。
  • 是的,这意味着 32 位操作不依赖于寄存器的先前值(短的 dep 链对于乱序执行/寄存器重命名非常重要)。这也意味着您可以使用 32 位操作,然后在 64 位上下文中使用它。 (例如,作为地址的一部分:inc ecx / mov eax, [rdi + 4*rcx]
  • Michael, Peter - movq rdi, xmm0 没有编译(register %rdi 仅在 64 位模式下可用),所以它不是 movqmovd edi, xmm0 已编译,但程序未能通过自检......我现在可以尖叫......我将不得不继续努力:(
猜你喜欢
  • 1970-01-01
  • 2011-08-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-04-04
  • 1970-01-01
  • 2011-04-18
  • 2022-01-11
相关资源
最近更新 更多