assembly - 分支预测如何与指令指针交互

标签 assembly x86 cpu cpu-architecture branch-prediction

据我了解,在处理器流水线的开头,指令指针(指向下一条要执行的指令的地址)在获取后由分支预测器更新,以便随后可以获取这个新地址下一个循环。

但是,如果在流水线的早期修改了指令指针,这不会影响当前可能依赖旧指令指针值的执行阶段的指令吗?例如,在进行 call 时,需要将当前 EIP 压入堆栈,但是在分支预测期间更新指令指针时,这不会受到影响吗?

最佳答案

您似乎假设整个 CPU 内核只使用一个物理 EIP 寄存器。

这是行不通的,因为每条可能发生异常的指令都需要知道自己的地址。或者当外部中断到达时,CPU 可以决定在任何指令之后服务中断,从而使该中断成为架构 EIP。在长模式 (x86-64) 中,还有 RIP 相对寻址模式,因此 call 并不是唯一需要当前程序计数器作为数据的指令。

一个简单的流水线 CPU 可能对每个流水线阶段都有一个 EIP。

现代的超标量乱序 x86 将 EIP(或 RIP)与每个运行中的指令(或者可能是每个 uop)相关联;但多 uop 指令的所有 uop 都与每个其他,因此指令不能部分退出。)

与架构状态的其他部分(例如 EFLAGS、EAX 等)不同,该值在解码后是静态已知的。实际上甚至早于即时值;在预解码阶段检测指令边界(或在 L1i 缓存中标记),以便将多条指令并行馈送到多个解码器。

早期获取/解码阶段可能只跟踪 16 字节或 32 字节获取 block 的地址,但在解码之后,我假设内部 uop 表示中有一个地址字段。对于非分支指令,它可能只是与前一个(以节省空间)的一个小偏移量,所以如果需要它可以计算出来,但我们在这里深入研究实现细节。乱序执行维护了以程序顺序运行的指令的错觉,它们确实按顺序发出和退出(进入/离开内核的乱序执行部分)。

相关:x86 registers: MBR/MDR and instruction registers根据对玩具 CPU 的研究,做出了类似的错误假设。也没有保存机器代码字节的“当前指令”寄存器。有关 OoO/流水线 CPU 的更多信息,请参阅我的答案中的更多链接。


分支预测必须在 block 被解码之前工作。即假设我们刚刚在地址 abc 处获取了一个 block ,我们需要预测下一个要获取的 block 。即预测必须预测一个 16 字节指令 block 中是否存在跳转,这些指令将被并行解码。

相关:Why did Intel change the static branch prediction mechanism over these years?

关于assembly - 分支预测如何与指令指针交互,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51942523/

相关文章:

visual-c++ - _umul128 在 Windows 32 位上

assembly - 为什么在xv6中gdtdesc中有sizeof(gdt)-1

java - 等待 Fork 加入池 (Java)

c++ - 在 win 7 64 位的 visual studio 2012 中编写 x86 汇编代码的问题

c - 为什么 gcc 使用 movl 而不是 push 来传递函数参数?

c - 获取指令指针指向的给定地址的指令

Javascript THREEJS 和 GC

caching - 写入mmio寄存器时如何避免缓存?

assembly - 为什么 objdump 显示此汇编语言指令的空操作码?

c++ - 无符号数学是否需要更多 CPU 指令?