我该怎么做?如果结果将在e * x寄存器中,那将是最好的。
答案 0 :(得分:5)
您已经问了几个琐碎的问题,您可以通过查看C编译器如何做到这一点来回答这些问题。从那里,您可以查看它使用的说明,并决定您想要实际使用哪些。 (在libm中有大量不同的舍入函数,因此首先选择正确的舍入函数并不总是那么容易。)
使用-O3 -ffast-math
获取内联最简单的libm函数(因为它不必在NaN上设置errno
,或者像那样废话)。
无论如何,编译器输入和输出来自gcc 5.3 on the Godbolt Compiler Explorer:
#include <math.h>
int floor_double(double x) { return (int) floor(x); }
roundsd xmm0, xmm0, 9
cvttsd2si eax, xmm0
ret
int truncate_double(double x) { return (int)x; }
cvttsd2si eax, xmm0
ret
有关英特尔指令集参考手册pdf的链接,请参阅x86标记wiki。还有一个unofficial HTML version从PDF生成。
cvttsd2si
truncates towards zero,与trunc()
一样,而不是像floor()
function一样向-Infinity舍入。
这就是floor()
在该指令集可用时编译为SSE4.1 roundsd
的原因。 (否则它必须摆弄舍入模式,你可以通过删除或更改godbolt上的-march
选项来看到。)
还有转换说明的打包版本,例如CVTTPD2DQ`一次执行2。 (或AVX 4)。
答案 1 :(得分:0)
使用CVTTPD2DQ—Convert with Truncation Packed Double-Precision FP Values to Packed Dword Integers至地板双打。
CVTTPD2DQ
在XMM注册表中将两个double
发送到两个int
。
相应的 Intel C / C ++ Compiler Intrinsic 是
____m128i _mm_cvttpd_epi32(__m128d a)
要将结果放到GPR(通用寄存器),如EAX
,您可以使用以下说明:
CVTTPD2DQ xmm0, xmm1 ; XMM1 is the source of doubles
movd eax, xmm0 ; extracts int(0) from XMM0 to EAX
pextrd ecx, xmm0, 1 ; extracts int(1) from XMM0 to ECX