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

Assembly 分支预测如何与指令指针交互,assembly,x86,cpu,cpu-architecture,branch-prediction,Assembly,X86,Cpu,Cpu Architecture,Branch Prediction,据我所知,在处理器管道的开始,指令指针(指向要执行的下一条指令的地址)在抓取后由分支预测器更新,这样就可以在下一个周期中抓取这个新地址 但是,如果在管道的早期修改了指令指针,这不会影响当前处于执行阶段的指令,这些指令可能依赖于旧的指令指针值吗?例如,在执行调用时,需要将当前EIP推入堆栈,但在分支预测期间更新指令指针时,这不会受到影响吗?您似乎假设整个CPU核心只使用一个物理EIP寄存器 这是行不通的,因为每个可能发生异常的指令都需要知道自己的地址。或者,当外部中断到达时,CPU可以决定在任何指

据我所知,在处理器管道的开始,指令指针(指向要执行的下一条指令的地址)在抓取后由分支预测器更新,这样就可以在下一个周期中抓取这个新地址


但是,如果在管道的早期修改了指令指针,这不会影响当前处于执行阶段的指令,这些指令可能依赖于旧的指令指针值吗?例如,在执行
调用时,需要将当前EIP推入堆栈,但在分支预测期间更新指令指针时,这不会受到影响吗?

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

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

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

现代超标量无序x86将EIP(或RIP)与每个正在运行的指令相关联(或可能与每个uop相关联);但多uop指令的所有uop都相互关联,因此指令不能部分失效。)

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

早期提取/解码阶段可能只跟踪16字节或32字节提取块的地址,但在解码之后,我假设内部uop表示中有一个地址字段。对于非分支指令,它可能只是以前的一个小偏移(为了节省空间),因此如果需要它,可以进行计算,但我们在这里深入讨论了实现细节。无序执行保持了指令按程序顺序运行的假象,它们确实按顺序发出和退出(进入/离开内核的无序执行部分)

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


分支预测必须在块被解码之前工作。i、 考虑到我们刚刚在地址abc获取了一个块,我们需要预测下一步获取哪个块。i、 e.预测必须预测将并行解码的16字节指令块中是否存在跳跃


相关:

现代超标量无序x86是否有一个与每条指令关联的EIP(或RIP)有点误导?我相信执行uop时,
EIP
与任何其他输入寄存器一样,也就是说,使用了
EIP
的微体系结构值。@MargaretBloom:不太可能;它不会存储在寄存器文件中,因为它在解码时对每条指令都是静态已知的,不能作为输出。控件依赖项的处理方式不同于数据依赖项。不过,我确实改写了那句话,因为它听起来与我的意思不完全一样。大多数指令从来都不需要知道它们自己的IP,至少是以有效的方式,所以完全有可能每个指令都不存储地址,但仅在发生中断或异常或其他情况时,以某种不一定快速的方式追溯计算。直接使用IP的指令,如
调用
或rip相关内容,仍然会在解码时间附近填充。正如您所指出的,这涉及到实现细节,我只是猜测。顺便说一句,我认为获取/解码单元必须计算预测的“精确”地址,而不是使用像32字节这样的更大粒度,因为(a)从解码开始,您就需要知道块中的正确偏移量,以便能够正确解码指令,还因为您需要形成正确的连续指令流,并且(b)预测器本身需要实际地址,以便进行下一次预测,因为块中可能有多个分支。所以(a)意味着粗略预测的窗口很小,(b)意味着它可能为零。有可能预测器的行为实际上并不像我在(b)中所建议的那样——也就是说,他们的“最紧密”循环只是在块级别上预测,然后他们细化目标以提供给解码器。这意味着它们会被同一块中具有不同目标和模式的多个分支所愚弄,这些分支可以通过软件进行测试。在许多流水线架构中,程序计数器是假的,软件可以看到的计数器具有正确的值。逻辑使用一些到许多其他指令指针地址来完成真正的繁重工作、一个或多个分支预测计算、用于获取内存的实际指针等。Arm是一个简单的指令,前面有两条指令的程序计数器已经很久没有这样做了,随着预测的深入,管道越来越深。然而,我们仍然有一个r15,它给出了指令集结果中设计的值。像EIP这样的可用(伪)寄存器将具有所用指令集的正确值,而不依赖于用于实际取数的任何锁存或组合地址。