1

我在 xmm 寄存器中有一个浮点值,我必须对其进行一些整数运算。整数算术是指位操作,如移位或按位和/或/异或。在 C++ 中,我可以编写如下内容:

float x;
int& x_i = *reinterpret_cast<int*>(&x);
x_i &= 0x7f800000
x_i >>= 23;
x_i %= 2;
x_i <<= 23;

当使用 gcc 编译时,这会将 xmm0 中的值复制到堆栈上,然后将相同的值从堆栈加载到通用寄存器 (eax),在那里进行整数运算,最后复制 eax -> 堆栈 -> xmm。

我的问题是是否有一种方法可以在不通过堆栈的情况下执行所有这些操作。x86_64 是否有将 xmm0 的内容复制到 eax 或其他通用寄存器的指令?

编辑:问题本身在讨论期间发生了变化。最后有两点评论,其中我提到了英特尔 C++ Intrisics 参考的相应部分。

  1. 可以使用内在函数在通用寄存器和 XMM 寄存器之间移动数据(“Steaming SIMD Extensions -> Conversion Operations for Streaming SIMD Extensions”和“Steaming SIMD Extensions 2 -> Integer Intrinsics -> Integer Move Operations for Streaming SIMD Extensions 2”部分)

  2. 可以对 XMM 寄存器执行整数算术(例如位操作)操作(“Steaming SIMD Extensions 2 -> Integer Intrinsics”部分)

这两个主题对我来说都特别感兴趣。

4

1 回答 1

1

我很惊讶 gcc 完全涉及堆栈。至少对于 ELF (SysV) ABI,第一个浮点参数将通过 register in 传递%xmm0

如果我理解正确,您希望将浮点值移动到 32 位 GPR 以进行按位操作。您可以使用以下movd指令完成此操作:

movd %xmm0, %eax

在 C 中,您可以查看汇编输出:

#include <immintrin.h> /* or older: <xmmintrin.h> */
...
unsigned int x_i;
*((float *) & ret) = _mm_cvtss_f32(v0);

您显然会用 C++ reinterpret_cast 替换此转换。


写回 SSE 寄存器:movd %eax, %xmm0,它对 的第 32..127 位进行零扩展%xmm0

于 2013-06-16T06:17:29.183 回答