5

我的问题涉及没有舍入语义的 EVEX 编码打包 reg-reg 指令,它允许 SAE 控制(抑制所有异常),例如 VMIN*、VCVTT*、VGETEXT*、VREDUCE*、VRANGE* 等。英特尔仅在完整的情况下声明 SAE 意识512bit向量长度,例如

VMINPD xmm1 {k1}{z}, xmm2, xmm3
VMINPD ymm1 {k1}{z}, ymm2, ymm3
VMINPD zmm1 {k1}{z}, zmm2, zmm3{sae}

但我看不出为什么不能将 SAE 应用于使用 xmm 或 ymm 寄存器的指令。

英特尔指令集扩展编程参考表 4-7 的第 4.6.4 章中,在没有舍入语义的指令中,EVEX.b 位指定应用 SAE,而 EVEX.L'L 位指定显式向量长度:

00b: 128bit (XMM)
01b: 256bit (YMM)
10b: 512bit (ZMM)
11b: reserved

所以他们的组合应该是合法的。

然而,NASM 组装vminpd zmm1,zmm2,zmm3,{sae} 为 62F1ED185DCB,即 EVEX.L'L=00b,EVEX.b=1,由 NDISASM 2.12 反汇编为vminpd xmm1,xmm2,xmm3

NASM 拒绝组装vminpd ymm1,ymm2,ymm3,{sae} ,NDISASM 将 62F1ED385DCB (EVEX.L'L=01b, EVEX.b=1) 分解为vminpd xmm1,xmm2,xmm3

我想知道 Knights Landing CPU 是如何执行VMINPD ymm1, ymm2, ymm3{sae} 的(组装为 62F1ED385DCB,EVEX.L'L=01b,EVEX.b=1)

  1. CPU 抛出异常。英特尔文档表 4-7 具有误导性。
  2. SAE 生效,CPU 仅使用 xmm 操作,与标量操作相同。NASM 和 NDISASM 做得对,英特尔文档是错误的。
  3. SAE 被忽略,CPU 根据 Intel 文档中的 VMINPD 规范以 256 位运行。NASM 和 NDISASM 是错误的。
  4. SAE 生效,CPU 以指令代码中指定的 256 位运行。NASM 和 NDISASM 错误,Intel doc 需要用 {sae} 补充修饰 xmm/ymm 指令。
  5. SAE 生效,CPU 以隐含的全向量大小 512 位运行,无论 EVEX.L'L 为何,就像允许静态舍入 {er} 一样。NDISASM 和 Intel 文档表 4-7 是错误的。
4

2 回答 2

4

您的VMINPD ymm1, ymm2, ymm3{sae}指示无效。根据英特尔架构指令集扩展编程参考(2016 年 2 月)中 MINPD 的指令集参考,仅允许以下编码:

66 0F 5D /r                  MINPD xmm1, xmm2/m128 
VEX.NDS.128.66.0F.WIG 5D /r  VMINPD xmm1, xmm2, xmm3/m128
VEX.NDS.256.66.0F.WIG 5D /r  VMINPD ymm1, ymm2, ymm3/m256
EVEX.NDS.128.66.0F.W1 5D /r  VMINPD xmm1 {k1}{z}, xmm2, xmm3/m128/m64bcst
EVEX.NDS.256.66.0F.W1 5D /r  VMINPD ymm1 {k1}{z}, ymm2, ymm3/m256/m64bcst
EVEX.NDS.512.66.0F.W1 5D /r  VMINPD zmm1 {k1}{z}, zmm2, zmm3/m512/m64bcst{sae}

请注意,只有最后一个版本带有{sae}后缀,这意味着它是您可以使用它的唯一指令形式。仅仅因为存在用于编码特定指令的位并不意味着它是有效的。

另请注意,第 4.6.3 节,EVEX 中的 SAE 支持,明确指出 SAE 不适用于 128 位或 256 位向量:

EVEX 编码系统允许使用 SAE 属性对没有舍入语义的算术浮点指令进行编码。通过设置 EVEX.b,此功能仅适用于寄存器到寄存器的标量和 512 位向量长度。当设置 EVEX.b 时,暗示“抑制所有异常”。[...]

但是,我不确定您手工制作的指令是否会生成无效操作码异常,是否会简单地忽略 EVEX.b 位,或者是否会忽略 EVEX.L'L 位。EVEX 编码的 VMINPD 指令属于 E2 类异常类,根据表 4-17,E2 类异常条件,该指令在以下任何一种情况下都会产生#UD 异常:

  • 状态要求,未满足表 4-8。
  • 表 4-9 中的操作码独立 #UD 条件。
  • 操作数编码#UD条件见表4-10。
  • Opmask 编码#UD 条件见表 4-11。
  • 如果 EVEX.L'L != 10b (VL=512)。

只有最后一个原因似乎适用于此,但这意味着您的指令将生成带有或不带有{sae}修饰符的#UD 异常。由于这似乎与指令摘要中允许的编码直接矛盾,我不确定会发生什么。

于 2016-08-15T18:20:55.277 回答
2

在 Twitter 上,iximeow 对上述 Ross Ridge 的回答做了一些补充:

  • ross ridge 是对的,文本无效,但重要的细节是L'L选择了特定的 SAE 模式,所以如果你设置L'L为指示ymm,你就会得到{rd-sae}
  • 也就是说,如果你设置bfor saeall,向量宽度立即固定为512位
  • 矢量宽度固定为 512 位*

    *除了一些 cvt 指令,其中一个操作数为 512 位且一个操作数更小

(@Pepijn 对罗斯回答的评论已经与这些推文相关联;但我认为值得将其作为一个单独的答案,即使只是为了提高知名度。)

于 2021-06-22T09:36:41.957 回答