我正在了解MIPS数据路径中的指令解码(ID)阶段,并且得到以下引号:“一旦知道了操作数,就从寄存器中读取实际数据或将数据扩展到32位(立即)。”
有人可以解释“将数据扩展到32位(立即数)”部分的含义吗?我知道所有寄存器都包含32位,并且我知道立即数是什么。我只是不明白为什么您需要将立即数从26位扩展到32位。
谢谢!
答案 0 :(得分:1)
26位立即数仅在跳转指令中,不会符号扩展或零扩展为32位,因为它们不是要加/减的位移。
具有16位立即数的I型指令是不同的。
addi
/ addui
的立即数被符号扩展(通过将立即数的最高位/符号位复制到所有更高的位)。-2^15
.. +2^15-1
中的2的补码进行编码。 ori
/ andi
/ xori
布尔立即数是零扩展的(通过将所有较高的位设置为零)0 .. 2^16-1
中的无符号/ 2的补码进行编码。 这使得可以将16位立即数用作32位二进制操作的输入,而32位二进制操作仅对2个等宽输入才有意义。 (在一个简单的经典MIPS流水线中,解码级从寄存器和/或立即数中提取操作数。寄存器输入始终为32位,因此将ALU连接到32位输入。将立即数扩展为32位意味着其余的CPU不必关心数据是来自立即数还是寄存器。)
也可以扩展符号:
lw
/ sw
和其他加载/存储指令使用的reg + imm16寻址模式下的偏移量PC += imm16<<2
)也许是其他人,请查看手册以获取我没有提到的说明,以了解它们是否为正负号或零扩展。
您可能想知道“ addiu
为什么用符号扩展其立即数,即使它是未签名的?”
请记住,没有subiu
,只有addiu
的立即数为负。能够添加或减去范围-2^15 .. +2^15-1
的数字比仅能够添加0 .. 2^16-1
有用。
通常,您不想在有符号溢出上引发异常,因此通常编译器甚至对有符号整数也使用addu
/ addiu
。 addu
的命名错误:它不是“用于无符号整数”,它只是add
/ addi
的允许包装/永不出错的版本。如果您想到的是C,这是有意义的,其中有符号的溢出是未定义的行为(因此,如果编译器希望以这种方式实现它,则可以使用add
并在这种情况下引发异常),但是无符号的整数有定义的溢出行为:以2为基础的环绕。
答案 1 :(得分:1)
在32位CPU上,您执行的大多数操作(如加,减,取消引用指针)都是使用32位数字完成的。当您拥有一个位数较少的数字时,您需要以某种方式决定当您想在这些操作之一中使用该数字时其他那些位数将是什么。决定这些新的高位是什么的行为称为“扩展”。
假设您只是在进行标准的零扩展或符号扩展,则扩展非常便宜。但是,它确实需要一些电路,因此在MIPS数据路径的描述中会提到它是有道理的。