ASM x86_64 AVX:xmm 和 ymm 寄存器差异

ASM x86_64 AVX: xmm and ymm registers differences

xmmymm 寄存器有什么区别? 我以为 xmm 是 SSE 的,ymm 是 AVX 的,但我写了一些代码:

vmovups     ymm1, [r9]      
vcvtss2si   rcx, ymm1

它给了我:

error: invalid combination of opcode and operands

关于线路:

vcvtss2si   rcx, ymm1

所以我写道:

vcvtss2si   rcx, xmm1

并且它按预期工作。 ymm1 向量的第一个值,转换为整数,现在在 rcx.

这是怎么回事? ymm1xmm1是同一个寄存器吗?

根据 wikipedia,在 AVX 中:

YMM 寄存器是 256 位 长。

XMM 寄存器的长度为 128 位,代表 YMM 寄存器的低 128 位

YMMXMM寄存器重叠,XMM包含在YMM中。

来自 wikimedia 的图表:

xmm0ymm0 的下半部分,就像 eaxrax 的下半部分一样。

写入 xmm0(使用 VEX 编码指令,而不是旧版 SSE)将 ymm0just like writing to eax zeros the upper half of rax to avoid false dependencies. Lack of zeroing the upper bytes for legacy SSE instructions is why there's a .

的上方通道归零

大多数 AVX 指令都具有 128 位或 256 位大小。例如vaddps xmm0, xmm1, xmm2vaddps ymm0, ymm1, ymm2。 (大多数整数指令的 256 位版本仅在 AVX2 中可用,而 AVX 仅提供 128 位版本。有几个例外,例如 AVX1 中的 vptest ymm, ymmvmovdqu 如果你算作为 "integer" 指令)。

vmovdvcvtss2sivcvtsi2ss 等标量指令仅适用于 XMM 寄存器。读取 YMM 寄存器在逻辑上与读取 XMM 寄存器没有区别,但是 写入 低元素(并保持其他元素不变,就像设计不佳的 vcvtsi2ss 那样)会XMM 与 YMM 不同,因为 YMM 版本会使上车道不归零。


但是带有 ymm 的标量在机器代码编码中不存在,即使对于像 vpinsrd / vpextrd 这样真正有用的指令(插入/提取一个标量)。

请注意,即使读取 XMM 寄存器并仅获取低标量元素在逻辑上与 YMM 相同,但对于实际实现而言,它 而不是 是相同的。读取 YMM 寄存器意味着 AVX-256 指令,它必须将 CPU 转换出 "saved upper" 状态(对于具有 SSE/AVX 转换/状态的 Intel CPU) .

在任何情况下,vcvtss2si rax, ymm0 都是不可编码的,assembler 不会像 vcvtss2si rax, xmm0 那样神奇地 assemble。如果你在用 asm 编写,你应该确切地知道你在做什么。 (虽然有些 assemble 会为你优化 mov rax, 1mov eax, 1,所以让你把 ymm 写成源寄存器是可行的。但是让你写 ymm 作为 vcvtsi2ss 的目标寄存器会改变含义,因此为了保持一致性,最好不要这样做。