浮点上的整数算术

时间:2013-06-16 00:20:21

标签: assembly x86-64 sse cpu-registers

我在xmm寄存器中有一个浮点值,我还要做一些整数运算。通过整数运算,我的意思是位操作,如移位或逐位和/或/ xor。在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 - &gt;堆栈 - &gt; XMM。

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

编辑:问题本身在讨论中发生了变化。有两个最后的评论,我在这两个评论中都引用了Intel C++ Intrisics Reference的相应部分。

  1. 可以使用内在函数在通用寄存器和XMM寄存器之间移动数据(“使用SIMD信息扩展 - &gt;流式SIMD扩展的转换操作”和“模拟SIMD扩展2 - &gt; Integer内在函数 - &gt;整数移动SIMD Extensions 2“)

  2. 的操作
  3. 可以在XMM寄存器上执行整数aritmetic(例如位操作)操作(“Steaming SIMD Extensions 2 - > Integer Intrinsics”部分

  4. 这两个主题对我来说都特别有用。

1 个答案:

答案 0 :(得分:1)

我很惊讶gcc涉及堆栈。至少对于ELF(SysV)ABI,第一个浮点参数将通过%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,它对%xmm0的32..127位进行零扩展。