使用寄存器作为偏移量

Using a register as an offset

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

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

I'm curious as to why we are not allowed to use registers as offsets in MIPS.

我不确定你是指 "why does MIPS assembly not permit you to write it this form" 还是 "why does the underlying ISA not offer this form"。

如果是前者,那么答案是基础 ISA 没有任何提供该功能的机器指令,显然设计者没有决定提供任何 pseudo-instruction 来实现该功能幕后.2

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

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

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

Is it a hardware restriction? Or simply just part of the ISA?

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


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

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

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