







4、RISC-V指令集的優勢
(1)完全開源。對于 RISC-V 指令集的使用,RISC-V基金會不收取高額的授權費。開源采用寬松的BSD 協議,企業可以完全自由免費使用,同時也允許企業添加自有指令集,而不必開放共享,實現差異化發展。
(2)架構簡單。RISC-V設。處理器領域,流的架構為x8與ARM架構。x86與ARM架構的發展過程也伴隨了現代處理器架構技術的不斷發展成熟,但作為商用的架構,為了能夠保持架構的向后兼容性,不得不保留許多過時的定義,導致其指令數目多,指令冗余嚴重,文檔數量龐大,所以要在這些架構上開發新的操作系統或者直接開發應用門檻很高。而RISC-V 架構則完全拋棄包袱,借助計算機體系結構經過多年的發展已經成為比較成熟的技術的優勢,從輕上路。RISC-V基礎指令集只有40多條,加上其他的模塊化擴展指令總共也就幾十條指令。RISC-V的規范文檔僅有145頁,而特權架構文檔的篇幅也僅為 91頁。
(3)易于移植操作系統。現代操作系統都做了特權級指令和用戶級指令的分離,特權指今只能由操作系統調用,而用戶級指令才能在用戶模式調用,保障操作系統的穩定。RISC-V提供了特權級指令和用戶級指令,同時提供了詳細的 RISC-V 特權級指令規范和 RISC-V 用戶級指令規范的詳細信息,使開發者能非常方便地移植 Linux 和 UNIX 系統到RISC-V平臺上。
(4)模塊化設計。RISC-V 架構不僅短小精悍,其不同的部分還能以模塊化的方式組紗在一起,從而試圖通過一套統一的架構滿足各種不同的應用場景。用戶能夠靈活選擇不同的模塊組合,來實現自己定制化設備的需要,比如針對小面積低功耗嵌入式場景,用戶可以選擇RV32IC 組合的指令集,僅使用Machine Mode(機器模式);而高性能應用操作系統場景則可以選擇RV32IMFDC 指令集,使用 Machine Mode(機器模式)與User Mode()戶模式)兩種模式。
(5)完整的工具鏈。對于設計CPU 來說,工具鏈是軟件開發人員和 CPU 交互的窗口,若沒有工具鏈,則對軟件開發人員開發軟件要求很高,甚至軟件開發者無法讓CPU 工作起來在CPU 設計中,工具鏈的開發是一個巨大的工作。如果用RISC-V來設計芯片,芯片設計公司則不用再擔心工具鏈問題,只需專注于芯片設計,RISC-V社區已經提供了完整的工具鏈 RISC-V 基金會持續維護該工具鏈。當前RISC-V的支持已經合并到主要的工具中,比如編評工具鏈 GCC、仿真工具 QEMU 等。
5、RISC-V的特點
1).沒有立即數減法
只有立即數加法指令(addi),沒有立即數減法指令(subi),那么減法怎么辦?無論是數學上還是程序上,x-y都等價于x+(-y),也就是說可以把減法變成加法,把被減數轉化成負數然后再加上減數就實現了和減法一樣的功能。正是基于這個原理,RISC-V只提供立即數加法,沒有提供立即數減法,如果需要立即數減法,那么就要麻煩編譯器把這個立即數轉化成負數,然后繼續使用加法。這也是 RISC-V將立即數作為有符號數處理的原因。
2). x0 寄存器簡化指令集
引入x0 寄存器后,很多特殊指令只需用普通的指令加上 x0 做操作數就能解決,指令的數量大大減少,處理器的解碼電路也大大簡化。
3).?32 位常量
之前使用的ARM 處理器是將立即數表示不下的常量存到常量池,然后用PC相關的LDR指令加載到寄存器。RISC-V 的常量完全是用指令拼接,不需要 Load 指令,使用 Load 指令需要額外的訪問周期。RISC-V 單條指令可以表示 12 位的有符號常量,超過 12 位需要兩條指令來合成。其中一條指令是 lui,lui 指令加載常量的高 20 位,低 12 位可以用addi指令上去,這個過程需要編譯器算出立即數到底是什么,因為 addi 指令執行的是有符號加法,其中的 12 位立即數會先被符號擴展成 32 位的有符號數再參與計算。ARM 的常量加載需要8個字節,一條指令加一個常量;RISC-V的常量加載也是需要8個字節,兩條指令,兩者占用的程序空間一樣。
4).只有小于和大于等于
RISC-V 的比較跳轉指令只有 blt 和 bge,即只有小于和大于等于。但大于和小于等于也是需要的,RISC-V用了一個很巧妙的辦法用兩條指令實現了四條指令的工作,將 blt 的兩個參與比較的操作數位置換一下就有了 bgt(大于跳轉),將bge 的兩個參與比較的操作數位置換一下就有了 ble(小于或等于跳轉)。
5).讓編譯器做更多工作
對 RISC 的理解是處理器盡量少做、編譯器盡量多做,這是非常有道理的,畢竟編譯的次數遠少于執行的次數。上面幾點就提到不少要讓編譯器多做的工作,又例如 B-type 是比較跳轉指令的格式,J-type 是長跳轉或函數調用指令格式,注意它們的立即數排列次序,把填充這里的立即數交給了鏈接器的工作。這樣排放偏移地址立即數是為了簡化處理器的設計,但明顯給編譯器增加了工作。
6).其他省掉的指令
很多常用的指令都被省掉了,比如nop、move、not、neg 等,但所有這些功能都還有只不過都是用其他的指令來等價實現,比如not 指令是用xorird,rs,-1實現。
6、RISC-V的x0寄存器
Linux 有兩個特殊的設備:/dev/zero 和/dev/null。從/dev/zero 可以源源不斷地讀到0,往dev/null 寫的任何內容都被丟棄。如果要創建一個需要填0的文件,就從dev/zero 拷貝,如
果要丟棄一些輸出,就把輸出重定向到/dev/null。RISC-V的x0寄存器就相當于是硬件版的/dev/zero 和/dev/null的組合體。從0讀出來的總是0,往x0 寫進去的總是被丟棄。所以 x0 提供兩種功能:一是提供常量0,在軟件編程中0可以說是最常用的常量:二是提供一個可以丟棄結果的場所。有了 x0 寄存器,很多本來需要單獨指令的操作只要在普通的指令前加上x0 就可以實現。
(1)nop 空指令,RISC-V沒有提供nop 指令,而是用addi x0,x0,0來實現空指令,這條addi 使用x0作為目標存器,會丟棄結果,所以這條指令不會對程序狀態產生任何影響,和空指令是完全等價的,這就不需要單獨的空指令了。
(2)neg 取負數指令,RISC-V用 sub rd,x0,rs 來實現,x0-rs 等價于0-rs,等價于-rs,有了x0,就可以用更普通的減法指令來實現取負數指令。
(3)j跳轉指令,RISC-V 沒有單獨的跳轉指令,只有jal跳轉鏈接指令,跳轉之前總是要把下一條指令的地址拷貝到寄存器,但是如果用 x0 作為jal 的操作寄存器,即把下-條指令的地址拷貝到 x0,那么效果就等價于j跳轉指令了,因為寫入 x0 的任何值都會被丟棄。
(4)beqz等于零跳轉指令等一系列和0比較的跳轉指令,程序中和0比較是相當常見的操作,RISC-V 中和0比較的指令是普通的比較跳轉指令,是用 x0 寄存器做指令的操作數。還有很多其他這樣的指令,用普通的指令加上 x0 做操作數,就實現了那些沒有x0 寄存器的處理器需要單獨指令或者需要組合兩條指令才能實現的操作。


