ASM x86_64 AVX:xmm 和 ymm 寄存器差异
ASM x86_64 AVX: xmm and ymm registers differences
xmm
和 ymm
寄存器有什么区别?
我以为 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
.
中
这是怎么回事? ymm1
和xmm1
是同一个寄存器吗?
根据 wikipedia,在 AVX 中:
YMM
寄存器是 256 位 长。
XMM
寄存器的长度为 128 位,代表 YMM
寄存器的低 128 位。
YMM
和XMM
寄存器重叠,XMM
包含在YMM
中。
来自 wikimedia 的图表:
xmm0
是 ymm0
的下半部分,就像 eax
是 rax
的下半部分一样。
写入 xmm0
(使用 VEX 编码指令,而不是旧版 SSE)将 ymm0
、just 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, xmm2
或 vaddps ymm0, ymm1, ymm2
。 (大多数整数指令的 256 位版本仅在 AVX2 中可用,而 AVX 仅提供 128 位版本。有几个例外,例如 AVX1 中的 vptest ymm, ymm
和 vmovdqu
如果你算作为 "integer" 指令)。
vmovd
、vcvtss2si
和 vcvtsi2ss
等标量指令仅适用于 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, 1
到 mov eax, 1
,所以让你把 ymm
写成源寄存器是可行的。但是让你写 ymm
作为 vcvtsi2ss
的目标寄存器会改变含义,因此为了保持一致性,最好不要这样做。
xmm
和 ymm
寄存器有什么区别?
我以为 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
.
这是怎么回事? ymm1
和xmm1
是同一个寄存器吗?
根据 wikipedia,在 AVX 中:
YMM
寄存器是 256 位 长。
XMM
寄存器的长度为 128 位,代表 YMM
寄存器的低 128 位。
YMM
和XMM
寄存器重叠,XMM
包含在YMM
中。
来自 wikimedia 的图表:
xmm0
是 ymm0
的下半部分,就像 eax
是 rax
的下半部分一样。
写入 xmm0
(使用 VEX 编码指令,而不是旧版 SSE)将 ymm0
、just 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, xmm2
或 vaddps ymm0, ymm1, ymm2
。 (大多数整数指令的 256 位版本仅在 AVX2 中可用,而 AVX 仅提供 128 位版本。有几个例外,例如 AVX1 中的 vptest ymm, ymm
和 vmovdqu
如果你算作为 "integer" 指令)。
vmovd
、vcvtss2si
和 vcvtsi2ss
等标量指令仅适用于 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, 1
到 mov eax, 1
,所以让你把 ymm
写成源寄存器是可行的。但是让你写 ymm
作为 vcvtsi2ss
的目标寄存器会改变含义,因此为了保持一致性,最好不要这样做。