x64 ymm / SIMD /向量指令,其中ymm寄存器在寄存器中指定?

时间:2014-02-03 10:09:15

标签: assembly x86-64 simd

是否存在任何SIMD /向量寄存器指令,其中ymm寄存器是在通用寄存器(或SIMD寄存器)中指定的,而不是在指令本身中指定的?

基本上我要做的是编写一个函数,将任何一系列连续的ymm寄存器保存到本地帧上。这是一个想法,除了我发明了我认为我正在寻找的指令的半合理虚构语法。

.text
.align 64
funcname:
    orq         %rcx, %rcx                # is register count <= 0 ???
    jle         funcdone                  # # of registers to save is <= 0

    xorq        %rax, %rax                # rax = 0 == vector save element #

funcloop:
    vmovapd     %ymm(%rsi), (%rdi, %rax)  # save ymm?? to address rdi + rax
    addq        $32, %rax                 # each ymm vector is 32-bytes
    loop        funcloop                  # --rcx; if (rcx > 0) { goto funcloop }

funcdone:
    ret

vmovapd指令是执行我正在寻找的奇怪指令。我确信我从未见过看起来像这样的指令,但这并不意味着没有一些不寻常的指令可以做我需要做的事情。

或许说明看起来像其中之一:

    vmovapd     %rsi, (%rdi, %rax)
    vmovapd     (%rsi), (%rdi, %rax)

另一个替代方案是%rsi中的位0到15对应于向量寄存器ymm00ymm15,并且保存对应于最低设置位的寄存器(或所有“设置位” “ymm寄存器得到保存。”

BTW,对于我需要完成的事情,自修改代码不是一种选择。

2 个答案:

答案 0 :(得分:1)

当谈到“SIMD加载/存储”时,可能有两种不同的方法:

  • 执行“宽负载”,从同一地址的连续数据中填充多个向量寄存器
  • 进行“分散聚集”,将矢量成分填充到多个地址

ARM和/或m68k总是完成前者 - 这些平台上的“移动多个”操作码(ARM上为[v]ldm,m68k上为movem)允许指定枚举寄存器的掩码从给定地址的(连续)数据填充。

英特尔x86在其历史上从来没有这样,除了32位中的PUSHA / POPA,它将无条件地/不可屏蔽地将通用寄存器保存/恢复到堆栈中,并且指令在64位模式下退役。

英特尔与AVX一起创建了同时从多个地址加载的功能,即“分散 - 聚集”。

所以是的,x86取代了ARM上的东西,如:

VLDM.64 r0, {d1, d3, d5, d7}    ; load odd-numbered vector regs from mem @r0

将是一个序列:

VMOVAPD YMM1, [ RAX ]
VMOVAPD YMM3, [ RAX + 32 ]
VMOVAPD YMM5, [ RAX + 64 ]
VMOVAPD YMM7, [ RAX + 96 ]

另一方面,x86 VGATHER指令的ARM等效项(请参阅ARM docs, "indirect addressing"),如:

VGATHERDD YMM0, [ RAX + YMM1 ]   ; YMM1[0..8] has 32bit offsets on RAX

需要对向量寄存器的单个元素进行多次加载,最后使用“组合” - 或者子寄存器加载;它变成了一个序列:

VLD1.32 {d0}, [r0]                    ; r0..r3 have the [32bit] addresses
VLD1.32 {d1}, [r1]
VLD1.32 {d2}, [r2]
VLD1.32 {d3}, [r3]
VTBL d0, { d0 - d3 }, d4         ; d4 is [ 0, .., 7, ..., 15, ..., 31, ... ] 

答案 1 :(得分:1)

x86的状态保存说明(xsave / xrstor执行edx:eax中执行掩码以控制要保存/恢复的状态。它真的很复杂,而insn ref手册只是指向另一本手册的一个单独的部分。但是,如果您可以选择单个向量寄存器的级别,则为IDK。更可能的是&#34;所有16个向量寄存器的低位128&#34;但是ymm0-7与其余的分开,以避免在32位代码可以&#39;时保存/恢复ymm8-15。影响他们。

  

保存的特定状态组件对应于中设置的位   请求特征位图(RFBM),它是EDX:EAX的逻辑AND   和XCR0。

为了在功能序言/尾声中保存/恢复几个ymm regs,它不太可能有用。我没有调查过它。 xsavec执行&#34;压缩&#34;:CPU跟踪实际修改了哪些状态。

没有其他指令具有寄存器的额外间接级别(寄存器指定哪个寄存器)。对于无序机制来说,这将是一个很大的复杂因素。甚至ARM加载多指令(参见另一个答案)都将寄存器位掩码嵌入到指令中,因此在解码指令时可以使用它(而不是稍后填写)。

你可能会更好地使用你想要使用的任何矢量寄存器的明显存储/重新加载,但是在你正在设计的调用约定中调用保存。

请注意,未来对更宽向量的扩展意味着您最终只会将所选向量reg的低256b保留为调用保留,其中上面的位被破坏。 (归零与否,当被访者不接触他们时,而不是保存/恢复)。