MIPS32的ADDI和ADDIU的实现要点(加法指令)
《自己动手写CPU》一书中对指令ADDI和ADDIU的实现方式是一样的。
对16位立即数imm,在执行加法指令之前都符号扩展成32位数(与符号扩展对应的是零扩展)。
这样看来ADDI和ADDIU指令都用于有符号数的加法,在指令集实现的时候没有任何区别。
如果是这种情况,那么ADDI和ADDIU都仅支持有符号数的加法,否则ADDI和ADDIU指令执行无符号加法的时候就会出错:
如32'b0001+16'b1000_0000_0000_0001
按照无符号加法,这是 1 + 32769 = 32770。
然而 16'b1000_0000_0000_0001 经过符号扩展变成 32'b1111_1111_1111_1111_1000_0000_0000_0001(4294934529)
相加的结果变成 1 + 4294934529 = 4294934530,显然不正确。
那么ADDI和ADDIU是否仅能够支持有符号加法?ADDIU中的U是否unsigned的意思?
在《MD00565-2B-MIPS32-QRC-01.01》文档中对ADDI和ADDIU有明确的说明:
这里±的意思是:
另外在《MIPS Instruction Reference》文档中对此也有明确的说明:
这两个文档都突出说明了ADDI和ADDIU的最大区别是有没有溢出标志(overflow)。
《MIPS体系结构剖析》(英文书名是see mips run linux)中对于带U和不带U的助记符描述如下:
这里将加法指令ADD和ADDU的区别描述为是否带“自陷”(异常,如检查除数为0)或者溢出检测,而非有符号无符号加法的区别。
那么ADDI的溢出判断需要怎么做?可以参考以下两个文档:
http://blog.csdn.net/u011225147/article/details/53707614
https://wenku.baidu.com/view/bbad4e73f46527d3240ce04d.html
那么最后总结ADDI和ADDIU的实现有以下2个要点:
1)仅支持有符号运算(补码运算),16位立即数需要进行符号扩展;
2)ADDI带有溢出检测(或者说带“自陷”功能,虽然不常用)。