assembly MIPS nop和sll的字节码如何区分?

j8ag8udp  于 2023-05-18  发布在  其他
关注(0)|答案(1)|浏览(139)

据我所知,这两条指令的操作码和函数码都是0,那么计算机如何知道它在做哪一条呢?

qq24tv8q

qq24tv8q1#

正如Jester所说,如果MIPS CPU不想进行任何特殊的性能优化,它就不必进行区分。sll $0, $0, 0已经没有架构影响,因为对$0的写入被丢弃,并且它没有副作用(MIPS没有FLAGS/条件码寄存器)。所以简单的硬件可以让它通过管道运行。
有一个商定的nop操作码的意义在于,如果硬件想要寻找一个特殊情况,甚至不执行它,它只需要匹配一个位模式,而不是考虑写入$0的每一个指令选择(除了可能仍然出错的加载)。
因此编译器/汇编器的开发人员不必猜测什么nop对于某些硬件来说可能是最便宜的。硬件可能做的事情包括:

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

即使sll $t0, $t0, 0也没有架构影响,因为它用已经拥有的相同值写入寄存器。但这是一个更糟糕的选择,因为危险检测通常会查看寄存器的读取和写入,因此它可能会导致停滞,或者在乱序的exec MIPS(如R10000)上产生更长的$t0依赖链。但是,如果MIPS没有零寄存器,那么将其作为NOP是一个合理的选择,除非在MIPS 1上,将其放在写入$t0的加载的延迟槽中是不安全的。
对于根本没有尝试特殊情况nop或零寄存器的硬件,是否存在lw $0, (mem)/nop的任何可能的极端情况,零寄存器丢弃写入,并且仅在寄存器文件中处理读取为零?
在这种情况下,它会看到一条阅读下一条指令中的加载结果的指令。在MIPS I上,这给出了读取的值的不可预测的结果,因为它不会因为旁路转发无法处理的危险而停止。(在后来的MIPS上,它失速了;加载延迟槽不是体系结构,只是性能。)当然,结果最终只是写入零寄存器,因此没有可观察到的差异。
但是,如果简单的硬件没有特殊情况下的零寄存器旁路转发,像addiu $0, $0, 123/addi $1, $0, 0可以复制一个非零值。因此,正确的MIPS设计不能那么简单,并且在进行旁路转发的危险检测时必须已经特殊情况$zero,以确保它不会旁路转发到$0的读取,这需要始终读取零。
暂停而不是旁路转发的MIPS设计在危险检测中不必特殊情况$0,因为所有值都将通过寄存器文件。但这可能不是MIPS架构师的考虑因素,因为旁路转发对于大多数代码的良好性能至关重要。

相关问题