2016-05-03 80 views
1

我正在学习MIPS指令,这个问题让我有些困惑,因为MIPS文档似乎在说一些与提供的答案不同的东西。这里是问题和答案:跳转和链接寄存器MIPS

什么寄存器引用和/或改变在这个指令在位置0x5000

0x5000 : 0x0140F809 

答案:

操作码= 0x00,R型,功能= 0×09(jalr),RS = 10($t2

跳跃$t2

提出0x5004解决在$ra

但是,从文档中可以看出,在寄存器31($ra)中,它将PC + 4置位。因此,由于指令在地址0x5000处执行,PC应该是0x5004吗?那么JALR指令不应该将0x5004 + 4或0x5008放入PC而不是0x5004?

对我来说它是有道理的,它应该跳回到0x5004,因为这在技术上是跳转后的下一条指令,但文档明确地说R [31] = PC + 4,所以它让我困惑一点,将是x5008。谢谢!

回答

2

你必须考虑的事情是分支延迟插槽

首先让我们来处理它们关闭的情况。这是模拟器的默认设置,如spimmars。事情很简单:

5000: jalr $10      # (1) $31 will have 5004 
5004: nop       # (2) this executed upon return 

这是大多数架构的工作方式。

但是,mips具有[上述]分支延迟时隙。

如果延迟被启用[在模拟器]或真实的硬件,传送控制指令的后(例如分支,跳转,JAL,JALR)是在作为无条件延迟槽遵循单指令之前执行分支实际上被采用[或]:

5000: jalr $10      # (1) $31 will have 5008 
5004: nop       # (2) this executed _before_ branch taken 
5008: nop       # (3) this executed upon return 

所以,有效执行顺序实际上是(2),(1),(3)。

在一般情况下,有一个三个步骤序列:

5000: beqz $10,foobar    # (1) conditional branch to foobar 
5004: nop       # (2) executed _before_ branch taken 
5008: nop       # (3) executed _after_ if branch _not_ taken 

再次,有效执行顺序为(2),(1)。然后,执行foobar的第一条指令[如果分支是取得了]或者执行5008(3)的指令,如果分支是而不是取得。

好的,您可能会问为什么

在早期的MIPS芯片中,指令被预取。例如,循环N + 1的指令在周期N中被预取[并且可能被预解码](一个周期延迟)。

因此,在周期N,执行单元执行该指令在周期N-1(例如5000)中取出的指令,指令预取单元被提取的下一个指令(在5004)。它们与一个循环延迟重叠。在周期N + 1中,执行单元正在执行预取指令(在5004)并且预取单元预取下一个指令(在5008)。

这很有效,直到遇到控制指令的条件传输。

如果没有延迟槽,处理器将不得不停止,并且执行与分支相同的周期预取的分支之后的指令将被浪费浪费。通过执行延迟插槽,通常可以使用一些有用的东西来填充插槽,所以不需要浪费预取。

但是,它确实使事情变得更加复杂。