assembly - 128 位值 - 从 XMM 寄存器到通用

标签 assembly x86 sse

我有几个与将 XMM 值移动到通用寄存器相关的问题。在 SO 上发现的所有问题都集中在相反的方面,即将 gp 寄存器中的值传输到 XMM。

  • 如何将 XMM 寄存器值(128 位)移动到两个 64 位通用寄存器?
    movq RAX XMM1 ; 0th bit to 63th bit
    mov? RCX XMM1 ; 64th bit to 127th bit
    
  • 同样,如何将 XMM 寄存器值(128 位)移动到四个 32 位通用寄存器?
    movd EAX XMM1 ; 0th bit to 31th bit
    mov? ECX XMM1 ; 32th bit to 63th bit
    
    mov? EDX XMM1 ; 64th bit to 95th bit
    mov? ESI XMM1 ; 96th bit to 127 bit
    
  • 最佳答案

    您不能将 XMM 寄存器的高位直接移动到通用寄存器中。
    您必须遵循两步过程,这可能涉及也可能不涉及内存往返或寄存器的销毁。

    在寄存器中 (SSE2)

    movq rax,xmm0       ;lower 64 bits
    movhlps xmm0,xmm0   ;move high 64 bits to low 64 bits.
    movq rbx,xmm0       ;high 64 bits.
    

    punpckhqdq xmm0,xmm0 是等效于 movhlps xmm0,xmm0 的 SSE2 整数.如果 xmm0 最后由整数指令而不是 FP 写入,则某些 CPU 可能会避免一两个周期的旁路延迟。

    通过内存 (SSE2)
    movdqu [mem],xmm0
    mov rax,[mem]
    mov rbx,[mem+8]
    

    慢,但不会破坏 xmm 寄存器 (SSE4.1)
    mov rax,xmm0
    pextrq rbx,xmm0,1        ;3 cycle latency on Ryzen! (and 2 uops)
    

    混合策略是可能的,例如存储到内存,movd/q e/rax,xmm0所以它很快就准备好了,然后重新加载更高的元素。 (不过,存储转发延迟并不比 ALU 差多少。)这为您提供了不同后端执行单元的 uops 平衡。当您需要大量小元素时,存储/重新加载尤其有用。 ( mov/movzx 加载到 32 位寄存器很便宜并且有 2 个时钟的吞吐量。)

    对于 32 位,代码类似:

    在寄存器中
    movd eax,xmm0
    psrldq xmm0,xmm0,4    ;shift 4 bytes to the right
    movd ebx,xmm0
    psrldq xmm0,xmm0,4    ; pshufd could copy-and-shuffle the original reg
    movd ecx,xmm0         ; not destroying the XMM and maybe creating some ILP
    psrlq xmm0,xmm0,4
    movd edx,xmm0
    

    通过内存
    movdqu [mem],xmm0
    mov eax,[mem]
    mov ebx,[mem+4]
    mov ecx,[mem+8]
    mov edx,[mem+12]
    

    不破坏 xmm 寄存器 (SSE4.1) (慢如 psrldq/pshufd 版本)
    movd eax,xmm0
    pextrd ebx,xmm0,1        ;3 cycle latency on Skylake!
    pextrd ecx,xmm0,2        ;also 2 uops: like a shuffle(port5) + movd(port0)
    pextrd edx,xmm0,3       
    

    64 位移位变体可以在 2 个周期内运行。 pextrq版本最少需要 4 个。对于 32 位,数字分别为 4 和 10。

    关于assembly - 128 位值 - 从 XMM 寄存器到通用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44018590/

    相关文章:

    debugging - mov eax, 大 fs :30h

    c - X86 32b 汇编 - 使用 atoll

    c - Websocket 数据揭露/多字节异或

    c++ - VC++ SSE 内在优化怪异

    visual-studio - Visual Studio 中的外部程序集文件

    c++ - 使用 Visual C++ 环境和 "Asm"关键字作为 Assembler IDE 的替代方案?

    c++ - 在 VS 中移动 [eax+4]

    visual-studio - Visual Studio 2017 上的简单汇编程序

    multithreading - memset 与绑定(bind)到每个物理内核的线程并行

    c - SSE 移位整数