X86 操作码将 xmm 寄存器移动到通用寄存器
Posted
技术标签:
【中文标题】X86 操作码将 xmm 寄存器移动到通用寄存器【英文标题】:X86 opcodes to move xmm register to general registers 【发布时间】:2016-06-10 04:47:32 【问题描述】:将 xmm0 寄存器移动到 eax 和 edx 的短 x86 指令序列是什么?
【问题讨论】:
除非必要,否则不要在不同的域之间移动 【参考方案1】:你想要 xmm0 的哪些部分?
movd eax, xmm0
pextrd edx, xmm0, 1 ; SSE4.1
将 xmm0 的低 64 位获取到 edx:eax
。如果您需要所有 4 个部分,请考虑存储到内存并重新加载:存储转发到加载具有更多延迟,但比随机播放具有更好的吞吐量(总 uops 更少),特别是如果您可以将它们用作内存源操作数而不仅仅是 mov
。
(但是如果你想要一个水平和什么的,通常do that with SIMD shuffles像pshufd
/paddd
两次将4个元素减少到2然后到1。虽然movd eax, xmm0
/movdqa [esp], xmm0
存储和3个标量在这种情况下,add eax, [esp + 4/8/12]
实际上对于总 uops 或延迟来说还不错,不像标量 FP,其中延迟更高,并且无论如何您都希望在 XMM reg 中得到结果。)
在 64 位代码中,movq rax, xmm0
/ shld rdx, rax, 32
可能优于 pextrd
,并且不需要 SSE4.1。
更普通的mov rdx, rax
/ shr rdx, 32
可能比 SHLD 更有效,即使它在 Intel CPU 上花费更多微指令。 shld
在 AMD CPU 上很慢,在 Zen 上是 8 uops。 (https://uops.info/)
BMI2 rorx rdx, rax, 32
是一种复制和移位的好方法,并且在所有支持它的 CPU 上都很有效。当然,RDX 的高半部分可能不为零,但这很好。
另一个选择是movd
/movq
,如果您没有接近他们竞争的单个端口的吞吐量瓶颈。在大多数 CPU 上,它们实际上不能并行运行,因此 movd/movq 竞争一个端口仍然会花费第二个端口的延迟。在具有 mov-elimination(Zen 或 IvyBridge)的现代 CPU 上,零延迟的mov rdx, rax
更好。但这确实会使您在 EAX 和 EDX 中的值零扩展为 RAX 和 RDX。
movq rdx, xmm0
movd eax, xmm0 ; or schedule this first if you can use EAX right away
shr rdx, 32
请参阅x86 标签 wiki 以获取指令集参考和其他内容。
请参阅Agner Fog's excellent Optimizing Assembly guide,了解使用说明的提示。
【讨论】:
希望在 x86(32 位)上的 xmm0 中从 64 位双精度中获取位。 @tgiphil:好的,我猜的是低 64。你有什么理由不接受这个答案吗?您是否需要使用矢量移位或随机播放的 32 位 SSE2 版本来将第二个单词降到元素 0 以获得另一个movd
?
有什么方法可以在没有 SSE4.1 的 x86 上做到这一点?
@tgiphil: pshufd
+ movd
,或任何其他方便的随机播放将您想要的元素带到低 64 位或 32 位。以上是关于X86 操作码将 xmm 寄存器移动到通用寄存器的主要内容,如果未能解决你的问题,请参考以下文章