我想在 c99 代码库中引入一些汇编代码。我想使用 ARM CPU 的 UMULL 指令将 2 uint32_t 相乘,然后立即将结果转换为 uint64_t。
现在一个 uint64_t 需要 2 个寄存器,那么如何指定 asm 块的输出和约束呢?
我想在 c99 代码库中引入一些汇编代码。我想使用 ARM CPU 的 UMULL 指令将 2 uint32_t 相乘,然后立即将结果转换为 uint64_t。
现在一个 uint64_t 需要 2 个寄存器,那么如何指定 asm 块的输出和约束呢?
好问题!
以下代码输出您想要使用GCC -O
或更高版本的内容,而无需使用汇编程序:
uint32_t a, b; uint64_t c; ... c = (uint64_t)a * (uint64_t)b;或者如果你觉得你必须使用机器特定的 asm,你可以去:
uint32_t a, b; uint64_t c;asm ("umull %Q0, %R0, %1, %2" : "=r"(c) : "r"(a), "r"(b));
c
的寄存器名称是寄存器对的第一个,%Q 和 %R 挑选出该对的低位和高位 32 位寄存器。有关示例,请参见 gcc/config/arm/arm.md -> umulsidi3。
但是,如果您可以留在 C 语言中,那么优化器就有机会做更多事情,并且对您的程序的读者更友善。
该umull
指令将其结果生成到两个 32 位寄存器中。我建议用类似的东西明确地重新组装 64 位值:
/* assuming the 64-bit result was stored in "hi" (upper
half) and "lo" (lower half) */
uint64_t v = ((uint64_t)hi << 32) | (uint64_t)lo;
编译器优化器应该注意到左移是纯数据路由,结果代码应该没问题。可以肯定的是,只需用于-S
检查编译器输出。