MIPSзҡ„nopе’ҢsllжҢҮд»Өзҡ„еӯ—иҠӮз ҒжңүдҪ•еҢәеҲ«пјҹ

3
据我所知,这两个指令的操作码和功能码都为0,那么计算机如何知道它正在执行哪个呢?

6
它不必要。 nopsll $0, $0, 0 的别名,它什么也不做。当然,如果硬件希望的话,它可以特别处理。 - Jester
1个回答

3

正如Jester所说,MIPS CPU如果不想进行任何特殊的性能优化,就不必进行区分。由于对$0的写入被丢弃,并且它没有副作用(MIPS没有FLAGS/condition-codes寄存器),因此sll $0, $0, 0已经没有架构效果。因此,简单的硬件可以让它通过管道运行。

约定一个nop操作码的重点在于,如果硬件想要查找一个特殊情况并且甚至不执行它,那么只有一个比特模式需要匹配,而不是考虑每个写入到$0的指令选择(除了可能仍然故障的负载)。

因此,编译器/汇编器的开发人员不必猜测nop对某些硬件来说可能是最便宜的。硬件可能会做的事情包括:

  • 只有一个移位执行单元的超标量流水线可以在同一时钟周期内运行nopsll $t0, $t1, 12,即使它通常无法同时运行两个移位。
  • 可能从不激活ALU中节省一点电源?
  • 可能根本不会通过流水线发送NOP,而是在解码时丢弃它并获取下一个真正的指令。(对于获取和解码比其流水线宽度更多的CPU或特别是乱序执行CPU而言,这是可行的。)
  • 如果冒险检测没有特殊处理$0上的每次读写,那么可以跳过nop。(仅适用于没有旁路转发的玩具CPU,见下文。)

即使 sll $t0, $t0, 0 没有架构效果,因为它将寄存器写入了已经存在的相同值。但这是一个更糟糕的选择,因为冒险检测通常会关注寄存器的读写操作,所以它可能导致停顿,或者在类似 R10000 的乱序执行 MIPS 上导致更长的依赖链对于 $t0。然而,如果 MIPS 没有零寄存器,那么将其作为 NOP 是一个合理的选择,除了在 MIPS 1 中,将其放置在写入 $t0 的加载延迟槽中是不安全的。

lw $0, (mem) / nop在硬件中是否存在任何可能的边角情况,这些硬件并没有特别处理nop或零寄存器,而是仅在寄存器文件中处理写入丢弃和读取为零的零寄存器?

在这种情况下,它将看到一个指令在下一条指令中读取负载结果。在MIPS I上,由于它不会为无法处理的旁路转发而停顿,因此会产生不可预测的读取值。(在后来的MIPS上,它会停顿;负载延迟槽不是体系结构,只是性能问题。)当然,结果最终只是写入零寄存器,因此没有可观察的差异。

但是,如果简单的硬件没有为旁路转发特别处理零寄存器,则类似addiu $0, $0, 123 / addi $1, $0, 0的操作可能会复制非零值。因此,正确的MIPS设计不能如此简单,并且必须在进行旁路转发的危险检测时已经特别处理了$zero,以确保它不会旁路转发到从$0读取的值,该值始终为零。

一个采用停顿而非旁路转发的MIPS设计不需要在危险检测中特殊处理$0,因为所有值都会经过寄存器文件。但这可能不是MIPS架构师考虑的因素,因为在大多数代码中,旁路转发对于良好的性能至关重要。

“put it in the load delay slot of a loat” 看起来不对。 - ecm

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接