将 xmm 寄存器移动到通用寄存器的 X86 操作码

X86 opcodes to move xmm register to general registers

将 xmm0 寄存器移动到 eax 和 edx 的短 x86 指令序列是什么?

你想要 xmm0 的哪些部分?

movd     eax, xmm0
pextrd   edx, xmm0, 1    ; SSE4.1

获取xmm0的低64位到edx:eax。如果您需要所有 4 个部分,请考虑存储到内存并重新加载:存储转发到加载比随机播放有更多的延迟但吞吐量更好(更少的总 uops),特别是如果您可以将它们用作内存源操作数而不仅仅是 mov.

(但是如果你想要一个水平和之类的东西,通常 do that with SIMD shufflespshufd / 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 更有效,即使它在英特尔 CPUs 上花费更多的微指令。 shld 在 AMD CPUs 上很慢,在 Zen 上是 8 微指令。 (https://uops.info/)

BMI2 rorx rdx, rax, 32 一种复制和移动的好方法,并且在所有支持它的 CPU 上都很有效。它当然会使 RDX 的高半部分可能不为零,但这没关系。

另一个选择是 movd/movq,如果您没有接近他们竞争的单个端口的吞吐量瓶颈。在大多数 CPU 上,它们实际上不能 运行 并行,因此 movd/movq 竞争一个端口仍然会花费第二个端口的延迟时间。在带有移动消除(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

有关指令集参考和其他内容,请参阅 标记 wiki。

有关使用说明的提示,请参阅 Agner Fog's excellent Optimizing Assembly guide