据我了解,在处理器流水线的开头,提取后分支预测器会更新指令指针(指向要执行的下一条指令的地址),以便随后可以在该地址上获取该新地址。下一个周期。
但是,如果在流水线的早期修改了指令指针,这是否会影响当前可能依赖于旧指令指针值的执行阶段中的指令?例如,当执行call
时,当前EIP需要被推入堆栈,但是在分支预测期间更新指令指针时,这不会受到影响吗?
答案 0 :(得分:9)
您似乎在假设整个CPU内核只使用一个物理EIP寄存器。
那是行不通的,因为每条可能发生异常的指令都需要知道自己的地址。或者,当外部中断到达时,CPU可以在收到任何指令后决定服务该中断,从而使该中断成为体系结构的EIP。在长模式(x86-64)中,还存在相对RIP寻址模式,因此call
并不是唯一需要当前程序计数器作为数据的指令。
一个简单的流水线CPU可能在每个流水线阶段都有一个EIP。
现代超标量无序x86将EIP(或RIP)与每个飞行指令(或也许每个uop关联);但是多uup指令的所有uop都与每个其他,因此指令不能部分退休。)
与架构状态的其他部分(例如EFLAGS,EAX等)不同,该值在解码后会静态地已知。实际上甚至比立即值还早;在预解码阶段检测指令边界(或在L1i缓存中标记),以便可以将多条指令并行地馈送到多个解码器。
早期的获取/解码阶段可能只跟踪16字节或32字节获取块的地址,但是在解码之后,我假设内部uop表示中有一个地址字段。对于非分支指令,它可能仅与前一个(以节省空间)相差很小,因此,如果需要,可以对其进行计算,但是我们在这里深入介绍实现细节。乱序执行会保持以程序顺序运行的指令的错觉,它们会按顺序发布和退出(输入/保留内核的乱序执行部分)。
相关:x86 registers: MBR/MDR and instruction registers根据看玩具CPU做出了类似的错误假设。也没有保存机器代码字节的“当前指令”寄存器。在我的答案中看到更多链接,以获取有关OoO /流水线CPU的更多信息。
分支预测必须在块被解码之前起作用。也就是说,假设我们刚刚在地址abc处获取了一个块,则需要预测接下来要获取的块。也就是说,预测必须预测将要并行解码的16字节指令块中是否存在跳转。
相关:Why did Intel change the static branch prediction mechanism over these years?