如何拆分 128 位 xmm
注册到两个 64 位四字?
我在 xmm1
中有一个非常大的数字并希望获得更高的四字到 r9
和下四字到 r10
, 或 RAX
和 RDX
.movlpd
或 movhpd
仅适用于 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/