在编码 VEX 指令时,NDS、NDD 和 DDS 代表什么?

Mat*_*ley 5 x86 assembly x86-64 intel machine-code

来自Intel 的 x86 手册,第 2 卷,第 3.1.1.2 节:指令汇总表中的操作码列(带有 VEX 前缀的指令)

NDSNDDDDS:指定 VEX.vvvv 字段对于寄存器操作数的编码有效:

  • VEX.NDS:VEX.vvvv 以指令语法对第一个源寄存器进行编码,其中源寄存器的内容将被保留。
  • VEX.NDD:VEX.vvvv 对 ModR/M:reg 字段无法编码的目标寄存器进行编码。
  • VEX.DDS:VEX.vvvv 以三操作数指令语法对第二个源寄存器进行编码,其中第一个源寄存器的内容将被结果覆盖。

我认为这与“非破坏性来源”有关,我认为这就是 NDS 所代表的意思。其他代表什么?这如何影响指令的编码?同样,为什么它们很重要 - 因为据我所知,AMD 手册不包含任何对这些术语的参考?

Pet*_*des 4

根据 Intel APX 文档(高级性能扩展:用于传统整数指令的 REX2 和 EVEX sub,最​​后setcc写入完整 32/64 位寄存器的编码:Intel APX 架构规范 - 2023 年 7 月修订版 1.0):

\n
    \n
  • NDD代表新数据目的地
  • \n
  • NDS代表无损源
  • \n
  • 该文档中未提及 DDS
  • \n
\n

据推测,2018 年之前的 SDM 版本对首字母缩略词使用了相同的扩展。

\n
\n

我没有看过 AMD 手册,但我假设他们选择了其他方式来指示哪个操作数是由VEX.vvvv,以供使用它的指令使用。

\n

Intel 使用此表示法来提醒您/明确哪个操作数是 vvvv 字段。它已经是多余的,因为每个指令的“操作数编码”表显示了哪个操作数被编码在哪个字段中。

\n
\n

更新:英特尔可能在 2018 年 11 月更新中将它们从手册中删除。它们也被从“未来扩展”手册中删除,该手册的指令列表与第 2 卷手册的格式相同,并且有一个修订表,其中提供了此变更日志:

\n
\n

从说明中删除 NDD/DDS/NDS 术语。注意: 以前,\n术语 NDS、NDD 和 DDS 在带有 EVEX(或 VEX)前缀的指令中使用。这些术语表明 vvvv 字段对于编码\n有效,并指定了寄存器用法。这些术语不再是必需的,并且对于每条指令提供的指令操作数编码表来说是多余的。指令操作数编码表给出了所有操作数的明确详细信息,表明每个操作数的存储位置以及它们是否被读取或写入。如果 vvvv 未在指令操作数编码表中列为操作数,则 EVEX(或 VEX)vvvv 必须为 0b1111。

\n
\n

这告诉我们,这些 NDD/DDS/NDS 标签的目的是指示哪个操作数是哪个操作数,以及它们是读还是写。

\n
\n

非破坏性源是本手册同一卷其他地方使用的一个短语(见下文),因此我非常有信心这是对NDS.

\n

我认为最明显的解释NDD是非破坏性目标(SSE2 版本的转变令人烦恼地具有破坏性)。

\n

目前尚不清楚DDS应该代表什么。“破坏性目标-源”不适合,因为它是被覆盖的另一个源注册表。

\n
\n

Intel 手册第 2卷第 2.3.5 节 VEX 前缀:

\n
\n

VEX 前缀的位字段可以按其功能用途进行总结:

\n
\n
\n
    \n
  • 非破坏性源寄存器编码(适用于三操作数和四操作数语法):这是指令语法中的第一个源操作数。VEX.vvvv。
  • \n
\n
\n

(反转:xmm0 为 1111,xmm15 为 0000。如下所述,反转避免与仅 32 位LESLDS(加载远指针)指令的有效编码重叠。32 位模式只能使用 xmm0-7,因此第一位始终是所需的 1,使其不是有效的LES/ LDS。)

\n

所以,是的,“非破坏性来源”是英特尔手册中使用的一个短语。

\n
\n

第 2.3.6 节:指令操作数编码和 VEX.vvvv、ModR/M

\n
\n

一些VEX编码指令具有少于三个操作数的语法,例如VEX编码的包移位指令支持一个源操作数和一个目标操作数。

\n

VEX.vvvv、ModR/M 字节的 reg 字段 (ModR/M.reg)、ModR/M 字节的 r/m 字段 (ModR/Mr/m) 相对于编码目标和源操作数的作用因不同而异指令语法类型。

\n

VEX.vvvv的作用可以概括为三种情况:

\n
    \n
  • VEX.vvvv 对第一个源寄存器操作数进行编码,以反转(1\xe2\x80\x99s 补码)形式指定,并且对于具有 2 个或更多源操作数的指令有效。(这是NDS的案例)

    \n
  • \n
  • VEX.vvvv 对目标寄存器操作数进行编码,对于某些向量移位,以 1\xe2\x80\x99s 补码形式指定。\n表 2-9 列出了使用 VEX.vvvv 作为目标的指令。表2-9中的\xe2\x80\x9cOpcode\xe2\x80\x9d\n列中的表示法在3.1.1节中有详细描述。(问题中引用的部分

    \n
  • \n
\n
\n
    \n
  • VEX.vvvv 不编码任何操作数(显然没有针对 FMADDS情况进行更新)。
  • \n
\n

所讨论的向量移位是VPS{R,L}L{W,D,Q}VPSRA{W,D,Q}VPS{R,L}LDQ(字节移位),它们使用/r字段mod/rm作为额外的操作码位,如某些单操作数整数指令(例如and r/m32, imm8)。例如

\n
    \n
  • VEX.NDD.128.66.0F 73 /7 ib VPSLLDQ
  • \n
  • VEX.NDD.128.66.0F 73 /3 ib VPSRLDQ
  • \n
\n

这就是为什么 SSE 版本是就地位/字节移位,经常需要 movdqa 指令。SSE2 编码空间中有一些免费的操作码66 0F xx,英特尔本可以使用这些操作码,而不是使这些常用指令具有破坏性。不过,我猜他们已经坚持了在 MMX 版本中使用该/r字段的决定0F xx。我认为,让 new-with-SSE2 字节移位 insn 也具有破坏性是没有必要的。至少他们成功地进行了一次非破坏性的洗牌pshufd

\n