JMP指令对8086的工作有何影响?

Jes*_*eph 3 x86 cpu-architecture machine-code x86-16

我知道 8086 有一个 BIU 和一个 EU,这有助于处理器的流水线化。BIU 有一个 6 字节预取队列,用于提取指令指针指向的地址后面的字节。现在,当要执行的指令是跳转到另一个位置的指令时,预取的所有 6 个字节会发生什么情况?它们会被冲掉然后重新加载吗?(这会破坏处理器的流水线效率,不是吗?)

Pet*_*des 5

是的,在 8086 和更高版本的工作类似的微体系结构中,跳转会丢弃指令预取队列。任何控制传输后的指令获取均以空缓冲区开始。

对于 JIT/自修改代码,这意味着任何跳转都足以避免过时的指令获取。

它们会被冲掉然后重新加载吗?这会破坏处理器的流水线效率,不是吗?

缓冲区中的指令来自错误的路径,除非它是 nop jmp +0。所以它们不会被重新加载;它们没有用,必须加载正确的路径。

这不太好,而且跳跃会产生额外的费用。 这就是为什么像 Pentium 这样的后来的有序 CPU 具有分支预测,因此它们可以在跳转甚至解码之前从正确的路径获取。 (分支预测需要预测分支的存在,例如给定提取块地址,预测接下来要提取什么块。以及预测条件分支将走哪条路。)

8086 很难像 5 级 RISC 那样是一种高效的流水线。

无论如何,取指令通常是 8086 上的主要瓶颈,因此在大多数跳转中缓冲区通常不会满。您最多只损失 6 个字节(3 个字的提取)的浪费预取工作,甚至可能更少。(这就是为什么在 8086 上优化速度几乎就是在优化代码大小,除了避免一些缓慢的指令(如乘法)。这也是为什么 x86 的紧凑可变长度指令对于 8086 来说是一个很好的设计。)

我不知道解码/执行跳转需要多长时间,但跳转是 2 或 3 个字节长(在 x86-16 中),对于带有 opcode+modrm+disp16 + 可选前缀的间接跳转,甚至是 4+ 字节长。刚刚执行的跳转指令可能使 8086 上的预取缓冲区接近于空。


从形式上看,x86 ISA 至少曾经需要类似iret或 的序列化指令cpuid,以避免任何陈旧指令的风险。但为了避免破坏现有代码,真正的 x86 CPU 只需要跳转1

现代 OoO x86 CPU 具有分支预测 + 推测执行(如 P6 系列)不需要任何东西;他们积极地窥探管道以检测与正在运行的指令重叠的存储。 使用自修改代码观察 x86 上的陈旧指令获取


脚注 1:多年来,超越纸质规范以保持与广泛使用的软件的兼容性是 x86 中的常见现象;真正的向后兼容和二进制兼容性基本上是 x86 与更干净的 RISC ISA 相比的主要卖点,直到 x86 占据主导地位,以至于其他 ISA 放弃了针对高功率/高性能市场的目标。(由于不断增长的晶体管预算和巧妙的设计理念,使得支付“x86 税”并仍然运行快速成为可能。

如果新的更快的 CPU 无法运行现有版本的 DOS、Windows、Lotus Notes 或其他任何版本,那么市场将会面临巨大的阻力。