如何将XMM 128位寄存器拆分为两个64位整数寄存器?

Mat*_*ias 6 x86 assembly sse

如何将128位xmm寄存器拆分为两个64位quadwords?

我输入的字数非常多xmm1,想要将较高的四字r9和较低的四字输入r10,或RAXRDX

movlpdmovhpd仅与reg到mem兼容,反之亦然。

Pet*_*des 5

SSE2(x86-64的基准)具有用于在XMM和整数寄存器之间直接移动数据的指令(不通过内存反弹)。向量的低位元素很容易:MOVD或MOVQ。要提取较高的元素,您可以将所需的元素洗牌到向量的较低元素。

SSE4.1还为16位以外的大小(例如PEXTRQ)添加了插入/提取。除了代码大小,它实际上没有比任何现有CPU上单独的shuffle和movq更快的速度,但这意味着您不需要任何额外的tmp寄存器。

#SSE4.1
movq    rax, xmm0       # low qword
pextrq  rdx,  xmm0, 1   # high qword
# 128b result in rdx:rax, ready for use with div r64 for example.
# (But watch out for #DE on overflow)
# also ready for returning as a __int128_t in the SystemV x86-64 ABI

#SSE2
movq       r10, xmm0
punpckhqdq xmm0, xmm0    # broadcast the high half of xmm0 to both halves
movq       r9,  xmm0
Run Code Online (Sandbox Code Playgroud)

PUNPCKHQDQ是执行此操作的最有效方法。即使是在元素大小小于64位的较慢CPU(如65nm Core2(Merom / Conroe))上进行慢速混洗的情况下,它的速度也很快。有关更多详细信息,请参见我的水平总和答案。PUNPCKHQDQ没有立即数,并且只有SSE2,因此它只有4个字节的代码大小。

要保留xmm0的原始值,请pshufd与其他目标一起使用。或就地交换上下半部分,或进行其他操作。


movlpd或movhpd ...

使用它们毫无意义。请改用movlps / movhps,因为它们较短,并且没有CPU关心float与double。

您可以用来movhlps xmm1, xmm0将xmm0的高半部分提取到另一个寄存器中,但是将FP shuffle与整数矢量操作混合会导致某些CPU(特别是Intel Nehalem)的旁路延迟。还要注意对xmm1的依赖性,这会导致延迟瓶颈。

pshufd总的来说,绝对喜欢这个。但是,movhlps如果要针对特定​​的CPU(例如Core2)进行调优,则可以使用该CPU,movhlps它的速度快且在整数域中运行,而pshufd速度慢。