"Undefined" 在 Intel 的 asm 文档中是什么意思? FST 对 C0、C2、C3 的影响

What does "Undefined" mean in Intel's asm documentation? FST effect on C0, C2, C3

Intel® 64 和 IA-32 架构软件开发人员手册(第 2 卷)说,对于指令 FST/FSTP FPU 影响标志:

简单test(几乎没有任何价值)告诉我,C0,C2,C3可以不受影响:

#include <iostream>
#include <bitset>

#include <cstdlib>
#include <cstdint>

int main()
{
    double x = -1.0;
    std::uint16_t a = 0, b = 0;
    asm volatile ("fld %[x] ; ftst ; fnstsw %%ax ; mov %%ax, %[a] ; fstp %%st ; fnstsw %%ax ; mov %%ax, %[b] ;"
       : [a]"=m"(a), [b]"=m"(b)
       : [x]"t"(x)
       : "cc", "memory");
    std::cout << std::bitset< 16 >(a) << std::endl;
    std::cout << std::bitset< 16 >(b) << std::endl;
    std::cout << "     ^^^" << std::endl;
}

"Undefined"是什么意思? FSTP 可以更改这些值,还是什么也不做?

它会说 "unmodified" 或 "unaffected" 如果它是这个意思。

"Undefined" 意味着该值可以是任何值,并且可能在 CPU 微体系结构之间有所不同。有些 CPU 可能会保留旧值,有些可能会清除或设置位,或者将某些微体系结构状态泄漏到每次您 运行 指令时可能不同的位中。或者根据数字是否为 NaN 或 Inf 来设置。

但是英特尔没有记录任何关于哪些行为会发生的信息。最重要的是,让他们的选择保持开放,使其 在未来 CPUs 可能有所不同,所以如果你想写,测试当前 CPUs 做什么是没有用的安全的面向未来的代码。

(尽管如此,英特尔很可能会继续做他们目前所做的事情。但是一些彻底的重新设计可能会有所不同。)当然,其他供应商可能会有所不同。值得查看 AMD 的 x86 手册,看看他们是否说明了他们的 CPU 所做的事情。


(产生未定义的 不是 就像 C 未定义的行为。它不会破坏程序的其余部分。C2 将读取为 0 或 1,不要将其置于某种奇怪的状态,即使没有 运行ing 任何记录为影响 C2 的指令,它也可能再次改变。)


asm 文档中 "undefined" 的另一种用法是用于 bsfbsr 指令,当输入 = 0 时目标寄存器值为 "undefined"。(并且ZF 设置为 1).

实际上,在这种情况下,英特尔硬件不会修改目标。 (因此它有点像 cmov,您可以在 运行 宁 bsf 之前将输入=0 的结果放入输出中。 AMD 实际上 确实 在他们的 AMD 手册中记录了这种行为,并且大概是 Intel 关心的一些软件依赖于这种行为。所以英特尔极不可能改变它,而 IDK 为什么他们不只是记录它以便我们可以利用它。 lzcnttzcnt 已经存在于 BMI1 中,具有明确的输入=0 行为。

这种未修改的 dst 行为具有实际的性能成本:这意味着该指令需要对原本是只写目标的输入依赖性。这会创建错误的依赖关系,以防止乱序执行。 (更糟糕的是,在 Skylake 之前的 CPU 秒,lzcnttzcnt 具有相同的错误输出依赖性。popcnt 在 Skylake 之后至少有几个 uarches 仍然具有这种依赖性。 )