在下面的图表和文本中,PC是分支指令本身的地址。PC+4是分支指令本身的结束,以及下一条指令(使用延迟槽的MIPS中的分支延迟槽)的开始。 除了在绝对跳转图中,我们实际上取跳转后指令地址的高4位。只有different at the end of a 256 MiB region。这些图在他们所谓的PC中彼此不一致,或者可能是通过简化PC+4与PC具有相同的前4位来创建的。
1.分支地址计算
在MIPS中,分支指令只有16位偏移量来确定下一条指令。我们需要一个寄存器添加到这个16位值,以确定下一个指令,这个寄存器实际上是由架构隐含的。它是PC寄存器,因为PC在取指周期中更新(PC+4),因此它保存下一条指令的地址。 我们还将分支距离限制为-2^15 to +2^15 - 1指令。然而,这不是真实的问题,因为大多数分支机构都是本地的。
4条答案
按热度按时间hfsqlsce1#
在下面的图表和文本中,
PC
是分支指令本身的地址。PC+4
是分支指令本身的结束,以及下一条指令(使用延迟槽的MIPS中的分支延迟槽)的开始。除了在绝对跳转图中,我们实际上取跳转后指令地址的高4位。只有different at the end of a 256 MiB region。这些图在他们所谓的PC中彼此不一致,或者可能是通过简化PC+4与PC具有相同的前4位来创建的。
1.分支地址计算
在MIPS中,分支指令只有16位偏移量来确定下一条指令。我们需要一个寄存器添加到这个16位值,以确定下一个指令,这个寄存器实际上是由架构隐含的。它是PC寄存器,因为PC在取指周期中更新(PC+4),因此它保存下一条指令的地址。
我们还将分支距离限制为
-2^15 to +2^15 - 1
指令。然而,这不是真实的问题,因为大多数分支机构都是本地的。一步一步来:
2.跳转地址计算
对于跳转指令,MIPS只有26位来确定跳转位置。跳转是相对于MIPS中的PC而言的。与分支一样,立即跳转值需要与字对齐;因此,我们需要将26位地址与4相乘。
一步一步来:
换句话说,将PC + 4的低28位替换为左移2位的取出指令的低26位。
跳转在包含分支延迟槽的区域内是绝对的,而不一定是分支本身。在上图中,PC已经在跳转计算之前前进到分支延迟槽。(在经典RISC 5级流水线中,BD在跳转被解码的同一周期中被获取,因此PC+4下一个指令地址已经可用于跳转以及分支,并且相对于跳转自身地址的计算将需要额外的工作来保存该地址。)
**来源:**Bilkent University CS 224 Course Slides
rfbsl7qr2#
通常你不必担心计算它们,因为你的汇编器(或链接器)会正确计算。假设你有一个小函数:
当把上面的代码转换成二进制指令流时,汇编器(或者如果你第一次汇编成一个目标文件,则是链接器)将确定函数将驻留在内存中的哪个位置(现在让我们忽略位置无关的代码)。它将驻留在内存中的位置通常在ABI中指定,或者如果您使用模拟器(如SPIM,它将在
0x400000
加载代码-请注意链接还包含对该过程的良好解释),则会提供给您。假设我们讨论的是SPIM情况,并且我们的函数首先位于内存中,则
slti
指令将驻留在0x400000
,beq
将驻留在0x400004
,依此类推。我们快到了!对于beq
指令,* 分支目标地址 * 是cont
(0x400010
)的地址,查看MIPS instruction reference,我们看到它被编码为相对于下一条指令的16位有符号立即数(除以4,因为所有指令无论如何都必须驻留在4字节对齐的地址上)。即:
beq $t0, $zero, cont
的编码正如您所看到的,您可以分支到
-0x1fffc .. 0x20000
字节内。如果出于某种原因,你需要跳得更远,你可以使用蹦床(无条件跳到放置在给定限制内的真实的目标)。与分支目标地址不同,* 跳转目标地址 * 使用 * 绝对 * 地址(再次除以4)进行编码。由于指令编码使用6位的操作码,这只留下26位的地址(有效地28给定的最后2位将是0),因此,4位的PC寄存器的最高有效位时,使用形成地址(不会有关系,除非你打算跨越256 MB的边界)。
回到上面的例子,
jal func
的编码是:您可以快速验证这一点,并使用我遇到的这个online MIPS assembler来尝试不同的指令(注意它不支持所有操作码,例如
slti
,所以我在这里将其更改为slt
):u0sqgete3#
我认为很难计算这些,因为分支目标地址是在运行时确定的,而预测是在硬件中完成的。如果你更深入地解释这个问题,并描述你正在努力做什么,那么帮助会更容易一些。(:
os8fio9y4#
对于像这样的小函数,您可以手动计算从分支指令下的指令到目标的跳数。如果它向后分支,使跳数为负。如果该数字不需要全部16位,那么对于跳数中最高有效位左边的每个数字,将其设为1,如果跳数为正数,则将其设为0。由于大多数分支都靠近目标,因此在大多数情况下,这可以节省大量额外的运算。