【问题标题】:Why the %r0 of SPARC or MIPS, is always 0?为什么 SPARC 或 MIPS 的 %r0 总是 0?
【发布时间】:2013-10-08 11:23:57
【问题描述】:

我知道当您在 SPARC CPU(和 MIPS)中读取 %r0 时,总是返回 0,但我想知道为什么?

这背后的设计决策是什么?为什么?

【问题讨论】:

  • g0 或 r0。我认为它是 SPARC 中的 g0!
  • 在 MIPS 中是 $0 或 $0
  • 它不仅出现在 SPARC 或 MIPS 中,而且在许多 RISC 架构中也很常见,因为零是一个非常常见的值。在 ARMv8 AArch64 模式下,寄存器 x31 也被硬连线到 0
  • @RahulTripathi:SPARC 寄存器(通过指令格式编码)是r0..r32%g0 r0。仅在汇编语言/助记符中,它们是“语法拆分”%g0..%g7%o0..%o7%l0..%l7%i0..%i7。如果你在 SPARC 汇编源代码中说 %r0,你会得到 %g0
  • @FrankH.:- 明白了。谢谢!!

标签: assembly mips cpu-architecture cpu-registers sparc


【解决方案1】:

这正是 CPU 的设计方式。一方面,确保r0 始终设置为零是一种避免对一个非常常见的值进行潜在成本高昂的内存访问的方法。

一方面(阅读),留出一个寄存器来保存零值是很方便的,这样您就可以使用它。否则,您必须自己将零加载到寄存器中。

许多 RISC 处理器倾向于在寄存器中进行数据操作,访问内存仅用于加载和存储操作。这不是 RISC 的硬性规定,更多的是一种趋势。留出一个寄存器以使您始终有零可用可能很有用 - 这是一种权衡,因为您可以减少一个用于通用值的寄存器,但 MIPS 设计人员显然认为这是值得的。

另一方面(写作),因为r0 与零值相关联,所以您可以将您想要的内容放在那里,它不会有任何区别——它将保持为零。这意味着如果您想丢弃该值,可以将其用作目标。

同样,这与 RISC 背后的理念有关。它倾向于支持极少数指令格式,例如 MIPS RIJ 格式(寄存器、立即数和跳转)。例如,您可以使用一组始终存储结果的集合,而不是根据您是否要存储结果来使用多种指令格式,然后如果您不关心它,只需将其存储到r0

因此,如果您想检查添加两个寄存器是否会导致溢出但又不想将结果存储在任何地方,您可以使用:

add $0, $7, $8  ; r0 <- r7 + r8, but r0 remains at 0.

MIPS 文档MIPS32 Architecture for Programmers Volume I: Introduction to the MIPS32 Architecture 确认了上述内容:

R0 被硬连线为零值,并且可以用作任何要丢弃其结果的指令的目标寄存器。当需要零值时,R0 也可以用作源。

【讨论】:

  • 我在 RISC 中工作,例如 16 位 cpu。我问了这个问题,因为我在想如果在我的情况下 r0 总是为零,可能会有用。就我而言,将寄存器设置为 0 值很便宜(单条指令即可));另外,我只有几条使用 3 个寄存器的指令(仅加载/存储),ALU 操作重用一个寄存器作为输出(如 ADD rd,rs -> rd += rs)。我认为 r0 始终为零,在我的情况下是浪费的。感谢您的回答!
  • @paxdiablo:我想你的意思是说add $0, $7, $8。目标寄存器在 MIPS 中首先出现。
  • 我不会说“RISC 背后的哲学”,这只是一个设计决策,RISC 与它无关,您可以轻松地使用另一个寄存器,而根本不保存或重新使用该值.拿走 r0 你会失去一个 gpr,这是一个沉重的成本,所以就一次性价值而言,它更像是一种负担,而不是一种节省。
  • @dwelch,我可能不清楚。设计理念建议简化指令格式,而不是使用始终为零的特定寄存器。也就是说,毕竟精简指令集计算是从哪里来的。
  • 是的,我完全理解 risc 设计、cisc 设计等。我只是指出 r0 是只读的,与 cisc 或 risc 设计无关。它确实支持整体 MIPS 指令集设计,不是作为 RISC,而是作为一个指令集。无论您使用什么指令集,都会有一些时候您想要执行一条指令但丢弃结果,对于其中一些指令集丢弃结果,或者您烧毁寄存器、内存位置或其他。跨度>
【解决方案2】:

从指令集设计的角度来看,主要原因是/dev/null-register 的存在允许某些“浓缩”否则必须是两个(或更多) 将不同的指令合并成一个单个。几个例子:

  • 函数callreturn,使用链接寄存器,可以用一条指令完成:
    • 作为函数调用指令:jmp &lt;tgtreg&gt;,&lt;pc&gt;,&lt;linkreg&gt;
      (SPARC jmp 是一个原子 mov &lt;pc&gt;,&lt;linkreg&gt;; mov &lt;tgtreg&gt;,&lt;pc&gt;),并且
    • 作为函数返回指令:jmp &lt;linkreg&gt;,&lt;nullreg&gt;,&lt;nullreg&gt;
  • cmptst 可以是简单的sub &lt;a&gt;,&lt;b&gt;,&lt;nullreg&gt;

这些完整的表格可以从 Oracle 的文档中找到,SPARC synthetic instructionssparcv9 synthetic instructions;其中大部分涉及%g0

【讨论】:

  • 零寄存器类似于/dev/zero,而不是/dev/null。两者都丢弃写入,但/dev/zero 读取为零,而/dev/null 读取为空(即无法从中读取)。顺便说一句,MIPS 没有标志(而不是使用compare-into-register instructions like sltu dst, src1, src2),所以sub 以零 reg 作为目标仅在带有标志的 CPU、like SPARC 或 ARM 上才有意义。但是 ARM 没有零注册,而且几乎没有 RISCy。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-04-14
  • 2011-12-28
  • 2011-12-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-01-24
相关资源
最近更新 更多