我们在默认配置中使用 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
指令的有效操作数组合。但是,支持以下两种形式:
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 集成汇编器和 "invalid operand for instruction",我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31558916/