《自己動手寫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帶有溢出檢測(或者說帶“自陷”功能,雖然不常用)。