从微架构中抽象出来的 x86 程序计数器?

标签 x86 cpu-architecture riscv instruction-set program-counter

我正在阅读 The RISC-V Reader: An Open Architecture Atlas 这本书。为了解释 ISA(指令集架构)与特定实现(即微架构)的隔离,作者写道:

The temptation for an architect is to include instructions in an ISA that helps performance or cost of one implementation at a particular time, but burden different or future implementations.



据我了解,它指出,在设计 ISA 时,ISA 理想情况下应该避免暴露实现它的特定微体系结构的细节。

记住上面的引用:当谈到程序计数器时,在 RISC-V ISA 上,程序计数器 (pc) 指向 当前正在执行的指令 .另一方面,在 x86 ISA 上,程序计数器( eip )不包含当前正在执行的指令的地址,而是包含一个 的地址。遵循当前指令 .

x86 程序计数器是从微架构中抽象出来的吗?

最佳答案

我将根据 MIPS 而不是 x86 来回答这个问题,因为 (1) MIPS 和 x86 在这方面有相似之处,并且因为 (2) RISC V 是由 Patterson 等人在使用 MIPS 数十年后开发的.我觉得在这个比较中最好理解他们书中的这些陈述,因为 x86 和 MIPS 都编码相对于指令末尾的分支偏移量(MIPS 中的 pc+4)。

在 MIPS 和 x86 中,PC 相对寻址模式仅在早期 ISA 版本的分支中找到。后来的修订版添加了 PC 相对地址计算(例如 MIPS auipc 或 x86-64 的 LEA 或加载/存储的 RIP 相对寻址模式)。这些都是相互一致的:偏移量是相对于(过去)指令的结尾(即下一条指令开始)进行编码的——而正如您所注意到的,在 RISC V 中,编码的分支偏移量(和 auipc , 等等) 是相对于指令的开始的。

这样做的值(value)在于它从某些数据路径中移除了一个加法器,有时这些数据路径之一可能位于关键路径上,因此对于某些实现,数据路径的这种微小缩短意味着更高的时钟速率。

(当然,RISC V 仍然必须为 pc-next 和调用指令的返回地址生成指令 + 4,但这在关键路径上要少得多。请注意,下图中都没有显示 pc+4 的捕获作为回邮地址。)

让我们比较一下硬件框图:

MIPS datapath (simplified)                                                MIPS datapath (simplified)



RISC V datapath (simplified)                                                RISC V datapath (simplified)



您可以在 RISC V 数据路径图上看到标记为 #5 的线(红色,在控制椭圆的正上方)绕过加法器(#4,为 pc-next 将 4 添加到 pc)。

图表的归属
  • MIPS:Need help in adding functionality to MIPS single cycle datapath?
  • RISC V:https://www.codementor.io/erikeidt/logic-block-diagrams-w6zxr6sp6


  • 为什么 x86/MIPS 在它们的初始版本中做出不同的选择?

    当然,我不能肯定地说。在我看来,有一个选择是可以做出的,而且对于最早的实现来说根本无关紧要,所以他们可能甚至没有意识到潜在的问题。无论如何,几乎每条指令都需要计算指令下一个,所以这似乎是合乎逻辑的选择。

    充其量,他们可能会节省一些电线,因为其他指令(例如调用)确实需要 pc-next 并且 pc+0 不一定需要其他指令。

    对先前处理器的检查可能表明,这只是当时的处理方式,因此这可能更多是对现有方法的继承,而不是设计选择。

    8086 不是流水线化的(指令预取缓冲区除外),并且可变长度解码在开始执行之前已经找到了指令的结尾。

    经过多年的后见之明,这个数据路径问题现在在 RISC V 中得到解决。

    我怀疑他们对此做出了相同级别的有意识的决定,例如,对于分支延迟槽 (MIPS)。

    根据评论中的讨论,8086 可能没有任何推送指令起始地址的异常。与后来的 x86 模型不同,除法异常将指令的地址推送到 div/idiv 之后。而在 8086 中,中断恢复后 cs rep movsb (或其他字符串指令)推送最后一个前缀的地址,而不是包含多个前缀的整个指令。这个“错误”记录在 Intel's 8086 manual (scanned PDF) 中.所以很有可能8086真的没有记录指令的起始地址或长度,只记录了开始执行前解码完成的地址。此 was fixed by at least 286 ,也许是 186,但适用于所有 8086/8088 CPU。

    MIPS 从一开始就有虚拟内存,因此它确实需要能够记录错误指令的地址,以便在异常返回后重新运行。此外,软件 TLB 未命中处理还需要重新运行出错指令。但是异常很慢并且无论如何都会刷新管道,并且在获取之后才检测到,因此可能无论如何都需要进行一些计算。

    关于从微架构中抽象出来的 x86 程序计数器?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57171220/

    相关文章:

    llvm - 使用 LLVM 编译 Linux 内核

    llvm - 如何在 LLVM IR 中使用 RISC-V 向量 (RVV) 指令?

    assembly - 我是在写程序集还是 NASM?

    c++ - 当前的 x86 架构是否支持非临时加载(来自 "normal"内存)?

    c - 将不正确的字符写入帧缓冲区

    c - 64 位 native 类型原子性和内存总线?

    assembly - 分支罚款是什么意思?

    cpu - Sandy-Bridge CPU 规范

    assembly - RISC-V SiFive HiFive Unleashed FMADD(32) 下溢标志未在次正常结果上设置

    assembly - 无法调整尺寸指令