在MIPS中,何时使用有符号扩展(signed-extend),何时使用零扩展(zero-extend)?

5
我正在设计一个MIPS处理器作为我的个人项目,目前我遇到了一个非常困惑的问题。我就是无法总结出在MIPS中何时使用符号扩展(signed-extend)和何时使用零扩展(zero-extend)。
我已经搜索了很多资源,大部分都说:
1) ADDI, ADDIU 都使用符号扩展。
2) ANDI, ORI, XORI 都使用零扩展。
然而,在以下这两个指令中,我开始感到困惑:
SLTIU/SLTI
在Imagination的《MIPS Architecture for Programmers Volume II-A: The MIPS instruction set Manual》第368页上写着: Picture 1 它清楚地说明了16位立即数是符号扩展的。但我不理解以下陈述:
[0, 32767] 或最大值[max_unsigned-32767, max_unsigned] 是无符号范围的末端。
还有一些人说16位立即数是零扩展的,就像这样: http://www.cs.umd.edu/class/sum2003/cmsc311/Notes/Mips/pseudojump.html 好的,有人能解释一下在MIPS中有符号指令和无符号指令之间的确切区别吗?

希望一些专家能够全面总结哪些指令使用有符号扩展,哪些指令使用零扩展。 - Shuaiyu Jiang
2个回答

4
我不确定你展示的两个描述是否完全一样,它们似乎是不同的实现。
想象公司MIPS的实现如下(使用SystemVerilog语法,假设通用寄存器为32位):
if ({1'b0 , GPR[rs]} < {1'b0 , sign_extend(immediate)} 
   GPR[rd] = 32'h00000001;
else
   GPR[rd] = 32'h00000000;

注意这是一个33位比较,其中第33位为0,因此是无符号比较。同时,请注意:
sign_extend(immediate) returns: { {16{immediate[15]}}, immediate }

这意味着 immediate 首先被视为有符号数,即一个 15 位的值,第 16 位是符号位。因此:
If immediate >=0, then sign_extend(immediate) is in [0,32767]. 

另一方面,如果 immediate 是一个负数,我们将会有:

sign_extend(immediate)  = { {16{1'b1}}, 1'b1, immediate[15:0] }, which is in [32'hFFFFFFFF-32767, 32'hFFFFFFFF]

32'hFFFFFFFF被称为max_unsigned。

简单来说,这个指令使你能够在GPR [rs]和一个无符号数字(范围为[0,32767]或[32'hFFFFFFFF-32767, 32'hFFFFFFFF])之间执行无符号比较。

第二种实现是在GPR [rs]和[0,65535]之间进行无符号比较。

编辑:

请注意,在SLTI和SLTIU中,立即值被符号扩展,但意图不同。在SLTIU中,将被比较的两个数字强制转换为无符号(通过添加第33位)。因此,立即数的符号扩展使得可以进行不同范围的比较:最小的32767个和最大的32767个无符号值,而不仅仅是0到65535。符号扩展并非出于用于签名比较的目的,这可能会让人感到困惑。

然而,在SLTI中,立即数的符号扩展是为了不同的目的:比较负数和正数(有符号比较)。


我更喜欢你的回答,能再问一个问题吗?在想象中的实现中,将立即数进行符号扩展然后将其视为无符号数与GPS [rs]进行比较的目的是什么?在我看来,如果您对数字进行符号扩展,然后将其视为无符号数,原始值将会失真。这对我来说毫无意义 :( - Shuaiyu Jiang
@ShuaiyuJiang:我已经在评论中回答了这个问题。我在上面的答案中添加了评论的摘要。 - Ari

1
文档暗示该指令首先进行16位立即数符号扩展,然后执行32位无符号比较。在Verilog中应该如下表述:
if (gpr[rs] < { {16{imm[15]}}, imm })
  gpr[rt] = 1;
else
  gpr[rt] = 0;

谢谢你的回答,Guy。让我困惑的是,当你比较两个二进制数时,无论你是将它们视为有符号还是无符号,结果都应该是相同的。例如4'b1011、4'b1001。当你将它们视为无符号时,11 >> 9;当你将它们视为有符号时,-5 >> -7。那么,有什么必要对立即数进行符号扩展呢?SLTI和SLTIU都得到了相同的结果,即第一个值大于第二个值。 - Shuaiyu Jiang
@ShuaiyuJiang:第二个实现中符号扩展立即数的重点在于能够比较有符号值(这也包括正数与负数的比较)。在Imagination的实现中,符号扩展会给您提供不同的范围:32767个最小和32767个最大的无符号值,而不仅仅是0到65535。 - Ari
在你的例子中,两个项目的大小是相同的,但这个指令是在比较一个32位的数量和一个16位的数量。如果你将你的例子看作是8'b00001011和4'b1001,那么答案就不同了。8'h0B > 8'h09,但8'h0B < 8'hF9。 - Guy
@Ari,首先感谢您的回答。让我这样问问题:手册上说SLTIU使用有符号扩展,然而SLTI也使用了有符号扩展(这是SLTI描述的副本:将GPR rs和16位有符号立即数作为有符号整数进行比较;在GPR rt中记录比较的布尔结果。如果GPR rs小于立即数,则结果为1(真);否则为0(假)。)由于这两个指令都使用了有符号扩展,那么这两个指令的区别是什么?希望这样说得清楚些:( - Shuaiyu Jiang
@ShuaiyuJiang:我认为SLTIU中的U很令人困惑。在SLTI和SLTIU中,立即值都是符号扩展的,但意图不同。在SLTIU中,被比较的两个数字被强制为无符号(通过添加33位0)。因此,立即数的符号扩展只是启用了不同范围的比较(它并不是为了进行有符号比较而执行的,这可能会让人感到困惑)。然而,在SLTI中,立即数的符号扩展是为了比较负值和正值(有符号比较)而执行的,目的不同。 - Ari

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