寄存器 X/Y/ZMM16-31 是如何编码的?

How Are Registers X/Y/ZMM16-31 Encoded?

据我了解,自从 AVX 以来,通过 3 字节 VEX 或 EVEX 前缀,您可以在 64 位模式下编码多达 32 XMM/YMM/ZMM 个寄存器,但是当通过英特尔手册查看事实时它告诉您这是可能的,但我找不到解释实际情况的部分。我只能看到一个扩展字段,它是 REX 反转字段,但除了 EVEX 前缀中用于编码掩码寄存器的特殊位置外,其他什么都看不到。

你可能需要 2 位才能对那么多寄存器进行编码。您是否必须以某种方式组合 VEX/EVEX 前缀内的 2 个倒置 REX 字段,或者这个过程是如何工作的?

xmm16..31(及其 ymm/zmm 等价物)是 AVX-512 的新特性,只能通过 EVEX 前缀 访问,其中 2 要添加到每个 ModRM 字段的额外位,以及另外 5 位作为第三个操作数的额外字段。

REX + legacy-SSE,以及 AVX1/2 编码的 VEX,只能访问 xmm/ymm0..15.

Wikipedia's EVEX article 有一个很好的 table 显示位的来源,我转录了一些:

Addr mode Bit 4 Bit 3 Bits [2:0] Register type
REG EVEX.R' EVEX.R ModRM.reg General Purpose, Vector
RM EVEX.X EVEX.B ModRM.r/m GPR, Vector
NDS/NDD EVEX.V' EVEX.v3 EVEX.v2v1v0 Vector
Base 0 EVEX.B SIB.base (or modrm) GPR
Index 0 EVEX.X SIB.index GPR

如果 R/M 操作数是向量寄存器而不是内存寻址模式,它使用 both X(索引)和 B(基)位作为额外寄存器号位。因为这意味着没有 SIB.index 字段也可能需要扩展到 select r8..r15.


在 REX 和 VEX 前缀中,当源操作数不是具有索引寻址模式的内存时,X 位将不被使用。 (https://wiki.osdev.org/X86-64_Instruction_Encoding#REX_prefix, but note in a register-number table earlier in that page showing X.Reg, ;该页面上令人困惑的选择)。

另请参阅 以获取使用 REX 前缀中的额外寄存器编号位的另一图表。