我在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的相应部分。可以使用内在函数在通用寄存器和XMM寄存器之间移动数据(“使用SIMD信息扩展 - &gt;流式SIMD扩展的转换操作”和“模拟SIMD扩展2 - &gt; Integer内在函数 - &gt;整数移动SIMD Extensions 2“)
可以在XMM寄存器上执行整数aritmetic(例如位操作)操作(“Steaming SIMD Extensions 2 - > Integer Intrinsics”部分
这两个主题对我来说都特别有用。
答案 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位进行零扩展。