【发布时间】:2018-11-27 00:24:28
【问题描述】:
我正在使用 Power9 并使用名为 DARN 的硬件随机数生成器指令。我有以下内联汇编:
uint64_t val;
__asm__ __volatile__ (
"xor 3,3,3 \n" // r3 = 0
"addi 4,3,-1 \n" // r4 = -1, failure
"1: \n"
".byte 0xe6, 0x05, 0x61, 0x7c \n" // r3 = darn 3, 1
"cmpd 3,4 \n" // r3 == -1?
"beq 1b \n" // retry on failure
"mr %0,3 \n" // val = r3
: "=g" (val) : : "r3", "r4", "cc"
);
我不得不添加mr %0,3 和"=g" (val),因为我无法让GCC 生成带有"=r3" (val) 的预期代码。另见Error: matching constraint not valid in output operand。
反汇编显示:
(gdb) b darn.cpp : 36
(gdb) r v
...
Breakpoint 1, DARN::GenerateBlock (this=<optimized out>,
output=0x7fffffffd990 "\b", size=0x100) at darn.cpp:77
77 DARN64(output+i*8);
Missing separate debuginfos, use: debuginfo-install glibc-2.17-222.el7.ppc64le libgcc-4.8.5-28.el7_5.1.ppc64le libstdc++-4.8.5-28.el7_5.1.ppc64le
(gdb) disass
Dump of assembler code for function DARN::GenerateBlock(unsigned char*, unsigned long):
...
0x00000000102442b0 <+48>: addi r10,r8,-8
0x00000000102442b4 <+52>: rldicl r10,r10,61,3
0x00000000102442b8 <+56>: addi r10,r10,1
0x00000000102442bc <+60>: mtctr r10
=> 0x00000000102442c0 <+64>: xor r3,r3,r3
0x00000000102442c4 <+68>: addi r4,r3,-1
0x00000000102442c8 <+72>: darn r3,1
0x00000000102442cc <+76>: cmpd r3,r4
0x00000000102442d0 <+80>: beq 0x102442c8 <DARN::GenerateBlock(unsigned char*, unsigned long)+72>
0x00000000102442d4 <+84>: mr r10,r3
0x00000000102442d8 <+88>: stdu r10,8(r9)
注意 GCC 忠实地再现了:
0x00000000102442d4 <+84>: mr r10,r3
0x00000000102442d8 <+88>: stdu r10,8(r9)
如何让 GCC 将两条指令折叠成:
0x00000000102442d8 <+84>: stdu r3,8(r9)
【问题讨论】:
-
你必须从你的内联汇编模板中去掉
mr,并告诉gcc你的输出在r3中。如有必要,在没有特定寄存器约束的平台上使用register int foo asm("r3");。 Gcc 将从不删除作为 asm 模板一部分的文本;除了替换%thing之外,它甚至不解析它。或者更好的是,不要硬编码注册号。使用支持DARN指令的汇编程序。 -
另外,
xor不是在 PowerPC 上将寄存器归零的有效方法。 PPC asm 等效于 C++11std::memory_order_consume的依赖规则要求它携带对输入寄存器的依赖。 xor-zeroing 仅适用于 x86,而不适用于固定指令宽度的 ISA。 -
谢谢彼得。 “或者更好......使用支持 DARN 指令的汇编程序” - 我明白你在说什么,但这几乎是不可能的。编译场上的 GCC135 是 Power9 和 2 个月大。它有 CentOS 7 和 GCC 4.8。编译器和汇编器比我们需要的支持落后了十年。 Clang 7.0 还有lacks support 我们需要。
-
关于 XOR 效率不高,您有什么建议?一个简单的
li 3, 0? -
是的,没错。这就是 gcc 为
int foo(){return 0;}godbolt.org/z/-gHI4C 所做的。 ARM 的相同交易:mov-immediate。
标签: gcc inline-assembly powerpc