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

标签 assembly x86 sse

如何拆分 128 位 xmm注册到两个 64 位四字?

我在 xmm1 中有一个非常大的数字并希望获得更高的四字到 r9和下四字到 r10 , 或 RAXRDX .
movlpdmovhpd仅适用于 reg 到 mem,反之亦然。

最佳答案

SSE2(x86-64 的基线)具有直接在 XMM 和整数寄存器之间移动数据的指令(无需在内存中弹跳)。向量的低元素很容易:MOVD or MOVQ .要提取更高的元素,您只需将您想要的元素打乱到向量的低元素。

SSE4.1 还为 16 位以外的大小添加了插入/提取(例如 PEXTRQ )。除了代码大小,它是 not actually faster than a separate shuffle and movq on any existing CPUs ,但这意味着您不需要任何额外的 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

PUNPCKHQDQ 是最有效的方法。即使在旧 CPU 上,对于小于 64 位的元素大小(如 65nm Core2(Merom/Conroe)),它也很快。见 my horizontal sum answer有关更多详细信息。 PUNPCKHQDQ 没有立即数操作数,而且只有 SSE2,所以它只有 4 个字节的代码大小。

要保留 xmm0 的原始值,请使用 pshufd与不同的目的地。或者就地交换高低半部分,或其他什么。

movlpd or movhpd ...



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

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

绝对喜欢pshufd对于这个一般。但是你可以使用 movhlps如果您正在针对 Core2 等特定 CPU 进行调优,其中 movhlps速度快且在整数域中运行,并且 pshufd是慢的。

关于assembly - 如何将 XMM 128 位寄存器拆分为两个 64 位整数寄存器?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41222574/

相关文章:

java - movzbl 如何与寄存器值 0xffffffffffffffff 交互?

assembly - E 和 R 前缀在英特尔 32 位和 64 位寄存器的名称中代表什么?

xcode - 在每个功能/每个代码块的基础上启用 SSE4 的正确方法?

c++ - 正确使用加载/存储

assembly - MOVDQA 和 MOVAPS x86 指令之间的区别?

assembly - 为什么逻辑右移和算术右移的移位范围是1-32

assembly - 设置和清除标志

c - 关于gcc编译的x86_64代码和C代码优化

c - 带有内联汇编段错误的程序,除非以函数调用为前缀

assembly - 在汇编中获取 _bss_start 时遇到问题