【问题标题】:Using a register as an offset使用寄存器作为偏移量
【发布时间】:2018-04-03 09:29:52
【问题描述】:

我很好奇为什么我们不允许在 MIPS 中使用寄存器作为偏移量。我知道您不能像这样使用寄存器作为偏移量:lw $t3, $t1($t4);我只是好奇为什么会这样。

这是硬件限制吗?或者只是ISA的一部分?

【问题讨论】:

  • 他们就是这样设计的。你必须问设计师他们为什么决定反对它。
  • 我认为后来的 MIPS 确实 有索引负载(以及相对于 PC 的负载)。 tkt.cs.tut.fi/kurssit/3200/S05/Luennot/Lec_notes05/…。可能支持 PC-relative 意味着他们需要 AGU 中的 2 个寄存器加法器,因此也可以允许 2 个任意寄存器,而不仅仅是 PC + 寄存器。 First-gen MIPS I had only one addressing mode: base + displacement(当然可以为零)。很明显,这使得解码和地址生成更简单。
  • 维基百科说MIPS IV added indexed addressing modes。嗯,但他们只提到 FP 加载/存储。 A current MIPS instruction-set quick ref 仅列出了用于整数加载/存储的 off(Rs) 模式,包括未对齐和 LL/SC。
  • lwpc is new in MIPS release 6,并使用通常的 sign_extend( offset << 2 ) 编码,但使用 PC 而不是 GPR。同一个文档确实记录了索引的 FP 负载(例如 lwxc1,它使用 GPR[base] + GPR[index])。所以是的,MIPS ISA 仍然不包括索引整数负载。你必须自己做地址数学。至少有一个移位和加法指令 (lsa) 用于生成缩放索引地址(例如 int[])。
  • 我猜这个动机是整个 RISC 哲学的一部分。 MIPS 是最早的 RISC 设计之一。

标签: assembly mips cpu-architecture addressing-mode


【解决方案1】:

我很好奇为什么我们不允许在 MIPS 中使用寄存器作为偏移量。

我不确定你的意思是“为什么 MIPS 程序集不允许你写这种形式”或“为什么底层 ISA 不提供这种形式”。

如果是前者,那么答案是基本 ISA 没有任何提供该功能的机器指令,而且显然设计者没有决定提供任何可以在幕后实现该功能的 pseudo-instruction2

如果您首先要问为什么 ISA 不提供它,那只是一种设计选择。通过提供更少或更简单的寻址模式,您可以获得以下优势:

  • 对一组更有限的可能性进行编码所需的空间更小,因此您可以为更多操作码、更短指令等节省编码空间。
  • 硬件可以更简单或更快。例如,在地址计算中允许两个寄存器可能会导致:
  • 寄存器文件中需要额外的读取端口1
  • 寄存器文件和 AGU 之间的附加连接可在其中获取两个寄存器值。
  • 需要对偏移量进行全宽(32 位或 64 位)加法,而不是更简单的地址端 + 16 位加法。
  • 如果您仍想支持使用 2 寄存器地址的立即偏移量,则需要一个三输入 ALU(如果您不这样做,它们的用处就会降低)。
  • 指令解码和地址生成的额外复杂性,因为您可能需要支持两种完全不同的地址生成路径。

当然,在某些情况下,所有这些权衡可能会得到很好的回报,这些情况可以通过更小或更快的代码充分利用 2-reg 寻址,但受 RISC 哲学启发的原始设计并没有不包括它。正如 Peter 指出的in the comments,随后在某些情况下添加了新的寻址模式,尽管显然不是用于加载或存储的通用 2-reg 寻址模式。

这是硬件限制吗?或者只是ISA的一部分?

那里有一点错误的二分法。当然,这不是硬件限制,因为硬件可以当然支持这一点,即使在设计 MIPS 时也是如此。这似乎暗示某些现有硬件具有该限制,因此 MIPS ISA 以某种方式继承了它。我怀疑情况恰恰相反:ISA 是这样定义的,基于对硬件实现可能性的分析,然后它变成了一种硬件简化,因为 MIPS 硬件不需要支持 MIPS ISA 之外的任何内容。


1 例如,支持需要从 3 个寄存器读取的存储指令。

2 当然值得一问这样的伪指令是否是一个好主意:它可能会扩展为将两个寄存器添加到临时寄存器,然后是 lw 与结果。这总是存在隐藏“太多”工作的危险。由于这部分掩盖了将 1:1 映射到硬件负载的真实负载与在幕后进行额外算术的版本之间的差异,因此很容易想象它可能会导致超优决策。

以在循环中线性访问两个元素大小相等的数组为例。对于 2-reg 寻址,很自然地将此循环写为两个 2-reg 访问(每个都有不同的基址寄存器和公共偏移寄存器)。偏移维护的唯一“开销”是单个偏移增量。这隐藏了一个事实,即在内部需要两个隐藏的添加来支持寻址模式:直接增加每个基数而不使用偏移量会更好。此外,一旦开销明确,您可以看到展开循环并使用立即偏移可以进一步减少开销。

【讨论】:

  • li 带有小常数只是一个指令,对于带有小偏移量的lw 也是如此。 lw 是常规的加载字机器指令。我认为一些 MIPS 汇编器有一个非伪模式,如果你想确保你没有无意中使用多条指令,你可以使用它。
  • 但无论如何,我一直在考虑寄存器读取端口参数,作为 MIPS still 没有索引整数加载/存储的一个很好的解释。剩下大量的编码空间,MIPS 第 6 版重新分配了一些操作码来为新指令腾出空间(例如,没有分支延迟槽的分支)!因此,就编码空间和向后兼容而言,它根本不像 x86 翻阅指令集参考手册(搜索 index)很有趣。 (并且 ports 解释了为什么它索引 FP 加载/存储,因为那是另一个寄存器文件。)
  • @PeterCordes - 是的,今天的理由很好。许多其他成本随着时间的推移而降低,但添加额外读取端口的成本仍然可能令人望而却步,因为它可能是简单芯片面积的很大一部分,它本质上是大多数重要关键路径的一部分并且可以限制周期时间,并且可以对重命名器之类的东西产生影响(如果芯片足够花哨,可以使用)。我添加了一个太长的脚注,说明伪指令是否是个好主意。
  • ... 其逻辑与divrem 等一些现有的伪指令并不完全一致,这些伪指令肯定会隐藏可能浪费精力的东西(例如,如果你需要两者那些你最好自己写并保存div)。实际上div 回答了我上面的一个问题:它们显然确实具有具有相同助记符的伪指令,这些伪指令要么是“伪”,要么是“真实”,具体取决于例如参数的数量。有趣的。不过,我喜欢偷偷摸摸。
  • 我不喜欢 MIPS 伪指令。如果你有一个“打算”用作隐藏临时的架构寄存器,你可能有太多的寄存器......(虽然老实说,有几个架构寄存器允许内核异步破坏快速中断处理程序是一个有趣的设计,包括 TLB 未命中处理程序。这意味着中断处理在架构上可以更简单;IDK 它是如何工作的,但也许它将旧 PC 放在其中一个寄存器中。)
猜你喜欢
  • 2016-11-11
  • 2014-09-28
  • 2018-08-29
  • 1970-01-01
  • 1970-01-01
  • 2017-01-30
  • 2011-07-16
  • 1970-01-01
相关资源
最近更新 更多